Commit Graph

61 Commits

Author SHA1 Message Date
Martin Atkins
0503163e28 tracing: Centralize our OpenTelemetry package imports
OpenTelemetry has various Go packages split across several Go modules that
often need to be carefully upgraded together. And in particular, we are
using the "semconv" package in conjunction with the OpenTelemetry SDK's
"resource" package in a way that requires that they both agree on which
version of the OpenTelemetry Semantic Conventions are being followed.

To help avoid "dependency hell" situations when upgrading, this centralizes
all of our direct calls into the OpenTelemetry SDK and tracing API into
packages under internal/tracing, by exposing a few thin wrapper functions
that other packages can use to access the same functionality indirectly.

We only use a relatively small subset of the OpenTelemetry library surface
area, so we don't need too many of these reexports and they should not
represent a significant additional maintenance burden.

For the semconv and resource interaction in particular this also factors
that out into a separate helper function with a unit test, so we should
notice quickly whenever they become misaligned. This complements the
end-to-end test previously added in opentofu/opentofu#3447 to give us
faster feedback about this particular problem, while the end-to-end test
has the broader scope of making sure there aren't any errors at all when
initializing OpenTelemetry tracing.

Finally, this also replaces the constants we previously had in package
traceaddrs with functions that return attribute.KeyValue values directly.
This matches the API style used by the OpenTelemetry semconv packages, and
makes the calls to these helpers from elsewhere in the system a little
more concise.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-10-30 13:27:10 -07:00
Christian Mesh
11694a6ac0 Alternate approach to linking and locking the global cache (#2708)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
2025-05-08 15:26:46 -04:00
Martin Atkins
be85918f53 providercache: Dir.LinkFromOtherCache takes a context.Context
This allows removing the last remaining context.TODO() from this package,
and allows incoming tracing spans to reach the underlying provider
installation operations in all cases.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-05-06 07:53:05 -07:00
James Humphries
6d3aed0e8f [OpenTelemetry] Add module init tracing (#2711)
Signed-off-by: James Humphries <james@james-humphries.co.uk>
2025-05-01 14:15:03 +01:00
James Humphries
8629b0a49a [OpenTelemetry] Add traces to providers lock command (#2694)
Signed-off-by: James Humphries <james@james-humphries.co.uk>
2025-04-28 17:01:38 +01:00
Christian Mesh
d0ee5a36a5 Provider plugin cache locking (#1878)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
2025-04-25 09:39:17 -04:00
James Humphries
d92d4f9c11 [OpenTelemetry] Add traces to init command (#2665)
Signed-off-by: James Humphries <james@james-humphries.co.uk>
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
2025-04-25 12:40:48 +01:00
Christian Mesh
0178912104 Refactor the provider installer loop (#2695)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
2025-04-24 05:57:07 -04:00
Martin Atkins
55855fca70 getproviders: Unify package authentication with hash lock selection
As discussed in opentofu/opentofu#2656, this consolidates the two concerns
of the PackageAuthentication interface into a single function that deals
both with package authentication _and_ with reporting all of the package
hashes that were used to make the authentication decision.

This means that any .zip archive that OpenTofu directly verifies during
installation can now have its hash recorded in the dependency lock file
even if that package didn't come from the provider's origin registry, which
is beneficial when the first installation of a provider comes from a
secondary ("mirror") source because it creates an additional hook by which
that dependency lock file entry can be "upgraded" to be complete in a
future "tofu init" run against the origin registry, or by the
"tofu providers lock" command.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-04-14 08:31:40 -07:00
Christian Mesh
b2bf39802a Implement the first part of RFC 20250303-linter-policy (#2577)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
2025-03-10 13:16:27 -04:00
Martin Atkins
f5eac16b00 providercache: Factor out installation from the global cache dir
This is another step towards breaking the huge functions in this package
into smaller parts that have a clearer set of inputs and outputs.

For the moment the goal is to modify the existing code as little as
possible to make this easier to review, and so the new function
tryInstallPackageFromCacheDir has an unfortunately-large number of
arguments. Future refactoring can hopefully improve on this further.

One significant change to the structure of this code is that because it's
now in a separate function working on only one provider at a time we can
rely on early return for error handling, letting the caller be responsible
for collecting any errors into the "errs" map, and so we don't need quite
as much nesting as the previous code had.

This should not change the observable behavior in any way, which is
reinforced by there being no changes to any tests in this commit.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-01-24 15:11:05 -08:00
Martin Atkins
eb3e21853e providercache: Decompose Installer.EnsureProviderVersions
This function has grown very large over time as the provider installation
requirements got more complicated. This is a first level of decomposition
of the three main steps into one separate function each.

The "ensureProviderVersionsInstall" method remains too large itself, but
for now that has just acquired a nolint directive so that we can approach
this gradually in the interests of making it easier to review.

This should not change the observable behavior of the provider installer
in any way, which is reinforced by the fact that there are no test changes
in this commit.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-01-24 15:11:05 -08:00
Ilia Gogotchuri
267b7f6008 Warn user about provider version 0.0.0 (#2281)
Signed-off-by: Ilia Gogotchuri <ilia.gogotchuri0@gmail.com>
2024-12-11 21:10:49 +04:00
Nathan Baulch
ea558d9d4b Fix typos (#1905)
Signed-off-by: Nathan Baulch <nathan.baulch@gmail.com>
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
2024-08-29 13:20:33 -04:00
Yuvraj
aa8b4a7cca feat: add retry in provider install (#1255)
Signed-off-by: Yuvraj <evalsocket@gmail.com>
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: James Humphries <James@james-humphries.co.uk>
2024-04-01 12:41:18 -04:00
namgyalangmo
cb2e9119aa Update copyright notice (#1232)
Signed-off-by: namgyalangmo <75657887+namgyalangmo@users.noreply.github.com>
2024-02-08 09:48:59 +00:00
Christian Mesh
f1a57344bd Improve unclear provider resolver error messages (#1003)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
2023-12-12 13:10:16 -05:00
Dmitry Kisler
a127607a85 Rename terraform to tofu in GoString method and docstrings (#576)
Signed-off-by: Dmitry Kisler <admin@dkisler.com>
2023-09-26 19:09:27 +02:00
Yaron Yarimi
0bac273d1c Rename internal/providercache + internal/refactoring to OpenTofu (#480) 2023-09-20 15:49:50 +03:00
Yaron Yarimi
c8acedd885 Rename github.com/placeholderplaceholderplaceholder/opentf to github.com/opentofu/opentofu (#461) 2023-09-20 14:35:35 +03:00
Lars Lehtonen
b65a5fd7a8 Multi Package Wrap Errors (#414) 2023-09-18 15:53:49 +03:00
James Humphries
0654ffd0dd [RFC Implementation] Bypass gpg validation of packages if the registry does not provide any keys (#309) 2023-09-14 13:55:01 +02:00
Marcin Wyszynski
b36ff25ea7 No special treatment for Hashi signatures (#185) 2023-08-28 13:41:25 +02:00
Marcin Wyszynski
a9a78c000d Adapt user-facing usages of terraform in internal/providercache (#119) 2023-08-23 12:24:02 +02:00
Kuba Martin
ebcf7455eb Rename root module name. (#4)
* Rename module name from "github.com/hashicorp/terraform" to "github.com/placeholderplaceholderplaceholder/opentf".

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Gofmt.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Regenerate protobuf.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Fix comments.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Undo issue and pull request link changes.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Undo comment changes.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Fix comment.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* Undo some link changes.

Signed-off-by: Jakub Martin <kubam@spacelift.io>

* make generate && make protobuf

Signed-off-by: Jakub Martin <kubam@spacelift.io>

---------

Signed-off-by: Jakub Martin <kubam@spacelift.io>
2023-08-17 14:45:11 +02:00
hashicorp-copywrite[bot]
325d18262e [COMPLIANCE] Add Copyright and License Headers 2023-05-02 15:33:06 +00:00
Martin Atkins
e2380b1038 cliconfig: Allow forcing use of the plugin cache despite the lock file
Currently Terraform will use an entry from the global plugin cache only if
it matches a checksum already recorded in the dependency lock file. This
allows Terraform to produce a complete lock file entry on the first
encounter with a new provider, whereas using the cache in that case would
cause the lock file to only cover the single package in the cache and
thereefore be unusable on any other operating system or CPU architecture.

This temporary CLI config option is a pragmatic exception to support those
who cannot currently correctly use the dependency lock file but who still
want to benefit from the plugin cache. With this setting enabled,
Terraform has permission to produce a dependency lock file that is only
suitable for the current system if that would allow use of an existing
entry in the plugin cache.

We are introducing this option to resolve a conflict between the needs of
folks who are using the dependency lock file as expected and the needs of
folks who cannot use the dependency lock file for some reason. The hope
then is to give respite to those who need this exception in the meantime
while we understand better why they cannot use the dependency lock file
and improve its design so that everyone will be able to use it
successfully in a future version of Terraform. This option will become a
silent no-op in a future version of Terraform, once the dependency lock
file behavior is sufficient for all supported Terraform development
workflows.
2023-01-25 08:23:01 -08:00
Martin Atkins
d0a35c60a7 providercache: Ignore lock-mismatching global cache entries
When we originally introduced the trust-on-first-use checksum locking
mechanism in v0.14, we had to make some tricky decisions about how it
should interact with the pre-existing optional read-through global cache
of provider packages:

The global cache essentially conflicts with the checksum locking because
if the needed provider is already in the cache then Terraform skips
installing the provider from upstream and therefore misses the opportunity
to capture the signed checksums published by the provider developer. We
can't use the signed checksums to verify a cache entry because the origin
registry protocol is still using the legacy ziphash scheme and that is
only usable for the original zipped provider packages and not for the
unpacked-layout cache directory. Therefore we decided to prioritize the
existing cache directory behavior at the expense of the lock file behavior,
making Terraform produce an incomplete lock file in that case.

Now that we've had some real-world experience with the lock file mechanism,
we can see that the chosen compromise was not ideal because it causes
"terraform init" to behave significantly differently in its lock file
update behavior depending on whether or not a particular provider is
already cached. By robbing Terraform of its opportunity to fetch the
official checksums, Terraform must generate a lock file that is inherently
non-portable, which is problematic for any team which works with the same
Terraform configuration on multiple different platforms.

This change addresses that problem by essentially flipping the decision so
that we'll prioritize the lock file behavior over the provider cache
behavior. Now a global cache entry is eligible for use if and only if the
lock file already contains a checksum that matches the cache entry. This
means that the first time a particular configuration sees a new provider
it will always be fetched from the configured installation source
(typically the origin registry) and record the checksums from that source.

On subsequent installs of the same provider version already locked,
Terraform will then consider the cache entry to be eligible and skip
re-downloading the same package.

This intentionally makes the global cache mechanism subordinate to the
lock file mechanism: the lock file must be populated in order for the
global cache to be effective. For those who have many separate
configurations which all refer to the same provider version, they will
need to re-download the provider once for each configuration in order to
gather the information needed to populate the lock file, whereas before
they would have only downloaded it for the _first_ configuration using
that provider.

This should therefore remove the most significant cause of folks ending
up with incomplete lock files that don't work for colleagues using other
platforms, and the expense of bypassing the cache for the first use of
each new package with each new configuration. This tradeoff seems
reasonable because otherwise such users would inevitably need to run
"terraform providers lock" separately anyway, and that command _always_
bypasses the cache. Although this change does decrease the hit rate of the
cache, if we subtract the never-cached downloads caused by
"terraform providers lock" then this is a net benefit overall, and does
the right thing by default without the need to run a separate command.
2022-11-04 16:18:15 -07:00
Liam Cervante
83e84e5477 terraform init: add warning and guidance when lock file is incomplete (#31399)
* terraform init: add warning and guidance when lock file is incomplete

* make the provider list in the warning deterministic

* create installer event for tracking provider lock hashes (#31406)

* create installer event for tracking provider lock hashes

* address comments

* fix tests

* improve error message

* Update internal/command/init.go

Co-authored-by: Martin Atkins <mart@degeneration.co.uk>

Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
2022-07-20 13:28:04 +01:00
Liam Cervante
224728879d Ignore existing package hashes for providers lock command (#31389)
* Ignore existing package hashes for  command

* missing new line

* Fix incorrect logic when deciding change message

* fix imports
2022-07-20 13:27:24 +01:00
Martin Atkins
23395a1022 providercache: Discard lock entries for unused providers
Previously we would only ever add new lock entries or update existing
ones. However, it's possible that over time a module may _cease_ using
a particular provider, at which point we ought to remove it from the lock
file so that operations won't fail when seeing that the provider cache
directory is inconsistent with the lock file.

Now the provider installer (EnsureProviderVersions) will remove any lock
file entries that relate to providers not included in the given
requirements, which therefore makes the resulting lock file properly match
the set of packages the installer wrote into the cache.

This does potentially mean that someone could inadvertently defeat the
lock by removing a provider dependency, running "terraform init", then
undoing that removal, and finally running "terraform init" again. However,
that seems relatively unlikely compared to the likelihood of removing
a provider and keeping it removed, and in the event it _did_ happen the
changes to the lock entry for that provider would be visible in the diff
of the provider lock file as usual, and so could be noticed in code
review just as for any other change to dependencies.
2021-12-17 15:30:21 -08:00
Martin Atkins
b9a93a0fe7 Move addrs/ to internal/addrs/
This is part of a general effort to move all of Terraform's non-library
package surface under internal in order to reinforce that these are for
internal use within Terraform only.

If you were previously importing packages under this prefix into an
external codebase, you could pin to an earlier release tag as an interim
solution until you've make a plan to achieve the same functionality some
other way.
2021-05-17 14:09:07 -07:00
Martin Atkins
7f78342953 command: Experimental "terraform test" command
This is just a prototype to gather some feedback in our ongoing research
on integration testing of Terraform modules. The hope is that by having a
command integrated into Terraform itself it'll be easier for interested
module authors to give it a try, and also easier for us to iterate quickly
based on feedback without having to coordinate across multiple codebases.

Everything about this is subject to change even in future patch releases.
Since it's a CLI command rather than a configuration language feature it's
not using the language experiments mechanism, but generates a warning
similar to the one language experiments generate in order to be clear that
backward compatibility is not guaranteed.
2021-02-22 14:21:45 -08:00
Pam Selle
aa24bfec47 Emit ProviderAlreadyInstalled when provider installed
Emit the ProviderAlreadyInstalled event when we successfully verify
that we've already installed this provider and are skipping
installation
2021-02-09 11:08:49 -05:00
Pam Selle
aedca597dd Reuse installed target dir providers in init
In init, we can check to see if the target dir already has the
provider we are seeking and skip further querying/installing of
that provider.
2021-01-25 11:13:57 -05:00
Martin Atkins
4b3e237668 command/init: Hint about providers in other namespaces
If a user forgets to specify the source address for a provider, Terraform
will assume they meant a provider in the registry.terraform.io/hashicorp/
namespace. If that ultimately doesn't exist, we'll now try to see if
there's some other provider source address recorded in the registry's
legacy provider lookup table, and suggest it if so.

The error message here is a terse one addressed primarily to folks who are
already somewhat familiar with provider source addresses and how to
specify them. Terraform v0.13 had a more elaborate version of this error
message which directed the user to try the v0.13 automatic upgrade tool,
but we no longer have that available in v0.14 and later so the user must
make the fix themselves.
2020-12-10 10:11:27 -08:00
James Bardin
276dfe634f internal/providercache: staticcheck 2020-12-02 13:59:19 -05:00
Martin Atkins
24d32e9ca2 providercache: More exhaustive testing of the main installer
We previously had some tests for some happy paths and a few specific
failures into an empty directory with no existing locks, but we didn't
have tests for the installer respecting existing lock file entries.

This is a start on a more exhaustive set of tests for the installer,
aiming to visit as many of the possible codepaths as we can reasonably
test using this mocking strategy. (Some other codepaths require different
underlying source implementations, etc, so we'll have to visit those in
other tests separately.)
2020-10-28 07:46:45 -07:00
Martin Atkins
2611e08430 command/init: Mention using the lock file for provider selection
This probably isn't the best UI we could do here, but it's a placeholder
for now just to avoid making it seem like we're ignoring the lock file
and checking for new versions anyway.
2020-10-09 09:26:23 -07:00
Martin Atkins
b3f5c7f1e6 command/init: Read, respect, and update provider dependency locks
This changes the approach used by the provider installer to remember
between runs which selections it has previously made, using the lock file
format implemented in internal/depsfile.

This means that version constraints in the configuration are considered
only for providers we've not seen before or when -upgrade mode is active.
2020-10-09 09:26:23 -07:00
Kristin Laemmert
04be220f5f deprecate helper/copy
helper/copy CopyDir was used heavily in tests. It differes from
internal/copydir in a few ways, the main one being that it creates the
dst directory while the internal version expected the dst to exist
(there are other differences, which is why I did not just switch tests
to using internal's CopyDir).

I moved the CopyDir func from helper/copy into command_test.go; I could
also have moved it into internal/copy and named it something like
CreateDirAndCopy so if that seems like a better option please let me
know.

helper/copy/CopyFile was used in a couple of spots so I moved it into
internal, at which point I thought it made more sense to rename the
package copy (instead of copydir).

There's also a `go mod tidy` included.
2020-10-08 08:42:16 -04:00
Martin Atkins
0b734a2803 command: Make provider installation interruptible
In earlier commits we started to make the installation codepath
context-aware so that it could be canceled in the event of a SIGINT, but
we didn't complete wiring that through the API of the getproviders
package.

Here we make the getproviders.Source interface methods, along with some
other functions that can make network requests, take a context.Context
argument and act appropriately if that context is cancelled.

The main providercache.Installer.EnsureProviderVersions method now also
has some context-awareness so that it can abort its work early if its
context reports any sort of error. That avoids waiting for the process
to wind through all of the remaining iterations of the various loops,
logging each request failure separately, and instead returns just
a single aggregate "canceled" error.

We can then set things up in the "terraform init" and
"terraform providers mirror" commands so that the context will be
cancelled if we get an interrupt signal, allowing provider installation
to abort early while still atomically completing any local-side effects
that may have started.
2020-09-29 10:00:35 -07:00
Martin Atkins
6694cfaa0e getproviders: Add a real type Hash for package hashes
The logic for what constitutes a valid hash and how different hash schemes
are represented was starting to get sprawled over many different files and
packages.

Consistently with other cases where we've used named types to gather the
definition of a particular string into a single place and have the Go
compiler help us use it properly, this introduces both getproviders.Hash
representing a hash value and getproviders.HashScheme representing the
idea of a particular hash scheme.

Most of this changeset is updating existing uses of primitive strings to
uses of getproviders.Hash. The new type definitions are in
internal/getproviders/hash.go.
2020-09-24 14:01:54 -07:00
Alisdair McDiarmid
3b1347ac1a providercache: Validate provider executable file
At the end of the EnsureProviderVersions process, we generate a lockfile
of the selected and installed provider versions. This includes a hash of
the unpacked provider directory.

When calculating this hash and generating the lockfile, we now also
verify that the provider directory contains a valid executable file. If
not, we return an error for this provider and trigger the installer's
HashPackageFailure event. Note that this event is not yet processed by
terraform init; that comes in the next commit.
2020-07-07 15:20:17 -04:00
Kristin Laemmert
47e657c611 internal/getproviders: decode and return any registry warnings (#25337)
* internal/getproviders: decode and return any registry warnings

The public registry may include a list of warnings in the "versions"
response for any given provider. This PR adds support for warnings from
the registry and an installer event to return those warnings to the
user.
2020-06-25 10:49:48 -04:00
Alisdair McDiarmid
ef28671b34 Merge pull request #24932 from hashicorp/signing-language
Modify language for reporting signing state
2020-05-28 09:09:34 -04:00
Paddy
5127f1ef8b command: Unmanaged providers
This adds supports for "unmanaged" providers, or providers with process
lifecycles not controlled by Terraform. These providers are assumed to
be started before Terraform is launched, and are assumed to shut
themselves down after Terraform has finished running.

To do this, we must update the go-plugin dependency to v1.3.0, which
added support for the "test mode" plugin serving that powers all this.

As a side-effect of not needing to manage the process lifecycle anymore,
Terraform also no longer needs to worry about the provider's binary, as
it won't be used for anything anymore. Because of this, we can disable
the init behavior that concerns itself with downloading that provider's
binary, checking its version, and otherwise managing the binary.

This is all managed on a per-provider basis, so managed providers that
Terraform downloads, starts, and stops can be used in the same commands
as unmanaged providers. The TF_REATTACH_PROVIDERS environment variable
is added, and is a JSON encoding of the provider's address to the
information we need to connect to it.

This change enables two benefits: first, delve and other debuggers can
now be attached to provider server processes, and Terraform can connect.
This allows for attaching debuggers to provider processes, which before
was difficult to impossible. Second, it allows the SDK test framework to
host the provider in the same process as the test driver, while running
a production Terraform binary against the provider. This allows for Go's
built-in race detector and test coverage tooling to work as expected in
provider tests.

Unmanaged providers are expected to work in the exact same way as
managed providers, with one caveat: Terraform kills provider processes
and restarts them once per graph walk, meaning multiple times during
most Terraform CLI commands. As unmanaged providers can't be killed by
Terraform, and have no visibility into graph walks, unmanaged providers
are likely to have differences in how their global mutable state behaves
when compared to managed providers. Namely, unmanaged providers are
likely to retain global state when managed providers would have reset
it. Developers relying on global state should be aware of this.
2020-05-26 17:48:57 -07:00
Paul Tyng
22ef5cc99c Modify language for reporting signing state
Be more explicit about the signing status of fetched plugins and provide documentation about the different signing options.
2020-05-26 13:14:05 -04:00
Kristin Laemmert
60321b41e8 getproviders: move protocol compatibility functions into registry client (#24846)
* internal/registry source: return error if requested provider version protocols are not supported

* getproviders: move responsibility for protocol compatibility checks into the registry client

The original implementation had the providercache checking the provider
metadata for protocol compatibility, but this is only relevant for the
registry source so it made more sense to move the logic into
getproviders.

This also addresses an issue where we were pulling the metadata for
every provider version until we found one that was supported. I've
extended the registry client to unmarshal the protocols in
`ProviderVersions` so we can filter through that list, instead of
pulling each version's metadata.
2020-05-11 13:49:12 -04:00
Kristin Laemmert
cca0526705 providercache: actually break out of the loop when a matching version is found (#24823) 2020-05-01 08:49:47 -04:00