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