depsfile

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2024 License: MPL-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package depsfile contains the logic for reading and writing OpenTofu's dependency lock and development override configuration files.

These files are separate from the main OpenTofu configuration files (.tf) for a number of reasons. The first is to help establish a distinction where .tf files configure a particular module while these configure a whole configuration tree. Another, more practical consideration is that we intend both of these files to be primarily maintained automatically by OpenTofu itself, rather than by human-originated edits, and so keeping them separate means that it's easier to distinguish the files that OpenTofu will change automatically during normal workflow from the files that OpenTofu only edits on direct request.

Both files use HCL syntax, for consistency with other files in OpenTofu that we expect humans to (in this case, only occasionally) edit directly. A dependency lock file tracks the most recently selected upstream versions of each dependency, and is intended for checkin to version control. A development override file allows for temporarily overriding upstream dependencies with local files/directories on disk as an aid to testing a cross-codebase change during development, and should not be saved in version control.

Index

Constants

View Source
const DevOverrideFilePath = ".terraform/dev-overrides.hcl"

DevOverrideFilePath is the path, relative to a configuration's root module directory, where OpenTofu will look to find a possible override file that represents a request to temporarily (within a single working directory only) use specific local directories in place of packages that would normally need to be installed from a remote location.

View Source
const LockFilePath = ".terraform.lock.hcl"

LockFilePath is the path, relative to a configuration's root module directory, where OpenTofu expects to find the dependency lock file for that configuration.

This file is intended to be kept in version control, so it lives directly in the root module directory. The ".terraform" prefix is intended to suggest that it's metadata about several types of objects that ultimately end up in the .terraform directory after running "tofu init".

Variables

View Source
var ProviderLockComparer cmp.Option

ProviderLockComparer is an option for github.com/google/go-cmp/cmp that specifies how to compare values of type depsfile.ProviderLock.

Use this, rather than crafting comparison options yourself, in case the comparison strategy needs to change in future due to implementation details of the ProviderLock type.

Functions

func ProviderIsLockable

func ProviderIsLockable(addr addrs.Provider) bool

ProviderIsLockable returns true if the given provider is eligible for version locking.

Currently, all providers except builtin and legacy providers are eligible for locking.

func SaveLocksToBytes

func SaveLocksToBytes(locks *Locks) ([]byte, tfdiags.Diagnostics)

SaveLocksToBytes writes the given locks object into a byte array, using the same syntax that LoadLocksFromBytes expects to parse.

func SaveLocksToFile

func SaveLocksToFile(locks *Locks, filename string) tfdiags.Diagnostics

SaveLocksToFile writes the given locks object to the given file, entirely replacing any content already in that file, or returns error diagnostics explaining why that was not possible.

SaveLocksToFile attempts an atomic replacement of the file, as an aid to external tools such as text editor integrations that might be monitoring the file as a signal to invalidate cached metadata. Consequently, other temporary files may be temporarily created in the same directory as the given filename during the operation.

Types

type Locks

type Locks struct {
	// contains filtered or unexported fields
}

Locks is the top-level type representing the information retained in a dependency lock file.

Locks and the other types used within it are mutable via various setter methods, but they are not safe for concurrent modifications, so it's the caller's responsibility to prevent concurrent writes and writes concurrent with reads.

func LoadLocksFromBytes

func LoadLocksFromBytes(src []byte, filename string) (*Locks, tfdiags.Diagnostics)

LoadLocksFromBytes reads locks from the given byte array, pretending that it was read from the given filename.

The constraints and behaviors are otherwise the same as for LoadLocksFromFile. LoadLocksFromBytes is primarily to allow more convenient integration testing (avoiding creating temporary files on disk); if you are writing non-test code, consider whether LoadLocksFromFile might be more appropriate to call.

