Skip to content

tools/terraform-bundle: refactor to use new provider installer and provider directory layouts#24629

Merged
mildwonkey merged 12 commits intomasterfrom
mildwonkey/ps-tf-bundle
Apr 21, 2020
Merged

tools/terraform-bundle: refactor to use new provider installer and provider directory layouts#24629
mildwonkey merged 12 commits intomasterfrom
mildwonkey/ps-tf-bundle

Conversation

@mildwonkey
Copy link
Copy Markdown
Contributor

@mildwonkey mildwonkey commented Apr 10, 2020

... to use new provider installer and provider directory layouts

UPDATE
This supersedes the "NOTE" below (saved for history).
I updated this branch to include the hard-coded requirement for terraform v0.13 and temporarily disabled the e2e tests, which will fail until there is a v0.13 on releases.hashicorp.com (or we decide it's worth the effort to do a bit of hacking for test purposes). We've had at least one user (understandably) try to build terraform-bundle from master and find that it does not work with terraform v0.12 so it seems better to merge now so other users will see the expected error (and updated documentation).

NOTE (obsolete, saved for history)
This PR is in an awkward state: it needs one more commit which will limit its use to Terraform v0.13 (see the zeroThirteen variable in config.go, currently and un-intuitively set to ">= 0.12.0"), but setting that variable properly causes tests to fail because there is no terraform v0.13 in releases. I would like a review on this PR, but it will not be merged before we have a 0.13 release (alpha or beta).


terraform-bundle now supports a "source" attribute for providers,
uses the new provider installer, and the archive it creates preserves
the new (required) directory hierarchy for providers, under a "plugins"
directory.

This is a breaking change in many ways: source is required for any
non-HashiCorp provider, locally-installed providers must be given a
source (can be arbitrary, see docs) and placed in the expected directory
hierarchy, and the unzipped archive is no longer flat; there is a new
"plugins" directory created with providers in the new directory layout.

I've open an internal task with the Terraform Enterprise team letting them know about this new directory layout; my hope is that we can use an environment variable (taking advantage of the provider installer's support for XDG basedir spec) to point TFE to the new plugins directory (which will be in the same directory as the terraform binary)

This PR also extends the existing test to check the contents of the zip file and adds the terraform-bundle e2e test to CircleCi.

I've also updated the documentation, though it definitely needs some editing/help!

@mildwonkey mildwonkey requested a review from a team April 10, 2020 13:11
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2020

Codecov Report

Merging #24629 into master will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted Files Coverage Δ
internal/providercache/dir.go 62.96% <100.00%> (ø)
...in/provisioners/local-exec/resource_provisioner.go 91.02% <0.00%> (+1.28%) ⬆️

Copy link
Copy Markdown
Contributor

@alisdair alisdair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! 👏 Being able to reuse the new provider installer code with multiple sources is really cool. I left a few minor notes inline. Note that I haven't tested this branch locally (yet), this review is just based on the diff.


