github.com/pulumi/terraform@v1.4.0/pkg/providercache/installer_events.go (about)

     1  package providercache
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/pulumi/terraform/pkg/addrs"
     7  	"github.com/pulumi/terraform/pkg/getproviders"
     8  )
     9  
    10  // InstallerEvents is a collection of function references that can be
    11  // associated with an Installer object in order to be notified about various
    12  // installation lifecycle events during an install operation.
    13  //
    14  // The set of supported events is primarily motivated by allowing ongoing
    15  // progress reports in the UI of the command running provider installation,
    16  // and so this only exposes information interesting to display and does not
    17  // allow the recipient of the events to influence the ongoing process.
    18  //
    19  // Any of the fields may be left as nil to signal that the caller is not
    20  // interested in the associated event. It's better to leave a field set to
    21  // nil than to assign a do-nothing function into it because the installer
    22  // may choose to skip preparing certain temporary data structures if it can see
    23  // that a particular event is not used.
    24  type InstallerEvents struct {
    25  	// The PendingProviders event is called prior to other events to give
    26  	// the recipient prior notice of the full set of distinct provider
    27  	// addresses it can expect to see mentioned in the other events.
    28  	//
    29  	// A recipient driving a UI might, for example, use this to pre-allocate
    30  	// UI space for status reports for all of the providers and then update
    31  	// those positions in-place as other events arrive.
    32  	PendingProviders func(reqs map[addrs.Provider]getproviders.VersionConstraints)
    33  
    34  	// ProviderAlreadyInstalled is called for any provider that was included
    35  	// in PendingProviders but requires no further action because a suitable
    36  	// version is already present in the local provider cache directory.
    37  	//
    38  	// This event can also appear after the QueryPackages... series if
    39  	// querying determines that a version already available is the newest
    40  	// available version.
    41  	ProviderAlreadyInstalled func(provider addrs.Provider, selectedVersion getproviders.Version)
    42  
    43  	// The BuiltInProvider... family of events describe the outcome for any
    44  	// requested providers that are built in to Terraform. Only one of these
    45  	// methods will be called for each such provider, and no other method
    46  	// will be called for them except that they are included in the
    47  	// aggregate PendingProviders map.
    48  	//
    49  	// The "Available" event reports that the requested builtin provider is
    50  	// available in this release of Terraform. The "Failure" event reports
    51  	// either that the provider is unavailable or that the request for it
    52  	// is invalid somehow.
    53  	BuiltInProviderAvailable func(provider addrs.Provider)
    54  	BuiltInProviderFailure   func(provider addrs.Provider, err error)
    55  
    56  	// The QueryPackages... family of events delimit the operation of querying
    57  	// a provider source for information about available packages matching
    58  	// a particular version constraint, prior to selecting a single version
    59  	// to install.
    60  	//
    61  	// A particular install operation includes only one query per distinct
    62  	// provider, so a caller can use the provider argument as a unique
    63  	// identifier to correlate between successive events.
    64  	//
    65  	// The Begin, Success, and Failure events will each occur only once per
    66  	// distinct provider.
    67  	//
    68  	// The Warning event is unique to the registry source
    69  	QueryPackagesBegin   func(provider addrs.Provider, versionConstraints getproviders.VersionConstraints, locked bool)
    70  	QueryPackagesSuccess func(provider addrs.Provider, selectedVersion getproviders.Version)
    71  	QueryPackagesFailure func(provider addrs.Provider, err error)
    72  	QueryPackagesWarning func(provider addrs.Provider, warn []string)
    73  
    74  	// The LinkFromCache... family of events delimit the operation of linking
    75  	// a selected provider package from the system-wide shared cache into the
    76  	// current configuration's local cache.
    77  	//
    78  	// This sequence occurs instead of the FetchPackage... sequence if the
    79  	// QueryPackages... sequence selects a version that is already in the
    80  	// system-wide cache, and thus we will skip fetching it from the
    81  	// originating provider source and take it from the shared cache instead.
    82  	//
    83  	// Linking should, in most cases, be a much faster operation than
    84  	// fetching. However, it could still potentially be slow in some unusual
    85  	// cases like a particularly large source package on a system where symlinks
    86  	// are impossible, or when either of the cache directories are on a network
    87  	// filesystem accessed over a slow link.
    88  	LinkFromCacheBegin   func(provider addrs.Provider, version getproviders.Version, cacheRoot string)
    89  	LinkFromCacheSuccess func(provider addrs.Provider, version getproviders.Version, localDir string)
    90  	LinkFromCacheFailure func(provider addrs.Provider, version getproviders.Version, err error)
    91  
    92  	// The FetchPackage... family of events delimit the operation of retrieving
    93  	// a package from a particular source location.
    94  	//
    95  	// A particular install operation includes only one fetch per distinct
    96  	// provider, so a caller can use the provider argument as a unique
    97  	// identifier to correlate between successive events.
    98  	//
    99  	// A particular provider will either notify the LinkFromCache... events
   100  	// or the FetchPackage... events, never both in the same install operation.
   101  	//
   102  	// The Query, Begin, Success, and Failure events will each occur only once
   103  	// per distinct provider.
   104  	FetchPackageMeta    func(provider addrs.Provider, version getproviders.Version) // fetching metadata prior to real download
   105  	FetchPackageBegin   func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation)
   106  	FetchPackageSuccess func(provider addrs.Provider, version getproviders.Version, localDir string, authResult *getproviders.PackageAuthenticationResult)
   107  	FetchPackageFailure func(provider addrs.Provider, version getproviders.Version, err error)
   108  
   109  	// The ProvidersLockUpdated event is called whenever the lock file will be
   110  	// updated. It provides the following information:
   111  	//
   112  	//   - `localHashes`: Hashes computed on the local system by analyzing
   113  	//                    files on disk.
   114  	//   - `signedHashes`: Hashes signed by the private key that the origin
   115  	//                     registry claims is the owner of this provider.
   116  	//   - `priorHashes`: Hashes already present in the lock file before we
   117  	//                    made any changes.
   118  	//
   119  	// The final lock file will be updated with a union of all the provided
   120  	// hashes. It not just likely, but expected that there will be duplicates
   121  	// shared between all three collections of hashes i.e. the local hash and
   122  	// remote hashes could already be in the cached hashes.
   123  	//
   124  	// In addition, we place a guarantee that the hash slices will be ordered
   125  	// in the same manner enforced by the lock file within NewProviderLock.
   126  	ProvidersLockUpdated func(provider addrs.Provider, version getproviders.Version, localHashes []getproviders.Hash, signedHashes []getproviders.Hash, priorHashes []getproviders.Hash)
   127  
   128  	// The ProvidersFetched event is called after all fetch operations if at
   129  	// least one provider was fetched successfully.
   130  	ProvidersFetched func(authResults map[addrs.Provider]*getproviders.PackageAuthenticationResult)
   131  }
   132  
   133  // OnContext produces a context with all of the same behaviors as the given
   134  // context except that it will additionally carry the receiving
   135  // InstallerEvents.
   136  //
   137  // Passing the resulting context to an installer request will cause the
   138  // installer to send event notifications via the callbacks inside.
   139  func (e *InstallerEvents) OnContext(ctx context.Context) context.Context {
   140  	return context.WithValue(ctx, ctxInstallerEvents, e)
   141  }
   142  
   143  // installerEventsForContext looks on the given context for a registered
   144  // InstallerEvents and returns a pointer to it if so.
   145  //
   146  // For caller convenience, if there is no events object attached to the
   147  // given context this function will construct one that has all of its
   148  // fields set to nil and return that, freeing the caller from having to
   149  // do a nil check on the result before dereferencing it.
   150  func installerEventsForContext(ctx context.Context) *InstallerEvents {
   151  	v := ctx.Value(ctxInstallerEvents)
   152  	if v != nil {
   153  		return v.(*InstallerEvents)
   154  	}
   155  	return &InstallerEvents{}
   156  }
   157  
   158  type ctxInstallerEventsType int
   159  
   160  const ctxInstallerEvents = ctxInstallerEventsType(0)