Skip to content

Commit

Permalink
Add an envar to disable automatic provider installation (#14083)
Browse files Browse the repository at this point in the history
<!--- 
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->

# Description

<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->

This is primarily for the providers team to enable during builds so they
can have more confidence about reproducibility of builds (especially
examples conversion), but I imagine some customers would enable this as
well.

Fixes #14086

## Checklist

- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
  - [ ] I have formatted my code using `gofumpt`

<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!--- 
User-facing changes require a CHANGELOG entry.
-->
- [x] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
  • Loading branch information
Frassle authored Oct 3, 2023
1 parent 0261d95 commit 961dfaa
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
changes:
- type: feat
scope: cli
description: Users can now set PULUMI_DISABLE_AUTOMATIC_PLUGIN_ACQUISITION to disable the engine trying to auto install missing plugins.
12 changes: 11 additions & 1 deletion pkg/cmd/pulumi/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ func loadConverterPlugin(
// Try and load the converter plugin for this
converter, err := plugin.NewConverter(ctx, name, nil)
if err != nil {
// If NewConverter returns a MissingError, we can try and install the plugin and try again.
// If NewConverter returns a MissingError, we can try and install the plugin if it was missing and try again,
// unless auto plugin installs are turned off.
if env.DisableAutomaticPluginAcquisition.Value() {
return nil, fmt.Errorf("load %q: %w", name, err)
}

var me *workspace.MissingError
if !errors.As(err, &me) {
// Not a MissingError, return the original error.
Expand Down Expand Up @@ -323,6 +328,11 @@ func runConvert(
}

installProvider := func(provider tokens.Package) *semver.Version {
// If auto plugin installs are disabled just return nil, the mapper will still carry on
if env.DisableAutomaticPluginAcquisition.Value() {
return nil
}

pluginSpec := workspace.PluginSpec{
Name: string(provider),
Kind: workspace.ResourcePlugin,
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/pulumi/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"github.com/pulumi/pulumi/pkg/v3/resource/stack"
pkgWorkspace "github.com/pulumi/pulumi/pkg/v3/workspace"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
Expand Down Expand Up @@ -566,6 +567,11 @@ func newImportCmd() *cobra.Command {
pCtx.Diag.Warningf(diag.RawMessage("", "Plugin converters are currently experimental"))

installProvider := func(provider tokens.Package) *semver.Version {
// If auto plugin installs are disabled just return nil, the mapper will still carry on
if env.DisableAutomaticPluginAcquisition.Value() {
return nil
}

log := func(sev diag.Severity, msg string) {
pCtx.Diag.Logf(sev, diag.RawMessage("", msg))
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/pulumi/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"

"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"

"github.com/blang/semver"
Expand Down Expand Up @@ -159,6 +160,11 @@ func providerFromSource(packageSource string) (plugin.Provider, error) {
return nil, fmt.Errorf("could not find installed plugin %s, did you mean ./%[1]s: %w", pkg, err)
}

// Try and install the plugin if it was missing and try again, unless auto plugin installs are turned off.
if env.DisableAutomaticPluginAcquisition.Value() {
return nil, err
}

var missingError *workspace.MissingError
if errors.As(err, &missingError) {
spec := workspace.PluginSpec{
Expand Down
6 changes: 6 additions & 0 deletions pkg/codegen/schema/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

pkgWorkspace "github.com/pulumi/pulumi/pkg/v3/workspace"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
Expand Down Expand Up @@ -215,6 +216,11 @@ func LoadPackageReference(loader Loader, pkg string, version *semver.Version) (P
func (l *pluginLoader) loadSchemaBytes(pkg string, version *semver.Version) ([]byte, *semver.Version, error) {
pluginInfo, err := l.host.ResolvePlugin(workspace.ResourcePlugin, pkg, version)
if err != nil {
// Try and install the plugin if it was missing and try again, unless auto plugin installs are turned off.
if env.DisableAutomaticPluginAcquisition.Value() {
return nil, nil, err
}

var missingError *workspace.MissingError
if errors.As(err, &missingError) {
spec := workspace.PluginSpec{
Expand Down
9 changes: 7 additions & 2 deletions pkg/resource/deploy/providers/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

pkgWorkspace "github.com/pulumi/pulumi/pkg/v3/workspace"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
Expand Down Expand Up @@ -163,8 +164,12 @@ func loadProvider(pkg tokens.Package, version *semver.Version, downloadURL strin
return nil, err
}

// Try to install the plugin, we have all the specific information we need to do so here while once we
// call into `host.Provider` we no longer have the download URL or checksums.
// Try to install the plugin, unless auto plugin installs are turned off, we have all the specific information we
// need to do so here while once we call into `host.Provider` we no longer have the download URL or checksums.
if env.DisableAutomaticPluginAcquisition.Value() {
return nil, err
}

pluginSpec := workspace.PluginSpec{
Kind: workspace.ResourcePlugin,
Name: string(pkg),
Expand Down
3 changes: 3 additions & 0 deletions sdk/go/common/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ var DisableOutputValues = env.Bool("DISABLE_OUTPUT_VALUES", "")
var IgnoreAmbientPlugins = env.Bool("IGNORE_AMBIENT_PLUGINS",
"Discover additional plugins by examining $PATH.")

var DisableAutomaticPluginAcquisition = env.Bool("DISABLE_AUTOMATIC_PLUGIN_ACQUISITION",
"Disables the automatic installation of missing plugins.")

var SkipConfirmations = env.Bool("SKIP_CONFIRMATIONS",
`Whether or not confirmation prompts should be skipped. This should be used by pass any requirement
that a --yes parameter has been set for non-interactive scenarios.
Expand Down
33 changes: 33 additions & 0 deletions tests/smoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,36 @@ func TestLanguageImportSmoke(t *testing.T) {
})
}
}

// Test that PULUMI_DISABLE_AUTOMATIC_PLUGIN_ACQUISITION disables plugin acquisition in convert.
//
//nolint:paralleltest // changes env vars and plugin cache
func TestConvertDisableAutomaticPluginAcquisition(t *testing.T) {
e := ptesting.NewEnvironment(t)
defer deleteIfNotFailed(e)

e.ImportDirectory("testdata/aws_tf")

// Delete all cached plugins and disable plugin acquisition.
e.RunCommand("pulumi", "plugin", "rm", "--all", "--yes")
// Disable acquisition.
e.SetEnvVars("PULUMI_DISABLE_AUTOMATIC_PLUGIN_ACQUISITION=true")

// This should fail because of no terraform converter
_, stderr := e.RunCommandExpectError(
"pulumi", "convert",
"--language", "pcl", "--from", "terraform", "--out", "out")
assert.Contains(t, stderr, "no converter plugin 'pulumi-converter-terraform' found")

// Install a _specific_ version of the terraform converter (so this test doesn't change due to a new release)
e.RunCommand("pulumi", "plugin", "install", "converter", "terraform", "v1.0.8")
// This should now convert, but won't use our full aws tokens
e.RunCommand(
"pulumi", "convert",
"--language", "pcl", "--from", "terraform", "--out", "out")

output, err := os.ReadFile(filepath.Join(e.RootPath, "out", "main.pp"))
require.NoError(t, err)
// If we had an AWS plugin and mapping this would be "aws:ec2/instance:Instance"
assert.Contains(t, string(output), "\"aws:index:instance\"")
}
8 changes: 8 additions & 0 deletions tests/testdata/aws_tf/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "aws_instance" "app_server" {
ami = "ami-830c94e3"
instance_type = "t2.micro"

tags = {
Name = "ExampleAppServerInstance"
}
}

0 comments on commit 961dfaa

Please sign in to comment.