// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or // implied. See the License for the specific language governing // permissions and limitations under the License. // Package birdwatcherarchive contains the struct that is called when the package information is stored in birdwatcher package birdwatcherarchive import ( "fmt" "github.com/aws/amazon-ssm-agent/agent/plugins/configurepackage/birdwatcher" "github.com/aws/amazon-ssm-agent/agent/plugins/configurepackage/birdwatcher/archive" "github.com/aws/amazon-ssm-agent/agent/plugins/configurepackage/birdwatcher/facade" "github.com/aws/amazon-ssm-agent/agent/plugins/configurepackage/packageservice" "github.com/aws/amazon-ssm-agent/agent/plugins/configurepackage/trace" "github.com/aws/aws-sdk-go/service/ssm" ) type PackageArchive struct { facadeClient facade.BirdwatcherFacade archiveType string cache packageservice.ManifestCache localManifests map[string]*localManifest } type localManifest struct { manifestString string packageArn string manifestVersion string } // New is a constructor for PackageArchive struct func New(facadeClientSession facade.BirdwatcherFacade, context map[string]string) archive.IPackageArchive { // TODO: Add a SetManifest method for PackageArchive to avoid the birdwatcherManifest in the constructor. manifests := make(map[string]*localManifest) setLocalManifestString(manifests, context) return &PackageArchive{ facadeClient: facadeClientSession, archiveType: archive.PackageArchiveBirdwatcher, localManifests: manifests, } } // Name of archive type func (ba *PackageArchive) Name() string { return ba.archiveType } // SetManifestCache sets the manifest cache func (ba *PackageArchive) SetManifestCache(manifestCache packageservice.ManifestCache) { ba.cache = manifestCache } // SetResource sets the package name and the manifest version func (ba *PackageArchive) SetResource(packageName string, version string, manifest *birdwatcher.Manifest) { key := archive.FormKey(packageName, version) if _, ok := ba.localManifests[key]; !ok { ba.localManifests[key] = &localManifest{} } ba.localManifests[key].packageArn = manifest.PackageArn ba.localManifests[key].manifestVersion = manifest.Version } // GetResourceArn returns the packageArn that is found i nthe manifest file func (ba *PackageArchive) GetResourceArn(packageName string, version string) string { key := archive.FormKey(packageName, version) if _, ok := ba.localManifests[key]; !ok { return "" } return ba.localManifests[key].packageArn } // GetResourceVersion returns the version func (ba *PackageArchive) GetResourceVersion(packageName string, packageVersion string) (name string, version string) { version = packageVersion if packageservice.IsLatest(packageVersion) { version = packageservice.Latest } return packageName, version } // GetFileDownloadLocation obtains the location of the file in the archive func (ba *PackageArchive) GetFileDownloadLocation(file *archive.File, packageName string, version string) (string, error) { if file == nil { return "", fmt.Errorf("file is empty") } return file.Info.DownloadLocation, nil } // DownloadArtifactInfo downloads the manifest for the original birwatcher service func (ba *PackageArchive) DownloadArchiveInfo(tracer trace.Tracer, packageName string, version string) (string, error) { trace := tracer.BeginSection("Downloading birdwatcher archive info") defer trace.End() key := archive.FormKey(packageName, version) if _, ok := ba.localManifests[key]; !ok { ba.localManifests[key] = &localManifest{} } if ba.localManifests[key].manifestString == "" { trace.AppendDebugf("Cannot find manifest with key: %v in localManifests, downloading from remote.", key) resp, err := ba.facadeClient.GetManifest( &ssm.GetManifestInput{ PackageName: &packageName, PackageVersion: &version, }, ) if err != nil { return "", fmt.Errorf("failed to retrieve manifest: %v", err) } ba.localManifests[key].manifestString = *resp.Manifest } else { trace.AppendDebugf("Found manifest with key: %v in localManifests", key) } return ba.localManifests[key].manifestString, nil } // ReadManifestFromCache to read the manifest from cache // Birdwatcher packages store the manifest with the package version func (ba *PackageArchive) ReadManifestFromCache(packageArn string, version string) (*birdwatcher.Manifest, error) { data, err := ba.cache.ReadManifest(packageArn, version) if err != nil { return nil, err } return archive.ParseManifest(&data) } // WriteManifestToCache stores the manifest in cache func (ba *PackageArchive) WriteManifestToCache(packageArn string, version string, manifest []byte) error { return ba.cache.WriteManifest(packageArn, version, manifest) } // DeleteCachedManifest Deletes manifest from cache func (ba *PackageArchive) DeleteCachedManifest(packageArn string, version string) error { return ba.cache.DeleteManifest(packageArn, version) } // Sets the manifest string in the localManifest func setLocalManifestString(localManifests map[string]*localManifest, context map[string]string) { if name, nOk := context["packageName"]; nOk { if version, vOk := context["packageVersion"]; vOk { if manifest, mOk := context["manifest"]; mOk { key := archive.FormKey(name, version) if _, ok := localManifests[key]; !ok { localManifests[key] = &localManifest{} } localManifests[key].manifestString = manifest } } } }