Beispiel #1
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var gitlab     = new GitLabClient(this.Template.ApiUrl, this.Template.UserName, this.Template.Password, this.Template.GroupName);
            var milestones = await gitlab.GetMilestonesAsync(this.Template.ProjectName, null, context.CancellationToken).ConfigureAwait(false);

            var milestone = milestones.FirstOrDefault(m => string.Equals(m["title"]?.ToString() ?? string.Empty, this.Template.Title, StringComparison.OrdinalIgnoreCase));

            if (milestone == null)
            {
                return(new GitLabMilestoneConfiguration
                {
                    Exists = false
                });
            }

            return(new GitLabMilestoneConfiguration
            {
                Exists = true,
                Title = milestone["title"]?.ToString() ?? string.Empty,
                Description = milestone["description"]?.ToString() ?? string.Empty,
                StartDate = milestone["start_date"]?.ToString(),
                DueDate = milestone["due_date"]?.ToString(),
                State = (GitLabMilestoneConfiguration.OpenOrClosed)Enum.Parse(typeof(GitLabMilestoneConfiguration.OpenOrClosed), milestone["state"]?.ToString())
            });
        }
Beispiel #2
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var scriptName = this.DefaultArgument.AsString();

            if (string.IsNullOrWhiteSpace(scriptName))
            {
                this.LogError("Bad or missing script name.");
                return(null);
            }

            if (context.Simulation)
            {
                this.LogInformation("Executing PowerShell Script...");
                return(null);
            }

            var result = await PSUtil.ExecuteScriptAssetAsync(
                logger : this,
                context : context,
                fullScriptName : scriptName,
                arguments : this.NamedArguments,
                outArguments : this.OutArguments,
                collectOutput : true,
                progressUpdateHandler : (s, e) => this.currentProgress = e,
                executionMode : PsExecutionMode.Collect
                );

            this.collectedConfiguration = new PSPersistedConfiguration(result);
            return(this.collectedConfiguration);
        }
Beispiel #3
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var github = new GitHubClient(this.Template.ApiUrl, this.Template.UserName, this.Template.Password, this.Template.OrganizationName);

            var ownerName = AH.CoalesceString(this.Template.OrganizationName, this.Template.UserName);

            var release = await github.GetReleaseAsync(ownerName, this.Template.RepositoryName, this.Template.Tag, context.CancellationToken);

            if (release == null)
            {
                return(new GitHubReleaseConfiguration {
                    Exists = false
                });
            }

            return(new GitHubReleaseConfiguration
            {
                Tag = (string)release["tag_name"],
                Target = (string)release["target_commitish"],
                Title = (string)release["name"],
                Description = (string)release["body"],
                Draft = (bool)release["draft"],
                Prerelease = (bool)release["prerelease"]
            });
        }
        public async override Task <DictionaryConfiguration> CollectConfigAsync(IOperationCollectionContext context)
        {
            using (var serverContext = context.GetServerCollectionContext())
            {
                var output = await this.ExecuteChocolateyAsync(context, "list --limit-output --local-only").ConfigureAwait(false);

                if (output == null)
                {
                    return(null);
                }

                await serverContext.ClearAllPackagesAsync("Chocolatey").ConfigureAwait(false);

                foreach (var values in output)
                {
                    string name    = values[0];
                    string version = values[1];

                    await serverContext.CreateOrUpdatePackageAsync(
                        packageType : "Chocolatey",
                        packageName : name,
                        packageVersion : version,
                        packageUrl : null
                        ).ConfigureAwait(false);
                }

                return(null);
            }
        }
        public async override Task <DscConfiguration> CollectConfigAsync(IOperationCollectionContext context)
        {
            var job = new CollectDscModulesJob
            {
                DebugLogging = true
            };

            job.MessageLogged += (s, e) => this.Log(e.Level, e.Message);

            var jobExecuter = await context.Agent.GetServiceAsync <IRemoteJobExecuter>();

            var result = (CollectDscModulesJob.Result) await jobExecuter.ExecuteJobAsync(job, context.CancellationToken);

            using (var serverContext = context.GetServerCollectionContext())
            {
                await serverContext.ClearAllPackagesAsync("DSC Module");

                foreach (var module in result.Modules)
                {
                    await serverContext.CreateOrUpdatePackageAsync(
                        packageType : "DSC Module",
                        packageName : module.Name,
                        packageVersion : module.Version,
                        packageUrl : null
                        );
                }

                return(null);
            }
        }
Beispiel #6
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var path = this.Template.Name;

            var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false);

            this.LogDebug($"Looking for {path}...");
            if (!await fileOps.DirectoryExistsAsync(path).ConfigureAwait(false))
            {
                this.LogDebug("Directory does not exist.");
                return(new DirectoryConfiguration
                {
                    Name = path,
                    Exists = false
                });
            }

            this.LogDebug("Directory exists, loading from disk...");

            var config = new DirectoryConfiguration {
                Name = this.Template.Name
            };

            var dir = await fileOps.GetDirectoryInfoAsync(path).ConfigureAwait(false);

            this.LogDebug("Directory configuration loaded.");
            return(config);
        }
Beispiel #7
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            if (!this.ValidateConfiguration())
            {
                return(null);
            }

            int?exitCode;
            var output = new List <string>();

            using (var scriptReader = this.OpenCollectScript(context))
            {
                exitCode = await SHUtil.ExecuteScriptAsync(
                    context,
                    scriptReader,
                    !string.IsNullOrWhiteSpace(this.CollectScriptAsset)?this.CollectScriptArgs : null,
                    this,
                    this.Verbose,
                    !this.UseExitCode?(Action <string>)
                        (s =>
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        output.Add(s);
                    }
                }) : null
                    );
            }

            return(new KeyValueConfiguration
            {
                Key = this.ConfigurationKey,
                Value = this.UseExitCode ? exitCode?.ToString() : string.Join(Environment.NewLine, output)
            });
        }
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            if (!this.ValidateConfiguration())
            {
                return(null);
            }

            ExecutePowerShellJob.Result result;

            if (!string.IsNullOrWhiteSpace(this.CollectScriptAsset))
            {
                result = await PSUtil.ExecuteScriptAsync(
                    logger : this,
                    context : context,
                    fullScriptName : this.CollectScriptAsset,
                    arguments : this.CollectScriptParams ?? new Dictionary <string, RuntimeValue>(),
                    outArguments : new Dictionary <string, RuntimeValue>(),
                    collectOutput : !this.UseExitCode,
                    progressUpdateHandler : (s, e) => Interlocked.Exchange(ref this.currentProgress, e)
                    );
            }
            else
            {
                var jobRunner = context.Agent.GetService <IRemoteJobExecuter>();

                var job = new ExecutePowerShellJob
                {
                    ScriptText     = this.CollectScript,
                    DebugLogging   = this.DebugLogging,
                    VerboseLogging = this.VerboseLogging,
                    CollectOutput  = !this.UseExitCode,
                    LogOutput      = this.UseExitCode,
                    Variables      = PowerShellScriptRunner.ExtractVariables(this.CollectScript, context)
                };

                job.MessageLogged  += (s, e) => this.Log(e.Level, e.Message);
                job.ProgressUpdate += (s, e) => Interlocked.Exchange(ref this.currentProgress, e);

                result = await jobRunner.ExecuteJobAsync(job, context.CancellationToken) as ExecutePowerShellJob.Result;
            }

            if (result.ExitCode != null)
            {
                this.LogDebug("Script exit code: " + result.ExitCode);
            }

            return(new KeyValueConfiguration
            {
                Key = this.ConfigurationKey,
                Value = this.UseExitCode ? result.ExitCode?.ToString() : string.Join(", ", result.Output)
            });
        }
