terraform/internal/providercache/dir_modify.go

82 lines
3.2 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) (*getproviders.PackageAuthenticationResult, error) {
if meta.TargetPlatform != d.targetPlatform {
return nil, 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
log.Printf("[TRACE] providercache.Dir.InstallPackage: installing %s v%s from %s", meta.Provider, meta.Version, meta.Location)
switch meta.Location.(type) {
case getproviders.PackageHTTPURL:
return installFromHTTPURL(ctx, meta, newPath)
case getproviders.PackageLocalArchive:
return installFromLocalArchive(ctx, meta, newPath)
case getproviders.PackageLocalDir:
return installFromLocalDir(ctx, meta, newPath)
default:
// Should not get here, because the above should be exhaustive for
// all implementations of getproviders.Location.
return nil, fmt.Errorf("don't know how to install from a %T location", meta.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.
meta := getproviders.PackageMeta{
Provider: entry.Provider,
Version: entry.Version,
// FIXME: How do we populate this?
ProtocolVersions: nil,
TargetPlatform: d.targetPlatform,
// Because this is already unpacked, the filename is synthetic
// based on the standard naming scheme.
Filename: fmt.Sprintf("terraform-provider-%s_%s_%s.zip",
entry.Provider.Type, entry.Version, d.targetPlatform),
Location: getproviders.PackageLocalDir(currentPath),
}
_, err := installFromLocalDir(context.TODO(), meta, newPath)
return err
}