Repository: kubevela/kubevela

Issue:
podsecuritycontext Trait Definition: localhostProfile Attribute Should Be Optional in seccompProfile and appArmorProfile for Type RuntimeDefault
**Describe the bug**
The localhostProfile attribute is currently required or improperly validated when the type field is set to RuntimeDefault in both seccompProfile and appArmorProfile. According to expected behavior, localhostProfile should be optional and ignored when type is RuntimeDefault, as the runtime’s default profile does not require a custom local profile.

**To Reproduce**

Steps to reproduce the behavior:
1. Apply the following application yaml:

```
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: podtato-head
  namespace: default
spec:
  components:
    - name: podtato-head-frontend
      type: webservice
      properties:
        image: ghcr.io/podtato-head/podtato-server:v0.3.1
        ports:
          - port: 8080
            expose: true
        cpu: "0.1"
        memory: "32Mi"
      traits:
        - type: podsecuritycontext
          properties:
            runAsNonRoot: true
            seccompProfile:
              type: RuntimeDefault
```

**Error:**

 Message:             function call error for : GenerateComponentManifest: evaluate base template component=podtatohead-frontend app=podtato-head: failed to have the workload/trait unstructured: spec.template.spec.securityContext.seccompProfile.localhostProfile: incomplete value string (value: cue/format: unsupported node type <nil>)


**Expected behavior**
When type: RuntimeDefault is specified:

The localhostProfile field should be optional.

If provided, it should be ignored or validated as unused.

No error or validation failure should occur due to presence or absence of localhostProfile.
<!--
If applicable, add screenshots to help explain your problem.
-->

**KubeVela Version** :  v1.10.2

<!--
Describe your KubeVela controller or CLI version information.
-->
CLI Version: 1.9.13
Core Version: 1.10.2
GitRevision: git-d56da069
GolangVersion: go1.19.13
**Cluster information**

<!--
Describe your kubernetes cluster information.
- Kubernetes Version :  v1.31.5-eks
-->



Discussion:

Solution patch:
diff --git a/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml b/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
index f3eeef97..dd02a14a 100644
--- a/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
+++ b/charts/vela-core/templates/admission-webhooks/job-patch/job-createSecret.yaml
@@ -2,7 +2,7 @@
 apiVersion: batch/v1
 kind: Job
 metadata:
-  name:  {{ template "kubevela.fullname" . }}-admission-create
+  name: {{ template "kubevela.fullname" . }}-admission-create
   namespace: {{ .Release.Namespace }}
   annotations:
     "helm.sh/hook": pre-install,pre-upgrade
@@ -17,7 +17,7 @@ spec:
   {{- end }}
   template:
     metadata:
-      name:  {{ template "kubevela.fullname" . }}-admission-create
+      name: {{ template "kubevela.fullname" . }}-admission-create
       labels:
         app: {{ template "kubevela.name" . }}-admission-create
         {{- include "kubevela.labels" . | nindent 8 }}
@@ -39,17 +39,26 @@ spec:
             - --cert-name=tls.crt
       restartPolicy: OnFailure
       serviceAccountName: {{ template "kubevela.fullname" . }}-admission
-      {{- with .Values.admissionWebhooks.patch.nodeSelector }}
+      {{- if .Values.admissionWebhooks.patch.nodeSelector }}
       nodeSelector:
-      {{- toYaml . | nindent 8 }}
+      {{- toYaml .Values.admissionWebhooks.patch.nodeSelector | nindent 8 }}
+      {{- else if .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.nodeSelector | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.affinity }}
+      {{- if .Values.admissionWebhooks.patch.affinity }}
       affinity:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.admissionWebhooks.patch.affinity | nindent 8 }}
+      {{- else if .Values.affinity }}
+      affinity:
+      {{- toYaml .Values.affinity | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.tolerations }}
+      {{- if .Values.admissionWebhooks.patch.tolerations }}
+      tolerations:
+      {{- toYaml .Values.admissionWebhooks.patch.tolerations | nindent 8 }}
+      {{- else if .Values.tolerations }}
       tolerations:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.tolerations | nindent 8 }}
       {{- end }}
       securityContext:
         runAsGroup: 2000
diff --git a/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml b/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
index 7b8b60aa..eb2e9847 100644
--- a/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
+++ b/charts/vela-core/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
@@ -2,7 +2,7 @@
 apiVersion: batch/v1
 kind: Job
 metadata:
-  name:  {{ template "kubevela.fullname" . }}-admission-patch
+  name: {{ template "kubevela.fullname" . }}-admission-patch
   namespace: {{ .Release.Namespace }}
   annotations:
     "helm.sh/hook": post-install,post-upgrade
@@ -17,7 +17,7 @@ spec:
   {{- end }}
   template:
     metadata:
-      name:  {{ template "kubevela.fullname" . }}-admission-patch
+      name: {{ template "kubevela.fullname" . }}-admission-patch
       labels:
         app: {{ template "kubevela.name" . }}-admission-patch
         {{- include "kubevela.labels" . | nindent 8 }}
@@ -41,13 +41,26 @@ spec:
             {{- end }}
       restartPolicy: OnFailure
       serviceAccountName: {{ template "kubevela.fullname" . }}-admission
