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

Extend ack-generate to generate slice with elements of type Kubernetes Secret #828

Closed
kumargauravsharma opened this issue Jun 10, 2021 · 0 comments
Labels
kind/enhancement Categorizes issue or PR as related to existing feature enhancements.

Comments

@kumargauravsharma
Copy link
Contributor

Is your feature request related to a problem?
When a resource field of type slice is configured as secret in generator config file, the generated code places single Kubernetes Secret as type in Spec. This leads to following issues:

  • As only 1 value can be specified in spec for a field that is supposed to take multiple values.
  • The generated code fails to compile as it tries to set single String value into API input's field of slice type.

For example:
ElastiCache User API has passwords filed of type []*string in the API input. Reference API docs

When this field is configured as secret type inside Generator config:

resources:
  User:
    fields:
      Passwords:
        is_secret: true

then generated service controller code looks like:
CRD yaml:

              passwords:
                description: Passwords used for this user. You can create up to two
                  passwords for each user.
                properties:
                  key:
                    description: Key is the key within the secret
                    type: string
                  name:
                    description: Name is unique within a namespace to reference a
                      secret resource.
                    type: string
                  namespace:
                    description: Namespace defines the space within which the secret
                      name must be unique.
                    type: string
                required:
                - key
                type: object

Observe that the password field type is generated as object of type k8s secret instead of array of k8s secrets.

And the generated sdk.go code looks like:

        if r.ko.Spec.Passwords != nil {
		tmpSecret, err := rm.rr.SecretValueFromReference(ctx, r.ko.Spec.Passwords)
		if err != nil {
			return nil, err
		}
		if tmpSecret != "" {
			res.SetPasswords(tmpSecret)
		}
	}

Observe the string value being supplied to res.SetPasswords which accepts []*string.
This leads to compilation issues.

Following ElastiCache ACK controller PR has related discussion about the password field in User API.

Describe the solution you'd like
When a field of type slice is configured as secret type inside Generator config, then the generated CRD yaml should allow specifying multiple k8s secret values for this field and sdk code should supply these values to the resource API input field as slice type.

For example, the generated CRD yaml for password field from previous example will look like:

              passwords:
                description: Passwords used for this user. You can create up to two
                  passwords for each user.
                items:
                  description: SecretKeyReference combines a k8s corev1.SecretReference
                    with a specific key within the referred-to Secret
                  properties:
                    key:
                      description: Key is the key within the secret
                      type: string
                    name:
                      description: Name is unique within a namespace to reference
                        a secret resource.
                      type: string
                    namespace:
                      description: Namespace defines the space within which the secret
                        name must be unique.
                      type: string
                  required:
                  - key
                  type: object
                type: array

and sdk.go will look like:

	if r.ko.Spec.Passwords != nil {
		f3 := []*string{}
		for _, f3iter := range r.ko.Spec.Passwords {
			var f3elem string
			if f3iter != nil {
				tmpSecret, err := rm.rr.SecretValueFromReference(ctx, f3iter)
				if err != nil {
					return nil, err
				}
				if tmpSecret != "" {
					f3elem = tmpSecret
				}
			}
			f3 = append(f3, &f3elem)
		}
		res.SetPasswords(f3)
	}

Describe alternatives you've considered
An option is to add such field to ignore config. But that removes it from the input spec.

@kumargauravsharma kumargauravsharma added the kind/enhancement Categorizes issue or PR as related to existing feature enhancements. label Jun 10, 2021
kumargauravsharma pushed a commit to kumargauravsharma/ack-code-generator that referenced this issue Jun 10, 2021
…s Secret

Related issue: aws-controllers-k8s/community#828

With this code change, when a field of type slice
is configured as secret type inside Generator config,
then the generated CRD yaml allows specifying multiple k8s secret values
for that field in input yaml and generated sdk code supplies these values
to the resource API input field as slice type.
kumargauravsharma pushed a commit to kumargauravsharma/ack-code-generator that referenced this issue Jun 10, 2021
…s Secret

Related issue: aws-controllers-k8s/community#828

With this code change, when a field of type slice
is configured as secret type inside Generator config,
then the generated CRD yaml allows specifying multiple k8s secret values
for that field in input yaml and generated sdk code supplies these values
to the resource API input field as slice type.
ack-bot pushed a commit to aws-controllers-k8s/code-generator that referenced this issue Jun 11, 2021
#87)

Issue: aws-controllers-k8s/community#828

Description of changes:
With this code change, when a field of type slice
is configured as secret type inside Generator config,
then the generated CRD yaml allows specifying multiple k8s secret values
for that field in input yaml and generated sdk code supplies these values
to the resource API input field as slice type.

Added unit tests to test the scenario.

Details on resultant generated code:
Taking ElastiCache User API has `passwords` filed as example:
ElastiCache User API has `passwords` filed of type `[]*string` in the API input. [Reference API docs](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/elasticache/create-user.html)

When this field is configured as secret type inside Generator config:
```
resources:
  User:
    fields:
      Passwords:
        is_secret: true
```
and service controller code is generated with changes from this PR then,
the generated CRD yaml for password field is:
```
              passwords:
                description: Passwords used for this user. You can create up to two
                  passwords for each user.
                items:
                  description: SecretKeyReference combines a k8s corev1.SecretReference
                    with a specific key within the referred-to Secret
                  properties:
                    key:
                      description: Key is the key within the secret
                      type: string
                    name:
                      description: Name is unique within a namespace to reference
                        a secret resource.
                      type: string
                    namespace:
                      description: Namespace defines the space within which the secret
                        name must be unique.
                      type: string
                  required:
                  - key
                  type: object
                type: array
```
Observe that the password field is `array` type with K8s Secreret as element type

and User resource sdk.go file contain following code for password field while setting the inputs:
```
	if r.ko.Spec.Passwords != nil {
		f3 := []*string{}
		for _, f3iter := range r.ko.Spec.Passwords {
			var f3elem string
			if f3iter != nil {
				tmpSecret, err := rm.rr.SecretValueFromReference(ctx, f3iter)
				if err != nil {
					return nil, err
				}
				if tmpSecret != "" {
					f3elem = tmpSecret
				}
			}
			f3 = append(f3, &f3elem)
		}
		res.SetPasswords(f3)
	}
```
Observe that it supplies the secrets values as slice type to the input API.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Testing:
1. ```make test``` passed for `code-generator` which contained already existing tests for secret fields code generation scenarios for MQ, ElastiCache ReplicationGroup.
2. ```make test``` passed for ElastiCache ACK controller generated code.
3. Generated ElastiCache controller code did not have any unrelated/unexpected changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement Categorizes issue or PR as related to existing feature enhancements.
Projects
None yet
Development

No branches or pull requests

2 participants