```
./plugins/example.com/myorg/customplugin/0.1/linux_amd64/
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌 This is example is very helpful!

},
FetchPackageBegin: func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation) {
c.ui.Info(fmt.Sprintf("- Installing %s v%s...", provider.ForDisplay(), version))
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to add the FetchPackageSuccess callback here after #24617 is merged, if only for consistency.

@alisdair
Copy link
Copy Markdown
Contributor

I was unable to convince terraform-bundle to package a locally-cached provider. The error:

Could not retrieve the list of available versions for provider example.com/myorg/customplugin: host example.com does not offer a Terraform provider registry.
some providers could not be installed:
- example.com/myorg/customplugin: host example.com does not offer a Terraform provider registry

Here's the config:

terraform {
  version = "0.12.0"
}

providers {
  aws = {
    versions = ["~> 1.0"]
  }

  google = {
    versions = ["~> 1.0", "~> 2.0"]
  }

  customplugin = {
    versions = ["0.1"]
    source = "example.com/myorg/customplugin"
  }
}

Local filesystem layout:

ls -lR
velara:tf-bundle $ ls -lR
total 8
-rw-r--r--  1 alisdair  staff  237 15 Apr 12:07 bundle.tf
drwxr-xr-x  3 alisdair  staff   96 15 Apr 11:51 plugins

./plugins:
total 0
drwxr-xr-x  3 alisdair  staff  96 15 Apr 11:44 example.com

./plugins/example.com:
total 0
drwxr-xr-x  3 alisdair  staff  96 15 Apr 11:44 myorg

./plugins/example.com/myorg:
total 0
drwxr-xr-x  3 alisdair  staff  96 15 Apr 11:59 customplugin

./plugins/example.com/myorg/customplugin:
total 0
drwxr-xr-x  3 alisdair  staff  96 15 Apr 11:59 0.1

./plugins/example.com/myorg/customplugin/0.1:
total 0
drwxr-xr-x  3 alisdair  staff  96 15 Apr 12:04 darwin_amd64

./plugins/example.com/myorg/customplugin/0.1/darwin_amd64:
total 0
-rwxr-xr-x  1 alisdair  staff  0 15 Apr 11:45 terraform-provider-customplugin_v0.1

Log output:

TF_LOG=trace terraform-bundle package bundle.tf
velara:tf-bundle $ TF_LOG=trace terraform-bundle package bundle.tf
Fetching Terraform 0.12.0 core package...
2020/04/15 12:07:31 [TRACE] HTTP client HEAD request to https://releases.hashicorp.com/terraform/0.12.0/terraform_0.12.0_darwin_amd64.zip
2020/04/15 12:07:32 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform/0.12.0/terraform_0.12.0_darwin_amd64.zip
2020/04/15 12:07:33 [TRACE] providercache.fillMetaCache: scanning directory /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:33 [WARN] Failed to scan provider cache directory /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins: cannot search /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins: lstat /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins: no such file or directory
- Finding hashicorp/aws versions matching "~> 1.0"...
2020/04/15 12:07:33 [TRACE] getproviders.SearchLocalDirectory: found example.com/myorg/customplugin v0.1.0 for darwin_amd64 at plugins/example.com/myorg/customplugin/0.1/darwin_amd64
2020/04/15 12:07:33 [DEBUG] Service discovery for registry.terraform.io at https://registry.terraform.io/.well-known/terraform.json
2020/04/15 12:07:34 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/aws/versions
2020/04/15 12:07:34 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/aws/1.60.0/download/darwin/amd64
- Installing hashicorp/aws v1.60.0...
2020/04/15 12:07:34 [TRACE] providercache.Dir.InstallPackage: installing registry.terraform.io/hashicorp/aws v1.60.0 from https://releases.hashicorp.com/terraform-provider-aws/1.60.0/terraform-provider-aws_1.60.0_darwin_amd64.zip
2020/04/15 12:07:34 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-aws/1.60.0/terraform-provider-aws_1.60.0_darwin_amd64.zip
2020/04/15 12:07:49 [TRACE] providercache.fillMetaCache: scanning directory /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:49 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/aws v1.60.0 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64
2020/04/15 12:07:49 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/aws 1.60.0
2020/04/15 12:07:49 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:50 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
- Finding hashicorp/google versions matching "~> 1.0"...
2020/04/15 12:07:50 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/google/versions
2020/04/15 12:07:51 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/google/1.20.0/download/darwin/amd64
- Installing hashicorp/google v1.20.0...
2020/04/15 12:07:51 [TRACE] providercache.Dir.InstallPackage: installing registry.terraform.io/hashicorp/google v1.20.0 from https://releases.hashicorp.com/terraform-provider-google/1.20.0/terraform-provider-google_1.20.0_darwin_amd64.zip
2020/04/15 12:07:51 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-google/1.20.0/terraform-provider-google_1.20.0_darwin_amd64.zip
2020/04/15 12:07:55 [TRACE] providercache.fillMetaCache: scanning directory /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:55 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/aws v1.60.0 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64
2020/04/15 12:07:55 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/google v1.20.0 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/1.20.0/darwin_amd64
2020/04/15 12:07:55 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/aws 1.60.0
2020/04/15 12:07:55 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/1.20.0/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/google 1.20.0
2020/04/15 12:07:55 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:55 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
- Finding hashicorp/google versions matching "~> 2.0"...
2020/04/15 12:07:55 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/google/2.20.3/download/darwin/amd64
- Installing hashicorp/google v2.20.3...
2020/04/15 12:07:55 [TRACE] providercache.Dir.InstallPackage: installing registry.terraform.io/hashicorp/google v2.20.3 from https://releases.hashicorp.com/terraform-provider-google/2.20.3/terraform-provider-google_2.20.3_darwin_amd64.zip
2020/04/15 12:07:55 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-google/2.20.3/terraform-provider-google_2.20.3_darwin_amd64.zip
2020/04/15 12:07:58 [TRACE] providercache.fillMetaCache: scanning directory /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:58 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/aws v1.60.0 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64
2020/04/15 12:07:58 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/google v1.20.0 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/1.20.0/darwin_amd64
2020/04/15 12:07:58 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/google v2.20.3 for darwin_amd64 at /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/2.20.3/darwin_amd64
2020/04/15 12:07:58 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/aws/1.60.0/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/aws 1.60.0
2020/04/15 12:07:58 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/1.20.0/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/google 1.20.0
2020/04/15 12:07:58 [TRACE] providercache.fillMetaCache: including /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins/registry.terraform.io/hashicorp/google/2.20.3/darwin_amd64 as a candidate package for registry.terraform.io/hashicorp/google 2.20.3
2020/04/15 12:07:58 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
2020/04/15 12:07:59 [TRACE] providercache.fillMetaCache: using cached result from previous scan of /var/folders/d6/3gfl83ks03sf7j34c0c9125r0000gn/T/terraform-bundle453651676/plugins
- Finding example.com/myorg/customplugin versions matching "0.1.*"...
2020/04/15 12:07:59 [DEBUG] Service discovery for example.com at https://example.com/.well-known/terraform.json
Could not retrieve the list of available versions for provider example.com/myorg/customplugin: host example.com does not offer a Terraform provider registry.
some providers could not be installed:
- example.com/myorg/customplugin: host example.com does not offer a Terraform provider registry

@mildwonkey mildwonkey force-pushed the mildwonkey/ps-tf-bundle branch from d12932b to e7e3139 Compare April 16, 2020 18:03
@mildwonkey
Copy link
Copy Markdown
Contributor Author

@apparentlymart this is the trace output when I've attempted to exclude locally-added providers from the registry search:

        excluding getproviders.MultiSourceMatchingPatterns{addrs.Provider{Type:"mycloud", Namespace:"myorg", Hostname:svchost.Hostname("example.com")}}
        2020/04/16 14:00:22 [TRACE] providercache.fillMetaCache: scanning directory /var/folders/21/xqyhts6j1gz849d8d0_cfm3r0000gq/T/terraform-bundle723486668/plugins
        2020/04/16 14:00:22 [WARN] Failed to scan provider cache directory /var/folders/21/xqyhts6j1gz849d8d0_cfm3r0000gq/T/terraform-bundle723486668/plugins: cannot search /var/folders/21/xqyhts6j1gz849d8d0_cfm3r0000gq/T/terraform-bundle723486668/plugins: lstat /var/folders/21/xqyhts6j1gz849d8d0_cfm3r0000gq/T/terraform-bundle723486668/plugins: no such file or directory
        2020/04/16 14:00:22 [DEBUG] Service discovery for example.com at https://example.com/.well-known/terraform.json
        Could not retrieve the list of available versions for provider example.com/mycorp/mycloud: host example.com does not offer a Terraform provider registry.
        some providers could not be installed:
        - example.com/mycorp/mycloud: host example.com does not offer a Terraform provider registry

in case you missed my super professional debugging statement in there 😉 :
excluding getproviders.MultiSourceMatchingPatterns{addrs.Provider{Type:"mycloud", Namespace:"myorg", Hostname:svchost.Hostname("example.com")}}

Copy link
Copy Markdown
Contributor

@alisdair alisdair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me! Verified working locally 👍

# a name of the form: terraform-provider-*, and must be build with the operating
# system and architecture that terraform enterprise is running, e.g. linux and amd64
customplugin = ["0.1"]
# plugins directory and package it with the bundle archive. Plugin must have
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# plugins directory and package it with the bundle archive. Plugin must have
# ./.plugins directory and package it with the bundle archive. Plugin must have

I'm less sure about the helpfulness of this one…

subdirectory under "./plugins". The directory must have the following layout:

```
./plugins/$SOURCEHOST/$SOURCENAMESPACE/$NAME/$VERSION/$OS_$ARCH/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
./plugins/$SOURCEHOST/$SOURCENAMESPACE/$NAME/$VERSION/$OS_$ARCH/
./.plugins/$SOURCEHOST/$SOURCENAMESPACE/$NAME/$VERSION/$OS_$ARCH/

