Example #1
0
 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 => (reader.Value != null)
         ? VersionInfo.Parse((string)reader.Value)
         : null;
Example #2
0
 //--- Constructors ---
 public LambdaSharpToolOutOfDateException(VersionInfo version) : base()
 {
     Version = version ?? throw new ArgumentNullException(nameof(version));
 }
Example #3
0
        public async Task <ModuleLocation> ResolveInfoToLocationAsync(ModuleInfo moduleInfo, ModuleManifestDependencyType dependencyType, bool allowImport, bool showError)
        {
            LogInfoVerbose($"=> Resolving module {moduleInfo}");

            // check if module can be found in the deployment bucket
            var result = await FindNewestModuleVersionAsync(Settings.DeploymentBucketName);

            // check if the origin bucket needs to be checked
            if (
                allowImport &&
                (Settings.DeploymentBucketName != moduleInfo.Origin) &&
                (

                    // no version has been found
                    (result.Version == null)

                    // no module version constraint was given; the ultimate floating version
                    || (moduleInfo.Version == null)

                    // the module version constraint is for a pre-release; we always prefer the origin version then
                    || moduleInfo.Version.IsPreRelease

                    // the module version constraint is floating; we need to check if origin has a newer version
                    || moduleInfo.Version.HasFloatingConstraints
                )
                )
            {
                var originResult = await FindNewestModuleVersionAsync(moduleInfo.Origin);

                // check if module found at origin should be kept instead
                if (
                    (originResult.Version != null) &&
                    (
                        (result.Version == null) ||
                        (moduleInfo.Version?.IsPreRelease ?? false) ||
                        originResult.Version.IsGreaterThanVersion(result.Version)
                    )
                    )
                {
                    result = originResult;
                }
            }

            // check if a module was found
            if (result.Version == null)
            {
                // could not find a matching version
                var versionConstraint = (moduleInfo.Version != null)
                    ? $"v{moduleInfo.Version} or later"
                    : "any version";
                if (showError)
                {
                    LogError($"could not find module '{moduleInfo}' ({versionConstraint})");
                }
                return(null);
            }
            LogInfoVerbose($"=> Selected module {moduleInfo.WithVersion(result.Version)} from {result.Origin}");
            return(MakeModuleLocation(result.Origin, result.Manifest));

            // local functions
            async Task <(string Origin, VersionInfo Version, ModuleManifest Manifest)> FindNewestModuleVersionAsync(string bucketName)
            {
                // enumerate versions in bucket
                var found = await FindModuleVersionsAsync(bucketName);

                if (!found.Any())
                {
                    return(Origin : bucketName, Version : null, Manifest : null);
                }

                // NOTE (2019-08-12, bjorg): unless the module is shared, we filter the list of found versions to
                //  only contain versions that meet the module version constraint; for shared modules, we want to
                //  keep the latest version that is compatible with the tool and is equal-or-greater than the
                //  module version constraint.
                if ((dependencyType != ModuleManifestDependencyType.Shared) && (moduleInfo.Version != null))
                {
                    found = found.Where(version => version.MatchesConstraint(moduleInfo.Version)).ToList();
                }

                // attempt to identify the newest module version compatible with the tool
                ModuleManifest manifest = null;
                var            match    = VersionInfo.FindLatestMatchingVersion(found, moduleInfo.Version, candidate => {
                    var candidateModuleInfo   = new ModuleInfo(moduleInfo.Namespace, moduleInfo.Name, candidate, moduleInfo.Origin);
                    var candidateManifestText = GetS3ObjectContentsAsync(bucketName, candidateModuleInfo.VersionPath).Result;
                    manifest = JsonConvert.DeserializeObject <ModuleManifest>(candidateManifestText);

                    // check if module is compatible with this tool
                    return(manifest.CoreServicesVersion.IsCoreServicesCompatible(Settings.CoreServicesVersion));
                });

                return(Origin : bucketName, Version : match, Manifest : manifest);
            }

            async Task <IEnumerable <VersionInfo> > FindModuleVersionsAsync(string bucketName)
            {
                // get bucket region specific S3 client
                var s3Client = await GetS3ClientByBucketNameAsync(bucketName);

                if (s3Client == null)
                {
                    // nothing to do; GetS3ClientByBucketName already emitted an error
                    return(new List <VersionInfo>());
                }

                // enumerate versions in bucket
                var versions = new List <VersionInfo>();
                var request  = new ListObjectsV2Request {
                    BucketName   = bucketName,
                    Prefix       = $"{moduleInfo.Origin ?? Settings.DeploymentBucketName}/{moduleInfo.Namespace}/{moduleInfo.Name}/",
                    Delimiter    = "/",
                    MaxKeys      = 100,
                    RequestPayer = RequestPayer.Requester
                };

                do
                {
                    try {
                        var response = await s3Client.ListObjectsV2Async(request);

                        versions.AddRange(response.S3Objects
                                          .Select(s3Object => s3Object.Key.Substring(request.Prefix.Length))
                                          .Select(found => VersionInfo.Parse(found))
                                          .Where(version => (moduleInfo.Version == null) || version.IsGreaterOrEqualThanVersion(moduleInfo.Version, strict: true))
                                          );
                        request.ContinuationToken = response.NextContinuationToken;
                    } catch (AmazonS3Exception e) when(e.Message == "Access Denied")
                    {
                        break;
                    }
                } while(request.ContinuationToken != null);
                LogInfoVerbose($"==> Found {versions.Count} version{((versions.Count == 1) ? "" : "s")} in {bucketName} [{s3Client.Config.RegionEndpoint.SystemName}]");
                return(versions);
            }

            ModuleLocation MakeModuleLocation(string sourceBucketName, ModuleManifest manifest)
            => new ModuleLocation(sourceBucketName, manifest.ModuleInfo, manifest.TemplateChecksum);
        }