Beispiel #9
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var path = this.Template.Name;

            var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false);

            this.LogDebug($"Looking for {path}...");
            if (!await fileOps.FileExistsAsync(path))
            {
                this.LogDebug("File does not exist.");
                return(new FileConfiguration
                {
                    Name = path,
                    Exists = false
                });
            }

            this.LogDebug("File exists, loading from disk...");

            var file = await fileOps.GetFileInfoAsync(path);

            var config = new FileConfiguration {
                Name = this.Template.Name
            };

            if (this.Template.Attributes.HasValue)
            {
                config.Attributes = file.Attributes;
            }

            if (this.Template.Contents != null)
            {
                config.Contents = await fileOps.ReadFileBytesAsync(path);
            }
            else if (this.Template.TextContents != null)
            {
                config.TextContents = await fileOps.ReadAllTextAsync(path);
            }

            if (this.Template.IsReadOnly.HasValue)
            {
                config.IsReadOnly = file.IsReadOnly;
            }

            if (this.Template.LastWriteTimeUtc != null)
            {
                config.LastWriteTimeUtc = file.LastWriteTimeUtc;
            }

            this.LogDebug("File configuration loaded.");
            return(config);
        }
Beispiel #10
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            IList <RegisteredPackage> packages;

            this.LogDebug("Connecting to machine package registry...");
            using (var registry = await PackageRegistry.GetRegistryAsync(context.Agent, false).ConfigureAwait(false))
            {
                this.LogDebug("Acquiring package registry lock...");
                await registry.LockAsync(context.CancellationToken).ConfigureAwait(false);

                this.LogDebug($"Package registry lock acquired (token={registry.LockToken}).");

                this.LogInformation("Retreiving list of packages...");
                packages = await registry.GetInstalledPackagesAsync().ConfigureAwait(false);

                this.LogInformation("Packages installed: " + packages.Count);

                // doesn't need to be in a finally because dispose will unlock if necessary, but prefer doing it asynchronously
                await registry.UnlockAsync().ConfigureAwait(false);
            }

            this.LogDebug("Recording installed packages...");

            using (var collect = context.GetServerCollectionContext())
            {
                await collect.ClearAllPackagesAsync("UPack");

                foreach (var p in packages)
                {
                    await collect.CreateOrUpdateUniversalPackageAsync(
                        "UPack",
                        string.IsNullOrWhiteSpace(p.Group)?p.Name : (p.Group + "/" + p.Name),
                        p.Version,
                        p.FeedUrl,
                        new CollectedUniversalPackageData
                    {
                        Path   = p.InstallPath,
                        Cached = false,
                        Date   = p.InstallationDate,
                        Reason = p.InstallationReason,
                        Tool   = p.InstalledUsing,
                        User   = p.InstalledBy
                    }
                        );
                }
            }

            this.LogInformation("Package collection complete.");
            return(null);
        }
Beispiel #11
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var config = new KubernetesResourceConfiguration
            {
                ResourceType = this.Template.ResourceType,
                Namespace    = this.Template.Namespace,
                Name         = this.Template.Name,
                Exists       = false
            };

            using (var sw = new StringWriter())
            {
                await this.RunKubeCtlAsync(context, "apply", new[]
                {
                    "--dry-run",
                    "--output",
                    "json"
                }, sw.WriteLine);

                config.NormalizedApplied = sw.ToString();
            }

            using (var sw = new StringWriter())
            {
                await this.RunKubeCtlAsync(context, "create", new[]
                {
                    "--dry-run",
                    "--output",
                    "json"
                }, sw.WriteLine);

                config.NormalizedTemplate = sw.ToString();
            }

            var body = await this.GetCurrentConfigurationAsync(context, "json");

            if (!string.IsNullOrWhiteSpace(body))
            {
                config.NormalizedActual = body;

                config.Exists = true;
                // Use non-breaking spaces to allow easier reading in the UI.
                config.Spec = (await this.GetCurrentConfigurationAsync(context, "yaml")).Replace(' ', '\u00a0');
            }

            return(config);
        }