foundLocally := map[addrs.Provider]struct{}{}

if absPluginDir, err := filepath.Abs(pluginDir); err == nil {
if _, err := os.Stat(absPluginDir); err == nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some logging around here might be helpful. Examples of things that would've helped me find my own mistake today

  • No ./.plugins directory found, skipping local provider discovery.
  • Found ./.plugins directory, discovering local providers.
  • Local provider found: "example.com/myorg/customplugin"
  • No local providers found.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love it, added all of them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope you like that commit message 😝

provider directory layouts

terraform-bundle now supports a "source" attribute for providers,
uses the new provider installer, and the archive it creates preserves
the new (required) directory hierarchy for providers, under a "plugins"
directory.

This is a breaking change in many ways: source is required for any
non-HashiCorp provider, locally-installed providers must be given a
source (can be arbitrary, see docs) and placed in the expected directory
hierarchy, and the unzipped archive is no longer flat; there is a new
"plugins" directory created with providers in the new directory layout.

This PR also extends the existing test to check the contents of the zip
file.
@mildwonkey mildwonkey force-pushed the mildwonkey/ps-tf-bundle branch from 87abaff to 30cb109 Compare April 21, 2020 12:36
@mildwonkey mildwonkey added this to the v0.13.0 milestone Apr 21, 2020
@mildwonkey mildwonkey changed the title [DO NOT MERGE] tools/terraform-bundle: refactor to use new provider installer and provider directory layouts tools/terraform-bundle: refactor to use new provider installer and provider directory layouts Apr 21, 2020
@mildwonkey mildwonkey merged commit a43f141 into master Apr 21, 2020
@mildwonkey mildwonkey deleted the mildwonkey/ps-tf-bundle branch April 21, 2020 21:09
@ghost
Copy link
Copy Markdown

ghost commented May 22, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators May 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants