From 5b92b0e990e67e11988cce7bdaaa0b62f048479b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 13 Sep 2024 14:33:49 +1000 Subject: [PATCH] feat: support for pod spread constraints and additional spot controls (#364) --- cmd/identify_dbaas_test.go | 1 + cmd/identify_feature_test.go | 1 + cmd/identify_imagebuild_test.go | 1 + cmd/identify_ingress_test.go | 4 + cmd/identify_lagoonservices_test.go | 1 + cmd/identify_native_cronjobs_test.go | 1 + cmd/template_autogen_ingress_test.go | 1 + cmd/template_backups_test.go | 1 + cmd/template_dbaas_test.go | 1 + cmd/template_ingress_test.go | 1 + cmd/template_lagoonservices_test.go | 40 ++++++ internal/generator/buildvalues.go | 1 + internal/generator/generator.go | 6 + internal/generator/services.go | 19 ++- .../services/templates_deployment.go | 86 ++++++++++++ .../services/templates_deployment_test.go | 56 ++++++++ .../deployment/result-basic-4.yaml | 112 +++++++++++++++ .../deployment-node.yaml | 132 ++++++++++++++++++ .../service-node.yaml | 39 ++++++ internal/testdata/testdata.go | 13 ++ 20 files changed, 514 insertions(+), 3 deletions(-) create mode 100644 internal/templating/services/test-resources/deployment/result-basic-4.yaml create mode 100644 internal/testdata/basic/service-templates/test-basic-spot-affinity/deployment-node.yaml create mode 100644 internal/testdata/basic/service-templates/test-basic-spot-affinity/service-node.yaml diff --git a/cmd/identify_dbaas_test.go b/cmd/identify_dbaas_test.go index e08ee046..808d505f 100644 --- a/cmd/identify_dbaas_test.go +++ b/cmd/identify_dbaas_test.go @@ -134,6 +134,7 @@ func TestIdentifyDBaaSConsumers(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(tt.vars) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/identify_feature_test.go b/cmd/identify_feature_test.go index 7f596f2e..7868ffe0 100644 --- a/cmd/identify_feature_test.go +++ b/cmd/identify_feature_test.go @@ -184,6 +184,7 @@ func TestIdentifyFeatureFlag(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(tt.vars) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/identify_imagebuild_test.go b/cmd/identify_imagebuild_test.go index 7490343f..871ffc09 100644 --- a/cmd/identify_imagebuild_test.go +++ b/cmd/identify_imagebuild_test.go @@ -795,6 +795,7 @@ func TestImageBuildConfigurationIdentification(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(tt.vars) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/identify_ingress_test.go b/cmd/identify_ingress_test.go index 25f31c4a..0f3ea1e2 100644 --- a/cmd/identify_ingress_test.go +++ b/cmd/identify_ingress_test.go @@ -529,6 +529,10 @@ func TestCreatedIngressIdentification(t *testing.T) { if string(retJSON) != tt.wantJSON { t.Errorf("returned autogen %v doesn't match want %v", string(retJSON), tt.wantJSON) } + t.Cleanup(func() { + helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) + }) }) } } diff --git a/cmd/identify_lagoonservices_test.go b/cmd/identify_lagoonservices_test.go index cc6e9f87..59521a60 100644 --- a/cmd/identify_lagoonservices_test.go +++ b/cmd/identify_lagoonservices_test.go @@ -341,6 +341,7 @@ func TestIdentifyLagoonServices(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/identify_native_cronjobs_test.go b/cmd/identify_native_cronjobs_test.go index b0bef816..e6040cdf 100644 --- a/cmd/identify_native_cronjobs_test.go +++ b/cmd/identify_native_cronjobs_test.go @@ -99,6 +99,7 @@ func TestIdentifyNativeCronjobs(t *testing.T) { t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/template_autogen_ingress_test.go b/cmd/template_autogen_ingress_test.go index a7cb5da6..f06e60a9 100644 --- a/cmd/template_autogen_ingress_test.go +++ b/cmd/template_autogen_ingress_test.go @@ -625,6 +625,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/template_backups_test.go b/cmd/template_backups_test.go index d16b2e9d..7fb56aef 100644 --- a/cmd/template_backups_test.go +++ b/cmd/template_backups_test.go @@ -325,6 +325,7 @@ func TestBackupTemplateGeneration(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/template_dbaas_test.go b/cmd/template_dbaas_test.go index b902e8e2..026845cf 100644 --- a/cmd/template_dbaas_test.go +++ b/cmd/template_dbaas_test.go @@ -202,6 +202,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/template_ingress_test.go b/cmd/template_ingress_test.go index f1e6f428..2136c9bc 100644 --- a/cmd/template_ingress_test.go +++ b/cmd/template_ingress_test.go @@ -511,6 +511,7 @@ func TestTemplateRoutes(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/cmd/template_lagoonservices_test.go b/cmd/template_lagoonservices_test.go index 561f2ea4..786d3eb0 100644 --- a/cmd/template_lagoonservices_test.go +++ b/cmd/template_lagoonservices_test.go @@ -441,6 +441,45 @@ func TestTemplateLagoonServices(t *testing.T) { templatePath: "testoutput", want: "internal/testdata/basic/service-templates/test15-basic-custom-volume-no-backup", }, + { + name: "test-basic-spot-affinity", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + EnvironmentType: "development", + LagoonYAML: "internal/testdata/basic/lagoon.yml", + ImageReferences: map[string]string{ + "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + BuildPodVariables: []helpers.EnvironmentVariable{ + { + Name: "LAGOON_FEATURE_FLAG_DEFAULT_POD_SPREADCONSTRAINTS", + Value: "enabled", + }, + { + Name: "LAGOON_FEATURE_FLAG_DEFAULT_ROOTLESS_WORKLOAD", + Value: "enabled", + }, + { + Name: "LAGOON_FEATURE_FLAG_DEFAULT_SPOT_INSTANCE_DEVELOPMENT", + Value: "enabled", + }, + { + Name: "LAGOON_FEATURE_FLAG_DEFAULT_SPOT_INSTANCE_DEVELOPMENT_TYPES", + Value: "basic,basic-persistent", + }, + { + // `ADMIN_` are only configurable by the remote-controller + Name: "ADMIN_LAGOON_FEATURE_FLAG_SPOT_TYPE_REPLICAS_DEVELOPMENT", + Value: "basic,basic-persistent", + }, + }, + }, true), + templatePath: "testoutput", + want: "internal/testdata/basic/service-templates/test-basic-spot-affinity", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -533,6 +572,7 @@ func TestTemplateLagoonServices(t *testing.T) { } t.Cleanup(func() { helpers.UnsetEnvVars(tt.vars) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) }) }) } diff --git a/internal/generator/buildvalues.go b/internal/generator/buildvalues.go index d9cd71c7..ed1be72b 100644 --- a/internal/generator/buildvalues.go +++ b/internal/generator/buildvalues.go @@ -82,6 +82,7 @@ type BuildValues struct { SSHPrivateKey string `json:"sshPrivateKey"` ForcePullImages []string `json:"forcePullImages"` Volumes []ComposeVolume `json:"volumes,omitempty" description:"stores any additional persistent volume definitions"` + PodAntiAffinity bool `json:"podAntiAffinity"` } type Resources struct { diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 80a7be5d..38182ee3 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -270,6 +270,12 @@ func NewGenerator( return nil, err } + // feature to enable pod antiaffinity on deployments + podAntiAffinity := CheckFeatureFlag("POD_SPREADCONSTRAINTS", buildValues.EnvironmentVariables, false) + if podAntiAffinity == "enabled" { + buildValues.PodAntiAffinity = true + } + // check for readwritemany to readwriteonce flag, disabled by default rwx2rwo := CheckFeatureFlag("RWX_TO_RWO", buildValues.EnvironmentVariables, generator.Debug) if rwx2rwo == "enabled" { diff --git a/internal/generator/services.go b/internal/generator/services.go index 51523e58..f3e8908e 100644 --- a/internal/generator/services.go +++ b/internal/generator/services.go @@ -399,8 +399,14 @@ func composeToServiceValues( // these services can support multiple replicas in production // @TODO this should probably be an admin only feature flag though - spotReplicaTypes := "nginx,nginx-persistent,nginx-php,nginx-php-persistent" - // spotReplicaTypes := CheckAdminFeatureFlag("SPOT_REPLICAS_PRODUCTION", buildValues.EnvironmentVariables, debug) // doesn't exist yet + prodSpotReplicaTypes := CheckAdminFeatureFlag("SPOT_TYPE_REPLICAS_PRODUCTION", debug) + if prodSpotReplicaTypes == "" { + prodSpotReplicaTypes = "nginx,nginx-persistent,nginx-php,nginx-php-persistent" + } + devSpotReplicaTypes := CheckAdminFeatureFlag("SPOT_TYPE_REPLICAS_DEVELOPMENT", debug) + if devSpotReplicaTypes == "" { + devSpotReplicaTypes = "" + } productionSpot := CheckFeatureFlag("SPOT_INSTANCE_PRODUCTION", buildValues.EnvironmentVariables, debug) developmentSpot := CheckFeatureFlag("SPOT_INSTANCE_DEVELOPMENT", buildValues.EnvironmentVariables, debug) @@ -439,13 +445,20 @@ func composeToServiceValues( } } // check if the this service is production and can support 2 replicas on spot - for _, t := range strings.Split(spotReplicaTypes, ",") { + for _, t := range strings.Split(prodSpotReplicaTypes, ",") { if t != "" { if t == lagoonType && buildValues.EnvironmentType == "production" && useSpot { spotReplicas = 2 } } } + for _, t := range strings.Split(devSpotReplicaTypes, ",") { + if t != "" { + if t == lagoonType && buildValues.EnvironmentType == "development" && useSpot { + spotReplicas = 2 + } + } + } // end spot instance handling // work out cronjobs for this service diff --git a/internal/templating/services/templates_deployment.go b/internal/templating/services/templates_deployment.go index d5c76596..880b6c8e 100644 --- a/internal/templating/services/templates_deployment.go +++ b/internal/templating/services/templates_deployment.go @@ -138,6 +138,92 @@ func GenerateDeploymentTemplate( } } } + if buildValues.PodAntiAffinity { + // if deployment.Spec.Template.Spec.Affinity == nil { + // deployment.Spec.Template.Spec.Affinity = &corev1.Affinity{} + // } + deployment.Spec.Template.Spec.TopologySpreadConstraints = []corev1.TopologySpreadConstraint{ + { + MaxSkew: 1, + WhenUnsatisfiable: corev1.ScheduleAnyway, + TopologyKey: "kubernetes.io/hostname", + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "app.kubernetes.io/name", + Operator: metav1.LabelSelectorOpIn, + Values: []string{ + serviceTypeValues.Name, + }, + }, + { + Key: "app.kubernetes.io/instance", + Operator: metav1.LabelSelectorOpIn, + Values: []string{ + serviceValues.OverrideName, + }, + }, + { + Key: "lagoon.sh/project", + Operator: metav1.LabelSelectorOpIn, + Values: []string{ + buildValues.Project, + }, + }, + { + Key: "lagoon.sh/environment", + Operator: metav1.LabelSelectorOpIn, + Values: []string{ + buildValues.Environment, + }, + }, + }, + }, + }, + } + // deployment.Spec.Template.Spec.Affinity.PodAntiAffinity = &corev1.PodAntiAffinity{ + // PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ + // { + // Weight: 100, + // PodAffinityTerm: corev1.PodAffinityTerm{ + // TopologyKey: "kubernetes.io/hostname", + // LabelSelector: &metav1.LabelSelector{ + // MatchExpressions: []metav1.LabelSelectorRequirement{ + // { + // Key: "app.kubernetes.io/name", + // Operator: metav1.LabelSelectorOpIn, + // Values: []string{ + // serviceTypeValues.Name, + // }, + // }, + // { + // Key: "app.kubernetes.io/instance", + // Operator: metav1.LabelSelectorOpIn, + // Values: []string{ + // serviceValues.OverrideName, + // }, + // }, + // { + // Key: "lagoon.sh/project", + // Operator: metav1.LabelSelectorOpIn, + // Values: []string{ + // buildValues.Project, + // }, + // }, + // { + // Key: "lagoon.sh/environment", + // Operator: metav1.LabelSelectorOpIn, + // Values: []string{ + // buildValues.Environment, + // }, + // }, + // }, + // }, + // }, + // }, + // }, + // } + } for key, value := range additionalLabels { deployment.ObjectMeta.Labels[key] = value diff --git a/internal/templating/services/templates_deployment_test.go b/internal/templating/services/templates_deployment_test.go index 824a46f5..ed41989c 100644 --- a/internal/templating/services/templates_deployment_test.go +++ b/internal/templating/services/templates_deployment_test.go @@ -856,6 +856,62 @@ func TestGenerateDeploymentTemplate(t *testing.T) { }, want: "test-resources/deployment/result-postgres-1.yaml", }, + { + name: "test-basic-antiaffinity", + args: args{ + buildValues: generator.BuildValues{ + Project: "example-project", + Environment: "environment-name", + EnvironmentType: "production", + Namespace: "myexample-project-environment-name", + BuildType: "branch", + LagoonVersion: "v2.x.x", + Kubernetes: "generator.local", + Branch: "environment-name", + Resources: generator.Resources{ + Limits: generator.ResourceLimits{ + Memory: "16Gi", + EphemeralStorage: "160Gi", + }, + Requests: generator.ResourceRequests{ + EphemeralStorage: "1Gi", + }, + }, + GitSHA: "0", + ConfigMapSha: "32bf1359ac92178c8909f0ef938257b477708aa0d78a5a15ad7c2d7919adf273", + ImageReferences: map[string]string{ + "myservice": "harbor.example.com/example-project/environment-name/myservice@latest", + }, + PodAntiAffinity: true, + Services: []generator.ServiceValues{ + { + Name: "myservice", + OverrideName: "myservice", + Type: "basic", + DBaaSEnvironment: "production", + AdditionalServicePorts: []generator.AdditionalServicePort{ + { + ServiceName: "myservice-8191", + ServicePort: types.ServicePortConfig{ + Target: 8191, + Protocol: "tcp", + }, + }, + { + ServiceName: "myservice-8211", + ServicePort: types.ServicePortConfig{ + Target: 8211, + Protocol: "tcp", + }, + }, + }, + Replicas: 2, + }, + }, + }, + }, + want: "test-resources/deployment/result-basic-4.yaml", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/templating/services/test-resources/deployment/result-basic-4.yaml b/internal/templating/services/test-resources/deployment/result-basic-4.yaml new file mode 100644 index 00000000..fd1de1a0 --- /dev/null +++ b/internal/templating/services/test-resources/deployment/result-basic-4.yaml @@ -0,0 +1,112 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + lagoon.sh/branch: environment-name + lagoon.sh/version: v2.x.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: myservice + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: myservice + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: myservice +spec: + replicas: 2 + selector: + matchLabels: + app.kubernetes.io/instance: myservice + app.kubernetes.io/name: basic + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: environment-name + lagoon.sh/configMapSha: 32bf1359ac92178c8909f0ef938257b477708aa0d78a5a15ad7c2d7919adf273 + lagoon.sh/version: v2.x.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: myservice + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: myservice + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: "0" + - name: CRONJOBS + - name: SERVICE_NAME + value: myservice + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example.com/example-project/environment-name/myservice@latest + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 8191 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 8191 + name: tcp-8191 + protocol: TCP + - containerPort: 8211 + name: tcp-8211 + protocol: TCP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 8191 + timeoutSeconds: 1 + resources: + limits: + ephemeral-storage: 160Gi + memory: 16Gi + requests: + cpu: 10m + ephemeral-storage: 1Gi + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + topologySpreadConstraints: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - basic + - key: app.kubernetes.io/instance + operator: In + values: + - myservice + - key: lagoon.sh/project + operator: In + values: + - example-project + - key: lagoon.sh/environment + operator: In + values: + - environment-name + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway +status: {} diff --git a/internal/testdata/basic/service-templates/test-basic-spot-affinity/deployment-node.yaml b/internal/testdata/basic/service-templates/test-basic-spot-affinity/deployment-node.yaml new file mode 100644 index 00000000..02c63353 --- /dev/null +++ b/internal/testdata/basic/service-templates/test-basic-spot-affinity/deployment-node.yaml @@ -0,0 +1,132 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: development + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/spot: "true" + lagoon.sh/template: basic-0.1.0 + name: node +spec: + replicas: 2 + selector: + matchLabels: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: development + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/spot: "true" + lagoon.sh/template: basic-0.1.0 + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: lagoon.sh/spot + operator: Exists + weight: 1 + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 1234 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 1234 + name: tcp-1234 + protocol: TCP + - containerPort: 8191 + name: tcp-8191 + protocol: TCP + - containerPort: 9001 + name: udp-9001 + protocol: UDP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 1234 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-development + securityContext: + fsGroup: 10001 + runAsGroup: 0 + runAsUser: 10000 + tolerations: + - effect: NoSchedule + key: lagoon.sh/spot + operator: Exists + - effect: PreferNoSchedule + key: lagoon.sh/spot + operator: Exists + topologySpreadConstraints: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - basic + - key: app.kubernetes.io/instance + operator: In + values: + - node + - key: lagoon.sh/project + operator: In + values: + - example-project + - key: lagoon.sh/environment + operator: In + values: + - main + maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: ScheduleAnyway +status: {} diff --git a/internal/testdata/basic/service-templates/test-basic-spot-affinity/service-node.yaml b/internal/testdata/basic/service-templates/test-basic-spot-affinity/service-node.yaml new file mode 100644 index 00000000..3099b224 --- /dev/null +++ b/internal/testdata/basic/service-templates/test-basic-spot-affinity/service-node.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: development + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: node +spec: + ports: + - name: tcp-1234 + port: 1234 + protocol: TCP + targetPort: tcp-1234 + - name: tcp-8191 + port: 8191 + protocol: TCP + targetPort: tcp-8191 + - name: udp-9001 + port: 9001 + protocol: UDP + targetPort: udp-9001 + selector: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic +status: + loadBalancer: {} diff --git a/internal/testdata/testdata.go b/internal/testdata/testdata.go index ac05adea..06cbd2f7 100644 --- a/internal/testdata/testdata.go +++ b/internal/testdata/testdata.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" generator "github.com/uselagoon/build-deploy-tool/internal/generator" + "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/machinery/utils/namespace" ) @@ -59,6 +60,7 @@ type TestData struct { DynamicDBaaSSecrets []string ImageCacheBuildArgsJSON string SSHPrivateKey string + BuildPodVariables []helpers.EnvironmentVariable } // helper function to set up all the environment variables from provided testdata @@ -197,6 +199,14 @@ func SetupEnvironment(rootCmd cobra.Command, templatePath string, t TestData) (g if err != nil { return generator.GeneratorInput{}, err } + // this can b used to pass OS level variables likw what would be present in a build pod when it + // is started by the remote-controller + for _, osv := range t.BuildPodVariables { + err = os.Setenv(osv.Name, osv.Value) + if err != nil { + return generator.GeneratorInput{}, err + } + } generator, err := generator.GenerateInput(rootCmd, false) if err != nil { @@ -344,5 +354,8 @@ func GetSeedData(t TestData, defaultProjectVariables bool) TestData { if t.SSHPrivateKey != "" { rt.SSHPrivateKey = t.SSHPrivateKey } + if t.BuildPodVariables != nil { + rt.BuildPodVariables = t.BuildPodVariables + } return rt }