Beispiel #12
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var buffer = new StringBuilder("upgrade --yes --limit-output --fail-on-unfound --what-if ", 200);

            if (!string.IsNullOrEmpty(this.Template.Source))
            {
                buffer.Append("--source \"");
                buffer.Append(this.Template.Source);
                buffer.Append("\" ");
            }

            buffer.Append('\"');
            buffer.Append(this.Template.PackageName);
            buffer.Append('\"');

            var output = await this.ExecuteChocolateyAsync(context, buffer.ToString());

            if (output == null || output.Count < 1 || output[0].Length < 4 || !string.Equals(output[0][3], "false", StringComparison.OrdinalIgnoreCase))
            {
                // this assumes packages are never pinned
                this.LogInformation($"Package {this.Template.PackageName} is not installed.");
                return(new ChocolateyPackageConfiguration
                {
                    Exists = false,
                    PackageName = this.Template.PackageName,
                    Source = this.Template.Source
                });
            }

            var installedVersion = output[0][1];
            var availableVersion = output[0][2];

            this.LogInformation($"Package {this.Template.PackageName} is at version {availableVersion}.");
            this.LogInformation($"Version {installedVersion} is installed.");

            return(new ChocolateyPackageConfiguration
            {
                Exists = true,
                PackageName = this.Template.PackageName,
                Version = installedVersion,
                IsLatestVersion = string.Equals(installedVersion, availableVersion, StringComparison.OrdinalIgnoreCase),
                Source = this.Template.Source
            });
        }
Beispiel #13
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var gitlab = new GitLabClient(this.Template.ApiUrl, this.Template.UserName, this.Template.Password, this.Template.GroupName);

            var tag = await gitlab.GetTagAsync(this.Template.ProjectName, this.Template.Tag, context.CancellationToken).ConfigureAwait(false);

            if (tag == null || !tag.ContainsKey("release") || tag["release"] == null)
            {
                return(new GitLabReleaseConfiguration {
                    Exists = false
                });
            }

            var release = (Dictionary <string, object>)tag["release"];

            return(new GitLabReleaseConfiguration
            {
                Tag = (string)release["tag_name"],
                Description = (string)release["description"]
            });
        }
Beispiel #14
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var features = await this.ExecuteChocolateyAsync(context, "feature list --limit-output");

            var feature = features.Find(f => string.Equals(f[0], this.Template.Feature, StringComparison.OrdinalIgnoreCase));

            if (feature == null)
            {
                this.LogError($"No such chocolatey feature: {this.Template.Feature}");
                return(new ChocolateyFeatureConfiguration());
            }

            return(new ChocolateyFeatureConfiguration
            {
                Feature = feature[0],
                Exists = AH.Switch <string, bool>(feature[1])
                         .Case("Enabled", true)
                         .Case("Disabled", false)
                         .End()
            });
        }
Beispiel #15
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>();

            var fileName = context.ResolvePath(this.FileName);

            if (!await fileOps.FileExistsAsync(fileName))
            {
                return(this.GetConfiguration(null));
            }

            using (var file = await fileOps.OpenFileAsync(fileName, FileMode.Open, FileAccess.Read))
            {
                var doc        = XDocument.Load(file);
                var keyElement = this.GetAppSettingsElements(doc)
                                 .Elements("add")
                                 .FirstOrDefault(e => string.Equals((string)e.Attribute("key"), this.ConfigurationKey, StringComparison.OrdinalIgnoreCase));

                return(this.GetConfiguration((string)keyElement?.Attribute("value")));
            }
        }
Beispiel #16
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            string hostsPath;
            var    fileOps = context.Agent.GetService <IFileOperationsExecuter>();

            if (fileOps is ILinuxFileOperationsExecuter)
            {
                hostsPath = "/etc/hosts";
            }
            else
            {
                var remoteMethod = context.Agent.GetService <IRemoteMethodExecuter>();
                hostsPath = await remoteMethod.InvokeFuncAsync(GetHostsFilePath).ConfigureAwait(false);
            }

            this.LogDebug("Hosts file is at " + hostsPath);

            var entries = (from l in await fileOps.ReadAllLinesAsync(hostsPath).ConfigureAwait(false)
                           where !string.IsNullOrWhiteSpace(l) && !CommentRegex.IsMatch(l)
                           let e = EntryRegex.Match(l)
                                   where e.Success
                                   select new HostsEntryConfiguration
            {
                Exists = true,
                IpAddress = e.Groups[1].Value,
                HostName = e.Groups[2].Value
            }).ToLookup(e => e.HostName, StringComparer.OrdinalIgnoreCase);

            var matches = entries[this.Template.HostName];

            return(matches.FirstOrDefault(e => string.Equals(e.IpAddress, this.Template.IpAddress, StringComparison.OrdinalIgnoreCase))
                   ?? matches.FirstOrDefault()
                   ?? new HostsEntryConfiguration
            {
                Exists = false,
                IpAddress = this.Template.IpAddress,
                HostName = this.Template.HostName
            });
        }
Beispiel #17
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            if (!this.ValidateConfiguration())
            {
                return(null);
            }

            var result = await PSUtil.ExecuteScriptAsync(
                logger : this,
                context : context,
                scriptNameOrContent : AH.CoalesceString(this.CollectScriptAsset, this.CollectScript),
                scriptIsAsset : !string.IsNullOrWhiteSpace(this.CollectScriptAsset),
                arguments : this.CollectScriptParams ?? new Dictionary <string, RuntimeValue>(),
                outArguments : new Dictionary <string, RuntimeValue>(),
                collectOutput : !this.UseExitCode,
                progressUpdateHandler : (s, e) => Interlocked.Exchange(ref this.currentProgress, e)
                );

            return(new KeyValueConfiguration
            {
                Key = this.ConfigurationKey,
                Value = this.UseExitCode ? result.ExitCode?.ToString() : string.Join(", ", result.Output)
            });
        }
Beispiel #18
0
 public override Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context) => Dsc.CollectAsync(context, this, this.GetTemplate());
Beispiel #19
0
        public static async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context, ILogSink log, DscConfiguration template)
        {
            if (string.IsNullOrEmpty(template.ResourceName))
            {
                log.LogError("Bad or missing DSC Resource name.");
                return(null);
            }

            var jobRunner = await context.Agent.GetServiceAsync <IRemoteJobExecuter>();

            var propertyTypes = await GetPropertyTypesAsync(context, jobRunner, template.ResourceName, template.ModuleName, log);

            var collectJob = CreateJob("Get", propertyTypes, template);

            log.LogDebug(collectJob.ScriptText);
            collectJob.MessageLogged += (s, e) => log.Log(e.Level, e.Message);

            var result = (ExecutePowerShellJob.Result) await jobRunner.ExecuteJobAsync(collectJob, context.CancellationToken);

            var collectValues = result.Output?.FirstOrDefault().AsDictionary() ?? new Dictionary <string, RuntimeValue>(StringComparer.OrdinalIgnoreCase);
            var removeKeys    = collectValues.Where(p => p.Value.ValueType == RuntimeValueType.Scalar && string.IsNullOrEmpty(p.Value.AsString())).Select(p => p.Key).ToList();

            foreach (var k in removeKeys)
            {
                collectValues.Remove(k);
            }

            var testJob = CreateJob("Test", propertyTypes, template);

            log.LogDebug(testJob.ScriptText);
            testJob.MessageLogged += (s, e) => log.Log(e.Level, e.Message);

            var result2 = (ExecutePowerShellJob.Result) await jobRunner.ExecuteJobAsync(testJob, context.CancellationToken);

            var output = result2.Output;

            if (output.Count == 0)
            {
                log.LogError("Invoke-DscResource did not return any values.");
                return(null);
            }

            var  testResult     = output.FirstOrDefault();
            bool?inDesiredState = null;

            if (testResult.ValueType == RuntimeValueType.Map && testResult.AsDictionary().ContainsKey("InDesiredState"))
            {
                if (bool.TryParse(testResult.AsDictionary()["InDesiredState"].AsString(), out bool d))
                {
                    inDesiredState = d;
                }
            }
            else
            {
                inDesiredState = testResult.AsBoolean();
            }

            if (inDesiredState == null)
            {
                log.LogError("Invoke-DscResource did not return a boolean value or an object with an InDesiredState property.");
                return(null);
            }

            return(new DscConfiguration(collectValues)
            {
                ModuleName = template.ModuleName,
                ResourceName = template.ResourceName,
                ConfigurationKeyName = template.ConfigurationKeyName,
                InDesiredState = inDesiredState.Value
            });
        }
Beispiel #20
0
        protected override async Task <IEnumerable <PackageConfiguration> > CollectPackagesAsync(IOperationCollectionContext context)
        {
            using var job      = new CollectDscModulesJob { DebugLogging = true };
            job.MessageLogged += (s, e) => this.Log(e.Level, e.Message);

            var jobExecuter = await context.Agent.GetServiceAsync <IRemoteJobExecuter>();

            var result = (CollectDscModulesJob.Result) await jobExecuter.ExecuteJobAsync(job, context.CancellationToken);

            return(result.Modules.Select(i => new DscModuleConfiguration {
                PackageName = i.Name, PackageVersion = i.Version
            }));
        }
Beispiel #21
0
        public override Task <ComparisonResult> CompareAsync(PersistedConfiguration other, IOperationCollectionContext context)
        {
            var diffs = this.comparisonResults.Where(d => d != null);

            if (diffs.Any())
            {
                return(Task.FromResult(new ComparisonResult(diffs)));
            }
            else
            {
                return(Task.FromResult(ComparisonResult.Identical));
            }
        }
Beispiel #22
0
        public override Task <ComparisonResult> CompareAsync(PersistedConfiguration other, IOperationCollectionContext context)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }
            if (!(other is GitHubMilestoneConfiguration c))
            {
                throw new InvalidOperationException("Cannot compare configurations of different types.");
            }

            return(Task.FromResult(this.Compare(c)));
        }
Beispiel #23
0
 public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
 {
     return(await this.CollectAsync((IOperationExecutionContext)context));
 }
Beispiel #24
0
 public override Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context) => PsRepositoryConfiguration.CollectAsync(context, this, this.Template);
Beispiel #25
0
        protected async override Task <IEnumerable <PackageConfiguration> > CollectPackagesAsync(IOperationCollectionContext context)
        {
            var jobRunner = await context.Agent.GetServiceAsync <IRemoteJobExecuter>();

            var scriptText = "$results = Get-Module -ListAvailable";

            var job = new ExecutePowerShellJob
            {
                CollectOutput = true,
                OutVariables  = new[] { "results" },
                ScriptText    = scriptText
            };

            var result = (ExecutePowerShellJob.Result) await jobRunner.ExecuteJobAsync(job);

            var modules = (result.OutVariables["results"].AsEnumerable() ?? result.OutVariables["results"].ParseDictionary() ?? Enumerable.Empty <RuntimeValue>())
                          .Select(parseModule).Where(m => m != null);

            return(modules);
Beispiel #26
0
        public override Task <ComparisonResult> CompareAsync(PersistedConfiguration other, IOperationCollectionContext context)
        {
            var config = (KubernetesResourceConfiguration)other;

            if (this.Template.Exists != config.Exists)
            {
                return(Task.FromResult(new ComparisonResult(new[] { new Difference(nameof(config.Exists), this.Template.Exists, config.Exists) })));
            }

            if (!this.Template.Exists)
            {
                return(Task.FromResult(ComparisonResult.Identical));
            }

            var actual   = JObject.Parse(config.NormalizedActual);
            var template = JObject.Parse(config.NormalizedApplied);

            // Kubernetes has a bad habit of not telling us when immutable properties differ
            // during the dry run. Figure it out ourselves.
            var fresh = JObject.Parse(config.NormalizedTemplate);

            template.Merge(fresh, new JsonMergeSettings {
                MergeArrayHandling = MergeArrayHandling.Merge
            });
            // Make sure we don't have any arrays in the template that have extra elements.
            FixArrayMergeLength(template, fresh);

            // We only care about metadata and spec - the other fields are  either part of
            // the configuration key or stats that can change during collection.
            return(Task.FromResult(new ComparisonResult(
                                       GetJsonDifferences("metadata", template.Property("metadata").Value, actual.Property("metadata").Value)
                                       .Concat(GetJsonDifferences("spec", template.Property("spec").Value, actual.Property("spec").Value))
                                       )));
        }
Beispiel #27
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var fileOps = context.Agent.GetService <IFileOperationsExecuter>();

            var client = new ProGetClient(this.Template.FeedUrl, this.Template.FeedName, this.Template.UserName, this.Template.Password, this);

            try
            {
                var packageId = PackageName.Parse(this.Template.PackageName);

                var packageInfo = await client.GetPackageInfoAsync(packageId).ConfigureAwait(false);

                var version = new ProGetPackageVersionSpecifier(this.Template.PackageVersion).GetBestMatch(packageInfo.versions);
                if (version == null)
                {
                    this.LogError($"Package {this.Template.PackageName} does not have a version {this.Template.PackageVersion}.");
                    return(null);
                }

                this.LogInformation($"Resolved package version is {version}.");

                if (!await fileOps.DirectoryExistsAsync(this.Template.TargetDirectory).ConfigureAwait(false))
                {
                    this.LogInformation(this.Template.TargetDirectory + " does not exist.");
                    return(new ProGetPackageConfiguration
                    {
                        TargetDirectory = this.Template.TargetDirectory
                    });
                }

                var mask = new MaskingContext(this.Template.Includes, this.Template.Excludes);

                this.LogInformation(this.Template.TargetDirectory + " exists; getting remote file list...");

                var remoteFileList = await fileOps.GetFileSystemInfosAsync(this.Template.TargetDirectory, mask).ConfigureAwait(false);

                var remoteFiles = new Dictionary <string, SlimFileSystemInfo>(remoteFileList.Count, StringComparer.OrdinalIgnoreCase);

                foreach (var file in remoteFileList)
                {
                    var relativeName = file.FullName.Substring(this.Template.TargetDirectory.Length).Replace('\\', '/').Trim('/');
                    if (file is SlimDirectoryInfo)
                    {
                        relativeName += "/";
                    }

                    remoteFiles.Add(relativeName, file);
                }

                remoteFileList = null; // async GC optimization

                this.LogDebug($"{this.Template.TargetDirectory} contains {remoteFiles.Count} file system entries.");

                this.LogInformation($"Connecting to {this.Template.FeedUrl} to get metadata for {this.Template.PackageName}:{version}...");
                var versionInfo = await client.GetPackageVersionInfoAsync(packageId, version).ConfigureAwait(false);

                if (versionInfo.fileList == null)
                {
                    this.LogError("File list is unavailable for this package; it may be an orphaned entry.");
                    return(null);
                }

                this.LogDebug($"Package contains {versionInfo.fileList.Length} file system entries.");

                foreach (var entry in versionInfo.fileList)
                {
                    var relativeName = entry.name;
                    if (!mask.IsMatch(relativeName))
                    {
                        continue;
                    }

                    var file = remoteFiles.GetValueOrDefault(relativeName);
                    if (file == null)
                    {
                        this.LogInformation($"Entry {relativeName} is not present in {this.Template.TargetDirectory}.");
                        return(new ProGetPackageConfiguration
                        {
                            TargetDirectory = this.Template.TargetDirectory
                        });
                    }

                    if (!entry.name.EndsWith("/"))
                    {
                        var fileInfo = (SlimFileInfo)file;
                        if (entry.size != fileInfo.Size || entry.date != fileInfo.LastWriteTimeUtc)
                        {
                            this.LogInformation($"File {relativeName} in {this.Template.TargetDirectory} is different from file in package.");
                            this.LogDebug($"Source info: {entry.size} bytes, {entry.date} timestamp");
                            this.LogDebug($"Target info: {fileInfo.Size} bytes, {fileInfo.LastWriteTimeUtc} timestamp");
                            return(new ProGetPackageConfiguration
                            {
                                TargetDirectory = this.Template.TargetDirectory
                            });
                        }
                    }
                }

                if (this.Template.DeleteExtra)
                {
                    foreach (var name in remoteFiles.Keys)
                    {
                        if (!versionInfo.fileList.Any(entry => entry.name == name))
                        {
                            this.LogInformation($"File {name} in {this.Template.TargetDirectory} does not exist in package.");
                            return(new ProGetPackageConfiguration
                            {
                                TargetDirectory = this.Template.TargetDirectory
                            });
                        }
                    }
                }

                this.LogInformation($"All package files and directories are present in {this.Template.TargetDirectory}.");
                return(new ProGetPackageConfiguration
                {
                    Current = true,
                    TargetDirectory = this.Template.TargetDirectory
                });
            }
            catch (ProGetException ex)
            {
                this.LogError(ex.FullMessage);
                return(null);
            }
        }