1
1
Experimenting with Kubernetes protobufs.
2
2
3
- ## Protobufs
3
+ ## Build Dependencies
4
4
5
- ### Download
5
+ - [ fd] ( https://github.com/sharkdp/fd )
6
+ - [ jq] ( https://stedolan.github.io/jq/ )
7
+ - [ just] ( https://github.com/casey/just )
8
+ - [ sd] ( https://github.com/chmln/sd )
6
9
7
- Get protos by extracting them from Kubernetes releases:
10
+ ## Protobufs
11
+ We get protos by extracting them from pinned Kubernetes releases:
8
12
9
13
- https://github.com/kubernetes/api/releases
10
14
- https://github.com/kubernetes/apimachinery/releases
11
15
- https://github.com/kubernetes/apiextensions-apiserver/releases
12
16
- https://github.com/kubernetes/kube-aggregator/releases
13
17
- https://github.com/kubernetes/metrics/releases
14
18
15
- ``` bash
16
- # In `protos/`
17
- VERSION=1.22.0
18
- for x in api apimachinery apiextensions-apiserver kube-aggregator metrics; do
19
- mkdir ./$x ;
20
- curl -sSL https://github.com/kubernetes/$x /archive/refs/tags/kubernetes-$VERSION .tar.gz | tar xzf - -C ./$x / --strip-components=1;
21
- fd -e proto -x sh -c " mkdir -p k8s.io/'{//}'; mv '{}' k8s.io/'{}'" ' ;' . ./$x ;
22
- rm -rf ./$x ;
23
- done
24
- ```
25
-
26
- ### Patch
19
+ We then do minor transforms on top of that to prepare for building.
20
+ Results of this step is committed already. But to run, invoke ` just protos `
27
21
28
- Removing ` k8s.io. ` :
22
+ ## Openapi
23
+ To complement the protos with generic information, we also download the swagger schema, patch it, and transform it as described below.
29
24
30
- ``` bash
31
- fd -e proto -x sd ' k8s\.io\.(.+);' ' $1;' {}
32
- fd -e proto -x sd ' import "k8s\.io/(.+)";' ' import "$1";' {}
33
- mv protos/k8s.io/* protos/
34
- rmdir protos/k8s.io/
35
- ```
25
+ Results of this step is committed already. But to run, invoke ` just swagger ` .
36
26
37
- ### Generate
38
27
39
- Collect all paths to generate:
28
+ ## Building
29
+ To build the [ out] ( ./out ) directory from [ build.rs] ( ./build.rs ) we will use the outputs from the ` swagger ` , ` protobuf ` , and ` protobuf-fds ` targets.
40
30
41
- ``` bash
42
- # In project root.
43
- fd -e proto -x echo ' "{}",' | sort
44
- ```
45
- Copy the output to ` build.rs ` , then:
46
-
47
- ``` bash
48
- cargo build
49
- ```
31
+ Results of this step is committed already. But to run, invoke ` just codegen `
50
32
51
33
### Hack
52
34
53
- Generate a [ ` FileDescriptorSet ` ] containing all of the input files:
54
-
55
- ``` bash
56
- protoc \
57
- --include_imports \
58
- --include_source_info \
59
- --descriptor_set_out=k8s.pb \
60
- --proto_path=./protos \
61
- ./protos/** /* .proto
62
- ```
35
+ Generate a [ ` FileDescriptorSet ` ] containing all of the input files wih ` just codegen-fds `
63
36
64
- Working with ` FileDescriptorSet ` :
65
- ``` rust
66
- use prost_types :: {FileDescriptorProto , FileDescriptorSet };
67
- let buf = fs :: read (fds_path ). unwrap ();
68
- let fds = FileDescriptorSet :: decode (& * buf ). unwrap ();
69
- let files = fds . files;
70
- ```
71
37
72
- See [ ` prost_build ` ] ( https://github.com/tokio-rs/prost/blob/32bc87cd0b7301f6af1a338e9afd7717d0f42ca9/prost-build/src/lib.rs#L765-L825 ) .
73
-
74
- [ `FileDescriptorSet` ] : https://github.com/tokio-rs/prost/blob/32bc87cd0b7301f6af1a338e9afd7717d0f42ca9/prost-types/src/protobuf.rs#L1-L7
75
-
76
-
77
- ## OpenAPI
38
+ ## OpenAPI Strategy
78
39
79
40
We need to use ` swagger.json ` to fill in some information.
80
41
@@ -96,146 +57,3 @@ We should be able to find the following:
96
57
- Namespaced if any possible path contains ` /namespaces/{namespace}/ `
97
58
- May also have paths for all namespaces for some verbs (e.g., ` list ` all pods)
98
59
- Subresource if path contains ` /{name}/ ` (` / ` after ` {name} ` )
99
-
100
- ### Download
101
-
102
- In ` openapi/ `
103
-
104
- ``` bash
105
- VERSION=1.22.0
106
- curl -sSL -o swagger.json \
107
- https://raw.githubusercontent.com/kubernetes/kubernetes/v$VERSION /api/openapi-spec/swagger.json
108
- ```
109
-
110
- ### Bug Fix
111
-
112
- Fix path operation annotated with a ` x-kubernetes-group-version-kind ` that references a type that doesn't exist in the schema. (See [ ` k8s-openapi ` ] ( https://github.com/Arnavion/k8s-openapi/blob/445e89ec444ebb1c68e61361e64eec4c4a3f4785/k8s-openapi-codegen/src/fixups/upstream_bugs.rs#L9 ) ).
113
-
114
- ``` bash
115
- gron swagger.json \
116
- | perl -pe ' s/(?<=kind = ")(Pod|Node|Service)(?:Attach|Exec|PortForward|Proxy)Options(?=")/$1/' \
117
- | gron -u \
118
- > swagger-patched.json
119
- mv swagger-patched.json swagger.json
120
- ```
121
-
122
- ### Transforming
123
-
124
- Transform ` swagger.json ` to something easier to explore.
125
-
126
- #### Like APIResourceList
127
-
128
- ``` bash
129
- cat swagger.json \
130
- | jq -f list-resources.jq \
131
- > api-resources.json
132
- ```
133
-
134
- ``` bash
135
- cat swagger.json | jq -f list-resources.jq | jq ' .[0]'
136
- ```
137
-
138
- ``` json
139
- {
140
- "apiGroupVersion" : " admissionregistration.k8s.io/v1" ,
141
- "resources" : [
142
- {
143
- "name" : " mutatingwebhookconfigurations" ,
144
- "namespaced" : false ,
145
- "apiGroupVersion" : " admissionregistration.k8s.io/v1" ,
146
- "group" : " admissionregistration.k8s.io" ,
147
- "version" : " v1" ,
148
- "kind" : " MutatingWebhookConfiguration" ,
149
- "verbs" : [
150
- " create" ,
151
- " delete" ,
152
- " deletecollection" ,
153
- " get" ,
154
- " list" ,
155
- " patch" ,
156
- " update"
157
- ]
158
- },
159
- {
160
- "name" : " validatingwebhookconfigurations" ,
161
- "namespaced" : false ,
162
- "apiGroupVersion" : " admissionregistration.k8s.io/v1" ,
163
- "group" : " admissionregistration.k8s.io" ,
164
- "version" : " v1" ,
165
- "kind" : " ValidatingWebhookConfiguration" ,
166
- "verbs" : [
167
- " create" ,
168
- " delete" ,
169
- " deletecollection" ,
170
- " get" ,
171
- " list" ,
172
- " patch" ,
173
- " update"
174
- ]
175
- }
176
- ]
177
- }
178
- ```
179
-
180
- #### Paths
181
-
182
- ``` typescript
183
- type ResourcePath = {
184
- // Request path.
185
- path: string ;
186
- // `x-kubernetes-action` or `method`.
187
- verb: string ;
188
- // Group and version of API. Can be different from `group` and `version` for subresources.
189
- apiGroupVersion: string ;
190
- // GVK
191
- group: string ;
192
- version: string ;
193
- kind: string ;
194
- // True if the path contains `/namespaces/{namespace}/`
195
- namespaced: boolean ;
196
- // True if the path contains a segment after `{name}`.
197
- subresource: boolean ;
198
- // MIME types of supported content types. Comma separated.
199
- consumes: string ;
200
- // MIME types of supported responses. Comma separated.
201
- produces: string ;
202
- // Plural name. Includes subresources like APIResourceList.
203
- name: string ;
204
- };
205
- ```
206
-
207
- ``` bash
208
- cat swagger.json | jq -f list-paths.jq
209
- ```
210
-
211
- ``` bash
212
- cat swagger.json \
213
- | jq -f list-paths.jq \
214
- | jq ' map(select(.kind == "Pod" and .verb == "get" and .subresource == false))'
215
- ```
216
-
217
- ``` json
218
- [
219
- {
220
- "path" : " /api/v1/namespaces/{namespace}/pods/{name}" ,
221
- "verb" : " get" ,
222
- "apiGroupVersion" : " v1" ,
223
- "group" : " " ,
224
- "version" : " v1" ,
225
- "kind" : " Pod" ,
226
- "namespaced" : true ,
227
- "subresource" : false ,
228
- "consumes" : " */*" ,
229
- "produces" : " application/json, application/yaml, application/vnd.kubernetes.protobuf" ,
230
- "name" : " pods"
231
- }
232
- ]
233
- ```
234
-
235
- Group by ` name ` :
236
-
237
- ``` bash
238
- cat swagger.json \
239
- | jq -f list-paths.jq \
240
- | jq ' group_by(.name)'
241
- ```
0 commit comments