From d5f633f546283b31e1b8b8d7c41c851f4f3e0600 Mon Sep 17 00:00:00 2001 From: David Sekula Date: Sun, 5 May 2024 21:53:01 +0100 Subject: [PATCH] Update nullability and inference logic for environment variables (#178) The code has been updated to allow null values in environment variables and secrets dictionaries. It also refactors retrieval methods for both environmental and secret variables. Now, instead of directly calling methods on object instances, it utilizes a pair of the resource key and object as function parameters for greater flexibility. The dashboard injection logic has been updated to avoid duplication. The unit tests have been adapted to reflect these changes. Otlp service name is now included and set to the resource key from the manifest (same for docker compose) which should fix the display on the dashboard. --- src/Aspirate.Cli/Templates/kustomization.hbs | 4 --- .../BaseResourceProcessor.cs | 34 +++++-------------- .../AbstractProcessors/ContainerProcessor.cs | 4 +-- .../Dockerfile/DockerfileProcessor.cs | 4 +-- .../Resources/Project/ProjectProcessor.cs | 4 +-- .../Extensions/ResourceExtensions.cs | 5 +-- .../Aspirate/KubernetesDeploymentData.cs | 8 ++--- .../KubernetesDeploymentDataExtensionTests.cs | 8 ++--- 8 files changed, 25 insertions(+), 46 deletions(-) diff --git a/src/Aspirate.Cli/Templates/kustomization.hbs b/src/Aspirate.Cli/Templates/kustomization.hbs index e6069a4..172b6d4 100644 --- a/src/Aspirate.Cli/Templates/kustomization.hbs +++ b/src/Aspirate.Cli/Templates/kustomization.hbs @@ -20,10 +20,6 @@ configMapGenerator: {{#if isProject}} - ASPNETCORE_URLS=http://+:8080; {{/if}} - {{#if withDashboard}} - - OTEL_EXPORTER_OTLP_ENDPOINT=http://aspire-dashboard:18889 - {{/if}} - {{/if}} {{#if hasAnySecrets}} diff --git a/src/Aspirate.Processors/BaseResourceProcessor.cs b/src/Aspirate.Processors/BaseResourceProcessor.cs index 98d6880..f0f4471 100644 --- a/src/Aspirate.Processors/BaseResourceProcessor.cs +++ b/src/Aspirate.Processors/BaseResourceProcessor.cs @@ -51,22 +51,13 @@ protected BaseResourceProcessor( /// /// The resource whose environmental variables need to be filtered. /// if secrets are disabled, do not filter + /// Should the dashboard be included. /// A dictionary representing the filtered environmental variables. - protected Dictionary GetFilteredEnvironmentalVariables(Resource resource, bool? disableSecrets = false) + protected Dictionary GetFilteredEnvironmentalVariables(KeyValuePair resource, bool? disableSecrets, bool? withDashboard) { - if (resource is not IResourceWithEnvironmentalVariables resourceWithEnv) - { - return []; - } + var resourceWithEnv = resource.MapResourceToEnvVars(withDashboard); - if (disableSecrets == true) - { - return resourceWithEnv.Env; - } - - var envVars = resourceWithEnv.Env; - - return envVars == null ? [] : envVars.Where(e => !ProtectorType.List.Any(p => e.Key.StartsWith(p))).ToDictionary(e => e.Key, e => e.Value); + return disableSecrets == true ? resourceWithEnv : resourceWithEnv.Where(e => !ProtectorType.List.Any(p => e.Key.StartsWith(p))).ToDictionary(e => e.Key, e => e.Value); } /// @@ -74,22 +65,13 @@ protected Dictionary GetFilteredEnvironmentalVariables(Resource /// /// The resource from which to retrieve the secret environmental variables. /// if secrets are disabled, do not filter + /// Should the dashboard be included. /// A dictionary representing the secret environmental variables. - protected Dictionary GetSecretEnvironmentalVariables(Resource resource, bool? disableSecrets = false) + protected Dictionary GetSecretEnvironmentalVariables(KeyValuePair resource, bool? disableSecrets, bool? withDashboard) { - if (resource is not IResourceWithEnvironmentalVariables resourceWithEnv) - { - return []; - } - - if (disableSecrets == true) - { - return []; - } - - var envVars = resourceWithEnv.Env; + var resourceWithEnv = resource.MapResourceToEnvVars(withDashboard); - return envVars == null ? [] : envVars.Where(e => ProtectorType.List.Any(p => e.Key.StartsWith(p))).ToDictionary(e => e.Key, e => e.Value); + return resourceWithEnv.Where(e => ProtectorType.List.Any(p => e.Key.StartsWith(p))).ToDictionary(e => e.Key, e => e.Value); } /// diff --git a/src/Aspirate.Processors/Resources/AbstractProcessors/ContainerProcessor.cs b/src/Aspirate.Processors/Resources/AbstractProcessors/ContainerProcessor.cs index ba75572..08b75a7 100644 --- a/src/Aspirate.Processors/Resources/AbstractProcessors/ContainerProcessor.cs +++ b/src/Aspirate.Processors/Resources/AbstractProcessors/ContainerProcessor.cs @@ -60,10 +60,10 @@ private KubernetesDeploymentData PopulateKubernetesDeploymentData(BaseKubernetes .SetName(options.Resource.Key) .SetContainerImage(container.Image) .SetImagePullPolicy(options.ImagePullPolicy) - .SetEnv(GetFilteredEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetEnv(GetFilteredEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetAnnotations(container.Annotations) .SetVolumes(container.Volumes.KuberizeVolumeNames(options.Resource)) - .SetSecrets(GetSecretEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetSecrets(GetSecretEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetSecretsFromSecretState(options.Resource, secretProvider, options.DisableSecrets) .SetPorts(options.Resource.MapBindingsToPorts()) .SetArgs(container.Args) diff --git a/src/Aspirate.Processors/Resources/Dockerfile/DockerfileProcessor.cs b/src/Aspirate.Processors/Resources/Dockerfile/DockerfileProcessor.cs index 3a96dc8..0ec3e5c 100644 --- a/src/Aspirate.Processors/Resources/Dockerfile/DockerfileProcessor.cs +++ b/src/Aspirate.Processors/Resources/Dockerfile/DockerfileProcessor.cs @@ -58,9 +58,9 @@ private KubernetesDeploymentData PopulateKubernetesDeploymentData(BaseKubernetes .SetContainerImage(containerImage) .SetImagePullPolicy(options.ImagePullPolicy) .SetArgs(dockerFile.Args) - .SetEnv(GetFilteredEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetEnv(GetFilteredEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetAnnotations(dockerFile.Annotations) - .SetSecrets(GetSecretEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetSecrets(GetSecretEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetSecretsFromSecretState(options.Resource, secretProvider, options.DisableSecrets) .SetPorts(options.Resource.MapBindingsToPorts()) .SetManifests(_manifests) diff --git a/src/Aspirate.Processors/Resources/Project/ProjectProcessor.cs b/src/Aspirate.Processors/Resources/Project/ProjectProcessor.cs index 4babc00..e20c7f4 100644 --- a/src/Aspirate.Processors/Resources/Project/ProjectProcessor.cs +++ b/src/Aspirate.Processors/Resources/Project/ProjectProcessor.cs @@ -57,10 +57,10 @@ private KubernetesDeploymentData PopulateKubernetesDeploymentData(BaseKubernetes .SetName(options.Resource.Key) .SetContainerImage(containerDetails.FullContainerImage) .SetImagePullPolicy(options.ImagePullPolicy) - .SetEnv(GetFilteredEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetEnv(GetFilteredEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetAnnotations(project.Annotations) .SetArgs(project.Args) - .SetSecrets(GetSecretEnvironmentalVariables(options.Resource.Value, options.DisableSecrets)) + .SetSecrets(GetSecretEnvironmentalVariables(options.Resource, options.DisableSecrets, options.WithDashboard)) .SetSecretsFromSecretState(options.Resource, secretProvider, options.DisableSecrets) .SetIsProject(true) .SetPorts(options.Resource.MapBindingsToPorts()) diff --git a/src/Aspirate.Shared/Extensions/ResourceExtensions.cs b/src/Aspirate.Shared/Extensions/ResourceExtensions.cs index ab72e68..c89b14c 100644 --- a/src/Aspirate.Shared/Extensions/ResourceExtensions.cs +++ b/src/Aspirate.Shared/Extensions/ResourceExtensions.cs @@ -18,9 +18,10 @@ public static class ResourceExtensions environment.Add(entry.Key, entry.Value); } - if (withDashboard.GetValueOrDefault()) + if (withDashboard == true) { - environment.Add("OTEL_EXPORTER_OTLP_ENDPOINT", "http://aspire-dashboard:18889"); + environment.TryAdd("OTEL_EXPORTER_OTLP_ENDPOINT", "http://aspire-dashboard:18889"); + environment.TryAdd("OTEL_SERVICE_NAME", resource.Key); } return environment; diff --git a/src/Aspirate.Shared/Models/Aspirate/KubernetesDeploymentData.cs b/src/Aspirate.Shared/Models/Aspirate/KubernetesDeploymentData.cs index 7f399a2..b62d3c1 100644 --- a/src/Aspirate.Shared/Models/Aspirate/KubernetesDeploymentData.cs +++ b/src/Aspirate.Shared/Models/Aspirate/KubernetesDeploymentData.cs @@ -7,8 +7,8 @@ public class KubernetesDeploymentData { public string? Name {get; private set;} public string? Namespace {get; private set;} - public Dictionary? Env {get; private set;} - public Dictionary? Secrets {get; private set;} + public Dictionary? Env {get; private set;} + public Dictionary? Secrets {get; private set;} public Dictionary? Annotations {get; private set;} public List? Volumes {get; private set;} public IReadOnlyCollection? Manifests {get; private set;} @@ -40,13 +40,13 @@ public KubernetesDeploymentData SetNamespace(string? ns) return this; } - public KubernetesDeploymentData SetEnv(Dictionary env) + public KubernetesDeploymentData SetEnv(Dictionary env) { Env = env.Where(x=>!string.IsNullOrEmpty(x.Value)).ToDictionary(x => x.Key, x => x.Value); return this; } - public KubernetesDeploymentData SetSecrets(Dictionary secrets) + public KubernetesDeploymentData SetSecrets(Dictionary secrets) { Secrets = secrets; return this; diff --git a/tests/Aspirate.Tests/ExtensionTests/KubernetesDeploymentDataExtensionTests.cs b/tests/Aspirate.Tests/ExtensionTests/KubernetesDeploymentDataExtensionTests.cs index 18d1e2d..904b687 100644 --- a/tests/Aspirate.Tests/ExtensionTests/KubernetesDeploymentDataExtensionTests.cs +++ b/tests/Aspirate.Tests/ExtensionTests/KubernetesDeploymentDataExtensionTests.cs @@ -39,7 +39,7 @@ public void ToKubernetesConfigMap_ShouldReturnCorrectConfigMap() // Arrange var data = new KubernetesDeploymentData() .SetName("test") - .SetEnv(new Dictionary { { "key", "value" } }); + .SetEnv(new Dictionary { { "key", "value" } }); // Act var result = data.ToKubernetesConfigMap(); @@ -55,7 +55,7 @@ public void ToKubernetesSecret_ShouldReturnCorrectSecret() // Arrange var data = new KubernetesDeploymentData() .SetName("test") - .SetSecrets(new Dictionary { { "key", "value" } }); + .SetSecrets(new Dictionary { { "key", "value" } }); // Act var result = data.ToKubernetesSecret(); @@ -121,8 +121,8 @@ public void ToKubernetesObjects_ShouldReturnCorrectObjects() .SetName("test") .SetContainerImage("test-image") .SetPorts(new List { new Ports { Name = "test-port", InternalPort = 8080, ExternalPort = 8080 } }) - .SetEnv(new Dictionary { { "key", "envvalue" } }) - .SetSecrets(new Dictionary { { "key", "secretvalue" } }); + .SetEnv(new Dictionary { { "key", "envvalue" } }) + .SetSecrets(new Dictionary { { "key", "secretvalue" } }); // Act var result = data.ToKubernetesObjects();