diff --git a/config/300-crdregistration.yaml b/config/300-crdregistration.yaml index 419966f..a59a653 100644 --- a/config/300-crdregistration.yaml +++ b/config/300-crdregistration.yaml @@ -155,8 +155,8 @@ spec: transformed into workload parameters. properties: addEnvs: - description: AddEnvs contains configurations for parameters - to be added to the workload not derived from the user instance. + description: AddEnvs contains instructions to create environment + variables at the workload not derived from the user instance. items: description: EnvVar represents an environment variable present in a Container. @@ -273,28 +273,21 @@ spec: - name type: object type: array - global: - description: Global defines the configuration to be applied - to all generated parameters. - properties: - defaultPrefix: - description: DefaultPrefix to be appeneded to keys by - all generated parameters. This configuration does not - affect parameter keys explicitly set by users. - type: string - type: object - specToEnvs: - description: SpecToEnvs contains instructions to modify parameters - generation from the instance's spec. + fromSpec: + description: FromSpec contains instructions to generate workload + items from the instance's spec. items: - description: SpecToEnvsParameterConfiguration contains instructions - to modify parameters generation for the controlled instance - spec. + description: FromSpecConfiguration contains instructions + to generate rendering from the controlled instance spec. properties: path: description: JSON simplified path for the parameter. type: string - render: + skip: + description: Skip sets whether the object should skip + rendering as a workload item. + type: boolean + toEnv: description: Render options for the parameter generation. properties: defaultValue: @@ -306,10 +299,6 @@ spec: description: Name is the name of the parameter to be created. type: string - skip: - description: Skip sets whether the object should - skip rendering as a workload parameter. - type: boolean valueFromBuiltInFunc: description: ValueFromBuiltInFunc configures the field to be rendered acording to the chosen built-in @@ -355,10 +344,58 @@ spec: - name type: object type: object + toVolume: + description: Render options for the parameter generation. + properties: + mountPath: + description: Path where the file will be mounted. + type: string + name: + description: Name for the volume. + type: string + valueFromConfigMap: + description: ValueFromConfigMap is a reference to + a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: Object name + type: string + required: + - key + - name + type: object + valueFromSecret: + description: ValueFromSecret is a reference to a + Secret. + properties: + key: + description: The key to select. + type: string + name: + description: Object name + type: string + required: + - key + - name + type: object + type: object required: - path type: object type: array + global: + description: Global defines the configuration to be applied + to all generated parameters. + properties: + defaultPrefix: + description: DefaultPrefix to be appeneded to keys by + all generated parameters. This configuration does not + affect parameter keys explicitly set by users. + type: string + type: object type: object statusConfiguration: description: StatusConfiguration contains rules to populate a diff --git a/docs/reference/registration.md b/docs/reference/registration.md index 5416b43..4b3ce39 100644 --- a/docs/reference/registration.md +++ b/docs/reference/registration.md @@ -158,19 +158,18 @@ The default behavior is to create parameters from each spec element (arrays will ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.bar - render: - skip: true + skip: true ``` - [x] Change key for generated param. Can be combined. ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.bar - render: + toEnv: name: FOO_BAR ``` @@ -178,9 +177,9 @@ The default behavior is to create parameters from each spec element (arrays will ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.bar - render: + toEnv: defaultValue: hello scoby ``` @@ -188,9 +187,9 @@ The default behavior is to create parameters from each spec element (arrays will ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.credentials - render: + toEnv: name: FOO_CREDENTIALS valueFromSecret: name: spec.credentials.name @@ -201,9 +200,9 @@ The default behavior is to create parameters from each spec element (arrays will ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.preferences - render: + toEnv: valueFromConfigmap: name: spec.preferences.name key: spec.preferences.key @@ -213,23 +212,41 @@ The default behavior is to create parameters from each spec element (arrays will ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.destination - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress ``` +### Generate Volumes From Spec + +Secrets and ConfigMaps can be mounted as a volume inside the workload. The registration needs a name for the volume, the file to mount inside the container and a reference to the Secret or ConfigMap. + +- [x] Function: resolve object to internal URL + +```yaml + parameterConfiguration: + fromSpec: + - path: spec.userList + toVolume: + name: userfile + mountPath: /opt/user.lst + valueFromConfigMap: + name: spec.userList.name + key: spec.userList.key +``` + ## Workload Status - [x] Use parameter value for status. ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.destination - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/docs/samples/01.kuard/03.param.skip/01.kuard-registration.yaml b/docs/samples/01.kuard/03.param.skip/01.kuard-registration.yaml index 5ecc84a..b321f63 100644 --- a/docs/samples/01.kuard/03.param.skip/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/03.param.skip/01.kuard-registration.yaml @@ -15,9 +15,8 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Skip variable2 from generating a parameter for the workload - path: spec.variable2 - render: - skip: true + skip: true diff --git a/docs/samples/01.kuard/04.param.rename/01.kuard-registration.yaml b/docs/samples/01.kuard/04.param.rename/01.kuard-registration.yaml index 00d97b9..6db929d 100644 --- a/docs/samples/01.kuard/04.param.rename/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/04.param.rename/01.kuard-registration.yaml @@ -15,9 +15,9 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Use a specific env var key for variable2 - path: spec.variable2 - render: + toEnv: name: KUARD_VARIABLE_TWO diff --git a/docs/samples/01.kuard/05.param.value/01.kuard-registration.yaml b/docs/samples/01.kuard/05.param.value/01.kuard-registration.yaml index dc73678..d82cfb0 100644 --- a/docs/samples/01.kuard/05.param.value/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/05.param.value/01.kuard-registration.yaml @@ -15,8 +15,8 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Set a default value for variable2 - path: spec.variable2 - render: + toEnv: defaultValue: new variable2 value diff --git a/docs/samples/01.kuard/06.param.secret/01.kuard-registration.yaml b/docs/samples/01.kuard/06.param.secret/01.kuard-registration.yaml index c47a60f..a4ac233 100644 --- a/docs/samples/01.kuard/06.param.secret/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/06.param.secret/01.kuard-registration.yaml @@ -16,10 +16,10 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Reference a secret - path: spec.refToSecret - render: + toEnv: name: FOO_CREDENTIALS valueFromSecret: name: spec.refToSecret.secretName diff --git a/docs/samples/01.kuard/07.param.configmap/01.kuard-registration.yaml b/docs/samples/01.kuard/07.param.configmap/01.kuard-registration.yaml index c06a791..bf29e48 100644 --- a/docs/samples/01.kuard/07.param.configmap/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/07.param.configmap/01.kuard-registration.yaml @@ -16,10 +16,10 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Reference a ConfigMap - path: spec.refToConfigMap - render: + toEnv: valueFromConfigMap: name: spec.refToConfigMap.configName key: spec.refToConfigMap.configKey diff --git a/docs/samples/01.kuard/08.param.addressable/01.kuard-registration.yaml b/docs/samples/01.kuard/08.param.addressable/01.kuard-registration.yaml index 2e6a1cf..14d4c00 100644 --- a/docs/samples/01.kuard/08.param.addressable/01.kuard-registration.yaml +++ b/docs/samples/01.kuard/08.param.addressable/01.kuard-registration.yaml @@ -16,10 +16,10 @@ spec: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Resolve an address - path: spec.refToAddress - render: + toEnv: name: FOO_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/docs/samples/02.webhooksource/02.webhooksource-registration.yaml b/docs/samples/02.webhooksource/02.webhooksource-registration.yaml index ab53e0d..15dc3ef 100644 --- a/docs/samples/02.webhooksource/02.webhooksource-registration.yaml +++ b/docs/samples/02.webhooksource/02.webhooksource-registration.yaml @@ -28,36 +28,36 @@ spec: - name: K_LOGGING_CONFIG value: "{}" - specToEnvs: + fromSpec: - path: spec.eventType - render: + toEnv: name: WEBHOOK_EVENT_TYPE - path: spec.eventSource - render: + toEnv: name: WEBHOOK_EVENT_SOURCE - path: spec.basicAuthUsername - render: + toEnv: name: WEBHOOK_BASICAUTH_USERNAME - path: spec.basicAuthPassword - render: + toEnv: name: WEBHOOK_BASICAUTH_PASSWORD valueFromSecret: name: spec.basicAuthPassword.valueFromSecret.name key: spec.basicAuthPassword.valueFromSecret.key - path: spec.eventExtensionAttributes.from - render: + toEnv: name: WEBHOOK_EVENT_EXTENSION_ATTRIBUTES_FROM - path: spec.corsAllowOrigin - render: + toEnv: name: WEBHOOK_CORS_ALLOW_ORIGIN - path: spec.sink - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/docs/samples/03.kafkasource/02.kafkasource-registration.yaml b/docs/samples/03.kafkasource/02.kafkasource-registration.yaml index f4534b0..24a72fc 100644 --- a/docs/samples/03.kafkasource/02.kafkasource-registration.yaml +++ b/docs/samples/03.kafkasource/02.kafkasource-registration.yaml @@ -22,69 +22,69 @@ spec: - name: K_LOGGING_CONFIG value: "{}" - specToEnvs: + fromSpec: - path: spec.bootstrapServers - render: + toEnv: name: BOOTSTRAP_SERVERS - path: spec.topic - render: + toEnv: name: TOPIC - path: spec.groupID - render: + toEnv: name: GROUP_ID - path: spec.auth.saslEnable - render: + toEnv: name: SASL_ENABLE - path: spec.auth.securityMechanism - render: + toEnv: name: SECURITY_MECHANISMS - path: spec.auth.tlsEnable - render: + toEnv: name: TLS_ENABLE - path: spec.auth.tls.skipVerify - render: + toEnv: name: SKIP_VERIFY - path: spec.auth.tls.ca - render: + toEnv: name: CA valueFromSecret: name: spec.auth.tls.ca.valueFromSecret.name key: spec.auth.tls.ca.valueFromSecret.key - path: spec.auth.tls.clientCert - render: + toEnv: name: CLIENT_CERT valueFromSecret: name: spec.auth.tls.clientCert.valueFromSecret.name key: spec.auth.tls.clientCert.valueFromSecret.key - path: spec.auth.tls.clientKey - render: + toEnv: name: CLIENT_KEY valueFromSecret: name: spec.auth.tls.clientKey.valueFromSecret.name key: spec.auth.tls.clientKey.valueFromSecret.key - path: spec.auth.username - render: + toEnv: name: USERNAME - path: spec.auth.password - render: + toEnv: name: PASSWORD valueFromSecret: name: spec.auth.password.valueFromSecret.name key: spec.auth.password.valueFromSecret.key - path: spec.sink - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/docs/samples/04.httppollersource/02.httppollersource-registration.yaml b/docs/samples/04.httppollersource/02.httppollersource-registration.yaml index 9be9b10..30b64f4 100644 --- a/docs/samples/04.httppollersource/02.httppollersource-registration.yaml +++ b/docs/samples/04.httppollersource/02.httppollersource-registration.yaml @@ -26,18 +26,18 @@ spec: - name: K_LOGGING_CONFIG value: "{}" - specToEnvs: + fromSpec: - path: spec.eventType - render: + toEnv: name: HTTPPOLLER_EVENT_TYPE - path: spec.eventSource - render: + toEnv: name: HTTPPOLLER_EVENT_SOURCE - path: spec.sink - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/docs/samples/05.httptarget/02.httptarget-registration.yaml b/docs/samples/05.httptarget/02.httptarget-registration.yaml index 3ead017..321f5cd 100644 --- a/docs/samples/05.httptarget/02.httptarget-registration.yaml +++ b/docs/samples/05.httptarget/02.httptarget-registration.yaml @@ -27,62 +27,62 @@ spec: - name: K_LOGGING_CONFIG value: "{}" - specToEnvs: + fromSpec: - path: spec.response.eventType - render: + toEnv: name: HTTP_EVENT_TYPE - path: spec.response.eventSource - render: + toEnv: name: HTTP_EVENT_SOURCE defaultValue: httptarget - path: spec.endpoint - render: + toEnv: name: HTTP_URL - path: spec.method - render: + toEnv: name: HTTP_METHOD - path: spec.skipVerify - render: + toEnv: name: HTTP_SKIP_VERIFY - path: spec.caCertificate - render: + toEnv: name: HTTP_CA_CERTIFICATE - path: spec.basicAuthUsername - render: + toEnv: name: HTTP_BASICAUTH_USERNAME - path: spec.basicAuthPassword - render: + toEnv: name: HTTP_BASICAUTH_PASSWORD valueFromSecret: name: spec.credentials.name key: spec.preferences.key - path: spec.oauthClientID - render: + toEnv: name: HTTP_OAUTH_CLIENT_ID - path: spec.oauthClientSecret - render: + toEnv: name: HTTP_OAUTH_CLIENT_SECRET valueFromSecret: name: spec.credentials.name key: spec.preferences.key - path: spec.oauthTokenURL - render: + toEnv: name: HTTP_OAUTH_TOKEN_URL - path: spec.oauthScopes - render: + toEnv: name: HTTP_OAUTH_SCOPE - path: spec.headers - render: + toEnv: name: HTTP_HEADERS diff --git a/docs/samples/06.kafkatarget/02.kafkatarget-registration.yaml b/docs/samples/06.kafkatarget/02.kafkatarget-registration.yaml index 373e989..7a30b93 100644 --- a/docs/samples/06.kafkatarget/02.kafkatarget-registration.yaml +++ b/docs/samples/06.kafkatarget/02.kafkatarget-registration.yaml @@ -27,70 +27,70 @@ spec: - name: K_LOGGING_CONFIG value: "{}" - specToEnvs: + fromSpec: - path: spec.bootstrapServers - render: + toEnv: name: BOOTSTRAP_SERVERS - path: spec.topic - render: + toEnv: name: TOPIC - path: spec.topicReplicationFactor - render: + toEnv: name: TOPIC_REPLICATION_FACTOR - path: spec.topicPartitions - render: + toEnv: name: TOPIC_PARTITIONS - path: spec.discardCloudEventContext - render: + toEnv: name: DISCARD_CE_CONTEXT - path: spec.auth.saslEnable - render: + toEnv: name: SASL_ENABLE - path: spec.auth.securityMechanism - render: + toEnv: name: SECURITY_MECHANISMS - path: spec.auth.tlsEnable - render: + toEnv: name: TLS_ENABLE - path: spec.auth.tls.skipVerify - render: + toEnv: name: SKIP_VERIFY - path: spec.auth.tls.ca - render: + toEnv: name: CA valueFromSecret: name: spec.auth.tls.ca.valueFromSecret.name key: spec.auth.tls.ca.valueFromSecret.key - path: spec.auth.tls.clientCert - render: + toEnv: name: CLIENT_CERT valueFromSecret: name: spec.auth.tls.clientCert.valueFromSecret.name key: spec.auth.tls.clientCert.valueFromSecret.key - path: spec.auth.tls.clientKey - render: + toEnv: name: CLIENT_KEY valueFromSecret: name: spec.auth.tls.clientKey.valueFromSecret.name key: spec.auth.tls.clientKey.valueFromSecret.key - path: spec.auth.username - render: + toEnv: name: USERNAME - path: spec.auth.password - render: + toEnv: name: PASSWORD valueFromSecret: name: spec.auth.password.valueFromSecret.name diff --git a/docs/triggermesh/README.md b/docs/triggermesh/README.md index 9e0b3b6..c12342c 100644 --- a/docs/triggermesh/README.md +++ b/docs/triggermesh/README.md @@ -118,36 +118,36 @@ Given the CRD element to environment variables table above, add this workload pa ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.eventType - render: + toEnv: name: WEBHOOK_EVENT_TYPE - path: spec.eventSource - render: + toEnv: name: WEBHOOK_EVENT_SOURCE - path: spec.basicAuthUsername - render: + toEnv: name: WEBHOOK_BASICAUTH_USERNAME - path: spec.eventExtensionAttributes.from - render: + toEnv: name: WEBHOOK_EVENT_EXTENSION_ATTRIBUTES_FROM - path: spec.corsAllowOrigin - render: + toEnv: name: WEBHOOK_CORS_ALLOW_ORIGIN - path: spec.basicAuthPassword - render: + toEnv: name: WEBHOOK_BASICAUTH_PASSWORD valueFromSecret: name: spec.basicAuthPassword.valueFromSecret.name key: spec.basicAuthPassword.valueFromSecret.key - path: spec.sink - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress @@ -207,69 +207,69 @@ Given the CRD element to environment variables table above, add this workload pa ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.bootstrapServers - render: + toEnv: name: BOOTSTRAP_SERVERS - path: spec.topic - render: + toEnv: name: TOPIC - path: spec.groupID - render: + toEnv: name: GROUP_ID - path: spec.auth.saslEnable - render: + toEnv: name: SASL_ENABLE - path: spec.auth.securityMechanism - render: + toEnv: name: SECURITY_MECHANISMS - path: spec.auth.tlsEnable - render: + toEnv: name: TLS_ENABLE - path: spec.auth.tls.skipVerify - render: + toEnv: name: SKIP_VERIFY - path: spec.auth.tls.ca - render: + toEnv: name: CA valueFromSecret: name: spec.auth.tls.ca.valueFromSecret.name key: spec.auth.tls.ca.valueFromSecret.key - path: spec.auth.tls.clientCert - render: + toEnv: name: CLIENT_CERT valueFromSecret: name: spec.auth.tls.clientCert.valueFromSecret.name key: spec.auth.tls.clientCert.valueFromSecret.key - path: spec.auth.tls.clientKey - render: + toEnv: name: CLIENT_KEY valueFromSecret: name: spec.auth.tls.clientKey.valueFromSecret.name key: spec.auth.tls.clientKey.valueFromSecret.key - path: spec.auth.username - render: + toEnv: name: USERNAME - path: spec.auth.password - render: + toEnv: name: PASSWORD valueFromSecret: name: spec.auth.password.valueFromSecret.name key: spec.auth.password.valueFromSecret.key - path: spec.sink - render: + toEnv: name: K_SINK valueFromBuiltInFunc: name: resolveAddress @@ -333,64 +333,64 @@ Given the CRD element to environment variables table above, add this workload pa ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.response.eventType - render: + toEnv: name: HTTP_EVENT_TYPE - path: spec.response.eventSource - render: + toEnv: name: HTTP_EVENT_SOURCE defaultValue: httptarget - path: spec.endpoint - render: + toEnv: name: HTTP_URL - path: spec.method - render: + toEnv: name: HTTP_METHOD - path: spec.skipVerify - render: + toEnv: name: HTTP_SKIP_VERIFY - path: spec.caCertificate - render: + toEnv: name: HTTP_CA_CERTIFICATE - path: spec.basicAuthUsername - render: + toEnv: name: HTTP_BASICAUTH_USERNAME - path: spec.basicAuthPassword - render: + toEnv: name: HTTP_BASICAUTH_PASSWORD valueFromSecret: name: spec.credentials.name key: spec.preferences.key - path: spec.oauthClientID - render: + toEnv: name: HTTP_OAUTH_CLIENT_ID - path: spec.oauthClientSecret - render: + toEnv: name: HTTP_OAUTH_CLIENT_SECRET valueFromSecret: name: spec.credentials.name key: spec.preferences.key - path: spec.oauthTokenURL - render: + toEnv: name: HTTP_OAUTH_TOKEN_URL - path: spec.oauthScopes - render: + toEnv: name: HTTP_OAUTH_SCOPE - path: spec.headers - render: + toEnv: name: HTTP_HEADERS ``` @@ -452,70 +452,70 @@ Given the CRD element to environment variables table above, add this workload pa ```yaml parameterConfiguration: - specToEnvs: + fromSpec: - path: spec.bootstrapServers - render: + toEnv: name: BOOTSTRAP_SERVERS - path: spec.topic - render: + toEnv: name: TOPIC - path: spec.topicReplicationFactor - render: + toEnv: name: TOPIC_REPLICATION_FACTOR - path: spec.topicPartitions - render: + toEnv: name: TOPIC_PARTITIONS - path: spec.discardCloudEventContext - render: + toEnv: name: DISCARD_CE_CONTEXT - path: spec.auth.saslEnable - render: + toEnv: name: SASL_ENABLE - path: spec.auth.securityMechanism - render: + toEnv: name: SECURITY_MECHANISMS - path: spec.auth.tlsEnable - render: + toEnv: name: TLS_ENABLE - path: spec.auth.tls.skipVerify - render: + toEnv: name: SKIP_VERIFY - path: spec.auth.tls.ca - render: + toEnv: name: CA valueFromSecret: name: spec.auth.tls.ca.valueFromSecret.name key: spec.auth.tls.ca.valueFromSecret.key - path: spec.auth.tls.clientCert - render: + toEnv: name: CLIENT_CERT valueFromSecret: name: spec.auth.tls.clientCert.valueFromSecret.name key: spec.auth.tls.clientCert.valueFromSecret.key - path: spec.auth.tls.clientKey - render: + toEnv: name: CLIENT_KEY valueFromSecret: name: spec.auth.tls.clientKey.valueFromSecret.name key: spec.auth.tls.clientKey.valueFromSecret.key - path: spec.auth.username - render: + toEnv: name: USERNAME - path: spec.auth.password - render: + toEnv: name: PASSWORD valueFromSecret: name: spec.auth.password.valueFromSecret.name diff --git a/docs/tutorial.md b/docs/tutorial.md index 1e2b673..89cda57 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -316,15 +316,14 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Skip variable2 from generating a parameter for the workload - path: spec.variable2 - render: - skip: true + skip: true ``` -The `spec.workload.parameterConfiguration.specToEnvs[].render.skip` boolean indicates whether the environment variable for the element should be generated. +The `spec.workload.parameterConfiguration.fromSpec[].skip` boolean indicates whether the environment variable for the element should be generated. Create the registration: @@ -377,7 +376,7 @@ kubectl delete crdregistration kuard ### Parameter Renaming -Most often expected environment variables at the container do not match Scoby's automatic rendering. All generated environment variables can be renamed using `spec.workload.parameterConfiguration.specToEnvs[].render.key`. +Most often expected environment variables at the container do not match Scoby's automatic rendering. All generated environment variables can be renamed using `spec.workload.parameterConfiguration.fromSpec[].toEnv.name`. ```yaml apiVersion: scoby.triggermesh.io/v1alpha1 @@ -396,10 +395,10 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Rename variable2 - path: spec.variable2 - render: + toEnv: name: KUARD_VARIABLE_TWO ``` @@ -458,7 +457,7 @@ kubectl delete crdregistration kuard ### Parameter Default Value -The value for an environment variable can be set to a default value using `spec.workload.parameterConfiguration.specToEnvs[].render.defaultValue`. +The value for an environment variable can be set to a default value using `spec.workload.parameterConfiguration.fromSpec[].toEnv.defaultValue`. ```yaml apiVersion: scoby.triggermesh.io/v1alpha1 @@ -477,10 +476,10 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Override variable2 value - path: spec.variable2 - render: + toEnv: defaultValue: new variable2 value ``` @@ -539,7 +538,7 @@ kubectl delete crdregistration kuard ### Parameter Value From Secret -The value for an environment variable can reference a Secret through the `spec.workload.parameterConfiguration.specToEnvs[].render.valueFromSecret` customization option, that needs the `name` and `key` subelements to be set. In this example we will also be setting the variable name. +The value for an environment variable can reference a Secret through the `spec.workload.parameterConfiguration.fromSpec[].toEnv.valueFromSecret` customization option, that needs the `name` and `key` subelements to be set. In this example we will also be setting the variable name. ```yaml apiVersion: scoby.triggermesh.io/v1alpha1 @@ -558,10 +557,10 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Reference a secret - path: spec.refToSecret - render: + toEnv: name: FOO_CREDENTIALS valueFromSecret: name: spec.refToSecret.secretName @@ -634,7 +633,7 @@ kubectl delete secret kuard-secret ### Parameter Value From ConfigMap -The value for an environment variable can reference a ConfigMap through the `spec.workload.parameterConfiguration.specToEnvs[].render.valueFromConfigMap` customization option, that needs the `name` and `key` subelements to be set. +The value for an environment variable can reference a ConfigMap through the `spec.workload.parameterConfiguration.fromSpec[].toEnv.valueFromConfigMap` customization option, that needs the `name` and `key` subelements to be set. ```yaml apiVersion: scoby.triggermesh.io/v1alpha1 @@ -653,10 +652,10 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Reference a ConfigMap - path: spec.refToConfigMap - render: + toEnv: valueFromConfigMap: name: spec.refToConfigMap.configName key: spec.refToConfigMap.configKey @@ -742,7 +741,7 @@ A destination duck type informs either an URI, a Kubernetes service, or a Kubern uri: ``` -Use the built-in function `spec.workload.parameterConfiguration.specToEnvs[].valueFromBuiltInFunc.resolveAddress` on the element that contains the Destination type. As an added feature this example also updates an status element with the resolved address. +Use the built-in function `spec.workload.parameterConfiguration.fromSpec[].toEnv.valueFromBuiltInFunc.resolveAddress` on the element that contains the Destination type. As an added feature this example also updates an status element with the resolved address. ```yaml apiVersion: scoby.triggermesh.io/v1alpha1 @@ -761,10 +760,10 @@ spec: fromImage: repo: gcr.io/kuar-demo/kuard-amd64:blue parameterConfiguration: - specToEnvs: + fromSpec: # Resolve an address - path: spec.refToAddress - render: + toEnv: name: FOO_SINK valueFromBuiltInFunc: name: resolveAddress diff --git a/pkg/apis/common/v1alpha1/workload_types.go b/pkg/apis/common/v1alpha1/workload_types.go index 53c83ac..8d2d8ba 100644 --- a/pkg/apis/common/v1alpha1/workload_types.go +++ b/pkg/apis/common/v1alpha1/workload_types.go @@ -37,15 +37,20 @@ type ParameterConfiguration struct { // +optional Global *GlobalParameterConfiguration `json:"global,omitempty"` - // AddEnvs contains configurations for parameters to be added to the workload + // AddEnvs contains instructions to create environment variables at the workload // not derived from the user instance. // +optional AddEnvs []corev1.EnvVar `json:"addEnvs,omitempty"` - // SpecToEnvs contains instructions to modify parameters generation from + // FromSpec contains instructions to generate workload items from // the instance's spec. // +optional - SpecToEnvs []SpecToEnvParameterConfiguration `json:"specToEnvs,omitempty"` + FromSpec []FromSpecConfiguration `json:"fromSpec,omitempty"` + + // // SpecToVolumes contains instructions to generate volumes and mounts from + // // the instance's spec. + // // +optional + // SpecToVolumes []SpecToVolumeParameterConfiguration `json:"specToVolumes,omitempty"` } // GlobalParameterConfiguration defines configuration to be applied to all generated parameters. @@ -63,20 +68,83 @@ func (gpc *GlobalParameterConfiguration) GetDefaultPrefix() string { return *gpc.DefaultPrefix } -// SpecToEnvsParameterConfiguration contains instructions to modify parameters generation for +// FromSpecConfiguration contains instructions to generate rendering from // the controlled instance spec. -type SpecToEnvParameterConfiguration struct { +type FromSpecConfiguration struct { // JSON simplified path for the parameter. Path string `json:"path"` + // Skip sets whether the object should skip rendering + // as a workload item. + // +optional + Skip *bool `json:"skip,omitempty"` + + // Render options for the parameter generation. + // +optional + ToEnv *SpecToEnvConfiguration `json:"toEnv,omitempty"` + // Render options for the parameter generation. // +optional - Render *ParameterRenderConfiguration `json:"render,omitempty"` + ToVolume *SpecToVolumeConfiguration `json:"toVolume,omitempty"` +} + +func (fsc *FromSpecConfiguration) IsRenderer() bool { + return fsc != nil && (fsc.ToEnv != nil || fsc.ToVolume == nil) +} + +func (fsc *FromSpecConfiguration) IsValueOverriden() bool { + if fsc == nil || (!fsc.ToEnv.IsValueOverriden() && !fsc.ToVolume.IsValueOverriden()) { + return false + } + return true +} + +// IsSkip returns if the parameter rendering should be skipped. +func (fsc *FromSpecConfiguration) IsSkip() bool { + if fsc == nil || fsc.Skip == nil { + return false + } + return *fsc.Skip +} + +// // SpecToVolumeParameterConfiguration contains instructions to generate volumes +// // and volume mounts from the controlled instance spec. +// type SpecToVolumeParameterConfiguration struct { +// // JSON simplified path for the parameter. +// Path string `json:"path"` + +// Render *SpecToVolumeRenderConfiguration `json:"render,omitempty"` +// } + +// SpecToVolumeRenderConfiguration are the customization options for an specific +// parameter generation. +type SpecToVolumeConfiguration struct { + // Name for the volume. + Name string `json:"name,omitempty"` + + // Path where the file will be mounted. + MountPath string `json:"mountPath,omitempty"` + + // ValueFromConfigMap is a reference to a ConfigMap. + // +optional + ValueFromConfigMap *ObjectReference `json:"valueFromConfigMap,omitempty"` + + // ValueFromSecret is a reference to a Secret. + // +optional + ValueFromSecret *ObjectReference `json:"valueFromSecret,omitempty"` } -// ParameterRenderConfiguration are the customization options for an specific +func (svc *SpecToVolumeConfiguration) IsValueOverriden() bool { + if svc == nil || (svc.ValueFromConfigMap == nil && + svc.ValueFromSecret == nil) { + return false + } + return true +} + +// SpecToEnvRenderConfiguration are the customization options for an specific // parameter generation. -type ParameterRenderConfiguration struct { +type SpecToEnvConfiguration struct { // Name is the name of the parameter to be created. // +optional Name *string `json:"name,omitempty"` @@ -98,17 +166,22 @@ type ParameterRenderConfiguration struct { // be rendered acording to the chosen built-in function. // +optional ValueFromBuiltInFunc *BuiltInfunction `json:"valueFromBuiltInFunc,omitempty"` +} - // Skip sets whether the object should skip rendering - // as a workload parameter. - // +optional - Skip *bool `json:"skip,omitempty"` +// GetName returns the key defined at the parameter rendering +// configuration. +// Returns an empty string if not defined. +func (sec *SpecToEnvConfiguration) GetName() string { + if sec == nil || sec.Name == nil { + return "" + } + return *sec.Name } -func (prc *ParameterRenderConfiguration) IsValueOverriden() bool { - if prc == nil || (prc.ValueFromConfigMap == nil && - prc.ValueFromSecret == nil && - prc.ValueFromBuiltInFunc == nil) { +func (sec *SpecToEnvConfiguration) IsValueOverriden() bool { + if sec == nil || (sec.ValueFromConfigMap == nil && + sec.ValueFromSecret == nil && + sec.ValueFromBuiltInFunc == nil) { return false } return true @@ -131,24 +204,6 @@ type BuiltInfunction struct { Args []string `json:"args,omitempty"` } -// IsSkip returns if the parameter rendering should be skipped. -func (prc *ParameterRenderConfiguration) IsSkip() bool { - if prc == nil || prc.Skip == nil { - return false - } - return *prc.Skip -} - -// GetName returns the key defined at the parameter rendering -// configuration. -// Returns an empty string if not defined. -func (prc *ParameterRenderConfiguration) GetName() string { - if prc == nil || prc.Name == nil { - return "" - } - return *prc.Name -} - // StatusConfiguration contains instructions to modify status generation for // the controlled instance. type StatusConfiguration struct { diff --git a/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go index 6379c03..ea7e310 100644 --- a/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/common/v1alpha1/zz_generated.deepcopy.go @@ -170,6 +170,36 @@ func (in *FormFactor) DeepCopy() *FormFactor { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FromSpecConfiguration) DeepCopyInto(out *FromSpecConfiguration) { + *out = *in + if in.Skip != nil { + in, out := &in.Skip, &out.Skip + *out = new(bool) + **out = **in + } + if in.ToEnv != nil { + in, out := &in.ToEnv, &out.ToEnv + *out = new(SpecToEnvConfiguration) + (*in).DeepCopyInto(*out) + } + if in.ToVolume != nil { + in, out := &in.ToVolume, &out.ToVolume + *out = new(SpecToVolumeConfiguration) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FromSpecConfiguration. +func (in *FromSpecConfiguration) DeepCopy() *FromSpecConfiguration { + if in == nil { + return nil + } + out := new(FromSpecConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GlobalParameterConfiguration) DeepCopyInto(out *GlobalParameterConfiguration) { *out = *in @@ -295,9 +325,9 @@ func (in *ParameterConfiguration) DeepCopyInto(out *ParameterConfiguration) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.SpecToEnvs != nil { - in, out := &in.SpecToEnvs, &out.SpecToEnvs - *out = make([]SpecToEnvParameterConfiguration, len(*in)) + if in.FromSpec != nil { + in, out := &in.FromSpec, &out.FromSpec + *out = make([]FromSpecConfiguration, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -315,7 +345,37 @@ func (in *ParameterConfiguration) DeepCopy() *ParameterConfiguration { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ParameterRenderConfiguration) DeepCopyInto(out *ParameterRenderConfiguration) { +func (in *Reference) DeepCopyInto(out *Reference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Reference. +func (in *Reference) DeepCopy() *Reference { + if in == nil { + return nil + } + out := new(Reference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistrationFromImage) DeepCopyInto(out *RegistrationFromImage) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrationFromImage. +func (in *RegistrationFromImage) DeepCopy() *RegistrationFromImage { + if in == nil { + return nil + } + out := new(RegistrationFromImage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SpecToEnvConfiguration) DeepCopyInto(out *SpecToEnvConfiguration) { *out = *in if in.Name != nil { in, out := &in.Name, &out.Name @@ -342,69 +402,39 @@ func (in *ParameterRenderConfiguration) DeepCopyInto(out *ParameterRenderConfigu *out = new(BuiltInfunction) (*in).DeepCopyInto(*out) } - if in.Skip != nil { - in, out := &in.Skip, &out.Skip - *out = new(bool) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParameterRenderConfiguration. -func (in *ParameterRenderConfiguration) DeepCopy() *ParameterRenderConfiguration { - if in == nil { - return nil - } - out := new(ParameterRenderConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Reference) DeepCopyInto(out *Reference) { - *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Reference. -func (in *Reference) DeepCopy() *Reference { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecToEnvConfiguration. +func (in *SpecToEnvConfiguration) DeepCopy() *SpecToEnvConfiguration { if in == nil { return nil } - out := new(Reference) + out := new(SpecToEnvConfiguration) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RegistrationFromImage) DeepCopyInto(out *RegistrationFromImage) { +func (in *SpecToVolumeConfiguration) DeepCopyInto(out *SpecToVolumeConfiguration) { *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrationFromImage. -func (in *RegistrationFromImage) DeepCopy() *RegistrationFromImage { - if in == nil { - return nil + if in.ValueFromConfigMap != nil { + in, out := &in.ValueFromConfigMap, &out.ValueFromConfigMap + *out = new(ObjectReference) + **out = **in } - out := new(RegistrationFromImage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SpecToEnvParameterConfiguration) DeepCopyInto(out *SpecToEnvParameterConfiguration) { - *out = *in - if in.Render != nil { - in, out := &in.Render, &out.Render - *out = new(ParameterRenderConfiguration) - (*in).DeepCopyInto(*out) + if in.ValueFromSecret != nil { + in, out := &in.ValueFromSecret, &out.ValueFromSecret + *out = new(ObjectReference) + **out = **in } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecToEnvParameterConfiguration. -func (in *SpecToEnvParameterConfiguration) DeepCopy() *SpecToEnvParameterConfiguration { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecToVolumeConfiguration. +func (in *SpecToVolumeConfiguration) DeepCopy() *SpecToVolumeConfiguration { if in == nil { return nil } - out := new(SpecToEnvParameterConfiguration) + out := new(SpecToVolumeConfiguration) in.DeepCopyInto(out) return out } diff --git a/pkg/component/reconciler/base/renderer/renderer.go b/pkg/component/reconciler/base/renderer/renderer.go index 7fe64ab..e1349f7 100644 --- a/pkg/component/reconciler/base/renderer/renderer.go +++ b/pkg/component/reconciler/base/renderer/renderer.go @@ -43,23 +43,37 @@ func NewRenderer(wkl *commonv1alpha1.Workload, resolver resolver.Resolver) recon copy(r.addEnvs, pcfg.AddEnvs) } - // Curate object fields customization, index them by their - // relaxed JSONPath. - if pcfg.SpecToEnvs != nil && len(pcfg.SpecToEnvs) != 0 { - r.specToEnvs = make(map[string]commonv1alpha1.SpecToEnvParameterConfiguration, len(pcfg.SpecToEnvs)) - for _, c := range pcfg.SpecToEnvs { - r.specToEnvs[strings.TrimLeft(c.Path, "$.")] = c - - // default values are set - if c.Render.DefaultValue != nil { + // Curate object fields, index them by their relaxed JSONPath. + + if pcfg.FromSpec != nil && len(pcfg.FromSpec) != 0 { + r.fromSpec = make(map[string]commonv1alpha1.FromSpecConfiguration, len(pcfg.FromSpec)) + for _, c := range pcfg.FromSpec { + r.fromSpec[strings.TrimLeft(c.Path, "$.")] = c + + if c.ToEnv == nil { + continue + } + + // Default values for environment variables are noted. We don't store + // the string but the whole object to be able to improve this feature and + // have default ConfigMap and Secrets. + if c.ToEnv.DefaultValue != nil { if r.defaultEnvs == nil { - r.defaultEnvs = make(map[string]*commonv1alpha1.ParameterRenderConfiguration) + r.defaultEnvs = make(map[string]*commonv1alpha1.SpecToEnvConfiguration) } - r.defaultEnvs[c.Path] = c.Render + r.defaultEnvs[c.Path] = c.ToEnv } } } + + // if pcfg.SpecToVolumes != nil && len(pcfg.SpecToVolumes) != 0 { + // r.specToVolumes = make(map[string]commonv1alpha1.SpecToVolumeParameterConfiguration, len(pcfg.SpecToVolumes)) + // for _, c := range pcfg.SpecToVolumes { + // r.specToVolumes[strings.TrimLeft(c.Path, "$.")] = c + // } + // } + } if wkl.StatusConfiguration != nil { @@ -77,8 +91,8 @@ func NewRenderer(wkl *commonv1alpha1.Workload, resolver resolver.Resolver) recon type renderer struct { resolver resolver.Resolver - // JSONPath indexed configuration parameters. - specToEnvs map[string]commonv1alpha1.SpecToEnvParameterConfiguration + // JSONPath indexed spec to envs. + fromSpec map[string]commonv1alpha1.FromSpecConfiguration // Global options to be applied while transforming object fields // into workload parameters. @@ -90,7 +104,8 @@ type renderer struct { // Default values that should be set if either the environment // variable does not exists, or it exists with an empty value. - defaultEnvs map[string]*commonv1alpha1.ParameterRenderConfiguration + defaultEnvs map[string]*commonv1alpha1.SpecToEnvConfiguration + // defaultEnvs map[string]*commonv1alpha1.SpecToEnvRenderConfiguration // Set of rules that add or fill elements at the object status. addStatus []commonv1alpha1.StatusAddElement @@ -203,15 +218,11 @@ func (r *renderer) renderParsedFields(ctx context.Context, obj reconciler.Object } pf := pfs[k] - // Retrieve custom render configuration for the field. - var renderConfig *commonv1alpha1.ParameterRenderConfiguration - if specToEnv, ok := r.specToEnvs[pf.toJSONPath()]; ok && specToEnv.Render != nil { - renderConfig = specToEnv.Render - } - // Create environment variable for this field. - ev := &corev1.EnvVar{ - Name: strings.ToUpper(strings.Join(pf.branch[1:], "_")), + // Retrieve custom render configuration for the field. + var fromSpec *commonv1alpha1.FromSpecConfiguration + if fs, ok := r.fromSpec[pf.toJSONPath()]; ok && fs.IsRenderer() { + fromSpec = &fs } // Check soon if the value needs to be skipped, move over to the next. @@ -219,7 +230,7 @@ func (r *renderer) renderParsedFields(ctx context.Context, obj reconciler.Object // Note: maybe in the future we will find skip conbined with a function // that would need to generate a result, probably because some other // registration configuration references it. - if renderConfig.IsSkip() { + if fromSpec.IsSkip() { continue } @@ -227,187 +238,225 @@ func (r *renderer) renderParsedFields(ctx context.Context, obj reconciler.Object // to allow them to be used for caluculations. // When customizations are defined they will need to parse to produce // an environment variable - if pf.intermediateNode && renderConfig == nil { + if pf.intermediateNode && !fromSpec.IsRenderer() { continue } - // If name is overriden by customization set it, if not - // apply global prefix. - if key := renderConfig.GetName(); key != "" { - ev.Name = key - } else if prefix := r.global.GetDefaultPrefix(); prefix != "" { - ev.Name = prefix + ev.Name + // TODO move somewhere up + // If this is no intermediate node and there is no instructions, perform + // default rendering + if fromSpec == nil { + ev := &corev1.EnvVar{ + Name: strings.ToUpper(strings.Join(pf.branch[1:], "_")), + } + + if prefix := r.global.GetDefaultPrefix(); prefix != "" { + ev.Name = prefix + ev.Name + } } - switch { - case !renderConfig.IsValueOverriden(): - // By default process the value depending on the type. - switch { - case pf.array != nil: - // primitive indicates that all elements in an array are the - // same primitive. We pre-create the primitive array to avoid - // a second loop. - primitive := true - primitiveArr := []string{} - - // preserve order for arrays by iterating using the map key, - // which contains the ornidal - paths := make([]string, 0, len(pf.array)) - for path := range pf.array { - paths = append(paths, path) - } - sort.Strings(paths) + // TODO maybe extract to function - for _, p := range paths { - switch v := pf.array[p].value.(type) { - case map[string]interface{}: - primitive = false - default: - primitiveArr = append(primitiveArr, fmt.Sprintf("%v", v)) + if fromSpec != nil && fromSpec.ToVolume != nil { + // TODO maybe extract to function + } else { + // TODO Ugly hack due to previous code, restructure this + var specToEnvConfig *commonv1alpha1.SpecToEnvConfiguration + if fromSpec != nil { + specToEnvConfig = fromSpec.ToEnv + } + + // if specToEnvConfig := fromSpec.ToEnv; specToEnvConfig != nil { + + // Create environment variable for this field. + ev := &corev1.EnvVar{ + Name: strings.ToUpper(strings.Join(pf.branch[1:], "_")), + } + + // If name is overriden by customization set it, if not + // apply global prefix. + if key := specToEnvConfig.GetName(); key != "" { + ev.Name = key + } else if prefix := r.global.GetDefaultPrefix(); prefix != "" { + ev.Name = prefix + ev.Name + } + + switch { + case !specToEnvConfig.IsValueOverriden(): + // By default process the value depending on the type. + switch { + case pf.array != nil: + // primitive indicates that all elements in an array are the + // same primitive. We pre-create the primitive array to avoid + // a second loop. + primitive := true + primitiveArr := []string{} + + // preserve order for arrays by iterating using the map key, + // which contains the ornidal + paths := make([]string, 0, len(pf.array)) + for path := range pf.array { + paths = append(paths, path) + } + sort.Strings(paths) + + for _, p := range paths { + switch v := pf.array[p].value.(type) { + case map[string]interface{}: + primitive = false + default: + primitiveArr = append(primitiveArr, fmt.Sprintf("%v", v)) + } } - } - // If the array contains primitives, return a comma separated string - if primitive { - ev.Value = strings.Join(primitiveArr, ",") - } else { - // If the array contains complex structures, return a JSON serialization - vb, err := json.Marshal(pf.value) - if err != nil { - return err + // If the array contains primitives, return a comma separated string + if primitive { + ev.Value = strings.Join(primitiveArr, ",") + } else { + // If the array contains complex structures, return a JSON serialization + vb, err := json.Marshal(pf.value) + if err != nil { + return err + } + ev.Value = string(vb) } - ev.Value = string(vb) - } - case pf.value != nil: - // Primitive values - switch v := pf.value.(type) { - case string: - ev.Value = v + case pf.value != nil: + // Primitive values + switch v := pf.value.(type) { + case string: + ev.Value = v - default: - vb, err := json.Marshal(v) - if err != nil { - return err - } - ev.Value = string(vb) + default: + vb, err := json.Marshal(v) + if err != nil { + return err + } + ev.Value = string(vb) + } + default: + // TODO this is not expected } - default: - // TODO this is not expected - } - case renderConfig.DefaultValue != nil: - ev.Value = *renderConfig.DefaultValue + case specToEnvConfig.DefaultValue != nil: + ev.Value = *specToEnvConfig.DefaultValue - // If there are further internal elements, avoid - // parsing them. - avoidFieldPrefixes = append(avoidFieldPrefixes, k) + // If there are further internal elements, avoid + // parsing them. + avoidFieldPrefixes = append(avoidFieldPrefixes, k) - case renderConfig.ValueFromConfigMap != nil: - refName, ok := pfs[renderConfig.ValueFromConfigMap.Name] - if !ok { - return fmt.Errorf("could not find reference to ConfigMap at %q", renderConfig.ValueFromConfigMap.Name) - } - name, ok := refName.value.(string) - if !ok { - return fmt.Errorf("reference to ConfigMap at %q is not a string: %v", renderConfig.ValueFromConfigMap.Name, refName) - } - refKey, ok := pfs[renderConfig.ValueFromConfigMap.Key] - if !ok { - return fmt.Errorf("could not find reference to ConfigMap key at %q", renderConfig.ValueFromConfigMap.Name) - } - key, ok := refKey.value.(string) - if !ok { - return fmt.Errorf("reference to ConfigMap key at %q is not a string: %v", renderConfig.ValueFromConfigMap.Name, refKey) - } + case specToEnvConfig.ValueFromConfigMap != nil: + refName, ok := pfs[specToEnvConfig.ValueFromConfigMap.Name] + if !ok { + return fmt.Errorf("could not find reference to ConfigMap at %q", specToEnvConfig.ValueFromConfigMap.Name) + } + name, ok := refName.value.(string) + if !ok { + return fmt.Errorf("reference to ConfigMap at %q is not a string: %v", specToEnvConfig.ValueFromConfigMap.Name, refName) + } + refKey, ok := pfs[specToEnvConfig.ValueFromConfigMap.Key] + if !ok { + return fmt.Errorf("could not find reference to ConfigMap key at %q", specToEnvConfig.ValueFromConfigMap.Name) + } + key, ok := refKey.value.(string) + if !ok { + return fmt.Errorf("reference to ConfigMap key at %q is not a string: %v", specToEnvConfig.ValueFromConfigMap.Name, refKey) + } - ev.ValueFrom = &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: name, + ev.ValueFrom = &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: name, + }, + Key: key, }, - Key: key, - }, - } + } - // If there are further internal elements, avoid - // parsing them. - avoidFieldPrefixes = append(avoidFieldPrefixes, k) + // If there are further internal elements, avoid + // parsing them. + avoidFieldPrefixes = append(avoidFieldPrefixes, k) - case renderConfig.ValueFromSecret != nil: - refName, ok := pfs[renderConfig.ValueFromSecret.Name] - if !ok { - return fmt.Errorf("could not find reference to Secret at %q", renderConfig.ValueFromSecret.Name) - } - name, ok := refName.value.(string) - if !ok { - return fmt.Errorf("reference to Secret at %q is not a string: %v", renderConfig.ValueFromSecret.Name, refName) - } - refKey, ok := pfs[renderConfig.ValueFromSecret.Key] - if !ok { - return fmt.Errorf("could not find reference to Secret key at %q", renderConfig.ValueFromSecret.Name) - } - key, ok := refKey.value.(string) - if !ok { - return fmt.Errorf("reference to Secret key at %q is not a string: %v", renderConfig.ValueFromSecret.Name, refKey) - } + case specToEnvConfig.ValueFromSecret != nil: + refName, ok := pfs[specToEnvConfig.ValueFromSecret.Name] + if !ok { + return fmt.Errorf("could not find reference to Secret at %q", specToEnvConfig.ValueFromSecret.Name) + } + name, ok := refName.value.(string) + if !ok { + return fmt.Errorf("reference to Secret at %q is not a string: %v", specToEnvConfig.ValueFromSecret.Name, refName) + } + refKey, ok := pfs[specToEnvConfig.ValueFromSecret.Key] + if !ok { + return fmt.Errorf("could not find reference to Secret key at %q", specToEnvConfig.ValueFromSecret.Name) + } + key, ok := refKey.value.(string) + if !ok { + return fmt.Errorf("reference to Secret key at %q is not a string: %v", specToEnvConfig.ValueFromSecret.Name, refKey) + } - ev.ValueFrom = &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: name, + ev.ValueFrom = &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: name, + }, + Key: key, }, - Key: key, - }, - } - - // If there are further internal elements, avoid - // parsing them. - avoidFieldPrefixes = append(avoidFieldPrefixes, k) - - case renderConfig.ValueFromBuiltInFunc != nil: - switch renderConfig.ValueFromBuiltInFunc.Name { - case "resolveAddress": - // element: - // ref: - // apiVersion: - // group: - // kind: - // name: - // uri: - - addressable, ok := pf.value.(map[string]interface{}) - if !ok { - return fmt.Errorf("unexpected addressable structure at %q: %+v", k, pf.value) } - if uri, ok := addressable["uri"]; ok { - value, ok := uri.(string) + // If there are further internal elements, avoid + // parsing them. + avoidFieldPrefixes = append(avoidFieldPrefixes, k) + + case specToEnvConfig.ValueFromBuiltInFunc != nil: + switch specToEnvConfig.ValueFromBuiltInFunc.Name { + case "resolveAddress": + // element: + // ref: + // apiVersion: + // group: + // kind: + // name: + // uri: + + addressable, ok := pf.value.(map[string]interface{}) if !ok { - return fmt.Errorf("uri value at %q is not a string", k) + return fmt.Errorf("unexpected addressable structure at %q: %+v", k, pf.value) } - ev.Value = value - } else if ref, ok := addressable["ref"]; ok { - uri, err := r.resolveAddress(ctx, obj.GetNamespace(), k, ref) - if err != nil { - return err + + if uri, ok := addressable["uri"]; ok { + value, ok := uri.(string) + if !ok { + return fmt.Errorf("uri value at %q is not a string", k) + } + ev.Value = value + } else if ref, ok := addressable["ref"]; ok { + uri, err := r.resolveAddress(ctx, obj.GetNamespace(), k, ref) + if err != nil { + return err + } + ev.Value = uri } - ev.Value = uri } + + // If there are further internal elements, avoid + // parsing them. + avoidFieldPrefixes = append(avoidFieldPrefixes, k) } - // If there are further internal elements, avoid - // parsing them. - avoidFieldPrefixes = append(avoidFieldPrefixes, k) - } + obj.AddEnvVar(k, ev) - obj.AddEnvVar(k, ev) + // } + } } return nil } +// func (r *renderer) defaultFieldRender(ctx context.Context, obj reconciler.Object, pfs map[string]parsedField) error { + +// } + // parsedField is a representation of a user instance element // containing the location, value, and in case of arrays the // parsedFields under it. diff --git a/pkg/component/reconciler/base/renderer/renderer_test.go b/pkg/component/reconciler/base/renderer/renderer_test.go index 0a05145..4160638 100644 --- a/pkg/component/reconciler/base/renderer/renderer_test.go +++ b/pkg/component/reconciler/base/renderer/renderer_test.go @@ -224,6 +224,117 @@ spec: ` ) +// func TestRenderedContainerCopy(t *testing.T) { + +// // Use the Kuard CRD for all cases +// crdv := basecrd.CRDPrioritizedVersion(ReadCRD(kuardCRD)) + +// testCases := map[string]struct { +// // Resolver related rendering might need existing objects. The +// // kuard instance used for reconciliation does not need to be +// // here, only any referenced object. +// existingObjects []client.Object + +// // Kuard instance fir rendering. +// kuardInstance string + +// // Registration sub-element for parameter configuration. +// parameterConfig string + +// // Managed conditions +// happyCond string +// conditionSet []string + +// // +// // Expected data fiels +// // + +// // Only if rendering should return an error. +// expectedError *string + +// // Environment variables for the rendered container. +// expectedEnvs []corev1.EnvVar +// }{ +// "no parameter policies": { +// kuardInstance: kuardInstance, +// expectedEnvs: []corev1.EnvVar{ +// {Name: "ARRAY", Value: "alpha,beta,gamma"}, +// {Name: "GROUP_VARIABLE3", Value: "false"}, +// {Name: "GROUP_VARIABLE4", Value: "42"}, +// {Name: "VARIABLE1", Value: "value 1"}, +// {Name: "VARIABLE2", Value: "value 2"}, +// }, +// }, +// "skip variable from rendering": { +// kuardInstance: kuardInstance, +// parameterConfig: ` +// fromSpec: +// - path: spec.variable2 +// skip: true +// `, +// expectedEnvs: []corev1.EnvVar{ +// {Name: "ARRAY", Value: "alpha,beta,gamma"}, +// {Name: "GROUP_VARIABLE3", Value: "false"}, +// {Name: "GROUP_VARIABLE4", Value: "42"}, +// {Name: "VARIABLE1", Value: "value 1"}, +// /* {Name: "VARIABLE2", Value: "value 2"}, */ +// }, +// }, +// } + +// logr := tlogr.NewTestLogger(t) + +// for name, tc := range testCases { +// t.Run(name, func(t *testing.T) { +// // for this test we can hardcode to deployment, we are only testing container output. +// wkl := &commonv1alpha1.Workload{ +// FormFactor: &commonv1alpha1.FormFactor{ +// Deployment: &commonv1alpha1.DeploymentFormFactor{ +// Replicas: 1, +// }, +// }, +// ParameterConfiguration: &commonv1alpha1.ParameterConfiguration{}, +// } + +// // Read parameter configuration into structure +// err := yaml.Unmarshal([]byte(tc.parameterConfig), wkl.ParameterConfiguration) +// require.NoError(t, err) + +// ctx := context.Background() + +// cb := fake.NewClientBuilder() +// rsv := resolver.New(cb.WithObjects(tc.existingObjects...).Build()) + +// r := NewRenderer(wkl, rsv) + +// smf := basestatus.NewStatusManagerFactory(crdv, tc.happyCond, tc.conditionSet, logr) +// mgr := baseobject.NewManager(gvk, r, smf) + +// // Replace with the test object +// obj := mgr.NewObject() +// u := obj.AsKubeObject().(*unstructured.Unstructured) +// err = yaml.Unmarshal([]byte(tc.kuardInstance), u) +// require.NoError(t, err) + +// err = r.Render(ctx, obj) +// if tc.expectedError != nil { +// require.Contains(t, err.Error(), *tc.expectedError) + +// } else { +// require.NoError(t, err) +// } + +// c := resources.NewContainer( +// "test-name", +// "test-image", +// obj.AsContainerOptions()..., +// ) + +// assert.Equal(t, tc.expectedEnvs, c.Env) +// }) +// } +// } + func TestRenderedContainer(t *testing.T) { // Use the Kuard CRD for all cases @@ -268,10 +379,9 @@ func TestRenderedContainer(t *testing.T) { "skip variable from rendering": { kuardInstance: kuardInstance, parameterConfig: ` -specToEnvs: +fromSpec: - path: spec.variable2 - render: - skip: true + skip: true `, expectedEnvs: []corev1.EnvVar{ {Name: "ARRAY", Value: "alpha,beta,gamma"}, @@ -284,9 +394,9 @@ specToEnvs: "rename variable": { kuardInstance: kuardInstance, parameterConfig: ` -specToEnvs: +fromSpec: - path: spec.variable2 - render: + toEnv: name: KUARD_VARIABLE_TWO `, expectedEnvs: []corev1.EnvVar{ @@ -300,9 +410,9 @@ specToEnvs: "default value - when present": { kuardInstance: kuardInstance, parameterConfig: ` -specToEnvs: +fromSpec: - path: spec.variable2 - render: + toEnv: defaultValue: new variable2 value `, expectedEnvs: []corev1.EnvVar{ @@ -317,10 +427,11 @@ specToEnvs: // remove variable2 entry from kuard instance. kuardInstance: strings.ReplaceAll(kuardInstance, "variable2: value 2", ""), parameterConfig: ` -specToEnvs: +fromSpec: - path: spec.variable2 - render: + toEnv: defaultValue: new variable2 value + `, expectedEnvs: []corev1.EnvVar{ {Name: "ARRAY", Value: "alpha,beta,gamma"}, @@ -338,9 +449,9 @@ specToEnvs: secretKey: kuard-key `, parameterConfig: ` -specToEnvs: +fromSpec: - path: spec.refToSecret - render: + toEnv: name: FOO_CREDENTIALS valueFromSecret: name: spec.refToSecret.secretName @@ -362,6 +473,38 @@ specToEnvs: {Name: "VARIABLE2", Value: "value 2"}, }, }, + "configmap reference": { + // add secret reference to kuard base instance. + kuardInstance: kuardInstance + ` + refToConfigMap: + configMapName: kuard-cm + configMapKey: kuard-cm-key +`, + parameterConfig: ` +fromSpec: +- path: spec.refToConfigMap + toEnv: + name: FOO_CONFIG + valueFromConfigMap: + name: spec.refToConfigMap.configMapName + key: spec.refToConfigMap.configMapKey +`, + expectedEnvs: []corev1.EnvVar{ + {Name: "ARRAY", Value: "alpha,beta,gamma"}, + {Name: "FOO_CONFIG", ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "kuard-cm", + }, + Key: "kuard-cm-key", + }, + }}, + {Name: "GROUP_VARIABLE3", Value: "false"}, + {Name: "GROUP_VARIABLE4", Value: "42"}, + {Name: "VARIABLE1", Value: "value 1"}, + {Name: "VARIABLE2", Value: "value 2"}, + }, + }, "add parameters": { kuardInstance: kuardInstance, parameterConfig: ` @@ -443,5 +586,4 @@ addEnvs: assert.Equal(t, tc.expectedEnvs, c.Env) }) } - }