It is valid to use this with dependency lock information recorded as part of a plan file, in which case the given filename will typically be a placeholder that will only be seen in the unusual case that the plan file contains an invalid lock file, which should only be possible if the user edited it directly (OpenTofu bugs notwithstanding).

func LoadLocksFromFile

func LoadLocksFromFile(filename string) (*Locks, tfdiags.Diagnostics)

LoadLocksFromFile reads locks from the given file, expecting it to be a valid dependency lock file, or returns error diagnostics explaining why that was not possible.

The returned locks are a snapshot of what was present on disk at the time the method was called. It does not take into account any subsequent writes to the file, whether through this package's functions or by external writers.

If the returned diagnostics contains errors then the returned Locks may be incomplete or invalid.

func NewLocks

func NewLocks() *Locks

NewLocks constructs and returns a new Locks object that initially contains no locks at all.

func (*Locks) AllProviders

func (l *Locks) AllProviders() map[addrs.Provider]*ProviderLock

AllProviders returns a map describing all of the provider locks in the receiver.

func (*Locks) DeepCopy

func (l *Locks) DeepCopy() *Locks

DeepCopy creates a new Locks that represents the same information as the receiver but does not share memory for any parts of the structure that. are mutable through methods on Locks.

Note that this does _not_ create deep copies of parts of the structure that are technically mutable but are immutable by convention, such as the array underlying the slice of version constraints. Callers may mutate the resulting data structure only via the direct methods of Locks.

func (*Locks) Empty

func (l *Locks) Empty() bool

Empty returns true if the given Locks object contains no actual locks.

UI code might wish to use this to distinguish a lock file being written for the first time from subsequent updates to that lock file.

func (*Locks) Equal

func (l *Locks) Equal(other *Locks) bool

Equal returns true if the given Locks represents the same information as the receiver.

Equal explicitly _does not_ consider the equality of version constraints in the saved locks, because those are saved only as hints to help the UI explain what's changed between runs, and are never used as part of dependency installation decisions.

func (*Locks) EqualProviderAddress

func (l *Locks) EqualProviderAddress(other *Locks) bool

EqualProviderAddress returns true if the given Locks have the same provider address as the receiver. This doesn't check version and hashes.

func (*Locks) Provider

func (l *Locks) Provider(addr addrs.Provider) *ProviderLock

Provider returns the stored lock for the given provider, or nil if that provider currently has no lock.

func (*Locks) ProviderIsOverridden

func (l *Locks) ProviderIsOverridden(addr addrs.Provider) bool

ProviderIsOverridden returns true only if the given provider address was previously registered as overridden by calling SetProviderOverridden.

func (*Locks) RemoveProvider

func (l *Locks) RemoveProvider(addr addrs.Provider)

RemoveProvider removes any existing lock file entry for the given provider.

If the given provider did not already have a lock entry, RemoveProvider is a no-op.

Only lockable providers can be passed to this method. If you pass a non-lockable provider address then this function will panic. Use function ProviderIsLockable to determine whether a particular provider should participate in the version locking mechanism.

func (*Locks) SetProvider

func (l *Locks) SetProvider(addr addrs.Provider, version getproviders.Version, constraints getproviders.VersionConstraints, hashes []getproviders.Hash) *ProviderLock

SetProvider creates a new lock or replaces the existing lock for the given provider.

SetProvider returns the newly-created provider lock object, which invalidates any ProviderLock object previously returned from Provider or SetProvider for the given provider address.

The ownership of the backing array for the slice of hashes passes to this function, and so the caller must not read or write that backing array after calling SetProvider.

Only lockable providers can be passed to this method. If you pass a non-lockable provider address then this function will panic. Use function ProviderIsLockable to determine whether a particular provider should participate in the version locking mechanism.

func (*Locks) SetProviderOverridden

func (l *Locks) SetProviderOverridden(addr addrs.Provider)

SetProviderOverridden records that this particular OpenTofu process will not pay attention to the recorded lock entry for the given provider, and will instead access that provider's functionality in some other special way that isn't sensitive to provider version selections or checksums.