-      {{- with .Values.admissionWebhooks.patch.affinity }}
+      {{- if .Values.admissionWebhooks.patch.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.admissionWebhooks.patch.nodeSelector | nindent 8 }}
+      {{- else if .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml .Values.nodeSelector | nindent 8 }}
+      {{- end }}
+      {{- if .Values.admissionWebhooks.patch.affinity }}
+      affinity:
+      {{- toYaml .Values.admissionWebhooks.patch.affinity | nindent 8 }}
+      {{- else if .Values.affinity }}
       affinity:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.affinity | nindent 8 }}
       {{- end }}
-      {{- with .Values.admissionWebhooks.patch.tolerations }}
+      {{- if .Values.admissionWebhooks.patch.tolerations }}
+      tolerations:
+      {{- toYaml .Values.admissionWebhooks.patch.tolerations | nindent 8 }}
+      {{- else if .Values.tolerations }}
       tolerations:
-{{ toYaml . | indent 8 }}
+      {{- toYaml .Values.tolerations | nindent 8 }}
       {{- end }}
       securityContext:
         runAsGroup: 2000
diff --git a/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml b/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
index c02d85ec..99d2cc32 100644
--- a/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
+++ b/charts/vela-core/templates/cluster-gateway/cluster-gateway.yaml
@@ -190,4 +190,4 @@ subjects:
   - kind: ServiceAccount
     name: {{ include "kubevela.serviceAccountName" . }}
     namespace: {{ .Release.Namespace }}
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/charts/vela-core/templates/cluster-gateway/job-patch.yaml b/charts/vela-core/templates/cluster-gateway/job-patch.yaml
index 23956465..f2190a6a 100644
--- a/charts/vela-core/templates/cluster-gateway/job-patch.yaml
+++ b/charts/vela-core/templates/cluster-gateway/job-patch.yaml
@@ -95,6 +95,18 @@ spec:
         runAsGroup: 2000
         runAsNonRoot: true
         runAsUser: 2000
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
 ---
 apiVersion: batch/v1
 kind: Job
@@ -138,4 +150,16 @@ spec:
         runAsGroup: 2000
         runAsNonRoot: true
         runAsUser: 2000
-{{ end }}
\ No newline at end of file
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+      {{- toYaml . | nindent 8 }}
+      {{- end }}
+{{ end }}
diff --git a/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml b/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
index 7707a50c..23aaee5f 100644
--- a/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
+++ b/charts/vela-core/templates/defwithtemplate/podsecuritycontext.yaml
@@ -39,8 +39,9 @@ spec:
         parameter: {
         	// +usage=Specify the AppArmor profile for the pod
         	appArmorProfile?: {
-        		type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-        		localhostProfile: string
+        		type: "RuntimeDefault" | "Unconfined" | "Localhost"
+        		// +usage:  localhostProfile is required when type is 'Localhost'
+        		localhostProfile?: string
         	}
         	fsGroup?:    int
         	runAsGroup?: int
@@ -50,8 +51,9 @@ spec:
         	runAsNonRoot: *true | bool
         	// +usage=Specify the seccomp profile for the pod
         	seccompProfile?: {
-        		type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-        		localhostProfile: string
+        		type: "RuntimeDefault" | "Unconfined" | "Localhost"
+        		// +usage:  localhostProfile is required when type is 'Localhost'
+        		localhostProfile?: string
         	}
         }
 
diff --git a/vela-templates/definitions/internal/trait/podsecuritycontext.cue b/vela-templates/definitions/internal/trait/podsecuritycontext.cue
index 09d2ba49..055b987b 100644
--- a/vela-templates/definitions/internal/trait/podsecuritycontext.cue
+++ b/vela-templates/definitions/internal/trait/podsecuritycontext.cue
@@ -33,8 +33,9 @@ template: {
 	parameter: {
 		// +usage=Specify the AppArmor profile for the pod
 		appArmorProfile?: {
-			type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-			localhostProfile: string
+			type: "RuntimeDefault" | "Unconfined" | "Localhost"
+			// +usage:  localhostProfile is required when type is 'Localhost'
+			localhostProfile?: string
 		}
 		fsGroup?:    int
 		runAsGroup?: int
@@ -44,8 +45,9 @@ template: {
 		runAsNonRoot: *true | bool
 		// +usage=Specify the seccomp profile for the pod
 		seccompProfile?: {
-			type:             "RuntimeDefault" | "Unconfined" | "Localhost"
-			localhostProfile: string
+			type: "RuntimeDefault" | "Unconfined" | "Localhost"
+			// +usage:  localhostProfile is required when type is 'Localhost'
+			localhostProfile?: string
 		}
 	}
 }



Test patch:
diff --git a/charts/vela-core/templates/test/test-application.yaml b/charts/vela-core/templates/test/test-application.yaml
index 5b3e8027..4cebf5ae 100644
--- a/charts/vela-core/templates/test/test-application.yaml
+++ b/charts/vela-core/templates/test/test-application.yaml
@@ -48,3 +48,15 @@ spec:
 
           echo "Application and its components are created"
   restartPolicy: Never
+  {{- with .Values.nodeSelector }}
+  nodeSelector:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- with .Values.affinity }}
+  affinity:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}
+  {{- with .Values.tolerations }}
+  tolerations:
+  {{- toYaml . | nindent 4 }}
+  {{- end }}