public async override Task ExecuteAsync(IOperationExecutionContext context)
        {
            this.LogInformation($"Setting Otter variable {this.Name}...");

            var variable = new ScopedVariableJsonModel
            {
                Name        = this.Name,
                Value       = this.Value,
                Environment = this.Environment,
                Server      = this.Server,
                ServerRole  = this.Role,
                Sensitive   = this.Sensitive
            };

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

            try
            {
                if (string.IsNullOrEmpty(variable.Server) && string.IsNullOrEmpty(variable.ServerRole) && string.IsNullOrEmpty(variable.Environment))
                {
                    this.LogDebug($"Setting Otter global variable '{variable.Name}' = '{variable.Value}'...");
                    await client.SetGlobalVariableAsync(variable.Name, variable.Value).ConfigureAwait(false);
                }
                else
                {
                    this.LogDebug($"Setting Otter scoped variable '{variable.Name}' = '{variable.Value}'...");
                    await client.SetSingleVariableAsync(variable).ConfigureAwait(false);
                }

                this.LogInformation("Otter variable value set.");
            }
            catch (OtterException ex)
            {
                this.LogError(ex.FullMessage);
            }
        }
        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);
            }
        }