This is an in-memory-only annotation which lives only inside a particular Locks object, and is never persisted as part of a saved lock file on disk. It's valid to still use other methods of the reciever to access already-stored lock information and to update lock information for an overridden provider, but some callers may need to use ProviderIsOverridden to selectively disregard stored lock information for overridden providers, depending on what they intended to use the lock information for.

func (*Locks) SetSameOverriddenProviders

func (l *Locks) SetSameOverriddenProviders(other *Locks)

SetSameOverriddenProviders updates the receiver to mark as overridden all of the same providers already marked as overridden in the other given locks.

This allows propagating override information between different lock objects, as if calling SetProviderOverridden for each address already overridden in the other given locks. If the reciever already has overridden providers, SetSameOverriddenProviders will preserve them.

func (*Locks) Sources

func (l *Locks) Sources() map[string][]byte

Sources returns the source code of the file the receiver was generated from, or an empty map if the receiver wasn't generated from a file.

This return type matches the one expected by HCL diagnostics printers to produce source code snapshots, which is the only intended use for this method.

type ProviderLock

type ProviderLock struct {
	// contains filtered or unexported fields
}

ProviderLock represents lock information for a specific provider.

func NewProviderLock

func NewProviderLock(addr addrs.Provider, version getproviders.Version, constraints getproviders.VersionConstraints, hashes []getproviders.Hash) *ProviderLock

NewProviderLock creates a new ProviderLock object that isn't associated with any Locks object.

This is here primarily for testing. Most callers should use Locks.SetProvider to construct a new provider lock and insert it into a Locks object at the same time.

The ownership of the backing array for the slice of hashes passes to this function, and so the caller must not read or write that backing array after calling NewProviderLock.

Only lockable providers can be passed to this method. If you pass a non-lockable provider address then this function will panic. Use function ProviderIsLockable to determine whether a particular provider should participate in the version locking mechanism.

func (*ProviderLock) AllHashes

func (l *ProviderLock) AllHashes() []getproviders.Hash

AllHashes returns all of the package hashes that were recorded when this lock was created. If no hashes were recorded for that platform, the result is a zero-length slice.

If your intent is to verify a package against the recorded hashes, use PreferredHashes to get only the hashes which the current version of OpenTofu considers the strongest of the available hashing schemes, one of which must match in order for verification to be considered successful.

Do not modify the backing array of the returned slice.

func (*ProviderLock) ContainsAll

func (l *ProviderLock) ContainsAll(target *ProviderLock) bool

ContainsAll returns true if the hashes in this ProviderLock contains all the hashes in the target.

This function assumes the hashes are in each ProviderLock are sorted. If the ProviderLock was created by the NewProviderLock constructor then the hashes are guaranteed to be sorted.

func (*ProviderLock) PreferredHashes

func (l *ProviderLock) PreferredHashes() []getproviders.Hash

PreferredHashes returns a filtered version of the AllHashes return value which includes only the strongest of the availabile hash schemes, in case legacy hash schemes are deprecated over time but still supported for upgrade purposes.

At least one of the given hashes must match for a package to be considered valud.

func (*ProviderLock) Provider

func (l *ProviderLock) Provider() addrs.Provider

Provider returns the address of the provider this lock applies to.

func (*ProviderLock) Version

func (l *ProviderLock) Version() getproviders.Version

Version returns the currently-selected version for the corresponding provider.

func (*ProviderLock) VersionConstraints

func (l *ProviderLock) VersionConstraints() getproviders.VersionConstraints

VersionConstraints returns the version constraints that were recorded as being used to choose the version returned by Version.

These version constraints are not authoritative for future selections and are included only so OpenTofu can detect if the constraints in configuration have changed since a selection was made, and thus hint to the user that they may need to run tofu init -upgrade to apply the new constraints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL