Awesome
swagger-k8s-crd-codegen
This naive proof-of-concept reads a swagger.yml
to produce Kubernetes CRDs of the specified models.
NOTE: This generator only parses model definitions, and does not parse, examine, or utilize any paths within your application.
Motivation
Swagger is a tool for documenting interactions that will take place in an API using OpenAPI. Kubernetes is a container orchestration environment that allows for extending their API using CustomResourceDefinitions.
CustomResourceDefinitions (CRDs) are defined using the same OpenAPI language used by Swagger.
By specifying a few additional annotations, we can generate a Kubernetes CRD from the same Swagger spec.
Running in Python
Install dependencies:
$ pip install --user -r requirements.txt
Run the Python script:
$ python ./swagger-k8s-crd-codegen.py
Running in Docker
Build the Docker image:
$ docker build -t bodom0015/swagger-k8s-crd-codegen .
Run the Docker image:
$ docker run -it --rm -v $(pwd)/target/:/app/target bodom0015/swagger-k8s-crd-codegen
Writing target/workbenchuserapps.crd.yml
Usage
This parser looks for special attributes in your model definition. Please define the following:
Key | Definition | Example |
---|---|---|
x-groupName | group name to use for generated CRD | ndslabs.org |
x-version | version name to use for generated CRD | v1 |
x-singular | name for a single CRD of this type | workbenchuserapp |
x-plural | name for multiple CRD of this type | workbenchuserapps |
x-kind | CamelCase kind for this CRD | WorkbenchUserApp |
x-scope | Namespaced , else Cluster will share to all namespaces | Namespaced or Cluster |
x-shortNames | list of shorter string aliases for this CRD | (See below) |
Defining Short Names
Short names allow you to use kubectl get <shortname>
to list the custom resources on the cluster.
Short names for a CRD can be defined as a list, for example:
x-shortNames:
- workbenchapp
- workbenchapps
- wbuserapp
- wbuserapps
- userapp
- userapps
- wbapp
- wbapps
- app
- apps
This would enable the use of kubectl get workbenchapp
or kubectl get userapp
or kubectl get apps
, etc.
Full Example
Sample Input (swagger.yml
):
swagger: '2.0'
info:
title: Fake Example API
description: Sample API for the swagger-k8s-crd-codegen
version: 0.0.1
host: localhost:5000
basePath: /api
produces:
- application/json
consumes:
- application/json
# NOTE: paths are ignored by swagger-k8s-crd-codegen
paths:
/hello:
get:
description: |
Say hello
responses:
'200':
description: OK
schema:
type: string
definitions:
UserApp:
x-groupName: "ndslabs.org"
x-version: "v1"
x-plural: "workbenchuserapps"
x-singular: "workbenchuserapp"
x-kind: "WorkbenchUserApp"
x-scope: "Namespaced"
x-shortNames:
- workbenchapp
- workbenchapps
- wbuserapp
- wbuserapps
- userapp
- userapps
- wbapp
- wbapps
- app
- apps
type: object
properties:
hello:
type: string
world:
type: string
Using the commands above, run the script using either Python or Docker.
This should produce the output below (e.g. target/workbenchuserapps.crd.yaml
):
## This file was generated by swagger-k8s-crd-codegen.
## Any manual changes to this file may be overwritten.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: workbenchuserapps.ndslabs.org
spec:
# group name to use for REST API: /apis/<group>/<version>
group: ndslabs.org
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
hello:
type: string
world:
type: string
type: object
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: workbenchuserapps
# singular name to be used as an alias on the CLI and for display
singular: workbenchuserapp
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: WorkbenchUserApp
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- workbenchapp
- workbenchapps
- wbuserapp
- wbuserapps
- userapp
- userapps
- wbapp
- wbapps
- app
- apps
Using kubectl
, add this new definition to your cluster:
$ kubectl apply -f target/workbenchuserapps.crd.yml
customresourcedefinition.apiextensions.k8s.io/workbenchuserapps.ndslabs.org created
Create a new resource using the custom definition (e.g. app1.userapp.yml
):
kind: WorkbenchUserApp
metadata:
name: my-user-app-number-1
spec:
hello: it
world: works
Note that our spec
here must match up with that of the openAPIV3Schema defined above.
Create this new resource on your cluster:
$ kubectl apply -f app1.userapp.yml
NOTE: you can use use any of the shortname aliases defined to list/view/describe your resource.
List your created resources:
$ kubectl get workbenchuserapps
NAME AGE
my-user-app-number-1 62m
View details about a particular resource
$ kubectl describe userapp my-user-app-number-1
Name: my-user-app-number-1
Namespace: default
Labels: <none>
Annotations: <none>
API Version: ndslabs.org/v1
Kind: WorkbenchUserApp
Metadata:
Creation Timestamp: 2021-10-21T18:41:31Z
Generation: 1
Managed Fields:
API Version: ndslabs.org/v1
Fields Type: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.:
f:kubectl.kubernetes.io/last-applied-configuration:
f:spec:
.:
f:hello:
f:world:
Manager: kubectl-client-side-apply
Operation: Update
Time: 2021-10-21T18:41:31Z
Resource Version: 9012421
Self Link: /apis/ndslabs.org/v1/namespaces/default/workbenchuserapps/my-user-app-number-1
UID: ae716796-258f-4d31-8c87-9af3fc65611d
Spec:
Hello: it
World: works
Events: <none>
Output the resource in YAML format:
$ kubectl get app my-user-app-number-1 -o yaml
apiVersion: ndslabs.org/v1
kind: WorkbenchUserApp
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"ndslabs.org/v1","kind":"WorkbenchUserApp","metadata":{"annotations":{},"name":"my-user-app-number-1","namespace":"default"},"spec":{"hello":"it","world":"works"}}
creationTimestamp: "2021-10-21T18:41:31Z"
generation: 1
name: my-user-app-number-1
namespace: default
resourceVersion: "9012421"
selfLink: /apis/ndslabs.org/v1/namespaces/default/workbenchuserapps/my-user-app-number-1
uid: ae716796-258f-4d31-8c87-9af3fc65611d
spec:
hello: it
world: works