Skip to content

Commit 0d3b4c5

Browse files
committed
Add doc to explain the whole JSONSchema generation
1 parent 82d7cb2 commit 0d3b4c5

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,7 @@ is different we will have to use a different file.
8686
The file [`deploymentspecmod.json`](https://github.com/kedgeproject/json-schema/blob/master/schema/deploymentspecmod.json)
8787
has schema for validating kedge.
8888
The above file [`db.json`](./example/db.json) is taken from [kedge repo example](https://github.com/kedgeproject/kedge/blob/master/examples/envFrom/db.yaml).
89+
90+
## JSONSchema generation process
91+
92+
Read more about the JSONSchema generation process in [conversion.md](conversion.md).

conversion.md

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
## Intro to JSONSchema
2+
3+
JSON Schema is a vocabulary that allows you to annotate and validate JSON/YAML
4+
documents.
5+
6+
- describes your existing data format
7+
- clear, human- and machine-readable documentation
8+
- complete structural validation, useful for
9+
- automated testing
10+
- validating client-submitted data
11+
12+
## Intro to OpenAPI or SwaggerSchame
13+
14+
The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to
15+
RESTful APIs which allows both humans and computers to discover and understand the
16+
capabilities of the service without access to source code, documentation, or
17+
through network traffic inspection. When properly defined, a consumer can
18+
understand and interact with the remote service with a minimal amount of
19+
implementation logic.
20+
21+
An OpenAPI definition can then be used by documentation generation tools to
22+
display the API, code generation tools to generate servers and clients in various
23+
programming languages, testing tools, and many other use cases.
24+
25+
26+
## Where do we get the OpenAPI for kedge from?
27+
28+
This could be an obvious question that comes to your mind because Kedge is not any
29+
web service where we have defined RESTful APIs. So even if Kedge is not a service,
30+
but it has it's language specification defined in the form or [golang structs](https://github.com/kedgeproject/kedge/blob/master/pkg/spec/types.go),
31+
which forms the basis of the language. Also since we are embedding the golang
32+
structs from upstream Kubernetes, and Kubernetes has it's own OpenAPI schema defined
33+
for each struct. So for Kedge this is good news, because now we have less work.
34+
35+
So the complete OpenAPI definition looks like the following, if you just look at the
36+
root keys: ([Kubernetes 1.7 OpenAPI definition](https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.7/api/openapi-spec/swagger.json))
37+
38+
```json
39+
{
40+
"swagger": "2.0",
41+
"info": {...},
42+
"paths": {...},
43+
"definitions": {...},
44+
"securityDefinitions": {...},
45+
"security": {...}
46+
}
47+
```
48+
49+
Now the part of interest for us is the root level field `"definitions": {...}`, it
50+
has definition of all Kubernetes structs in OpenAPI format. If we dig deeper in
51+
the `definitions` part, you will see something like this:
52+
53+
```json
54+
{
55+
"swagger": "2.0",
56+
"definitions": {
57+
"io.k8s.kubernetes.pkg.api.v1.Pod": {...},
58+
"io.k8s.kubernetes.pkg.api.v1.PodAffinity": {...},
59+
"io.k8s.kubernetes.pkg.api.v1.PodAffinityTerm": {...},
60+
"io.k8s.kubernetes.pkg.api.v1.PodAntiAffinity": {...},
61+
...
62+
"io.k8s.kubernetes.pkg.apis.apps.v1beta1.Deployment": {...},
63+
"io.k8s.kubernetes.pkg.apis.apps.v1beta1.DeploymentCondition": {...},
64+
"io.k8s.kubernetes.pkg.apis.apps.v1beta1.DeploymentList": {...},
65+
...
66+
},
67+
}
68+
```
69+
70+
So all we need to do is inject the definition of Pod from here into our defintion.
71+
But before we do that kinda injection first we need to know what to inject where.
72+
To identify that we have introduced a convention in Kedge schema's golang struct
73+
definition which looks something like the following. More information about the
74+
conventions used in Kedge's golang struct definition can be found [here](https://github.com/kedgeproject/kedge/blob/3ade8541e2209148c21c636464e12aea75e35e3a/docs/development.md#specgo-conventions).
75+
76+
```go
77+
// Container defines a single application container that you want to run within a pod.
78+
// kedgeSpec: io.kedge.ContainerSpec
79+
type Container struct {
80+
// One common definitions for 'livenessProbe' and 'readinessProbe'
81+
// this allows to have only one place to define both probes (if they are the same)
82+
// Periodic probe of container liveness and readiness. Container will be restarted
83+
// if the probe fails. Cannot be updated. More info:
84+
// https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
85+
// ref: io.k8s.kubernetes.pkg.api.v1.Probe
86+
// +optional
87+
Health *api_v1.Probe `json:"health,omitempty"`
88+
// k8s: io.k8s.kubernetes.pkg.api.v1.Container
89+
api_v1.Container `json:",inline"`
90+
}
91+
```
92+
Above code can be found [here](https://github.com/kedgeproject/kedge/blob/ecc7df1b0bb46ff43d5f830e08c0d0ddafd8e710/pkg/spec/types.go#L84-L97).
93+
94+
Line `api_v1.Container `json:",inline"`` has a comment above it
95+
`k8s: io.k8s.kubernetes.pkg.api.v1.Container` in this
96+
`io.k8s.kubernetes.pkg.api.v1.Container` is a key of the Container definition in
97+
Kubernetes's OpenAPI schema. This is how we know that for the Kedge's container
98+
definition, the definition of upstream container comes from
99+
`io.k8s.kubernetes.pkg.api.v1.Container` key in comment.
100+
101+
Fields those are embedded are put in with `k8s` as the way to tell that this
102+
definition comes from Kubernetes.
103+
104+
105+
Similarly ```Health *api_v1.Probe `json:"health,omitempty"` ``` has multiple
106+
comments one says `+optional` which means that this field in this struct while
107+
generation of definition is marked optional. And then there are bunch of comments
108+
above `Health` field which explains what it does. These comments then become
109+
description of the field in OpenAPI schema.
110+
111+
Above struct definition you can also see the comment
112+
`kedgeSpec: io.kedge.ContainerSpec`. Here `io.kedge.ContainerSpec` is the key for
113+
the Kedge's Container definition in the final output of the OpenAPI for Kedge.
114+
115+
With help of these conventions and parsing of go code and injecting upstream
116+
Kubernetes OpenAPI schema into the Kedge's OpenAPI schema we generate final
117+
OpenAPI schema which is superset of the Kubernetes OpenAPI schema.
118+
119+
## JSONSchema for Kedge
120+
121+
This the easiest part, we hand off this work to the tool called
122+
[openapi2jsonschema](https://github.com/garethr/openapi2jsonschema). This then
123+
reads all the keys from the definition part and creates JSONSchema for each key in
124+
the definitions part of the OpenAPI Schema for kedge. All the JSONSchemas for the
125+
Kedge can be found at [github.com/kedgeproject/json-schema](https://github.com/kedgeproject/json-schema/tree/master/schema).
126+
127+
Depending on what is the input at root level there are multiple schema files like
128+
for Kubernetes Deployment with kedge we have [deploymentspecmod.json](https://github.com/kedgeproject/json-schema/blob/master/schema/deploymentspecmod.json), [jobspecmod.json](https://github.com/kedgeproject/json-schema/blob/master/schema/jobspecmod.json).
129+
130+
## Ref:
131+
132+
- JSON Schema http://json-schema.org/
133+
- OpenAPI Specification https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
134+
- Kubernetes master OpenAPI definition https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json
135+
- openapi2jsonschema - https://github.com/garethr/openapi2jsonschema
136+
- kedgeproject/json-schema - https://github.com/kedgeproject/json-schema

0 commit comments

Comments
 (0)