Skip to content
This repository has been archived by the owner on Nov 20, 2023. It is now read-only.

Commit

Permalink
Refactor core validate secret step (#787)
Browse files Browse the repository at this point in the history
* ValidateSecretStep remove nested if

* applied format

* added both missing nit nit: prefer braces around ifs
  • Loading branch information
sirh3e authored Nov 18, 2020
1 parent 1f22ae5 commit f5218f8
Showing 1 changed file with 112 additions and 110 deletions.
222 changes: 112 additions & 110 deletions src/Microsoft.Tye.Core/ValidateSecretStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,142 +41,144 @@ public override async Task ExecuteAsync(OutputContext output, ApplicationBuilder

foreach (var binding in bindings.Bindings)
{
if (binding is SecretInputBinding secretInputBinding)
if (!(binding is SecretInputBinding secretInputBinding))
{
if (!Secrets.Add(secretInputBinding.Name))
{
output.WriteDebugLine($"Already validated secret '{secretInputBinding.Name}'.");
continue;
}
continue;
}

output.WriteDebugLine($"Validating secret '{secretInputBinding.Name}'.");
if (!Secrets.Add(secretInputBinding.Name))
{
output.WriteDebugLine($"Already validated secret '{secretInputBinding.Name}'.");
continue;
}

var config = KubernetesClientConfiguration.BuildDefaultConfig();
output.WriteDebugLine($"Validating secret '{secretInputBinding.Name}'.");

// If namespace is null, set it to default
config.Namespace ??= "default";
var config = KubernetesClientConfiguration.BuildDefaultConfig();

var kubernetes = new Kubernetes(config);
// If namespace is null, set it to default
config.Namespace ??= "default";

try
{
var result = await kubernetes.ReadNamespacedSecretWithHttpMessagesAsync(secretInputBinding.Name, config.Namespace);
output.WriteInfoLine($"Found existing secret '{secretInputBinding.Name}'.");
continue;
}
catch (HttpOperationException ex) when (ex.Response.StatusCode == HttpStatusCode.NotFound)
{
// The kubernetes client uses exceptions for 404s.
}
catch (Exception ex)
{
output.WriteDebugLine("Failed to query secret.");
output.WriteDebugLine(ex.ToString());
throw new CommandException("Unable connect to kubernetes.", ex);
}
var kubernetes = new Kubernetes(config);

if (Force)
{
output.WriteDebugLine("Skipping because force was specified.");
continue;
}
try
{
var result = await kubernetes.ReadNamespacedSecretWithHttpMessagesAsync(secretInputBinding.Name, config.Namespace);
output.WriteInfoLine($"Found existing secret '{secretInputBinding.Name}'.");
continue;
}
catch (HttpOperationException ex) when (ex.Response.StatusCode == HttpStatusCode.NotFound)
{
// The kubernetes client uses exceptions for 404s.
}
catch (Exception ex)
{
output.WriteDebugLine("Failed to query secret.");
output.WriteDebugLine(ex.ToString());
throw new CommandException("Unable connect to kubernetes.", ex);
}

if (!Interactive && secretInputBinding is SecretConnectionStringInputBinding)
{
throw new CommandException(
$"The secret '{secretInputBinding.Name}' used for service '{secretInputBinding.Service.Name}' is missing from the deployment environment. " +
$"Rerun the command with --interactive to specify the value interactively, or with --force to skip validation. Alternatively " +
$"use the following command to manually create the secret." + System.Environment.NewLine +
$"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=connectionstring=<value>");
}
if (Force)
{
output.WriteDebugLine("Skipping because force was specified.");
continue;
}

if (!Interactive && secretInputBinding is SecretConnectionStringInputBinding)
{
throw new CommandException(
$"The secret '{secretInputBinding.Name}' used for service '{secretInputBinding.Service.Name}' is missing from the deployment environment. " +
$"Rerun the command with --interactive to specify the value interactively, or with --force to skip validation. Alternatively " +
$"use the following command to manually create the secret." + System.Environment.NewLine +
$"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=connectionstring=<value>");
}

if (!Interactive && secretInputBinding is SecretUrlInputBinding)
if (!Interactive && secretInputBinding is SecretUrlInputBinding)
{
throw new CommandException(
$"The secret '{secretInputBinding.Name}' used for service '{secretInputBinding.Service.Name}' is missing from the deployment environment. " +
$"Rerun the command with --interactive to specify the value interactively, or with --force to skip validation. Alternatively " +
$"use the following command to manually create the secret." + System.Environment.NewLine +
$"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=protocol=<value> --from-literal=host=<value> --from-literal=port=<value>");
}

V1Secret secret;
if (secretInputBinding is SecretConnectionStringInputBinding)
{
// If we get here then we should create the secret.
var text = output.Prompt($"Enter the connection string to use for service '{secretInputBinding.Service.Name}'", allowEmpty: true);
if (string.IsNullOrWhiteSpace(text))
{
throw new CommandException(
$"The secret '{secretInputBinding.Name}' used for service '{secretInputBinding.Service.Name}' is missing from the deployment environment. " +
$"Rerun the command with --interactive to specify the value interactively, or with --force to skip validation. Alternatively " +
$"use the following command to manually create the secret." + System.Environment.NewLine +
$"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=protocol=<value> --from-literal=host=<value> --from-literal=port=<value>");
output.WriteAlwaysLine($"Skipping creation of secret for '{secretInputBinding.Service.Name}'. This may prevent creation of pods until secrets are created.");
output.WriteAlwaysLine($"Manually create a secret with:");
output.WriteAlwaysLine($"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=connectionstring=<value>");
continue;
}

V1Secret secret;
if (secretInputBinding is SecretConnectionStringInputBinding)
secret = new V1Secret(type: "Opaque", stringData: new Dictionary<string, string>()
{
// If we get here then we should create the secret.
var text = output.Prompt($"Enter the connection string to use for service '{secretInputBinding.Service.Name}'", allowEmpty: true);
if (string.IsNullOrWhiteSpace(text))
{
output.WriteAlwaysLine($"Skipping creation of secret for '{secretInputBinding.Service.Name}'. This may prevent creation of pods until secrets are created.");
output.WriteAlwaysLine($"Manually create a secret with:");
output.WriteAlwaysLine($"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=connectionstring=<value>");
continue;
}

secret = new V1Secret(type: "Opaque", stringData: new Dictionary<string, string>()
{
{ "connectionstring", text },
});
}
else if (secretInputBinding is SecretUrlInputBinding)
{ "connectionstring", text },
});
}
else if (secretInputBinding is SecretUrlInputBinding)
{
// If we get here then we should create the secret.
string text;
Uri? uri = null;
while (true)
{
// If we get here then we should create the secret.
string text;
Uri? uri = null;
while (true)
text = output.Prompt($"Enter the URI to use for service '{secretInputBinding.Service.Name}'", allowEmpty: true);
if (string.IsNullOrEmpty(text))
{
text = output.Prompt($"Enter the URI to use for service '{secretInputBinding.Service.Name}'", allowEmpty: true);
if (string.IsNullOrEmpty(text))
{
break; // skip
}
else if (Uri.TryCreate(text, UriKind.Absolute, out uri))
{
break; // success
}

output.WriteAlwaysLine($"Invalid URI: '{text}'");
break; // skip
}

if (string.IsNullOrWhiteSpace(text))
else if (Uri.TryCreate(text, UriKind.Absolute, out uri))
{
output.WriteAlwaysLine($"Skipping creation of secret for '{secretInputBinding.Service.Name}'. This may prevent creation of pods until secrets are created.");
output.WriteAlwaysLine($"Manually create a secret with:");
output.WriteAlwaysLine($"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=protocol=<value> --from-literal=host=<value> --from-literal=port=<value>");
continue;
break; // success
}

secret = new V1Secret(type: "Opaque", stringData: new Dictionary<string, string>()
{
{ "protocol", uri!.Scheme },
{ "host", uri!.Host },
{ "port", uri!.Port.ToString(CultureInfo.InvariantCulture) },
});
output.WriteAlwaysLine($"Invalid URI: '{text}'");
}
else

if (string.IsNullOrWhiteSpace(text))
{
throw new InvalidOperationException("Unknown Secret type: " + secretInputBinding);
output.WriteAlwaysLine($"Skipping creation of secret for '{secretInputBinding.Service.Name}'. This may prevent creation of pods until secrets are created.");
output.WriteAlwaysLine($"Manually create a secret with:");
output.WriteAlwaysLine($"kubectl create secret generic {secretInputBinding.Name} --namespace {config.Namespace} --from-literal=protocol=<value> --from-literal=host=<value> --from-literal=port=<value>");
continue;
}

secret.Metadata = new V1ObjectMeta();
secret.Metadata.Name = secretInputBinding.Name;
secret.Metadata.Labels = new Dictionary<string, string>()
secret = new V1Secret(type: "Opaque", stringData: new Dictionary<string, string>()
{
["app.kubernetes.io/part-of"] = application.Name,
};
{ "protocol", uri!.Scheme },
{ "host", uri!.Host },
{ "port", uri!.Port.ToString(CultureInfo.InvariantCulture) },
});
}
else
{
throw new InvalidOperationException("Unknown Secret type: " + secretInputBinding);
}

output.WriteDebugLine($"Creating secret '{secret.Metadata.Name}'.");
secret.Metadata = new V1ObjectMeta();
secret.Metadata.Name = secretInputBinding.Name;
secret.Metadata.Labels = new Dictionary<string, string>()
{
["app.kubernetes.io/part-of"] = application.Name,
};

try
{
await kubernetes.CreateNamespacedSecretWithHttpMessagesAsync(secret, config.Namespace);
output.WriteInfoLine($"Created secret '{secret.Metadata.Name}'.");
}
catch (Exception ex)
{
output.WriteDebugLine("Failed to create secret.");
output.WriteDebugLine(ex.ToString());
throw new CommandException("Failed to create secret.", ex);
}
output.WriteDebugLine($"Creating secret '{secret.Metadata.Name}'.");

try
{
await kubernetes.CreateNamespacedSecretWithHttpMessagesAsync(secret, config.Namespace);
output.WriteInfoLine($"Created secret '{secret.Metadata.Name}'.");
}
catch (Exception ex)
{
output.WriteDebugLine("Failed to create secret.");
output.WriteDebugLine(ex.ToString());
throw new CommandException("Failed to create secret.", ex);
}
}
}
Expand Down

0 comments on commit f5218f8

Please sign in to comment.