protected override ExtendedRichDescription GetDescription(IOperationConfiguration config)
 {
     return(new ExtendedRichDescription(
                new RichDescription(
                    "Remediate drift for ",
                    new Hilite(InfrastructureEntity.Create(serverName: config[nameof(this.Server)], roleName: config[nameof(this.Role)])?.ToString())
                    )
                ));
 }
Beispiel #2
0
 public async Task TriggerConfigurationCheckAsync(InfrastructureEntity entity)
 {
     using (var client = this.CreateClient())
     {
         string url = $"api/configuration/check?{entity.Type}={Uri.EscapeDataString(entity.Name)}";
         this.LogRequest(url);
         using (var response = await client.GetAsync(url, this.cancellationToken).ConfigureAwait(false))
         {
             await HandleError(response).ConfigureAwait(false);
         }
     }
 }
Beispiel #3
0
        public async Task <string> TriggerRemediationJobAsync(InfrastructureEntity entity, string jobName = null)
        {
            using (var client = this.CreateClient())
            {
                string url = $"api/configuration/remediate/{entity.Type}/{Uri.EscapeDataString(entity.Name)}";
                if (jobName != null)
                {
                    url += $"?job={jobName}";
                }

                using (var response = await client.GetAsync(url, this.cancellationToken).ConfigureAwait(false))
                {
                    await HandleError(response).ConfigureAwait(false);

                    string jobToken = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    return(jobToken);
                }
            }
        }
Beispiel #4
0
        public async Task <ConfigurationStatusJsonModel> GetConfigurationStatusAsync(InfrastructureEntity entity)
        {
            using (var client = this.CreateClient())
            {
                string url = $"api/configuration/status?{entity.Type}={Uri.EscapeDataString(entity.Name)}";
                this.LogRequest(url);

                using (var response = await client.GetAsync(url, this.cancellationToken).ConfigureAwait(false))
                {
                    await HandleError(response).ConfigureAwait(false);

                    using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                        using (var reader = new StreamReader(stream))
                            using (var jsonReader = new JsonTextReader(reader))
                            {
                                var result = JsonSerializer.CreateDefault().Deserialize <ConfigurationStatusJsonModel>(jsonReader);
                                return(result);
                            }
                }
            }
        }
        public async override Task ExecuteAsync(IOperationExecutionContext context)
        {
            var entity = InfrastructureEntity.Create(serverName: this.Server, roleName: this.Role);

            if (entity == null)
            {
                this.LogError("A server or role name is required to remediate drift in Otter.");
                return;
            }

            this.LogInformation($"Remediating drift for {entity}...");

            var client = new OtterClient(this.Host, this.ApiKey, this, context.CancellationToken);

            try
            {
                this.LogDebug("Triggering configuration check...");
                await client.TriggerConfigurationCheckAsync(entity).ConfigureAwait(false);

                this.LogDebug("Waiting a few seconds to get new configuration status...");
                await Task.Delay(3 * 1000, context.CancellationToken).ConfigureAwait(false);

                var configuration = await client.GetConfigurationStatusAsync(entity).ConfigureAwait(false);

                if (string.Equals(configuration.Status, "error", StringComparison.OrdinalIgnoreCase))
                {
                    this.LogError($"Configuration status is 'error': {configuration.ErrorText ?? ""}; will not attempt to remediate.");
                    return;
                }
                else if (string.Equals(configuration.Status, "current", StringComparison.OrdinalIgnoreCase))
                {
                    this.LogInformation("Configuration status is already 'current'.");
                    return;
                }
                else if (string.Equals(configuration.Status, "disabled", StringComparison.OrdinalIgnoreCase))
                {
                    this.LogWarning("Configuration status is 'disabled', will not attempt to remediate.");
                    return;
                }
                else if (new[] { "unknown", "pendingRemediation", "executing" }.Contains(configuration.Status, StringComparer.OrdinalIgnoreCase))
                {
                    this.LogInformation($"Configuration status is '{configuration.Status}', will not attempt to remediate.");
                    return;
                }
                else if (string.Equals(configuration.Status, "drifted", StringComparison.OrdinalIgnoreCase))
                {
                    this.LogInformation("Configuration status is 'drifted', triggering remediation job...");
                    string jobToken = await client.TriggerRemediationJobAsync(entity).ConfigureAwait(false);

                    this.LogInformation("Remediation job triggered successfully.");
                    this.LogDebug("Job token: " + jobToken);

                    if (!this.WaitForCompletion)
                    {
                        this.LogDebug("Operation specified false for wait until remediated.");
                        return;
                    }

                    this.LogInformation("Waiting for remediation job to complete...");

                    RemediationStatus status;
                    do
                    {
                        await Task.Delay(3 * 1000, context.CancellationToken).ConfigureAwait(false);

                        status = await client.GetRemediationJobStatusAsync(jobToken).ConfigureAwait(false);
                    }while (status == RemediationStatus.Pending || status == RemediationStatus.Running);

                    if (status == RemediationStatus.Completed)
                    {
                        this.LogInformation("Drift remediation complete.");
                    }
                    else
                    {
                        this.LogError($"Drift remediation execution was '{status.ToString().ToLowerInvariant()}', see Otter for more details.");
                    }
                }
                else
                {
                    this.LogError($"Unexpected configuration status '{configuration.Status}' returned from Otter.");
                }
            }
            catch (OtterException ex)
            {
                this.LogError(ex.FullMessage);
            }
        }