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()) ) )); }
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); } } }
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); } } }
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); } }