mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-04-19 21:02:09 -04:00
Earlier on in the stubbing of this package we realized that it wasn't going to be possible to populate the authentication-related bits for all packages because the relevant metadata just isn't available for packages that are already local. However, we just moved ahead with that awkward design at the time because we needed to get other work done, and so we've been mostly producing PackageMeta values with all-zeros hashes and just ignoring them entirely as a temporary workaround. This is a first step towards what is hopefully a more intuitive model: authentication is an optional thing in a PackageMeta that is currently populated only for packages coming from a registry. So far this still just models checking a SHA256 hash, which is not a sufficient set of checks for a real release but hopefully the "real" implementation is a natural iteration of this starting point, and if not then at least this interim step is a bit more honest about the fact that Authentication will not be populated on every PackageMeta.
72 lines
3.0 KiB
Go
72 lines
3.0 KiB
Go
package providercache
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/internal/getproviders"
|
|
)
|
|
|
|
// InstallPackage takes a metadata object describing a package available for
|
|
// installation, retrieves that package, and installs it into the receiving
|
|
// cache directory.
|
|
func (d *Dir) InstallPackage(ctx context.Context, meta getproviders.PackageMeta) error {
|
|
if meta.TargetPlatform != d.targetPlatform {
|
|
return fmt.Errorf("can't install %s package into cache directory expecting %s", meta.TargetPlatform, d.targetPlatform)
|
|
}
|
|
newPath := getproviders.UnpackedDirectoryPathForPackage(
|
|
d.baseDir, meta.Provider, meta.Version, d.targetPlatform,
|
|
)
|
|
|
|
// Invalidate our metaCache so that subsequent read calls will re-scan to
|
|
// incorporate any changes we make here.
|
|
d.metaCache = nil
|
|
|
|
// TODO: If meta.Authentication is non-nil, we should call it at some point
|
|
// in the rest of this process (perhaps inside installFromLocalArchive and
|
|
// installFromLocalDir, so we already have the local copy?) and return an
|
|
// error if the authentication fails.
|
|
|
|
log.Printf("[TRACE] providercache.Dir.InstallPackage: installing %s v%s from %s", meta.Provider, meta.Version, meta.Location)
|
|
switch location := meta.Location.(type) {
|
|
case getproviders.PackageHTTPURL:
|
|
return installFromHTTPURL(ctx, string(location), newPath)
|
|
case getproviders.PackageLocalArchive:
|
|
return installFromLocalArchive(ctx, string(location), newPath)
|
|
case getproviders.PackageLocalDir:
|
|
return installFromLocalDir(ctx, string(location), newPath)
|
|
default:
|
|
// Should not get here, because the above should be exhaustive for
|
|
// all implementations of getproviders.Location.
|
|
return fmt.Errorf("don't know how to install from a %T location", location)
|
|
}
|
|
}
|
|
|
|
// LinkFromOtherCache takes a CachedProvider value produced from another Dir
|
|
// and links it into the cache represented by the receiver Dir.
|
|
//
|
|
// This is used to implement tiered caching, where new providers are first
|
|
// populated into a system-wide shared cache and then linked from there into
|
|
// a configuration-specific local cache.
|
|
//
|
|
// It's invalid to link a CachedProvider from a particular Dir into that same
|
|
// Dir, because that would otherwise potentially replace a real package
|
|
// directory with a circular link back to itself.
|
|
func (d *Dir) LinkFromOtherCache(entry *CachedProvider) error {
|
|
newPath := getproviders.UnpackedDirectoryPathForPackage(
|
|
d.baseDir, entry.Provider, entry.Version, d.targetPlatform,
|
|
)
|
|
currentPath := entry.PackageDir
|
|
log.Printf("[TRACE] providercache.Dir.LinkFromOtherCache: linking %s v%s from existing cache %s to %s", entry.Provider, entry.Version, currentPath, newPath)
|
|
|
|
// Invalidate our metaCache so that subsequent read calls will re-scan to
|
|
// incorporate any changes we make here.
|
|
d.metaCache = nil
|
|
|
|
// We re-use the process of installing from a local directory here, because
|
|
// the two operations are fundamentally the same: symlink if possible,
|
|
// deep-copy otherwise.
|
|
return installFromLocalDir(context.TODO(), currentPath, newPath)
|
|
}
|