diff --git a/internal/servicetypes/types.go b/internal/servicetypes/types.go index bc8b0bc9..0aa11ea2 100644 --- a/internal/servicetypes/types.go +++ b/internal/servicetypes/types.go @@ -34,6 +34,8 @@ type ServiceContainer struct { VolumeMounts []corev1.VolumeMount Command []string FeatureFlags map[string]bool + // define additional variables here, this can be used by types that inherit from another type + EnvVars []corev1.EnvVar } type ServiceVolume struct { @@ -81,6 +83,8 @@ var ServiceTypes = map[string]ServiceType{ "varnish": varnish, "varnish-persistent": varnishPersistent, "solr": solr, + "valkey": valkey, + "valkey-persistent": valkeyPersistent, "worker": worker, "worker-persistent": workerPersistent, "rabbitmq": rabbitmq, diff --git a/internal/servicetypes/valkey.go b/internal/servicetypes/valkey.go new file mode 100644 index 00000000..aad78e68 --- /dev/null +++ b/internal/servicetypes/valkey.go @@ -0,0 +1,101 @@ +package servicetypes + +import ( + "fmt" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/intstr" +) + +var defaultValkeyPort int32 = 6379 + +var valkey = ServiceType{ + Name: "valkey", + Ports: ServicePorts{ + Ports: []corev1.ServicePort{ + { + Port: defaultValkeyPort, + TargetPort: intstr.IntOrString{ + Type: intstr.Int, + IntVal: defaultValkeyPort, + }, + Protocol: corev1.ProtocolTCP, + Name: fmt.Sprintf("%d-tcp", defaultValkeyPort), + }, + }, + }, + PrimaryContainer: ServiceContainer{ + Name: "valkey", + Container: corev1.Container{ + ImagePullPolicy: corev1.PullAlways, + SecurityContext: &corev1.SecurityContext{}, + Ports: []corev1.ContainerPort{ + { + Name: fmt.Sprintf("%d-tcp", defaultValkeyPort), + ContainerPort: defaultValkeyPort, + Protocol: corev1.ProtocolTCP, + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + TCPSocket: &corev1.TCPSocketAction{ + Port: intstr.IntOrString{ + Type: intstr.Int, + IntVal: defaultValkeyPort, + }, + }, + }, + InitialDelaySeconds: 1, + TimeoutSeconds: 1, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + TCPSocket: &corev1.TCPSocketAction{ + Port: intstr.IntOrString{ + Type: intstr.Int, + IntVal: defaultValkeyPort, + }, + }, + }, + InitialDelaySeconds: 120, + TimeoutSeconds: 1, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("10Mi"), + }, + }, + }, + }, +} + +var valkeyPersistent = ServiceType{ + Name: "valkey-persistent", + Ports: valkey.Ports, + ProvidesPersistentVolume: true, + PrimaryContainer: ServiceContainer{ + Name: valkey.PrimaryContainer.Name, + Container: valkey.PrimaryContainer.Container, + EnvVars: []corev1.EnvVar{ + { + Name: "VALKEY_FLAVOR", + Value: "persistent", + }, + }, + }, + Volumes: ServiceVolume{ + PersistentVolumeSize: "5Gi", + PersistentVolumeType: corev1.ReadWriteOnce, + PersistentVolumePath: "/data", + BackupConfiguration: BackupConfiguration{ + Command: `/bin/sh -c "timeout 5400 tar -cf - -C {{ if .ServiceValues.PersistentVolumePath }}{{.ServiceValues.PersistentVolumePath}}{{else}}{{.ServiceTypeValues.Volumes.PersistentVolumePath}}{{end}} ."`, + FileExtension: ".{{ .ServiceValues.OverrideName }}.tar", + }, + }, + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + }, +} diff --git a/internal/templating/services/templates_cronjob.go b/internal/templating/services/templates_cronjob.go index 4bab1134..f885b93b 100644 --- a/internal/templating/services/templates_cronjob.go +++ b/internal/templating/services/templates_cronjob.go @@ -323,6 +323,7 @@ func GenerateCronjobTemplate( for _, cronjob := range serviceValues.InPodCronjobs { cronjobs = fmt.Sprintf("%s%s %s\n", cronjobs, cronjob.Schedule, cronjob.Command) } + container.Container.Env = append(container.Container.Env, container.EnvVars...) envvars := []corev1.EnvVar{ { Name: "LAGOON_GIT_SHA", diff --git a/internal/templating/services/templates_deployment.go b/internal/templating/services/templates_deployment.go index d9e69c70..b2aba00b 100644 --- a/internal/templating/services/templates_deployment.go +++ b/internal/templating/services/templates_deployment.go @@ -459,6 +459,8 @@ func GenerateDeploymentTemplate( for _, cronjob := range serviceValues.InPodCronjobs { cronjobs = fmt.Sprintf("%s%s %s\n", cronjobs, cronjob.Schedule, cronjob.Command) } + // add any variables from the servicetype container overrides here + container.Container.Env = append(container.Container.Env, container.EnvVars...) envvars := []corev1.EnvVar{ { Name: "LAGOON_GIT_SHA", @@ -589,6 +591,7 @@ func GenerateDeploymentTemplate( return nil, fmt.Errorf("no image reference was found for secondary container %s of service %s", serviceValues.LinkedService.Name, serviceValues.Name) } + linkedContainer.Container.Env = append(linkedContainer.Container.Env, linkedContainer.EnvVars...) envvars := []corev1.EnvVar{ { Name: "LAGOON_GIT_SHA", diff --git a/internal/templating/services/templates_deployment_test.go b/internal/templating/services/templates_deployment_test.go index cefe7546..91b8c8c2 100644 --- a/internal/templating/services/templates_deployment_test.go +++ b/internal/templating/services/templates_deployment_test.go @@ -943,6 +943,46 @@ func TestGenerateDeploymentTemplate(t *testing.T) { }, want: "test-resources/deployment/result-basic-5.yaml", }, + { + name: "test-valkey", + args: args{ + buildValues: generator.BuildValues{ + Project: "example-project", + Environment: "environment-name", + EnvironmentType: "production", + Namespace: "example-project-environment-name", + BuildType: "branch", + LagoonVersion: "v2.x.x", + Kubernetes: "generator.local", + Branch: "environment-name", + PodSecurityContext: generator.PodSecurityContext{ + RunAsGroup: 0, + RunAsUser: 10000, + FsGroup: 10001, + OnRootMismatch: true, + }, + GitSHA: "0", + ConfigMapSha: "32bf1359ac92178c8909f0ef938257b477708aa0d78a5a15ad7c2d7919adf273", + ImageReferences: map[string]string{ + "valkey": "harbor.example.com/example-project/environment-name/valkey@latest", + "valkey-persist": "harbor.example.com/example-project/environment-name/valkey-persist@latest", + }, + Services: []generator.ServiceValues{ + { + Name: "valkey", + OverrideName: "valkey", + Type: "valkey", + }, + { + Name: "valkey-persist", + OverrideName: "valkey-persist", + Type: "valkey-persistent", + }, + }, + }, + }, + want: "test-resources/deployment/result-valkey-1.yaml", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/templating/services/test-resources/deployment/result-valkey-1.yaml b/internal/templating/services/test-resources/deployment/result-valkey-1.yaml new file mode 100644 index 00000000..666aca17 --- /dev/null +++ b/internal/templating/services/test-resources/deployment/result-valkey-1.yaml @@ -0,0 +1,189 @@ +--- +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: valkey + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: valkey + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: valkey + lagoon.sh/service-type: valkey + lagoon.sh/template: valkey-0.1.0 + name: valkey +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: valkey + app.kubernetes.io/name: valkey + 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: valkey + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: valkey + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: valkey + lagoon.sh/service-type: valkey + lagoon.sh/template: valkey-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: "0" + - name: CRONJOBS + - name: SERVICE_NAME + value: valkey + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example.com/example-project/environment-name/valkey@latest + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 120 + tcpSocket: + port: 6379 + timeoutSeconds: 1 + name: valkey + ports: + - containerPort: 6379 + name: 6379-tcp + protocol: TCP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 6379 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + securityContext: + fsGroup: 10001 + fsGroupChangePolicy: OnRootMismatch + runAsGroup: 0 + runAsUser: 10000 +status: {} +--- +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: valkey-persist + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: valkey-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: valkey-persist + lagoon.sh/service-type: valkey-persistent + lagoon.sh/template: valkey-persistent-0.1.0 + name: valkey-persist +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: valkey-persist + app.kubernetes.io/name: valkey-persistent + strategy: + type: Recreate + template: + metadata: + annotations: + k8up.syn.tools/backupcommand: /bin/sh -c "timeout 5400 tar -cf - -C /data + ." + k8up.syn.tools/file-extension: .valkey-persist.tar + lagoon.sh/branch: environment-name + lagoon.sh/configMapSha: 32bf1359ac92178c8909f0ef938257b477708aa0d78a5a15ad7c2d7919adf273 + lagoon.sh/version: v2.x.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: valkey-persist + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: valkey-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: environment-name + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: valkey-persist + lagoon.sh/service-type: valkey-persistent + lagoon.sh/template: valkey-persistent-0.1.0 + spec: + containers: + - env: + - name: VALKEY_FLAVOR + value: persistent + - name: LAGOON_GIT_SHA + value: "0" + - name: CRONJOBS + - name: SERVICE_NAME + value: valkey-persist + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example.com/example-project/environment-name/valkey-persist@latest + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 120 + tcpSocket: + port: 6379 + timeoutSeconds: 1 + name: valkey + ports: + - containerPort: 6379 + name: 6379-tcp + protocol: TCP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 6379 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /data + name: valkey-persist + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + securityContext: + fsGroup: 10001 + fsGroupChangePolicy: OnRootMismatch + runAsGroup: 0 + runAsUser: 10000 + volumes: + - name: valkey-persist + persistentVolumeClaim: + claimName: valkey-persist +status: {}