Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Operator: more workload configs added #49

Merged
merged 3 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,926 changes: 1,763 additions & 163 deletions crds/sme.sap.com_capapplicationversions.yaml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions internal/controller/reconcile-capapplicationversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,14 @@ func newContentDeploymentJob(ca *v1alpha1.CAPApplication, cav *v1alpha1.CAPAppli
{Name: EnvCAPOpAppVersion, Value: cav.Spec.Version},
}, workload.JobDefinition.Env...),
EnvFrom: getEnvFrom(vcapSecretName),
VolumeMounts: workload.JobDefinition.VolumeMounts,
Resources: workload.JobDefinition.Resources,
SecurityContext: workload.JobDefinition.SecurityContext,
},
},
SecurityContext: workload.JobDefinition.PodSecurityContext,
ServiceAccountName: workload.JobDefinition.ServiceAccountName,
Volumes: workload.JobDefinition.Volumes,
ImagePullSecrets: convertToLocalObjectReferences(cav.Spec.RegistrySecrets),
RestartPolicy: corev1.RestartPolicyOnFailure,
NodeSelector: workload.JobDefinition.NodeSelector,
Expand Down Expand Up @@ -593,6 +596,8 @@ func createDeployment(params *DeploymentParameters) *appsv1.Deployment {
Spec: corev1.PodSpec{
ImagePullSecrets: convertToLocalObjectReferences(params.CAV.Spec.RegistrySecrets),
Containers: getContainer(params),
ServiceAccountName: params.WorkloadDetails.DeploymentDefinition.ServiceAccountName,
Volumes: params.WorkloadDetails.DeploymentDefinition.Volumes,
SecurityContext: params.WorkloadDetails.DeploymentDefinition.PodSecurityContext,
NodeSelector: params.WorkloadDetails.DeploymentDefinition.NodeSelector,
NodeName: params.WorkloadDetails.DeploymentDefinition.NodeName,
Expand All @@ -614,6 +619,7 @@ func getContainer(params *DeploymentParameters) []corev1.Container {
Command: params.WorkloadDetails.DeploymentDefinition.Command,
Env: getEnv(params),
EnvFrom: getEnvFrom(params.VCAPSecretName),
VolumeMounts: params.WorkloadDetails.DeploymentDefinition.VolumeMounts,
LivenessProbe: params.WorkloadDetails.DeploymentDefinition.LivenessProbe,
ReadinessProbe: params.WorkloadDetails.DeploymentDefinition.ReadinessProbe,
Resources: params.WorkloadDetails.DeploymentDefinition.Resources,
Expand Down
20 changes: 20 additions & 0 deletions internal/controller/reconcile-capapplicationversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -724,3 +724,23 @@ func TestCAV_Node_PriorityClass_Names(t *testing.T) {
},
)
}

func TestCAV_Volumes_and_ServiceAccountName(t *testing.T) {
reconcileTestItem(
context.TODO(), t,
QueueItem{Key: ResourceCAPApplicationVersion, ResourceKey: NamespacedResourceKey{Namespace: "default", Name: "test-cap-01-cav-v1"}},
TestData{
description: "capapplication version with volumes and serviceAccountName",
initialResources: []string{
"testdata/common/capapplication.yaml",
"testdata/common/credential-secrets.yaml",
"testdata/capapplicationversion/content-job-completed.yaml",
"testdata/capapplicationversion/cav-vol.yaml",
},
expectedResources: "testdata/capapplicationversion/expected/cav-ready-vol.yaml",
backlogItems: []string{
"ERP4SMEPREPWORKAPPPLAT-6370", // More workload configuration enhancements
},
},
)
}
54 changes: 30 additions & 24 deletions internal/controller/reconcile-captenantoperation.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type tentantOperationWorkload struct {
imagePullPolicy corev1.PullPolicy
command []string
env []corev1.EnvVar
volumeMounts []corev1.VolumeMount
volumes []corev1.Volume
serviceAccountName string
resources corev1.ResourceRequirements
securityContext *corev1.SecurityContext
podSecurityContext *corev1.PodSecurityContext
Expand Down Expand Up @@ -493,6 +496,8 @@ func (c *Controller) createTenantOperationJob(ctx context.Context, ctop *v1alpha
RestartPolicy: corev1.RestartPolicyNever,
ImagePullSecrets: params.imagePullSecrets,
Containers: getContainers(payload, ctop, derivedWorkload, workload, params),
Volumes: derivedWorkload.volumes,
ServiceAccountName: derivedWorkload.serviceAccountName,
SecurityContext: derivedWorkload.podSecurityContext,
NodeSelector: derivedWorkload.nodeSelector,
NodeName: derivedWorkload.nodeName,
Expand All @@ -513,19 +518,20 @@ func isMTXSDisabled(envVars []corev1.EnvVar) bool {
}

func getContainers(payload []byte, ctop *v1alpha1.CAPTenantOperation, derivedWorkload tentantOperationWorkload, workload *v1alpha1.WorkloadDetails, params *jobCreateParams) []corev1.Container {
container := &corev1.Container{
Name: workload.Name,
Image: derivedWorkload.image,
ImagePullPolicy: derivedWorkload.imagePullPolicy,
Env: append([]corev1.EnvVar{
{Name: EnvCAPOpAppVersion, Value: params.version}, {Name: EnvCAPOpTenantID, Value: ctop.Spec.TenantId}, {Name: EnvCAPOpTenantOperation, Value: string(ctop.Spec.Operation)}, {Name: EnvCAPOpTenantSubDomain, Value: string(ctop.Spec.SubDomain)},
}, derivedWorkload.env...),
EnvFrom: params.envFromVCAPSecret,
VolumeMounts: derivedWorkload.volumeMounts,
Resources: derivedWorkload.resources,
SecurityContext: derivedWorkload.securityContext,
}
if !isMTXSDisabled(derivedWorkload.env) {
var operation string
container := &corev1.Container{
Name: workload.Name,
Image: derivedWorkload.image,
ImagePullPolicy: derivedWorkload.imagePullPolicy,
Env: append([]corev1.EnvVar{
{Name: EnvCAPOpAppVersion, Value: params.version}, {Name: EnvCAPOpTenantID, Value: ctop.Spec.TenantId}, {Name: EnvCAPOpTenantOperation, Value: string(ctop.Spec.Operation)}, {Name: EnvCAPOpTenantSubDomain, Value: string(ctop.Spec.SubDomain)},
}, derivedWorkload.env...),
EnvFrom: params.envFromVCAPSecret,
Resources: derivedWorkload.resources,
SecurityContext: derivedWorkload.securityContext,
}

if ctop.Spec.Operation == v1alpha1.CAPTenantOperationTypeProvisioning {
operation = "subscribe"
Expand All @@ -544,6 +550,9 @@ func getContainers(payload []byte, ctop *v1alpha1.CAPTenantOperation, derivedWor
return append([]corev1.Container{}, *container)
}

container.Command = []string{"/bin/sh", "-c"}
container.Args = []string{"node ./node_modules/@sap/cds/bin/cds run & nc -lv -s localhost -p 8080"}

return []corev1.Container{
{
Name: "trigger", // TODO: get rid of this --> hopefully with mtxs cli where we start a single container image
Expand All @@ -558,19 +567,7 @@ func getContainers(payload []byte, ctop *v1alpha1.CAPTenantOperation, derivedWor
},
EnvFrom: params.envFromVCAPSecret,
},
{
Name: workload.Name,
Image: derivedWorkload.image,
ImagePullPolicy: derivedWorkload.imagePullPolicy,
Env: append([]corev1.EnvVar{
{Name: EnvCAPOpAppVersion, Value: params.version}, {Name: EnvCAPOpTenantID, Value: ctop.Spec.TenantId}, {Name: EnvCAPOpTenantOperation, Value: string(ctop.Spec.Operation)}, {Name: EnvCAPOpTenantSubDomain, Value: string(ctop.Spec.SubDomain)},
}, derivedWorkload.env...),
EnvFrom: params.envFromVCAPSecret,
Resources: derivedWorkload.resources,
SecurityContext: derivedWorkload.securityContext,
Command: []string{"/bin/sh", "-c"},
Args: []string{"node ./node_modules/@sap/cds/bin/cds run & nc -lv -s localhost -p 8080"},
},
*container,
}
}

Expand All @@ -581,6 +578,9 @@ func deriveWorkloadForTenantOperation(workload *v1alpha1.WorkloadDetails) tentan
result.image = workload.DeploymentDefinition.Image
result.imagePullPolicy = workload.DeploymentDefinition.ImagePullPolicy
result.env = workload.DeploymentDefinition.Env
result.volumeMounts = workload.DeploymentDefinition.VolumeMounts
result.volumes = workload.DeploymentDefinition.Volumes
result.serviceAccountName = workload.DeploymentDefinition.ServiceAccountName
result.resources = workload.DeploymentDefinition.Resources
result.backoffLimit = &backoffLimitValue
result.ttlSecondsAfterFinished = &tTLSecondsAfterFinishedValue
Expand All @@ -598,6 +598,9 @@ func deriveWorkloadForTenantOperation(workload *v1alpha1.WorkloadDetails) tentan
result.imagePullPolicy = workload.JobDefinition.ImagePullPolicy
result.command = workload.JobDefinition.Command
result.env = workload.JobDefinition.Env
result.volumeMounts = workload.JobDefinition.VolumeMounts
result.volumes = workload.JobDefinition.Volumes
result.serviceAccountName = workload.JobDefinition.ServiceAccountName
result.resources = workload.JobDefinition.Resources
result.securityContext = workload.JobDefinition.SecurityContext
result.podSecurityContext = workload.JobDefinition.PodSecurityContext
Expand Down Expand Up @@ -638,6 +641,8 @@ func (c *Controller) createCustomTenantOperationJob(ctx context.Context, ctop *v
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
SecurityContext: workload.JobDefinition.PodSecurityContext,
Volumes: workload.JobDefinition.Volumes,
ServiceAccountName: workload.JobDefinition.ServiceAccountName,
NodeSelector: workload.JobDefinition.NodeSelector,
NodeName: workload.JobDefinition.NodeName,
PriorityClassName: workload.JobDefinition.PriorityClassName,
Expand All @@ -654,6 +659,7 @@ func (c *Controller) createCustomTenantOperationJob(ctx context.Context, ctop *v
{Name: EnvCAPOpAppVersion, Value: params.version}, {Name: EnvCAPOpTenantID, Value: ctop.Spec.TenantId}, {Name: EnvCAPOpTenantOperation, Value: string(ctop.Spec.Operation)}, {Name: EnvCAPOpTenantSubDomain, Value: string(ctop.Spec.SubDomain)},
}, workload.JobDefinition.Env...),
EnvFrom: params.envFromVCAPSecret,
VolumeMounts: workload.JobDefinition.VolumeMounts,
Command: workload.JobDefinition.Command,
Resources: workload.JobDefinition.Resources,
SecurityContext: workload.JobDefinition.SecurityContext,
Expand Down
44 changes: 44 additions & 0 deletions internal/controller/reconcile-captenantoperation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,3 +704,47 @@ func TestProvisioningWithSchedulingConfigCustom(t *testing.T) {
},
)
}

func TestProvisioningWithVolAndServiceAccountName(t *testing.T) {
_ = reconcileTestItem(
context.TODO(), t,
QueueItem{Key: ResourceCAPTenantOperation, ResourceKey: NamespacedResourceKey{Namespace: "default", Name: "test-cap-01-provider-abcd"}},
TestData{
backlogItems: []string{"ERP4SMEPREPWORKAPPPLAT-6370"}, // More workload configuration enhancements
description: "Provisioning - With volume and service account config",
initialResources: []string{
"testdata/common/capapplication.yaml",
"testdata/common/captenant-provider-ready.yaml",
"testdata/common/capapplicationversion-v1-vol.yaml",
"testdata/common/credential-secrets.yaml",
"testdata/captenantoperation/ctop-vol.initial.yaml", // The config in there might not make sense in the real world!
},
expectedResources: "testdata/captenantoperation/ctop-vol.expected.yaml",
expectedRequeue: map[int][]NamespacedResourceKey{
ResourceCAPTenantOperation: {{Namespace: "default", Name: "test-cap-01-provider-abcd"}},
},
},
)
}

func TestProvisioningWithVolumeAndServiceAccountNameCustom(t *testing.T) {
_ = reconcileTestItem(
context.TODO(), t,
QueueItem{Key: ResourceCAPTenantOperation, ResourceKey: NamespacedResourceKey{Namespace: "default", Name: "test-cap-01-provider-abcd"}},
TestData{
backlogItems: []string{"ERP4SMEPREPWORKAPPPLAT-6370"}, // More workload configuration enhancements
description: "Provisioning - With volume and serviceAccountName config for CustomTenantOperation",
initialResources: []string{
"testdata/common/capapplication.yaml",
"testdata/common/captenant-provider-ready.yaml",
"testdata/common/capapplicationversion-v1-vol-custom.yaml",
"testdata/common/credential-secrets.yaml",
"testdata/captenantoperation/ctop-vol-custom.initial.yaml",
},
expectedResources: "testdata/captenantoperation/ctop-vol-custom.expected.yaml",
expectedRequeue: map[int][]NamespacedResourceKey{
ResourceCAPTenantOperation: {{Namespace: "default", Name: "test-cap-01-provider-abcd"}},
},
},
)
}
172 changes: 172 additions & 0 deletions internal/controller/testdata/capapplicationversion/cav-vol.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
apiVersion: sme.sap.com/v1alpha1
kind: CAPApplicationVersion
metadata:
creationTimestamp: "2022-07-18T06:13:52Z"
generation: 1
annotations:
sme.sap.com/btp-app-identifier: btp-glo-acc-id.test-cap-01
sme.sap.com/owner-identifier: default.test-cap-01
labels:
sme.sap.com/btp-app-identifier-hash: f20cc8aeb2003b3abc33f749a16bd53544b6bab2
sme.sap.com/owner-generation: "2"
sme.sap.com/owner-identifier-hash: 1f74ae2fbff71a708786a4df4bb2ca87ec603581
name: test-cap-01-cav-v1
namespace: default
ownerReferences:
- apiVersion: sme.sap.com/v1alpha1
blockOwnerDeletion: true
controller: true
kind: CAPApplication
name: test-cap-01
uid: 3c7ba7cb-dc04-4fd1-be86-3eb3a5c64a98
resourceVersion: "11371108"
uid: 5e64489b-7346-4984-8617-e8c37338b3d8
spec:
capApplicationInstance: test-cap-01
registrySecrets:
- regcred
version: 1.2.3
workloads:
- name: cap-backend-srv
consumedBTPServices:
- cap-uaa
- cap-service-manager
- cap-saas-registry
deploymentDefinition:
image: docker.image.repo/srv/server:latest
type: CAP
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.PodIp
ports:
- name: "app-port"
port: 4004
routerDestinationName: "srv-api"
appProtocol: http
- name: "app-tech-port"
port: 4005
networkPolicy: "Cluster"
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4004
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4004
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
- name: app-router
consumedBTPServices:
- cap-uaa
- cap-saas-registry
deploymentDefinition:
image: docker.image.repo/approuter/approuter:latest
type: Router
volumeMounts:
- name: xsapp-vol
mountPath: /usr/app/xsapp.json
subPath: xsapp.json
env:
- name: debug
valueFrom:
configMapKeyRef:
key: someKey
name: someCM
optional: true
ports:
- name: "router-port"
port: 4000
appProtocol: http
- name: "router-tech-port"
port: 4004
networkPolicy: "Cluster"
- name: "router-metrics-port"
port: 4007
networkPolicy: "Cluster"
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
nodeName: app
priorityClassName: some-prio
serviceAccountName: custom-router-sa
volumes:
- name: xsapp-vol
configMap:
name: xsapp-config
- name: content-job
consumedBTPServices:
- cap-uaa
jobDefinition:
image: docker.image.repo/content/cap-content:latest
type: Content
env:
- name: SOME_VERSION
value: 0.0.1
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 10m
memory: 20Mi
- name: mtx-job
consumedBTPServices:
- cap-uaa
- cap-service-manager
- cap-saas-registry
jobDefinition:
image: docker.image.repo/srv/server:latest
type: TenantOperation
- name: job-worker
consumedBTPServices:
- cap-uaa
- cap-service-manager
- cap-saas-registry
deploymentDefinition:
image: docker.image.repo/srv/server:latest
type: Additional
env:
- name: TEST_SEC_REF
valueFrom:
secretKeyRef:
key: someKey
name: someSecret
optional: true
status:
state: Processing
Loading
Loading