Skip to content

encoding/openapi: add support for openapi extension attributes in builder #3797

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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nkvoll
Copy link

@nkvoll nkvoll commented Mar 6, 2025

This is just taking a quick stab at something for #2638, just to see what it would take to fix. I'm not experienced with nor do I fully understand the ast or if what I'm doing is very uncanonical (just learning cue and first time potential contributor), so please bear with me as I'm looking for some feedback on whether some direction like this makes sense or if I'm looking in the wrong directions.

What I wanted to add support for is extending the openapi schema to support extensions like CEL (see https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules). This requires a little more than adding string string:string key:value pairs, so I opted for using JSON inside the cue attribute.

Having the attribute be @openapi(extension:keyName:json-value) meant a little more parsing than something like @openapiExtension(keyName:json-value) (or similar).

Example

Example resource (example.cue):

package example

#SomeResource: {
	spec: {
		parameters: {
			foo: string
        } @openapi(extension=x-kubernetes-validations:[
            {
                "rule": "self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas",
                "message": "replicas should be in the range minReplicas..maxReplicas."
            }
        ])
    }
}

Generate:

go run ./cmd/cue def example.cue -o example.openapi.yaml --out openapi+yaml

Output

openapi: 3.0.0
info:
  title: Generated by cue.
  version: no version
paths: {}
components:
  schemas:
    SomeResource:
      type: object
      required:
        - spec
      properties:
        spec:
          type: object
          required:
            - parameters
          properties:
            parameters:
              type: object
              required:
                - foo
              properties:
                foo:
                  type: string
              x-kubernetes-validations:
                - rule: self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas
                  message: replicas should be in the range minReplicas..maxReplicas.

@nkvoll nkvoll force-pushed the openapi-extensions branch from d657071 to 82a7575 Compare March 6, 2025 23:16
@myitcv
Copy link
Member

myitcv commented Mar 8, 2025

Thanks for this @nkvoll - I'll ask @rogpeppe to take a look and get back to you!

@rogpeppe
Copy link
Member

@nkvoll Thanks very much for the PR! We definitely want to support aspects of OpenAPI like this, although the right approach isn't entirely clear currently. For now, we are super busy in the run up to Kubecon. We will get back to you with feedback on this after that :)

@nkvoll
Copy link
Author

nkvoll commented May 23, 2025

Hi @rogpeppe, just checking in if you have had some time to take a look. I just pushed a change that moves the extension definition from being json to being in cue (not 100% sure on the implementation, whether there is a better / more canonical approach available -- happy to learn).

Example usage right now (pluralized extensions since multiple extensions can be defined here -- though there are currently no explicit guardrails for not colliding with the built-in attributes):

package example

#SomeResource: {
    spec: {
        parameters: {
            minReplicas: int
            maxReplicas: int
            replicas: int
        } @openapi(extensions={
            "x-kubernetes-validations": [
                {
                    rule: "self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas",
                    message: "replicas should be in the range minReplicas..maxReplicas",
                }
            ]
        })
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants