diff --git a/internal/generator/services.go b/internal/generator/services.go index f3e8908e..35928703 100644 --- a/internal/generator/services.go +++ b/internal/generator/services.go @@ -29,6 +29,7 @@ var supportedAutogeneratedTypes = []string{ // "kibana", //@TODO: don't even need this anymore? "basic", "basic-persistent", + "basic-single", "node", "node-persistent", "nginx", @@ -60,6 +61,7 @@ var supportedDBTypes = []string{ // these are lagoon types that come with resources requiring backups var typesWithBackups = []string{ "basic-persistent", + "basic-single", "node-persistent", "nginx-php-persistent", "python-persistent", diff --git a/internal/servicetypes/basic.go b/internal/servicetypes/basic.go index a2d2f6e7..608b65f1 100644 --- a/internal/servicetypes/basic.go +++ b/internal/servicetypes/basic.go @@ -1,6 +1,7 @@ package servicetypes import ( + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" @@ -88,3 +89,22 @@ var basicPersistent = ServiceType{ Backup: true, }, } + +// contains all the single type overrides that the basic service doesn't have +// basicSingle is like basic persistent except that the volume is not bulk, and the pod can only ever have 1 replica because of this +var basicSingle = ServiceType{ + Name: "basic-single", + Ports: basic.Ports, + PrimaryContainer: ServiceContainer{ + Name: basic.PrimaryContainer.Name, + Container: basic.PrimaryContainer.Container, + }, + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + }, + Volumes: ServiceVolume{ + PersistentVolumeSize: "5Gi", + PersistentVolumeType: corev1.ReadWriteOnce, + Backup: true, + }, +} diff --git a/internal/servicetypes/types.go b/internal/servicetypes/types.go index fca42486..bc8b0bc9 100644 --- a/internal/servicetypes/types.go +++ b/internal/servicetypes/types.go @@ -61,6 +61,7 @@ type ServicePorts struct { var ServiceTypes = map[string]ServiceType{ "basic": basic, "basic-persistent": basicPersistent, + "basic-single": basicSingle, "cli": cli, "cli-persistent": cliPersistent, "elasticsearch": elasticsearch, diff --git a/internal/templating/services/templates_deployment_test.go b/internal/templating/services/templates_deployment_test.go index ed41989c..d445f575 100644 --- a/internal/templating/services/templates_deployment_test.go +++ b/internal/templating/services/templates_deployment_test.go @@ -856,6 +856,37 @@ func TestGenerateDeploymentTemplate(t *testing.T) { }, want: "test-resources/deployment/result-postgres-1.yaml", }, + { + name: "test20 - basic-single", + 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", + GitSHA: "0", + ConfigMapSha: "32bf1359ac92178c8909f0ef938257b477708aa0d78a5a15ad7c2d7919adf273", + ImageReferences: map[string]string{ + "myservice": "harbor.example.com/example-project/environment-name/myservice@latest", + }, + Services: []generator.ServiceValues{ + { + Name: "myservice", + OverrideName: "myservice", + Type: "basic-single", + DBaaSEnvironment: "production", + ServicePort: 8080, + Replicas: 1, + }, + }, + }, + }, + want: "test-resources/deployment/result-basic-4.yaml", + }, { name: "test-basic-antiaffinity", args: args{ @@ -910,7 +941,7 @@ func TestGenerateDeploymentTemplate(t *testing.T) { }, }, }, - want: "test-resources/deployment/result-basic-4.yaml", + want: "test-resources/deployment/result-basic-5.yaml", }, } for _, tt := range tests { @@ -1092,7 +1123,7 @@ func TestLinkedServiceCalculator(t *testing.T) { lValues, _ := json.Marshal(got) wValues, _ := json.Marshal(tt.want) if !reflect.DeepEqual(string(lValues), string(wValues)) { - t.Errorf("LinkedServiceCalculator() = %v, want %v", string(lValues), string(wValues)) + t.Errorf("LinkedServiceCalculator() = \n%v", diff.LineDiff(string(lValues), string(wValues))) } }) } diff --git a/internal/templating/services/templates_pvc_test.go b/internal/templating/services/templates_pvc_test.go index e92731e4..6848b313 100644 --- a/internal/templating/services/templates_pvc_test.go +++ b/internal/templating/services/templates_pvc_test.go @@ -213,6 +213,31 @@ func TestGeneratePVCTemplate(t *testing.T) { }, want: "test-resources/pvc/result-basic-3.yaml", }, + { + name: "test8 - basic-single", + 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", + RWX2RWO: true, + Services: []generator.ServiceValues{ + { + Name: "myservice", + OverrideName: "myservice", + Type: "basic-single", + DBaaSEnvironment: "development", + }, + }, + }, + }, + want: "test-resources/pvc/result-basic-4.yaml", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/templating/services/templates_service_test.go b/internal/templating/services/templates_service_test.go index 1dad3d26..6aa050ea 100644 --- a/internal/templating/services/templates_service_test.go +++ b/internal/templating/services/templates_service_test.go @@ -244,6 +244,30 @@ func TestGenerateServiceTemplate(t *testing.T) { }, want: "test-resources/service/result-nginx-php-1.yaml", }, + { + name: "test6 - basic-single", + 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", + Services: []generator.ServiceValues{ + { + Name: "myservice", + OverrideName: "myservice", + Type: "basic-single", + DBaaSEnvironment: "development", + }, + }, + }, + }, + want: "test-resources/service/result-basic-3.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 index fd1de1a0..ac282848 100644 --- a/internal/templating/services/test-resources/deployment/result-basic-4.yaml +++ b/internal/templating/services/test-resources/deployment/result-basic-4.yaml @@ -9,22 +9,23 @@ metadata: labels: app.kubernetes.io/instance: myservice app.kubernetes.io/managed-by: build-deploy-tool - app.kubernetes.io/name: basic + app.kubernetes.io/name: basic-single 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 + lagoon.sh/service-type: basic-single + lagoon.sh/template: basic-single-0.1.0 name: myservice spec: - replicas: 2 + replicas: 1 selector: matchLabels: app.kubernetes.io/instance: myservice - app.kubernetes.io/name: basic - strategy: {} + app.kubernetes.io/name: basic-single + strategy: + type: Recreate template: metadata: annotations: @@ -35,14 +36,14 @@ spec: labels: app.kubernetes.io/instance: myservice app.kubernetes.io/managed-by: build-deploy-tool - app.kubernetes.io/name: basic + app.kubernetes.io/name: basic-single 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 + lagoon.sh/service-type: basic-single + lagoon.sh/template: basic-single-0.1.0 spec: containers: - env: @@ -59,54 +60,32 @@ spec: livenessProbe: initialDelaySeconds: 60 tcpSocket: - port: 8191 + port: 8080 timeoutSeconds: 10 name: basic ports: - - containerPort: 8191 - name: tcp-8191 - protocol: TCP - - containerPort: 8211 - name: tcp-8211 + - containerPort: 8080 + name: http protocol: TCP readinessProbe: initialDelaySeconds: 1 tcpSocket: - port: 8191 + port: 8080 timeoutSeconds: 1 resources: - limits: - ephemeral-storage: 160Gi - memory: 16Gi requests: cpu: 10m - ephemeral-storage: 1Gi memory: 10Mi securityContext: {} + volumeMounts: + - mountPath: "" + name: myservice 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 + volumes: + - name: myservice + persistentVolumeClaim: + claimName: myservice status: {} diff --git a/internal/templating/services/test-resources/deployment/result-basic-5.yaml b/internal/templating/services/test-resources/deployment/result-basic-5.yaml new file mode 100644 index 00000000..fd1de1a0 --- /dev/null +++ b/internal/templating/services/test-resources/deployment/result-basic-5.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/templating/services/test-resources/pvc/result-basic-4.yaml b/internal/templating/services/test-resources/pvc/result-basic-4.yaml new file mode 100644 index 00000000..ce90e68c --- /dev/null +++ b/internal/templating/services/test-resources/pvc/result-basic-4.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + k8up.io/backup: "true" + k8up.syn.tools/backup: "true" + 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-single + 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-single + lagoon.sh/template: basic-single-0.1.0 + name: myservice +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +status: {} diff --git a/internal/templating/services/test-resources/service/result-basic-3.yaml b/internal/templating/services/test-resources/service/result-basic-3.yaml new file mode 100644 index 00000000..5a18549a --- /dev/null +++ b/internal/templating/services/test-resources/service/result-basic-3.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: v1 +kind: Service +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-single + 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-single + lagoon.sh/template: basic-single-0.1.0 + name: myservice +spec: + ports: + - name: http + port: 3000 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: myservice + app.kubernetes.io/name: basic-single +status: + loadBalancer: {}