├── .gitignore ├── .header ├── LICENSE ├── Makefile ├── README.md ├── example └── prometheus-crd-gen │ ├── Makefile │ ├── generated-crd │ ├── alertmanager.crd.yaml │ ├── prometheus.crd.yaml │ └── servicemonitor.crd.yaml │ ├── main.go │ └── v1 │ ├── openapi_generated.go │ └── types.go └── pkg ├── cli-utils.go ├── convert_types.go ├── crdvalidation.go └── crdvalidation_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /.header: -------------------------------------------------------------------------------- 1 | // Copyright YEAR 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TAG?=$(shell git rev-parse --short HEAD) 2 | PREFIX ?= $(shell pwd) 3 | REPO = github.com/ant31/crd-validation 4 | pkgs = $(shell go list ./... | grep -v /vendor/ | grep -v /test/) 5 | 6 | all: check-license format build test 7 | 8 | run: 9 | go run cmd/openapi-crd-gen/main.go 10 | 11 | install: openapi-gen 12 | 13 | 14 | test: 15 | @go test -short $(pkgs) 16 | 17 | format: 18 | go fmt $(pkgs) 19 | 20 | openapi-gen: 21 | go get -u -v -d k8s.io/code-generator/cmd/openapi-gen 22 | cd $(GOPATH)/src/k8s.io/code-generator; git checkout release-1.8 23 | go install k8s.io/code-generator/cmd/openapi-gen 24 | 25 | 26 | .PHONY: all build test format generate-openapi openapi-gen 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # crd-validation 2 | Generator for crd validation openapi 3 | -------------------------------------------------------------------------------- /example/prometheus-crd-gen/Makefile: -------------------------------------------------------------------------------- 1 | OPENAPI_GEN := $(shell command -v openapi-gen 2> /dev/null) 2 | REPO :=github.com/ant31/crd-validation/example/prometheus-crd-gen 3 | ifeq ($(GOBIN),) 4 | GOBIN :=${GOPATH}/bin 5 | endif 6 | DATE := $(shell date '+%Y-%m-%d %H:%M:%S') 7 | 8 | all: generate-crds 9 | 10 | $(GOBIN)/openapi-gen: 11 | go get -u -v -d k8s.io/code-generator/cmd/openapi-gen 12 | cd $(GOPATH)/src/k8s.io/code-generator; git checkout release-1.8 13 | go install k8s.io/code-generator/cmd/openapi-gen 14 | 15 | 16 | 17 | v1/openapi_generated.go: $(GOBIN)/openapi-gen 18 | openapi-gen -i $(REPO)/v1,k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/api/core/v1 -p $(REPO)/v1 --go-header-file="$(GOPATH)/src/github.com/ant31/crd-validation/.header" 19 | 20 | generate-openapi: v1/openapi_generated.go 21 | 22 | build: generate-openapi 23 | go install $(REPO) 24 | 25 | $(GOBIN)/prometheus-crd-gen: build 26 | 27 | install: $(GOBIN)/prometheus-crd-gen 28 | 29 | 30 | generated-crd/prometheus.crd.yaml: $(GOBIN)/prometheus-crd-gen 31 | prometheus-crd-gen --kind=Prometheus --plural=prometheuses --apigroup=monitoring.coreos.com --labels generation-date="$(DATE)" --scope=Namespaced --version=v1 --spec-name=github.com/ant31/crd-validation/example/prometheus-crd-gen/v1.Prometheus > generated-crd/prometheus.crd.yaml 32 | 33 | generated-crd/alertmanager.crd.yaml: $(GOBIN)/prometheus-crd-gen 34 | prometheus-crd-gen --kind=Alertmanager --plural=alertmanagers --apigroup=monitoring.coreos.com --labels generation-date="$(DATE)" --scope=Namespaced --version=v1 --spec-name=github.com/ant31/crd-validation/example/prometheus-crd-gen/v1.Alertmanager > generated-crd/alertmanager.crd.yaml 35 | 36 | generated-crd/servicemonitor.crd.yaml: $(GOBIN)/prometheus-crd-gen 37 | prometheus-crd-gen --kind=ServiceMonitor --plural=servicemonitors --apigroup=monitoring.coreos.com --labels generation-date="$(DATE)" --scope=Cluster --version=v1 --spec-name=github.com/ant31/crd-validation/example/prometheus-crd-gen/v1.ServiceMonitor > generated-crd/servicemonitor.crd.yaml 38 | 39 | generate-crds: clean generated-crd/prometheus.crd.yaml generated-crd/alertmanager.crd.yaml generated-crd/servicemonitor.crd.yaml 40 | 41 | .PHONY: openapi-gen build all 42 | 43 | 44 | clean: 45 | rm -rf generated-crd/*.yaml 46 | -------------------------------------------------------------------------------- /example/prometheus-crd-gen/generated-crd/alertmanager.crd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1beta1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | creationTimestamp: null 6 | labels: 7 | generation-date: 2018-01-29 20:02:17 8 | name: alertmanagers.monitoring.coreos.com 9 | spec: 10 | group: monitoring.coreos.com 11 | names: 12 | kind: Alertmanager 13 | plural: alertmanagers 14 | scope: Namespaced 15 | validation: 16 | openAPIV3Schema: 17 | description: Describes an Alertmanager cluster. 18 | properties: 19 | apiVersion: 20 | description: 'APIVersion defines the versioned schema of this representation 21 | of an object. Servers should convert recognized schemas to the latest 22 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 23 | type: string 24 | kind: 25 | description: 'Kind is a string value representing the REST resource this 26 | object represents. Servers may infer this from the endpoint the client 27 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 28 | type: string 29 | spec: 30 | description: 'Specification of the desired behavior of the Alertmanager 31 | cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status' 32 | properties: 33 | affinity: 34 | description: Affinity is a group of affinity scheduling rules. 35 | properties: 36 | nodeAffinity: 37 | description: Node affinity is a group of node affinity scheduling 38 | rules. 39 | properties: 40 | preferredDuringSchedulingIgnoredDuringExecution: 41 | description: The scheduler will prefer to schedule pods to nodes 42 | that satisfy the affinity expressions specified by this field, 43 | but it may choose a node that violates one or more of the 44 | expressions. The node that is most preferred is the one with 45 | the greatest sum of weights, i.e. for each node that meets 46 | all of the scheduling requirements (resource request, requiredDuringScheduling 47 | affinity expressions, etc.), compute a sum by iterating through 48 | the elements of this field and adding "weight" to the sum 49 | if the node matches the corresponding matchExpressions; the 50 | node(s) with the highest sum are the most preferred. 51 | items: 52 | description: An empty preferred scheduling term matches all 53 | objects with implicit weight 0 (i.e. it's a no-op). A null 54 | preferred scheduling term matches no objects (i.e. is also 55 | a no-op). 56 | properties: 57 | preference: 58 | description: A null or empty node selector term matches 59 | no objects. 60 | properties: 61 | matchExpressions: 62 | description: Required. A list of node selector requirements. 63 | The requirements are ANDed. 64 | items: 65 | description: A node selector requirement is a selector 66 | that contains values, a key, and an operator that 67 | relates the key and values. 68 | properties: 69 | key: 70 | description: The label key that the selector 71 | applies to. 72 | type: string 73 | operator: 74 | description: Represents a key's relationship 75 | to a set of values. Valid operators are In, 76 | NotIn, Exists, DoesNotExist. Gt, and Lt. 77 | type: string 78 | values: 79 | description: An array of string values. If the 80 | operator is In or NotIn, the values array 81 | must be non-empty. If the operator is Exists 82 | or DoesNotExist, the values array must be 83 | empty. If the operator is Gt or Lt, the values 84 | array must have a single element, which will 85 | be interpreted as an integer. This array is 86 | replaced during a strategic merge patch. 87 | items: 88 | type: string 89 | type: array 90 | required: 91 | - key 92 | - operator 93 | type: array 94 | required: 95 | - matchExpressions 96 | weight: 97 | description: Weight associated with matching the corresponding 98 | nodeSelectorTerm, in the range 1-100. 99 | format: int32 100 | type: integer 101 | required: 102 | - weight 103 | - preference 104 | type: array 105 | requiredDuringSchedulingIgnoredDuringExecution: 106 | description: A node selector represents the union of the results 107 | of one or more label queries over a set of nodes; that is, 108 | it represents the OR of the selectors represented by the node 109 | selector terms. 110 | properties: 111 | nodeSelectorTerms: 112 | description: Required. A list of node selector terms. The 113 | terms are ORed. 114 | items: 115 | description: A null or empty node selector term matches 116 | no objects. 117 | properties: 118 | matchExpressions: 119 | description: Required. A list of node selector requirements. 120 | The requirements are ANDed. 121 | items: 122 | description: A node selector requirement is a selector 123 | that contains values, a key, and an operator that 124 | relates the key and values. 125 | properties: 126 | key: 127 | description: The label key that the selector 128 | applies to. 129 | type: string 130 | operator: 131 | description: Represents a key's relationship 132 | to a set of values. Valid operators are In, 133 | NotIn, Exists, DoesNotExist. Gt, and Lt. 134 | type: string 135 | values: 136 | description: An array of string values. If the 137 | operator is In or NotIn, the values array 138 | must be non-empty. If the operator is Exists 139 | or DoesNotExist, the values array must be 140 | empty. If the operator is Gt or Lt, the values 141 | array must have a single element, which will 142 | be interpreted as an integer. This array is 143 | replaced during a strategic merge patch. 144 | items: 145 | type: string 146 | type: array 147 | required: 148 | - key 149 | - operator 150 | type: array 151 | required: 152 | - matchExpressions 153 | type: array 154 | required: 155 | - nodeSelectorTerms 156 | podAffinity: 157 | description: Pod affinity is a group of inter pod affinity scheduling 158 | rules. 159 | properties: 160 | preferredDuringSchedulingIgnoredDuringExecution: 161 | description: The scheduler will prefer to schedule pods to nodes 162 | that satisfy the affinity expressions specified by this field, 163 | but it may choose a node that violates one or more of the 164 | expressions. The node that is most preferred is the one with 165 | the greatest sum of weights, i.e. for each node that meets 166 | all of the scheduling requirements (resource request, requiredDuringScheduling 167 | affinity expressions, etc.), compute a sum by iterating through 168 | the elements of this field and adding "weight" to the sum 169 | if the node has pods which matches the corresponding podAffinityTerm; 170 | the node(s) with the highest sum are the most preferred. 171 | items: 172 | description: The weights of all of the matched WeightedPodAffinityTerm 173 | fields are added per-node to find the most preferred node(s) 174 | properties: 175 | podAffinityTerm: 176 | description: Defines a set of pods (namely those matching 177 | the labelSelector relative to the given namespace(s)) 178 | that this pod should be co-located (affinity) or not 179 | co-located (anti-affinity) with, where co-located is 180 | defined as running on a node whose value of the label 181 | with key matches that of any node on which 182 | a pod of the set of pods is running 183 | properties: 184 | labelSelector: 185 | description: A label selector is a label query over 186 | a set of resources. The result of matchLabels and 187 | matchExpressions are ANDed. An empty label selector 188 | matches all objects. A null label selector matches 189 | no objects. 190 | properties: 191 | matchExpressions: 192 | description: matchExpressions is a list of label 193 | selector requirements. The requirements are 194 | ANDed. 195 | items: 196 | description: A label selector requirement is 197 | a selector that contains values, a key, and 198 | an operator that relates the key and values. 199 | properties: 200 | key: 201 | description: key is the label key that the 202 | selector applies to. 203 | type: string 204 | operator: 205 | description: operator represents a key's 206 | relationship to a set of values. Valid 207 | operators are In, NotIn, Exists and DoesNotExist. 208 | type: string 209 | values: 210 | description: values is an array of string 211 | values. If the operator is In or NotIn, 212 | the values array must be non-empty. If 213 | the operator is Exists or DoesNotExist, 214 | the values array must be empty. This array 215 | is replaced during a strategic merge patch. 216 | items: 217 | type: string 218 | type: array 219 | required: 220 | - key 221 | - operator 222 | type: array 223 | matchLabels: 224 | description: matchLabels is a map of {key,value} 225 | pairs. A single {key,value} in the matchLabels 226 | map is equivalent to an element of matchExpressions, 227 | whose key field is "key", the operator is "In", 228 | and the values array contains only "value". 229 | The requirements are ANDed. 230 | type: object 231 | namespaces: 232 | description: namespaces specifies which namespaces 233 | the labelSelector applies to (matches against); 234 | null or empty list means "this pod's namespace" 235 | items: 236 | type: string 237 | type: array 238 | topologyKey: 239 | description: This pod should be co-located (affinity) 240 | or not co-located (anti-affinity) with the pods 241 | matching the labelSelector in the specified namespaces, 242 | where co-located is defined as running on a node 243 | whose value of the label with key topologyKey matches 244 | that of any node on which any of the selected pods 245 | is running. Empty topologyKey is not allowed. 246 | type: string 247 | required: 248 | - topologyKey 249 | weight: 250 | description: weight associated with matching the corresponding 251 | podAffinityTerm, in the range 1-100. 252 | format: int32 253 | type: integer 254 | required: 255 | - weight 256 | - podAffinityTerm 257 | type: array 258 | requiredDuringSchedulingIgnoredDuringExecution: 259 | description: If the affinity requirements specified by this 260 | field are not met at scheduling time, the pod will not be 261 | scheduled onto the node. If the affinity requirements specified 262 | by this field cease to be met at some point during pod execution 263 | (e.g. due to a pod label update), the system may or may not 264 | try to eventually evict the pod from its node. When there 265 | are multiple elements, the lists of nodes corresponding to 266 | each podAffinityTerm are intersected, i.e. all terms must 267 | be satisfied. 268 | items: 269 | description: Defines a set of pods (namely those matching 270 | the labelSelector relative to the given namespace(s)) that 271 | this pod should be co-located (affinity) or not co-located 272 | (anti-affinity) with, where co-located is defined as running 273 | on a node whose value of the label with key 274 | matches that of any node on which a pod of the set of pods 275 | is running 276 | properties: 277 | labelSelector: 278 | description: A label selector is a label query over a 279 | set of resources. The result of matchLabels and matchExpressions 280 | are ANDed. An empty label selector matches all objects. 281 | A null label selector matches no objects. 282 | properties: 283 | matchExpressions: 284 | description: matchExpressions is a list of label selector 285 | requirements. The requirements are ANDed. 286 | items: 287 | description: A label selector requirement is a selector 288 | that contains values, a key, and an operator that 289 | relates the key and values. 290 | properties: 291 | key: 292 | description: key is the label key that the selector 293 | applies to. 294 | type: string 295 | operator: 296 | description: operator represents a key's relationship 297 | to a set of values. Valid operators are In, 298 | NotIn, Exists and DoesNotExist. 299 | type: string 300 | values: 301 | description: values is an array of string values. 302 | If the operator is In or NotIn, the values 303 | array must be non-empty. If the operator is 304 | Exists or DoesNotExist, the values array must 305 | be empty. This array is replaced during a 306 | strategic merge patch. 307 | items: 308 | type: string 309 | type: array 310 | required: 311 | - key 312 | - operator 313 | type: array 314 | matchLabels: 315 | description: matchLabels is a map of {key,value} pairs. 316 | A single {key,value} in the matchLabels map is equivalent 317 | to an element of matchExpressions, whose key field 318 | is "key", the operator is "In", and the values array 319 | contains only "value". The requirements are ANDed. 320 | type: object 321 | namespaces: 322 | description: namespaces specifies which namespaces the 323 | labelSelector applies to (matches against); null or 324 | empty list means "this pod's namespace" 325 | items: 326 | type: string 327 | type: array 328 | topologyKey: 329 | description: This pod should be co-located (affinity) 330 | or not co-located (anti-affinity) with the pods matching 331 | the labelSelector in the specified namespaces, where 332 | co-located is defined as running on a node whose value 333 | of the label with key topologyKey matches that of any 334 | node on which any of the selected pods is running. Empty 335 | topologyKey is not allowed. 336 | type: string 337 | required: 338 | - topologyKey 339 | type: array 340 | podAntiAffinity: 341 | description: Pod anti affinity is a group of inter pod anti affinity 342 | scheduling rules. 343 | properties: 344 | preferredDuringSchedulingIgnoredDuringExecution: 345 | description: The scheduler will prefer to schedule pods to nodes 346 | that satisfy the anti-affinity expressions specified by this 347 | field, but it may choose a node that violates one or more 348 | of the expressions. The node that is most preferred is the 349 | one with the greatest sum of weights, i.e. for each node that 350 | meets all of the scheduling requirements (resource request, 351 | requiredDuringScheduling anti-affinity expressions, etc.), 352 | compute a sum by iterating through the elements of this field 353 | and adding "weight" to the sum if the node has pods which 354 | matches the corresponding podAffinityTerm; the node(s) with 355 | the highest sum are the most preferred. 356 | items: 357 | description: The weights of all of the matched WeightedPodAffinityTerm 358 | fields are added per-node to find the most preferred node(s) 359 | properties: 360 | podAffinityTerm: 361 | description: Defines a set of pods (namely those matching 362 | the labelSelector relative to the given namespace(s)) 363 | that this pod should be co-located (affinity) or not 364 | co-located (anti-affinity) with, where co-located is 365 | defined as running on a node whose value of the label 366 | with key matches that of any node on which 367 | a pod of the set of pods is running 368 | properties: 369 | labelSelector: 370 | description: A label selector is a label query over 371 | a set of resources. The result of matchLabels and 372 | matchExpressions are ANDed. An empty label selector 373 | matches all objects. A null label selector matches 374 | no objects. 375 | properties: 376 | matchExpressions: 377 | description: matchExpressions is a list of label 378 | selector requirements. The requirements are 379 | ANDed. 380 | items: 381 | description: A label selector requirement is 382 | a selector that contains values, a key, and 383 | an operator that relates the key and values. 384 | properties: 385 | key: 386 | description: key is the label key that the 387 | selector applies to. 388 | type: string 389 | operator: 390 | description: operator represents a key's 391 | relationship to a set of values. Valid 392 | operators are In, NotIn, Exists and DoesNotExist. 393 | type: string 394 | values: 395 | description: values is an array of string 396 | values. If the operator is In or NotIn, 397 | the values array must be non-empty. If 398 | the operator is Exists or DoesNotExist, 399 | the values array must be empty. This array 400 | is replaced during a strategic merge patch. 401 | items: 402 | type: string 403 | type: array 404 | required: 405 | - key 406 | - operator 407 | type: array 408 | matchLabels: 409 | description: matchLabels is a map of {key,value} 410 | pairs. A single {key,value} in the matchLabels 411 | map is equivalent to an element of matchExpressions, 412 | whose key field is "key", the operator is "In", 413 | and the values array contains only "value". 414 | The requirements are ANDed. 415 | type: object 416 | namespaces: 417 | description: namespaces specifies which namespaces 418 | the labelSelector applies to (matches against); 419 | null or empty list means "this pod's namespace" 420 | items: 421 | type: string 422 | type: array 423 | topologyKey: 424 | description: This pod should be co-located (affinity) 425 | or not co-located (anti-affinity) with the pods 426 | matching the labelSelector in the specified namespaces, 427 | where co-located is defined as running on a node 428 | whose value of the label with key topologyKey matches 429 | that of any node on which any of the selected pods 430 | is running. Empty topologyKey is not allowed. 431 | type: string 432 | required: 433 | - topologyKey 434 | weight: 435 | description: weight associated with matching the corresponding 436 | podAffinityTerm, in the range 1-100. 437 | format: int32 438 | type: integer 439 | required: 440 | - weight 441 | - podAffinityTerm 442 | type: array 443 | requiredDuringSchedulingIgnoredDuringExecution: 444 | description: If the anti-affinity requirements specified by 445 | this field are not met at scheduling time, the pod will not 446 | be scheduled onto the node. If the anti-affinity requirements 447 | specified by this field cease to be met at some point during 448 | pod execution (e.g. due to a pod label update), the system 449 | may or may not try to eventually evict the pod from its node. 450 | When there are multiple elements, the lists of nodes corresponding 451 | to each podAffinityTerm are intersected, i.e. all terms must 452 | be satisfied. 453 | items: 454 | description: Defines a set of pods (namely those matching 455 | the labelSelector relative to the given namespace(s)) that 456 | this pod should be co-located (affinity) or not co-located 457 | (anti-affinity) with, where co-located is defined as running 458 | on a node whose value of the label with key 459 | matches that of any node on which a pod of the set of pods 460 | is running 461 | properties: 462 | labelSelector: 463 | description: A label selector is a label query over a 464 | set of resources. The result of matchLabels and matchExpressions 465 | are ANDed. An empty label selector matches all objects. 466 | A null label selector matches no objects. 467 | properties: 468 | matchExpressions: 469 | description: matchExpressions is a list of label selector 470 | requirements. The requirements are ANDed. 471 | items: 472 | description: A label selector requirement is a selector 473 | that contains values, a key, and an operator that 474 | relates the key and values. 475 | properties: 476 | key: 477 | description: key is the label key that the selector 478 | applies to. 479 | type: string 480 | operator: 481 | description: operator represents a key's relationship 482 | to a set of values. Valid operators are In, 483 | NotIn, Exists and DoesNotExist. 484 | type: string 485 | values: 486 | description: values is an array of string values. 487 | If the operator is In or NotIn, the values 488 | array must be non-empty. If the operator is 489 | Exists or DoesNotExist, the values array must 490 | be empty. This array is replaced during a 491 | strategic merge patch. 492 | items: 493 | type: string 494 | type: array 495 | required: 496 | - key 497 | - operator 498 | type: array 499 | matchLabels: 500 | description: matchLabels is a map of {key,value} pairs. 501 | A single {key,value} in the matchLabels map is equivalent 502 | to an element of matchExpressions, whose key field 503 | is "key", the operator is "In", and the values array 504 | contains only "value". The requirements are ANDed. 505 | type: object 506 | namespaces: 507 | description: namespaces specifies which namespaces the 508 | labelSelector applies to (matches against); null or 509 | empty list means "this pod's namespace" 510 | items: 511 | type: string 512 | type: array 513 | topologyKey: 514 | description: This pod should be co-located (affinity) 515 | or not co-located (anti-affinity) with the pods matching 516 | the labelSelector in the specified namespaces, where 517 | co-located is defined as running on a node whose value 518 | of the label with key topologyKey matches that of any 519 | node on which any of the selected pods is running. Empty 520 | topologyKey is not allowed. 521 | type: string 522 | required: 523 | - topologyKey 524 | type: array 525 | baseImage: 526 | description: Base image that is used to deploy pods. 527 | type: string 528 | externalUrl: 529 | description: The external URL the Alertmanager instances will be available 530 | under. This is necessary to generate correct URLs. This is necessary 531 | if Alertmanager is not served from root of a DNS name. 532 | type: string 533 | imagePullSecrets: 534 | description: An optional list of references to secrets in the same namespace 535 | to use for pulling prometheus and alertmanager images from registries 536 | see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod 537 | items: 538 | description: LocalObjectReference contains enough information to let 539 | you locate the referenced object inside the same namespace. 540 | properties: 541 | name: 542 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' 543 | type: string 544 | type: array 545 | nodeSelector: 546 | description: Define which Nodes the Pods are scheduled on. 547 | type: object 548 | paused: 549 | description: If set to true all actions on the underlaying managed objects 550 | are not goint to be performed, except for delete actions. 551 | type: boolean 552 | podMetadata: 553 | description: ObjectMeta is metadata that all persisted resources must 554 | have, which includes all objects users must create. 555 | properties: 556 | annotations: 557 | description: 'Annotations is an unstructured key value map stored 558 | with a resource that may be set by external tools to store and 559 | retrieve arbitrary metadata. They are not queryable and should 560 | be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' 561 | type: object 562 | clusterName: 563 | description: The name of the cluster which the object belongs to. 564 | This is used to distinguish resources with same name and namespace 565 | in different clusters. This field is not set anywhere right now 566 | and apiserver is going to ignore it if set in create or update 567 | request. 568 | type: string 569 | creationTimestamp: 570 | description: Time is a wrapper around time.Time which supports correct 571 | marshaling to YAML and JSON. Wrappers are provided for many of 572 | the factory methods that the time package offers. 573 | properties: 574 | Time: 575 | format: date-time 576 | type: string 577 | required: 578 | - Time 579 | deletionGracePeriodSeconds: 580 | description: Number of seconds allowed for this object to gracefully 581 | terminate before it will be removed from the system. Only set 582 | when deletionTimestamp is also set. May only be shortened. Read-only. 583 | format: int64 584 | type: integer 585 | deletionTimestamp: 586 | description: Time is a wrapper around time.Time which supports correct 587 | marshaling to YAML and JSON. Wrappers are provided for many of 588 | the factory methods that the time package offers. 589 | properties: 590 | Time: 591 | format: date-time 592 | type: string 593 | required: 594 | - Time 595 | finalizers: 596 | description: Must be empty before the object is deleted from the 597 | registry. Each entry is an identifier for the responsible component 598 | that will remove the entry from the list. If the deletionTimestamp 599 | of the object is non-nil, entries in this list can only be removed. 600 | items: 601 | type: string 602 | type: array 603 | generateName: 604 | description: |- 605 | GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server. 606 | 607 | If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header). 608 | 609 | Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency 610 | type: string 611 | generation: 612 | description: A sequence number representing a specific generation 613 | of the desired state. Populated by the system. Read-only. 614 | format: int64 615 | type: integer 616 | initializers: 617 | description: Initializers tracks the progress of initialization. 618 | properties: 619 | pending: 620 | description: Pending is a list of initializers that must execute 621 | in order before this object is visible. When the last pending 622 | initializer is removed, and no failing result is set, the 623 | initializers struct will be set to nil and the object is considered 624 | as initialized and visible to all clients. 625 | items: 626 | description: Initializer is information about an initializer 627 | that has not yet completed. 628 | properties: 629 | name: 630 | description: name of the process that is responsible for 631 | initializing this object. 632 | type: string 633 | required: 634 | - name 635 | type: array 636 | result: 637 | description: Status is a return value for calls that don't return 638 | other objects. 639 | properties: 640 | apiVersion: 641 | description: 'APIVersion defines the versioned schema of 642 | this representation of an object. Servers should convert 643 | recognized schemas to the latest internal value, and may 644 | reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 645 | type: string 646 | code: 647 | description: Suggested HTTP return code for this status, 648 | 0 if not set. 649 | format: int32 650 | type: integer 651 | details: 652 | description: StatusDetails is a set of additional properties 653 | that MAY be set by the server to provide additional information 654 | about a response. The Reason field of a Status object 655 | defines what attributes will be set. Clients must ignore 656 | fields that do not match the defined type of each attribute, 657 | and should assume that any attribute may be empty, invalid, 658 | or under defined. 659 | properties: 660 | causes: 661 | description: The Causes array includes more details 662 | associated with the StatusReason failure. Not all 663 | StatusReasons may provide detailed causes. 664 | items: 665 | description: StatusCause provides more information 666 | about an api.Status failure, including cases when 667 | multiple errors are encountered. 668 | properties: 669 | field: 670 | description: |- 671 | The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional. 672 | 673 | Examples: 674 | "name" - the field "name" on the current resource 675 | "items[0].name" - the field "name" on the first array entry in "items" 676 | type: string 677 | message: 678 | description: A human-readable description of the 679 | cause of the error. This field may be presented 680 | as-is to a reader. 681 | type: string 682 | reason: 683 | description: A machine-readable description of 684 | the cause of the error. If this value is empty 685 | there is no information available. 686 | type: string 687 | type: array 688 | group: 689 | description: The group attribute of the resource associated 690 | with the status StatusReason. 691 | type: string 692 | kind: 693 | description: 'The kind attribute of the resource associated 694 | with the status StatusReason. On some operations may 695 | differ from the requested resource Kind. More info: 696 | https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 697 | type: string 698 | name: 699 | description: The name attribute of the resource associated 700 | with the status StatusReason (when there is a single 701 | name which can be described). 702 | type: string 703 | retryAfterSeconds: 704 | description: If specified, the time in seconds before 705 | the operation should be retried. Some errors may indicate 706 | the client must take an alternate action - for those 707 | errors this field may indicate how long to wait before 708 | taking the alternate action. 709 | format: int32 710 | type: integer 711 | uid: 712 | description: 'UID of the resource. (when there is a 713 | single resource which can be described). More info: 714 | http://kubernetes.io/docs/user-guide/identifiers#uids' 715 | type: string 716 | kind: 717 | description: 'Kind is a string value representing the REST 718 | resource this object represents. Servers may infer this 719 | from the endpoint the client submits requests to. Cannot 720 | be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 721 | type: string 722 | message: 723 | description: A human-readable description of the status 724 | of this operation. 725 | type: string 726 | metadata: 727 | description: ListMeta describes metadata that synthetic 728 | resources must have, including lists and various status 729 | objects. A resource may have only one of {ObjectMeta, 730 | ListMeta}. 731 | properties: 732 | continue: 733 | description: continue may be set if the user set a limit 734 | on the number of items returned, and indicates that 735 | the server has more data available. The value is opaque 736 | and may be used to issue another request to the endpoint 737 | that served this list to retrieve the next set of 738 | available objects. Continuing a list may not be possible 739 | if the server configuration has changed or more than 740 | a few minutes have passed. The resourceVersion field 741 | returned when using this continue value will be identical 742 | to the value in the first response. 743 | type: string 744 | resourceVersion: 745 | description: 'String that identifies the server''s internal 746 | version of this object that can be used by clients 747 | to determine when objects have changed. Value must 748 | be treated as opaque by clients and passed unmodified 749 | back to the server. Populated by the system. Read-only. 750 | More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' 751 | type: string 752 | selfLink: 753 | description: selfLink is a URL representing this object. 754 | Populated by the system. Read-only. 755 | type: string 756 | reason: 757 | description: A machine-readable description of why this 758 | operation is in the "Failure" status. If this value is 759 | empty there is no information available. A Reason clarifies 760 | an HTTP status code but does not override it. 761 | type: string 762 | status: 763 | description: 'Status of the operation. One of: "Success" 764 | or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status' 765 | type: string 766 | required: 767 | - pending 768 | labels: 769 | description: 'Map of string keys and values that can be used to 770 | organize and categorize (scope and select) objects. May match 771 | selectors of replication controllers and services. More info: 772 | http://kubernetes.io/docs/user-guide/labels' 773 | type: object 774 | name: 775 | description: 'Name must be unique within a namespace. Is required 776 | when creating resources, although some resources may allow a client 777 | to request the generation of an appropriate name automatically. 778 | Name is primarily intended for creation idempotence and configuration 779 | definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' 780 | type: string 781 | namespace: 782 | description: |- 783 | Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty. 784 | 785 | Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces 786 | type: string 787 | ownerReferences: 788 | description: List of objects depended by this object. If ALL objects 789 | in the list have been deleted, this object will be garbage collected. 790 | If this object is managed by a controller, then an entry in this 791 | list will point to this controller, with the controller field 792 | set to true. There cannot be more than one managing controller. 793 | items: 794 | description: OwnerReference contains enough information to let 795 | you identify an owning object. Currently, an owning object must 796 | be in the same namespace, so there is no namespace field. 797 | properties: 798 | apiVersion: 799 | description: API version of the referent. 800 | type: string 801 | blockOwnerDeletion: 802 | description: If true, AND if the owner has the "foregroundDeletion" 803 | finalizer, then the owner cannot be deleted from the key-value 804 | store until this reference is removed. Defaults to false. 805 | To set this field, a user needs "delete" permission of the 806 | owner, otherwise 422 (Unprocessable Entity) will be returned. 807 | type: boolean 808 | controller: 809 | description: If true, this reference points to the managing 810 | controller. 811 | type: boolean 812 | kind: 813 | description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 814 | type: string 815 | name: 816 | description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' 817 | type: string 818 | uid: 819 | description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' 820 | type: string 821 | required: 822 | - apiVersion 823 | - kind 824 | - name 825 | - uid 826 | type: array 827 | resourceVersion: 828 | description: |- 829 | An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources. 830 | 831 | Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency 832 | type: string 833 | selfLink: 834 | description: SelfLink is a URL representing this object. Populated 835 | by the system. Read-only. 836 | type: string 837 | uid: 838 | description: |- 839 | UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations. 840 | 841 | Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids 842 | type: string 843 | replicas: 844 | description: Size is the expected size of the alertmanager cluster. 845 | The controller will eventually make the size of the running cluster 846 | equal to the expected size. 847 | format: int32 848 | type: integer 849 | resources: 850 | description: ResourceRequirements describes the compute resource requirements. 851 | properties: 852 | limits: 853 | description: 'Limits describes the maximum amount of compute resources 854 | allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 855 | type: object 856 | requests: 857 | description: 'Requests describes the minimum amount of compute resources 858 | required. If Requests is omitted for a container, it defaults 859 | to Limits if that is explicitly specified, otherwise to an implementation-defined 860 | value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 861 | type: object 862 | routePrefix: 863 | description: The route prefix Alertmanager registers HTTP handlers for. 864 | This is useful, if using ExternalURL and a proxy is rewriting HTTP 865 | routes of a request, and the actual ExternalURL is still true, but 866 | the server serves requests under a different route prefix. For example 867 | for use with `kubectl proxy`. 868 | type: string 869 | storage: 870 | description: StorageSpec defines the configured storage for a group 871 | Prometheus servers. 872 | properties: 873 | class: 874 | description: 'Name of the StorageClass to use when requesting storage 875 | provisioning. More info: https://kubernetes.io/docs/user-guide/persistent-volumes/#storageclasses 876 | DEPRECATED' 877 | type: string 878 | emptyDir: 879 | description: Represents an empty directory for a pod. Empty directory 880 | volumes support ownership management and SELinux relabeling. 881 | properties: 882 | medium: 883 | description: 'What type of storage medium should back this directory. 884 | The default is "" which means to use the node''s default medium. 885 | Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' 886 | type: string 887 | sizeLimit: {} 888 | resources: 889 | description: ResourceRequirements describes the compute resource 890 | requirements. 891 | properties: 892 | limits: 893 | description: 'Limits describes the maximum amount of compute 894 | resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 895 | type: object 896 | requests: 897 | description: 'Requests describes the minimum amount of compute 898 | resources required. If Requests is omitted for a container, 899 | it defaults to Limits if that is explicitly specified, otherwise 900 | to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 901 | type: object 902 | selector: 903 | description: A label selector is a label query over a set of resources. 904 | The result of matchLabels and matchExpressions are ANDed. An empty 905 | label selector matches all objects. A null label selector matches 906 | no objects. 907 | properties: 908 | matchExpressions: 909 | description: matchExpressions is a list of label selector requirements. 910 | The requirements are ANDed. 911 | items: 912 | description: A label selector requirement is a selector that 913 | contains values, a key, and an operator that relates the 914 | key and values. 915 | properties: 916 | key: 917 | description: key is the label key that the selector applies 918 | to. 919 | type: string 920 | operator: 921 | description: operator represents a key's relationship 922 | to a set of values. Valid operators are In, NotIn, Exists 923 | and DoesNotExist. 924 | type: string 925 | values: 926 | description: values is an array of string values. If the 927 | operator is In or NotIn, the values array must be non-empty. 928 | If the operator is Exists or DoesNotExist, the values 929 | array must be empty. This array is replaced during a 930 | strategic merge patch. 931 | items: 932 | type: string 933 | type: array 934 | required: 935 | - key 936 | - operator 937 | type: array 938 | matchLabels: 939 | description: matchLabels is a map of {key,value} pairs. A single 940 | {key,value} in the matchLabels map is equivalent to an element 941 | of matchExpressions, whose key field is "key", the operator 942 | is "In", and the values array contains only "value". The requirements 943 | are ANDed. 944 | type: object 945 | volumeClaimTemplate: 946 | description: PersistentVolumeClaim is a user's request for and claim 947 | to a persistent volume 948 | properties: 949 | apiVersion: 950 | description: 'APIVersion defines the versioned schema of this 951 | representation of an object. Servers should convert recognized 952 | schemas to the latest internal value, and may reject unrecognized 953 | values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 954 | type: string 955 | kind: 956 | description: 'Kind is a string value representing the REST resource 957 | this object represents. Servers may infer this from the endpoint 958 | the client submits requests to. Cannot be updated. In CamelCase. 959 | More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 960 | type: string 961 | metadata: 962 | description: ObjectMeta is metadata that all persisted resources 963 | must have, which includes all objects users must create. 964 | properties: 965 | annotations: 966 | description: 'Annotations is an unstructured key value map 967 | stored with a resource that may be set by external tools 968 | to store and retrieve arbitrary metadata. They are not 969 | queryable and should be preserved when modifying objects. 970 | More info: http://kubernetes.io/docs/user-guide/annotations' 971 | type: object 972 | clusterName: 973 | description: The name of the cluster which the object belongs 974 | to. This is used to distinguish resources with same name 975 | and namespace in different clusters. This field is not 976 | set anywhere right now and apiserver is going to ignore 977 | it if set in create or update request. 978 | type: string 979 | creationTimestamp: 980 | description: Time is a wrapper around time.Time which supports 981 | correct marshaling to YAML and JSON. Wrappers are provided 982 | for many of the factory methods that the time package 983 | offers. 984 | properties: 985 | Time: 986 | format: date-time 987 | type: string 988 | required: 989 | - Time 990 | deletionGracePeriodSeconds: 991 | description: Number of seconds allowed for this object to 992 | gracefully terminate before it will be removed from the 993 | system. Only set when deletionTimestamp is also set. May 994 | only be shortened. Read-only. 995 | format: int64 996 | type: integer 997 | deletionTimestamp: 998 | description: Time is a wrapper around time.Time which supports 999 | correct marshaling to YAML and JSON. Wrappers are provided 1000 | for many of the factory methods that the time package 1001 | offers. 1002 | properties: 1003 | Time: 1004 | format: date-time 1005 | type: string 1006 | required: 1007 | - Time 1008 | finalizers: 1009 | description: Must be empty before the object is deleted 1010 | from the registry. Each entry is an identifier for the 1011 | responsible component that will remove the entry from 1012 | the list. If the deletionTimestamp of the object is non-nil, 1013 | entries in this list can only be removed. 1014 | items: 1015 | type: string 1016 | type: array 1017 | generateName: 1018 | description: |- 1019 | GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server. 1020 | 1021 | If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header). 1022 | 1023 | Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency 1024 | type: string 1025 | generation: 1026 | description: A sequence number representing a specific generation 1027 | of the desired state. Populated by the system. Read-only. 1028 | format: int64 1029 | type: integer 1030 | initializers: 1031 | description: Initializers tracks the progress of initialization. 1032 | properties: 1033 | pending: 1034 | description: Pending is a list of initializers that 1035 | must execute in order before this object is visible. 1036 | When the last pending initializer is removed, and 1037 | no failing result is set, the initializers struct 1038 | will be set to nil and the object is considered as 1039 | initialized and visible to all clients. 1040 | items: 1041 | description: Initializer is information about an initializer 1042 | that has not yet completed. 1043 | properties: 1044 | name: 1045 | description: name of the process that is responsible 1046 | for initializing this object. 1047 | type: string 1048 | required: 1049 | - name 1050 | type: array 1051 | result: 1052 | description: Status is a return value for calls that 1053 | don't return other objects. 1054 | properties: 1055 | apiVersion: 1056 | description: 'APIVersion defines the versioned schema 1057 | of this representation of an object. Servers should 1058 | convert recognized schemas to the latest internal 1059 | value, and may reject unrecognized values. More 1060 | info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 1061 | type: string 1062 | code: 1063 | description: Suggested HTTP return code for this 1064 | status, 0 if not set. 1065 | format: int32 1066 | type: integer 1067 | details: 1068 | description: StatusDetails is a set of additional 1069 | properties that MAY be set by the server to provide 1070 | additional information about a response. The Reason 1071 | field of a Status object defines what attributes 1072 | will be set. Clients must ignore fields that do 1073 | not match the defined type of each attribute, 1074 | and should assume that any attribute may be empty, 1075 | invalid, or under defined. 1076 | properties: 1077 | causes: 1078 | description: The Causes array includes more 1079 | details associated with the StatusReason failure. 1080 | Not all StatusReasons may provide detailed 1081 | causes. 1082 | items: 1083 | description: StatusCause provides more information 1084 | about an api.Status failure, including cases 1085 | when multiple errors are encountered. 1086 | properties: 1087 | field: 1088 | description: |- 1089 | The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional. 1090 | 1091 | Examples: 1092 | "name" - the field "name" on the current resource 1093 | "items[0].name" - the field "name" on the first array entry in "items" 1094 | type: string 1095 | message: 1096 | description: A human-readable description 1097 | of the cause of the error. This field 1098 | may be presented as-is to a reader. 1099 | type: string 1100 | reason: 1101 | description: A machine-readable description 1102 | of the cause of the error. If this value 1103 | is empty there is no information available. 1104 | type: string 1105 | type: array 1106 | group: 1107 | description: The group attribute of the resource 1108 | associated with the status StatusReason. 1109 | type: string 1110 | kind: 1111 | description: 'The kind attribute of the resource 1112 | associated with the status StatusReason. On 1113 | some operations may differ from the requested 1114 | resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 1115 | type: string 1116 | name: 1117 | description: The name attribute of the resource 1118 | associated with the status StatusReason (when 1119 | there is a single name which can be described). 1120 | type: string 1121 | retryAfterSeconds: 1122 | description: If specified, the time in seconds 1123 | before the operation should be retried. Some 1124 | errors may indicate the client must take an 1125 | alternate action - for those errors this field 1126 | may indicate how long to wait before taking 1127 | the alternate action. 1128 | format: int32 1129 | type: integer 1130 | uid: 1131 | description: 'UID of the resource. (when there 1132 | is a single resource which can be described). 1133 | More info: http://kubernetes.io/docs/user-guide/identifiers#uids' 1134 | type: string 1135 | kind: 1136 | description: 'Kind is a string value representing 1137 | the REST resource this object represents. Servers 1138 | may infer this from the endpoint the client submits 1139 | requests to. Cannot be updated. In CamelCase. 1140 | More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 1141 | type: string 1142 | message: 1143 | description: A human-readable description of the 1144 | status of this operation. 1145 | type: string 1146 | metadata: 1147 | description: ListMeta describes metadata that synthetic 1148 | resources must have, including lists and various 1149 | status objects. A resource may have only one of 1150 | {ObjectMeta, ListMeta}. 1151 | properties: 1152 | continue: 1153 | description: continue may be set if the user 1154 | set a limit on the number of items returned, 1155 | and indicates that the server has more data 1156 | available. The value is opaque and may be 1157 | used to issue another request to the endpoint 1158 | that served this list to retrieve the next 1159 | set of available objects. Continuing a list 1160 | may not be possible if the server configuration 1161 | has changed or more than a few minutes have 1162 | passed. The resourceVersion field returned 1163 | when using this continue value will be identical 1164 | to the value in the first response. 1165 | type: string 1166 | resourceVersion: 1167 | description: 'String that identifies the server''s 1168 | internal version of this object that can be 1169 | used by clients to determine when objects 1170 | have changed. Value must be treated as opaque 1171 | by clients and passed unmodified back to the 1172 | server. Populated by the system. Read-only. 1173 | More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' 1174 | type: string 1175 | selfLink: 1176 | description: selfLink is a URL representing 1177 | this object. Populated by the system. Read-only. 1178 | type: string 1179 | reason: 1180 | description: A machine-readable description of why 1181 | this operation is in the "Failure" status. If 1182 | this value is empty there is no information available. 1183 | A Reason clarifies an HTTP status code but does 1184 | not override it. 1185 | type: string 1186 | status: 1187 | description: 'Status of the operation. One of: "Success" 1188 | or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status' 1189 | type: string 1190 | required: 1191 | - pending 1192 | labels: 1193 | description: 'Map of string keys and values that can be 1194 | used to organize and categorize (scope and select) objects. 1195 | May match selectors of replication controllers and services. 1196 | More info: http://kubernetes.io/docs/user-guide/labels' 1197 | type: object 1198 | name: 1199 | description: 'Name must be unique within a namespace. Is 1200 | required when creating resources, although some resources 1201 | may allow a client to request the generation of an appropriate 1202 | name automatically. Name is primarily intended for creation 1203 | idempotence and configuration definition. Cannot be updated. 1204 | More info: http://kubernetes.io/docs/user-guide/identifiers#names' 1205 | type: string 1206 | namespace: 1207 | description: |- 1208 | Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty. 1209 | 1210 | Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces 1211 | type: string 1212 | ownerReferences: 1213 | description: List of objects depended by this object. If 1214 | ALL objects in the list have been deleted, this object 1215 | will be garbage collected. If this object is managed by 1216 | a controller, then an entry in this list will point to 1217 | this controller, with the controller field set to true. 1218 | There cannot be more than one managing controller. 1219 | items: 1220 | description: OwnerReference contains enough information 1221 | to let you identify an owning object. Currently, an 1222 | owning object must be in the same namespace, so there 1223 | is no namespace field. 1224 | properties: 1225 | apiVersion: 1226 | description: API version of the referent. 1227 | type: string 1228 | blockOwnerDeletion: 1229 | description: If true, AND if the owner has the "foregroundDeletion" 1230 | finalizer, then the owner cannot be deleted from 1231 | the key-value store until this reference is removed. 1232 | Defaults to false. To set this field, a user needs 1233 | "delete" permission of the owner, otherwise 422 1234 | (Unprocessable Entity) will be returned. 1235 | type: boolean 1236 | controller: 1237 | description: If true, this reference points to the 1238 | managing controller. 1239 | type: boolean 1240 | kind: 1241 | description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 1242 | type: string 1243 | name: 1244 | description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' 1245 | type: string 1246 | uid: 1247 | description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' 1248 | type: string 1249 | required: 1250 | - apiVersion 1251 | - kind 1252 | - name 1253 | - uid 1254 | type: array 1255 | resourceVersion: 1256 | description: |- 1257 | An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources. 1258 | 1259 | Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency 1260 | type: string 1261 | selfLink: 1262 | description: SelfLink is a URL representing this object. 1263 | Populated by the system. Read-only. 1264 | type: string 1265 | uid: 1266 | description: |- 1267 | UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations. 1268 | 1269 | Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids 1270 | type: string 1271 | spec: 1272 | description: PersistentVolumeClaimSpec describes the common 1273 | attributes of storage devices and allows a Source for provider-specific 1274 | attributes 1275 | properties: 1276 | accessModes: 1277 | description: 'AccessModes contains the desired access modes 1278 | the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' 1279 | items: 1280 | type: string 1281 | type: array 1282 | resources: 1283 | description: ResourceRequirements describes the compute 1284 | resource requirements. 1285 | properties: 1286 | limits: 1287 | description: 'Limits describes the maximum amount of 1288 | compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 1289 | type: object 1290 | requests: 1291 | description: 'Requests describes the minimum amount 1292 | of compute resources required. If Requests is omitted 1293 | for a container, it defaults to Limits if that is 1294 | explicitly specified, otherwise to an implementation-defined 1295 | value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' 1296 | type: object 1297 | selector: 1298 | description: A label selector is a label query over a set 1299 | of resources. The result of matchLabels and matchExpressions 1300 | are ANDed. An empty label selector matches all objects. 1301 | A null label selector matches no objects. 1302 | properties: 1303 | matchExpressions: 1304 | description: matchExpressions is a list of label selector 1305 | requirements. The requirements are ANDed. 1306 | items: 1307 | description: A label selector requirement is a selector 1308 | that contains values, a key, and an operator that 1309 | relates the key and values. 1310 | properties: 1311 | key: 1312 | description: key is the label key that the selector 1313 | applies to. 1314 | type: string 1315 | operator: 1316 | description: operator represents a key's relationship 1317 | to a set of values. Valid operators are In, 1318 | NotIn, Exists and DoesNotExist. 1319 | type: string 1320 | values: 1321 | description: values is an array of string values. 1322 | If the operator is In or NotIn, the values array 1323 | must be non-empty. If the operator is Exists 1324 | or DoesNotExist, the values array must be empty. 1325 | This array is replaced during a strategic merge 1326 | patch. 1327 | items: 1328 | type: string 1329 | type: array 1330 | required: 1331 | - key 1332 | - operator 1333 | type: array 1334 | matchLabels: 1335 | description: matchLabels is a map of {key,value} pairs. 1336 | A single {key,value} in the matchLabels map is equivalent 1337 | to an element of matchExpressions, whose key field 1338 | is "key", the operator is "In", and the values array 1339 | contains only "value". The requirements are ANDed. 1340 | type: object 1341 | storageClassName: 1342 | description: 'Name of the StorageClass required by the claim. 1343 | More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' 1344 | type: string 1345 | volumeMode: 1346 | description: volumeMode defines what type of volume is required 1347 | by the claim. Value of Filesystem is implied when not 1348 | included in claim spec. This is an alpha feature and may 1349 | change in the future. 1350 | type: string 1351 | volumeName: 1352 | description: VolumeName is the binding reference to the 1353 | PersistentVolume backing this claim. 1354 | type: string 1355 | status: 1356 | description: PersistentVolumeClaimStatus is the current status 1357 | of a persistent volume claim. 1358 | properties: 1359 | accessModes: 1360 | description: 'AccessModes contains the actual access modes 1361 | the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' 1362 | items: 1363 | type: string 1364 | type: array 1365 | capacity: 1366 | description: Represents the actual resources of the underlying 1367 | volume. 1368 | type: object 1369 | conditions: 1370 | description: Current Condition of persistent volume claim. 1371 | If underlying persistent volume is being resized then 1372 | the Condition will be set to 'ResizeStarted'. 1373 | items: 1374 | description: PersistentVolumeClaimCondition contails details 1375 | about state of pvc 1376 | properties: 1377 | lastProbeTime: 1378 | description: Time is a wrapper around time.Time which 1379 | supports correct marshaling to YAML and JSON. Wrappers 1380 | are provided for many of the factory methods that 1381 | the time package offers. 1382 | properties: 1383 | Time: 1384 | format: date-time 1385 | type: string 1386 | required: 1387 | - Time 1388 | lastTransitionTime: 1389 | description: Time is a wrapper around time.Time which 1390 | supports correct marshaling to YAML and JSON. Wrappers 1391 | are provided for many of the factory methods that 1392 | the time package offers. 1393 | properties: 1394 | Time: 1395 | format: date-time 1396 | type: string 1397 | required: 1398 | - Time 1399 | message: 1400 | description: Human-readable message indicating details 1401 | about last transition. 1402 | type: string 1403 | reason: 1404 | description: Unique, this should be a short, machine 1405 | understandable string that gives the reason for 1406 | condition's last transition. If it reports "ResizeStarted" 1407 | that means the underlying persistent volume is being 1408 | resized. 1409 | type: string 1410 | status: 1411 | type: string 1412 | type: 1413 | type: string 1414 | required: 1415 | - type 1416 | - status 1417 | type: array 1418 | phase: 1419 | description: Phase represents the current phase of PersistentVolumeClaim. 1420 | type: string 1421 | required: 1422 | - class 1423 | - selector 1424 | - resources 1425 | tolerations: 1426 | description: If specified, the pod's tolerations. 1427 | items: 1428 | description: The pod this Toleration is attached to tolerates any 1429 | taint that matches the triple using the matching 1430 | operator . 1431 | properties: 1432 | effect: 1433 | description: Effect indicates the taint effect to match. Empty 1434 | means match all taint effects. When specified, allowed values 1435 | are NoSchedule, PreferNoSchedule and NoExecute. 1436 | type: string 1437 | key: 1438 | description: Key is the taint key that the toleration applies 1439 | to. Empty means match all taint keys. If the key is empty, operator 1440 | must be Exists; this combination means to match all values and 1441 | all keys. 1442 | type: string 1443 | operator: 1444 | description: Operator represents a key's relationship to the value. 1445 | Valid operators are Exists and Equal. Defaults to Equal. Exists 1446 | is equivalent to wildcard for value, so that a pod can tolerate 1447 | all taints of a particular category. 1448 | type: string 1449 | tolerationSeconds: 1450 | description: TolerationSeconds represents the period of time the 1451 | toleration (which must be of effect NoExecute, otherwise this 1452 | field is ignored) tolerates the taint. By default, it is not 1453 | set, which means tolerate the taint forever (do not evict). 1454 | Zero and negative values will be treated as 0 (evict immediately) 1455 | by the system. 1456 | format: int64 1457 | type: integer 1458 | value: 1459 | description: Value is the taint value the toleration matches to. 1460 | If the operator is Exists, the value should be empty, otherwise 1461 | just a regular string. 1462 | type: string 1463 | type: array 1464 | version: 1465 | description: Version the cluster should be on. 1466 | type: string 1467 | status: 1468 | description: 'Most recent observed status of the Alertmanager cluster. Read-only. 1469 | Not included when requesting from the apiserver, only from the Prometheus 1470 | Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status' 1471 | properties: 1472 | availableReplicas: 1473 | description: Total number of available pods (ready for at least minReadySeconds) 1474 | targeted by this Alertmanager cluster. 1475 | format: int32 1476 | type: integer 1477 | paused: 1478 | description: Represents whether any actions on the underlaying managed 1479 | objects are being performed. Only delete actions will be performed. 1480 | type: boolean 1481 | replicas: 1482 | description: Total number of non-terminated pods targeted by this Alertmanager 1483 | cluster (their labels match the selector). 1484 | format: int32 1485 | type: integer 1486 | unavailableReplicas: 1487 | description: Total number of unavailable pods targeted by this Alertmanager 1488 | cluster. 1489 | format: int32 1490 | type: integer 1491 | updatedReplicas: 1492 | description: Total number of non-terminated pods targeted by this Alertmanager 1493 | cluster that have the desired version spec. 1494 | format: int32 1495 | type: integer 1496 | required: 1497 | - paused 1498 | - replicas 1499 | - updatedReplicas 1500 | - availableReplicas 1501 | - unavailableReplicas 1502 | required: 1503 | - spec 1504 | version: v1 1505 | status: 1506 | acceptedNames: 1507 | kind: "" 1508 | plural: "" 1509 | conditions: null 1510 | -------------------------------------------------------------------------------- /example/prometheus-crd-gen/generated-crd/servicemonitor.crd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1beta1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | creationTimestamp: null 6 | labels: 7 | generation-date: 2018-01-29 20:02:17 8 | name: servicemonitors.monitoring.coreos.com 9 | spec: 10 | group: monitoring.coreos.com 11 | names: 12 | kind: ServiceMonitor 13 | plural: servicemonitors 14 | scope: Cluster 15 | validation: 16 | openAPIV3Schema: 17 | description: ServiceMonitor defines monitoring for a set of services. 18 | properties: 19 | apiVersion: 20 | description: 'APIVersion defines the versioned schema of this representation 21 | of an object. Servers should convert recognized schemas to the latest 22 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' 23 | type: string 24 | kind: 25 | description: 'Kind is a string value representing the REST resource this 26 | object represents. Servers may infer this from the endpoint the client 27 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' 28 | type: string 29 | spec: 30 | description: ServiceMonitorSpec contains specification parameters for a 31 | ServiceMonitor. 32 | properties: 33 | endpoints: 34 | description: A list of endpoints allowed as part of this ServiceMonitor. 35 | items: 36 | description: Endpoint defines a scrapeable endpoint serving Prometheus 37 | metrics. 38 | properties: 39 | basicAuth: 40 | description: 'BasicAuth allow an endpoint to authenticate over 41 | basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' 42 | properties: 43 | password: 44 | description: SecretKeySelector selects a key of a Secret. 45 | properties: 46 | key: 47 | description: The key of the secret to select from. Must 48 | be a valid secret key. 49 | type: string 50 | name: 51 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' 52 | type: string 53 | optional: 54 | description: Specify whether the Secret or it's key must 55 | be defined 56 | type: boolean 57 | required: 58 | - key 59 | username: 60 | description: SecretKeySelector selects a key of a Secret. 61 | properties: 62 | key: 63 | description: The key of the secret to select from. Must 64 | be a valid secret key. 65 | type: string 66 | name: 67 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' 68 | type: string 69 | optional: 70 | description: Specify whether the Secret or it's key must 71 | be defined 72 | type: boolean 73 | required: 74 | - key 75 | bearerTokenFile: 76 | description: File to read bearer token for scraping targets. 77 | type: string 78 | honorLabels: 79 | description: HonorLabels chooses the metric's labels on collisions 80 | with target labels. 81 | type: boolean 82 | interval: 83 | description: Interval at which metrics should be scraped 84 | type: string 85 | metricRelabelings: 86 | description: MetricRelabelConfigs to apply to samples before ingestion. 87 | items: 88 | description: RelabelConfig allows dynamic rewriting of the label 89 | set. 90 | properties: 91 | action: 92 | description: Action to perform based on regex matching. 93 | Default is 'replace' 94 | type: string 95 | modulus: 96 | description: Modulus to take of the hash of the source label 97 | values. 98 | format: int64 99 | type: integer 100 | regex: 101 | description: Regular expression against which the extracted 102 | value is matched. defailt is '(.*)' 103 | type: string 104 | replacement: 105 | description: Replacement value against which a regex replace 106 | is performed if the regular expression matches. Regex 107 | capture groups are available. Default is '$1' 108 | type: string 109 | separator: 110 | description: Separator placed between concatenated source 111 | label values. default is ';'. 112 | type: string 113 | sourceLabels: 114 | description: The source labels select values from existing 115 | labels. Their content is concatenated using the configured 116 | separator and matched against the configured regular expression 117 | for the replace, keep, and drop actions. 118 | items: 119 | type: string 120 | type: array 121 | targetLabel: 122 | description: Label to which the resulting value is written 123 | in a replace action. It is mandatory for replace actions. 124 | Regex capture groups are available. 125 | type: string 126 | required: 127 | - sourceLabels 128 | - replacement 129 | type: array 130 | params: 131 | description: Optional HTTP URL parameters 132 | type: object 133 | path: 134 | description: HTTP path to scrape for metrics. 135 | type: string 136 | port: 137 | description: Name of the service port this endpoint refers to. 138 | Mutually exclusive with targetPort. 139 | type: string 140 | scheme: 141 | description: HTTP scheme to use for scraping. 142 | type: string 143 | scrapeTimeout: 144 | description: Timeout after which the scrape is ended 145 | type: string 146 | targetPort: {} 147 | tlsConfig: 148 | description: TLSConfig specifies TLS configuration parameters. 149 | properties: 150 | caFile: 151 | description: The CA cert to use for the targets. 152 | type: string 153 | certFile: 154 | description: The client cert file for the targets. 155 | type: string 156 | insecureSkipVerify: 157 | description: Disable target certificate validation. 158 | type: boolean 159 | keyFile: 160 | description: The client key file for the targets. 161 | type: string 162 | serverName: 163 | description: Used to verify the hostname for the targets. 164 | type: string 165 | type: array 166 | jobLabel: 167 | description: The label to use to retrieve the job name from. 168 | type: string 169 | namespaceSelector: 170 | description: A selector for selecting namespaces either selecting all 171 | namespaces or a list of namespaces. 172 | properties: 173 | any: 174 | description: Boolean describing whether all namespaces are selected 175 | in contrast to a list restricting them. 176 | type: boolean 177 | matchNames: 178 | description: List of namespace names. 179 | items: 180 | type: string 181 | type: array 182 | selector: 183 | description: A label selector is a label query over a set of resources. 184 | The result of matchLabels and matchExpressions are ANDed. An empty 185 | label selector matches all objects. A null label selector matches 186 | no objects. 187 | properties: 188 | matchExpressions: 189 | description: matchExpressions is a list of label selector requirements. 190 | The requirements are ANDed. 191 | items: 192 | description: A label selector requirement is a selector that contains 193 | values, a key, and an operator that relates the key and values. 194 | properties: 195 | key: 196 | description: key is the label key that the selector applies 197 | to. 198 | type: string 199 | operator: 200 | description: operator represents a key's relationship to a 201 | set of values. Valid operators are In, NotIn, Exists and 202 | DoesNotExist. 203 | type: string 204 | values: 205 | description: values is an array of string values. If the operator 206 | is In or NotIn, the values array must be non-empty. If the 207 | operator is Exists or DoesNotExist, the values array must 208 | be empty. This array is replaced during a strategic merge 209 | patch. 210 | items: 211 | type: string 212 | type: array 213 | required: 214 | - key 215 | - operator 216 | type: array 217 | matchLabels: 218 | description: matchLabels is a map of {key,value} pairs. A single 219 | {key,value} in the matchLabels map is equivalent to an element 220 | of matchExpressions, whose key field is "key", the operator is 221 | "In", and the values array contains only "value". The requirements 222 | are ANDed. 223 | type: object 224 | required: 225 | - endpoints 226 | - selector 227 | required: 228 | - spec 229 | version: v1 230 | status: 231 | acceptedNames: 232 | kind: "" 233 | plural: "" 234 | conditions: null 235 | -------------------------------------------------------------------------------- /example/prometheus-crd-gen/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | v1 "github.com/ant31/crd-validation/example/prometheus-crd-gen/v1" 19 | crdutils "github.com/ant31/crd-validation/pkg" 20 | "os" 21 | ) 22 | 23 | var ( 24 | cfg crdutils.Config 25 | ) 26 | 27 | func init() { 28 | flagset := flag.NewFlagSet(os.Args[0], flag.ExitOnError) 29 | flagset := crdutils.InitFlags(&cfg, flagset) 30 | flagset.Parse(os.Args[1:]) 31 | } 32 | 33 | func main() { 34 | cfg.GetOpenAPIDefinitions = v1.GetOpenAPIDefinitions 35 | crd := crdutils.NewCustomResourceDefinition(cfg) 36 | crdutils.MarshallCrd(crd, cfg.OutputFormat) 37 | os.Exit(0) 38 | } 39 | -------------------------------------------------------------------------------- /example/prometheus-crd-gen/v1/types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The prometheus-operator Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package v1 16 | 17 | import ( 18 | "k8s.io/api/core/v1" 19 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 20 | "k8s.io/apimachinery/pkg/util/intstr" 21 | ) 22 | 23 | // Prometheus defines a Prometheus deployment. 24 | // +k8s:openapi-gen=true 25 | type Prometheus struct { 26 | metav1.TypeMeta `json:",inline"` 27 | // Standard object’s metadata. More info: 28 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 29 | // +k8s:openapi-gen=false 30 | metav1.ObjectMeta `json:"metadata,omitempty"` 31 | // Specification of the desired behavior of the Prometheus cluster. More info: 32 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 33 | Spec PrometheusSpec `json:"spec"` 34 | // Most recent observed status of the Prometheus cluster. Read-only. Not 35 | // included when requesting from the apiserver, only from the Prometheus 36 | // Operator API itself. More info: 37 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 38 | Status *PrometheusStatus `json:"status,omitempty"` 39 | } 40 | 41 | // PrometheusList is a list of Prometheuses. 42 | // +k8s:openapi-gen=true 43 | type PrometheusList struct { 44 | metav1.TypeMeta `json:",inline"` 45 | // Standard list metadata 46 | // More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 47 | metav1.ListMeta `json:"metadata,omitempty"` 48 | // List of Prometheuses 49 | Items []*Prometheus `json:"items"` 50 | } 51 | 52 | // Specification of the desired behavior of the Prometheus cluster. More info: 53 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 54 | // +k8s:openapi-gen=true 55 | type PrometheusSpec struct { 56 | // Standard object’s metadata. More info: 57 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 58 | // Metadata Labels and Annotations gets propagated to the prometheus pods. 59 | PodMetadata *metav1.ObjectMeta `json:"podMetadata,omitempty"` 60 | // ServiceMonitors to be selected for target discovery. 61 | ServiceMonitorSelector *metav1.LabelSelector `json:"serviceMonitorSelector,omitempty"` 62 | // Version of Prometheus to be deployed. 63 | Version string `json:"version,omitempty"` 64 | // When a Prometheus deployment is paused, no actions except for deletion 65 | // will be performed on the underlying objects. 66 | Paused bool `json:"paused,omitempty"` 67 | // Base image to use for a Prometheus deployment. 68 | BaseImage string `json:"baseImage,omitempty"` 69 | // An optional list of references to secrets in the same namespace 70 | // to use for pulling prometheus and alertmanager images from registries 71 | // see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod 72 | ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` 73 | // Number of instances to deploy for a Prometheus deployment. 74 | Replicas *int32 `json:"replicas,omitempty"` 75 | // Time duration Prometheus shall retain data for. 76 | Retention string `json:"retention,omitempty"` 77 | // Log level for Prometheus be configured in. 78 | LogLevel string `json:"logLevel,omitempty"` 79 | // Interval between consecutive scrapes. 80 | ScrapeInterval string `json:"scrapeInterval,omitempty"` 81 | // Interval between consecutive evaluations. 82 | EvaluationInterval string `json:"evaluationInterval,omitempty"` 83 | // The labels to add to any time series or alerts when communicating with 84 | // external systems (federation, remote storage, Alertmanager). 85 | ExternalLabels map[string]string `json:"externalLabels,omitempty"` 86 | // The external URL the Prometheus instances will be available under. This is 87 | // necessary to generate correct URLs. This is necessary if Prometheus is not 88 | // served from root of a DNS name. 89 | ExternalURL string `json:"externalUrl,omitempty"` 90 | // The route prefix Prometheus registers HTTP handlers for. This is useful, 91 | // if using ExternalURL and a proxy is rewriting HTTP routes of a request, 92 | // and the actual ExternalURL is still true, but the server serves requests 93 | // under a different route prefix. For example for use with `kubectl proxy`. 94 | RoutePrefix string `json:"routePrefix,omitempty"` 95 | // Storage spec to specify how storage shall be used. 96 | Storage *StorageSpec `json:"storage,omitempty"` 97 | // A selector to select which ConfigMaps to mount for loading rule files from. 98 | RuleSelector *metav1.LabelSelector `json:"ruleSelector,omitempty"` 99 | // Define details regarding alerting. 100 | Alerting AlertingSpec `json:"alerting,omitempty"` 101 | // Define resources requests and limits for single Pods. 102 | Resources v1.ResourceRequirements `json:"resources,omitempty"` 103 | // Define which Nodes the Pods are scheduled on. 104 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 105 | // ServiceAccountName is the name of the ServiceAccount to use to run the 106 | // Prometheus Pods. 107 | ServiceAccountName string `json:"serviceAccountName,omitempty"` 108 | // Secrets is a list of Secrets in the same namespace as the Prometheus 109 | // object, which shall be mounted into the Prometheus Pods. 110 | // The Secrets are mounted into /etc/prometheus/secrets/. 111 | // Secrets changes after initial creation of a Prometheus object are not 112 | // reflected in the running Pods. To change the secrets mounted into the 113 | // Prometheus Pods, the object must be deleted and recreated with the new list 114 | // of secrets. 115 | Secrets []string `json:"secrets,omitempty"` 116 | // If specified, the pod's scheduling constraints. 117 | Affinity *v1.Affinity `json:"affinity,omitempty"` 118 | // If specified, the pod's tolerations. 119 | Tolerations []v1.Toleration `json:"tolerations,omitempty"` 120 | // If specified, the remote_write spec. This is an experimental feature, it may change in any upcoming release in a breaking way. 121 | RemoteWrite []RemoteWriteSpec `json:"remoteWrite,omitempty"` 122 | // If specified, the remote_read spec. This is an experimental feature, it may change in any upcoming release in a breaking way. 123 | RemoteRead []RemoteReadSpec `json:"remoteRead,omitempty"` 124 | // SecurityContext holds pod-level security attributes and common container settings. 125 | // This defaults to non root user with uid 1000 and gid 2000 for Prometheus >v2.0 and 126 | // default PodSecurityContext for other versions. 127 | SecurityContext *v1.PodSecurityContext `json:"securityContext,omitempty"` 128 | } 129 | 130 | // Most recent observed status of the Prometheus cluster. Read-only. Not 131 | // included when requesting from the apiserver, only from the Prometheus 132 | // Operator API itself. More info: 133 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 134 | // +k8s:openapi-gen=true 135 | type PrometheusStatus struct { 136 | // Represents whether any actions on the underlaying managed objects are 137 | // being performed. Only delete actions will be performed. 138 | Paused bool `json:"paused"` 139 | // Total number of non-terminated pods targeted by this Prometheus deployment 140 | // (their labels match the selector). 141 | Replicas int32 `json:"replicas"` 142 | // Total number of non-terminated pods targeted by this Prometheus deployment 143 | // that have the desired version spec. 144 | UpdatedReplicas int32 `json:"updatedReplicas"` 145 | // Total number of available pods (ready for at least minReadySeconds) 146 | // targeted by this Prometheus deployment. 147 | AvailableReplicas int32 `json:"availableReplicas"` 148 | // Total number of unavailable pods targeted by this Prometheus deployment. 149 | UnavailableReplicas int32 `json:"unavailableReplicas"` 150 | } 151 | 152 | // AlertingSpec defines parameters for alerting configuration of Prometheus servers. 153 | // +k8s:openapi-gen=true 154 | type AlertingSpec struct { 155 | // AlertmanagerEndpoints Prometheus should fire alerts against. 156 | Alertmanagers []AlertmanagerEndpoints `json:"alertmanagers"` 157 | } 158 | 159 | // StorageSpec defines the configured storage for a group Prometheus servers. 160 | // +k8s:openapi-gen=true 161 | type StorageSpec struct { 162 | // Name of the StorageClass to use when requesting storage provisioning. More 163 | // info: https://kubernetes.io/docs/user-guide/persistent-volumes/#storageclasses 164 | // DEPRECATED 165 | Class string `json:"class"` 166 | // EmptyDirVolumeSource to be used by the Prometheus StatefulSets. If specified, used in place of any volumeClaimTemplate. More 167 | // info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir 168 | EmptyDir *v1.EmptyDirVolumeSource `json:"emptyDir,omitempty"` 169 | // A label query over volumes to consider for binding. 170 | // DEPRECATED 171 | Selector *metav1.LabelSelector `json:"selector"` 172 | // Resources represents the minimum resources the volume should have. More 173 | // info: http://kubernetes.io/docs/user-guide/persistent-volumes#resources 174 | // DEPRECATED 175 | Resources v1.ResourceRequirements `json:"resources"` 176 | // A PVC spec to be used by the Prometheus StatefulSets. 177 | VolumeClaimTemplate v1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"` 178 | } 179 | 180 | // RemoteWriteSpec defines the remote_write configuration for prometheus. 181 | // +k8s:openapi-gen=true 182 | type RemoteWriteSpec struct { 183 | //The URL of the endpoint to send samples to. 184 | URL string `json:"url"` 185 | //Timeout for requests to the remote write endpoint. 186 | RemoteTimeout string `json:"remoteTimeout,omitempty"` 187 | //The list of remote write relabel configurations. 188 | WriteRelabelConfigs []RelabelConfig `json:"writeRelabelConfigs,omitempty"` 189 | //BasicAuth for the URL. 190 | BasicAuth *BasicAuth `json:"basicAuth,omitempty"` 191 | // File to read bearer token for remote write. 192 | BearerToken string `json:"bearerToken,omitempty"` 193 | // File to read bearer token for remote write. 194 | BearerTokenFile string `json:"bearerTokenFile,omitempty"` 195 | // TLS Config to use for remote write. 196 | TLSConfig *TLSConfig `json:"tlsConfig,omitempty"` 197 | //Optional ProxyURL 198 | ProxyURL string `json:"proxy_url,omitempty"` 199 | } 200 | 201 | // RemoteReadSpec defines the remote_read configuration for prometheus. 202 | // +k8s:openapi-gen=true 203 | type RemoteReadSpec struct { 204 | //The URL of the endpoint to send samples to. 205 | URL string `json:"url"` 206 | //Timeout for requests to the remote write endpoint. 207 | RemoteTimeout string `json:"remoteTimeout,omitempty"` 208 | //BasicAuth for the URL. 209 | BasicAuth *BasicAuth `json:"basicAuth,omitempty"` 210 | // bearer token for remote write. 211 | BearerToken string `json:"bearerToken,omitempty"` 212 | // File to read bearer token for remote write. 213 | BearerTokenFile string `json:"bearerTokenFile,omitempty"` 214 | // TLS Config to use for remote write. 215 | TLSConfig *TLSConfig `json:"tlsConfig,omitempty"` 216 | //Optional ProxyURL 217 | ProxyURL string `json:"proxy_url,omitempty"` 218 | } 219 | 220 | // RelabelConfig allows dynamic rewriting of the label set. 221 | // +k8s:openapi-gen=true 222 | type RelabelConfig struct { 223 | //The source labels select values from existing labels. Their content is concatenated 224 | //using the configured separator and matched against the configured regular expression 225 | //for the replace, keep, and drop actions. 226 | SourceLabels []string `json:"sourceLabels"` 227 | //Separator placed between concatenated source label values. default is ';'. 228 | Separator string `json:"separator,omitempty"` 229 | //Label to which the resulting value is written in a replace action. 230 | //It is mandatory for replace actions. Regex capture groups are available. 231 | TargetLabel string `json:"targetLabel,omitempty"` 232 | //Regular expression against which the extracted value is matched. defailt is '(.*)' 233 | Regex string `json:"regex,omitempty"` 234 | // Modulus to take of the hash of the source label values. 235 | Modulus uint64 `json:"modulus,omitempty"` 236 | //Replacement value against which a regex replace is performed if the 237 | //regular expression matches. Regex capture groups are available. Default is '$1' 238 | Replacement string `json:"replacement"` 239 | // Action to perform based on regex matching. Default is 'replace' 240 | Action string `json:"action,omitempty"` 241 | } 242 | 243 | // AlertmanagerEndpoints defines a selection of a single Endpoints object 244 | // containing alertmanager IPs to fire alerts against. 245 | // +k8s:openapi-gen=true 246 | type AlertmanagerEndpoints struct { 247 | // Namespace of Endpoints object. 248 | Namespace string `json:"namespace"` 249 | // Name of Endpoints object in Namespace. 250 | Name string `json:"name"` 251 | // Port the Alertmanager API is exposed on. 252 | Port intstr.IntOrString `json:"port"` 253 | // Scheme to use when firing alerts. 254 | Scheme string `json:"scheme,omitempty"` 255 | // Prefix for the HTTP path alerts are pushed to. 256 | PathPrefix string `json:"pathPrefix,omitempty"` 257 | } 258 | 259 | // ServiceMonitor defines monitoring for a set of services. 260 | // +k8s:openapi-gen=true 261 | type ServiceMonitor struct { 262 | metav1.TypeMeta `json:",inline"` 263 | // Standard object’s metadata. More info: 264 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 265 | // +k8s:openapi-gen=false 266 | metav1.ObjectMeta `json:"metadata,omitempty"` 267 | // Specification of desired Service selection for target discrovery by 268 | // Prometheus. 269 | Spec ServiceMonitorSpec `json:"spec"` 270 | } 271 | 272 | // ServiceMonitorSpec contains specification parameters for a ServiceMonitor. 273 | // +k8s:openapi-gen=true 274 | type ServiceMonitorSpec struct { 275 | // The label to use to retrieve the job name from. 276 | JobLabel string `json:"jobLabel,omitempty"` 277 | // A list of endpoints allowed as part of this ServiceMonitor. 278 | Endpoints []Endpoint `json:"endpoints"` 279 | // Selector to select Endpoints objects. 280 | Selector metav1.LabelSelector `json:"selector"` 281 | // Selector to select which namespaces the Endpoints objects are discovered from. 282 | NamespaceSelector NamespaceSelector `json:"namespaceSelector,omitempty"` 283 | } 284 | 285 | // Endpoint defines a scrapeable endpoint serving Prometheus metrics. 286 | // +k8s:openapi-gen=true 287 | type Endpoint struct { 288 | // Name of the service port this endpoint refers to. Mutually exclusive with targetPort. 289 | Port string `json:"port,omitempty"` 290 | // Name or number of the target port of the endpoint. Mutually exclusive with port. 291 | TargetPort intstr.IntOrString `json:"targetPort,omitempty"` 292 | // HTTP path to scrape for metrics. 293 | Path string `json:"path,omitempty"` 294 | // HTTP scheme to use for scraping. 295 | Scheme string `json:"scheme,omitempty"` 296 | // Optional HTTP URL parameters 297 | Params map[string][]string `json:"params,omitempty"` 298 | // Interval at which metrics should be scraped 299 | Interval string `json:"interval,omitempty"` 300 | // Timeout after which the scrape is ended 301 | ScrapeTimeout string `json:"scrapeTimeout,omitempty"` 302 | // TLS configuration to use when scraping the endpoint 303 | TLSConfig *TLSConfig `json:"tlsConfig,omitempty"` 304 | // File to read bearer token for scraping targets. 305 | BearerTokenFile string `json:"bearerTokenFile,omitempty"` 306 | // HonorLabels chooses the metric's labels on collisions with target labels. 307 | HonorLabels bool `json:"honorLabels,omitempty"` 308 | // BasicAuth allow an endpoint to authenticate over basic authentication 309 | // More info: https://prometheus.io/docs/operating/configuration/#endpoints 310 | BasicAuth *BasicAuth `json:"basicAuth,omitempty"` 311 | // MetricRelabelConfigs to apply to samples before ingestion. 312 | MetricRelabelConfigs []*RelabelConfig `json:"metricRelabelings,omitempty"` 313 | } 314 | 315 | // BasicAuth allow an endpoint to authenticate over basic authentication 316 | // More info: https://prometheus.io/docs/operating/configuration/#endpoints 317 | // +k8s:openapi-gen=true 318 | type BasicAuth struct { 319 | // The secret that contains the username for authenticate 320 | Username v1.SecretKeySelector `json:"username,omitempty"` 321 | // The secret that contains the password for authenticate 322 | Password v1.SecretKeySelector `json:"password,omitempty"` 323 | } 324 | 325 | // TLSConfig specifies TLS configuration parameters. 326 | // +k8s:openapi-gen=true 327 | type TLSConfig struct { 328 | // The CA cert to use for the targets. 329 | CAFile string `json:"caFile,omitempty"` 330 | // The client cert file for the targets. 331 | CertFile string `json:"certFile,omitempty"` 332 | // The client key file for the targets. 333 | KeyFile string `json:"keyFile,omitempty"` 334 | // Used to verify the hostname for the targets. 335 | ServerName string `json:"serverName,omitempty"` 336 | // Disable target certificate validation. 337 | InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` 338 | } 339 | 340 | // A list of ServiceMonitors. 341 | // +k8s:openapi-gen=true 342 | type ServiceMonitorList struct { 343 | metav1.TypeMeta `json:",inline"` 344 | // Standard list metadata 345 | // More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 346 | metav1.ListMeta `json:"metadata,omitempty"` 347 | // List of ServiceMonitors 348 | Items []*ServiceMonitor `json:"items"` 349 | } 350 | 351 | // Describes an Alertmanager cluster. 352 | // +k8s:openapi-gen=true 353 | type Alertmanager struct { 354 | metav1.TypeMeta `json:",inline"` 355 | // Standard object’s metadata. More info: 356 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 357 | // +k8s:openapi-gen=false 358 | metav1.ObjectMeta `json:"metadata,omitempty"` 359 | // Specification of the desired behavior of the Alertmanager cluster. More info: 360 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 361 | Spec AlertmanagerSpec `json:"spec"` 362 | // Most recent observed status of the Alertmanager cluster. Read-only. Not 363 | // included when requesting from the apiserver, only from the Prometheus 364 | // Operator API itself. More info: 365 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 366 | Status *AlertmanagerStatus `json:"status,omitempty"` 367 | } 368 | 369 | // Specification of the desired behavior of the Alertmanager cluster. More info: 370 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 371 | // +k8s:openapi-gen=true 372 | type AlertmanagerSpec struct { 373 | // Standard object’s metadata. More info: 374 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 375 | // Metadata Labels and Annotations gets propagated to the prometheus pods. 376 | PodMetadata *metav1.ObjectMeta `json:"podMetadata,omitempty"` 377 | // Version the cluster should be on. 378 | Version string `json:"version,omitempty"` 379 | // Base image that is used to deploy pods. 380 | BaseImage string `json:"baseImage,omitempty"` 381 | // An optional list of references to secrets in the same namespace 382 | // to use for pulling prometheus and alertmanager images from registries 383 | // see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod 384 | ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` 385 | // Size is the expected size of the alertmanager cluster. The controller will 386 | // eventually make the size of the running cluster equal to the expected 387 | // size. 388 | Replicas *int32 `json:"replicas,omitempty"` 389 | // Storage is the definition of how storage will be used by the Alertmanager 390 | // instances. 391 | Storage *StorageSpec `json:"storage,omitempty"` 392 | // The external URL the Alertmanager instances will be available under. This is 393 | // necessary to generate correct URLs. This is necessary if Alertmanager is not 394 | // served from root of a DNS name. 395 | ExternalURL string `json:"externalUrl,omitempty"` 396 | // The route prefix Alertmanager registers HTTP handlers for. This is useful, 397 | // if using ExternalURL and a proxy is rewriting HTTP routes of a request, 398 | // and the actual ExternalURL is still true, but the server serves requests 399 | // under a different route prefix. For example for use with `kubectl proxy`. 400 | RoutePrefix string `json:"routePrefix,omitempty"` 401 | // If set to true all actions on the underlaying managed objects are not 402 | // goint to be performed, except for delete actions. 403 | Paused bool `json:"paused,omitempty"` 404 | // Define which Nodes the Pods are scheduled on. 405 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 406 | // Define resources requests and limits for single Pods. 407 | Resources v1.ResourceRequirements `json:"resources,omitempty"` 408 | // If specified, the pod's scheduling constraints. 409 | Affinity *v1.Affinity `json:"affinity,omitempty"` 410 | // If specified, the pod's tolerations. 411 | Tolerations []v1.Toleration `json:"tolerations,omitempty"` 412 | } 413 | 414 | // A list of Alertmanagers. 415 | // +k8s:openapi-gen=true 416 | type AlertmanagerList struct { 417 | metav1.TypeMeta `json:",inline"` 418 | // Standard list metadata 419 | // More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata 420 | metav1.ListMeta `json:"metadata,omitempty"` 421 | // List of Alertmanagers 422 | Items []Alertmanager `json:"items"` 423 | } 424 | 425 | // Most recent observed status of the Alertmanager cluster. Read-only. Not 426 | // included when requesting from the apiserver, only from the Prometheus 427 | // Operator API itself. More info: 428 | // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status 429 | // +k8s:openapi-gen=true 430 | type AlertmanagerStatus struct { 431 | // Represents whether any actions on the underlaying managed objects are 432 | // being performed. Only delete actions will be performed. 433 | Paused bool `json:"paused"` 434 | // Total number of non-terminated pods targeted by this Alertmanager 435 | // cluster (their labels match the selector). 436 | Replicas int32 `json:"replicas"` 437 | // Total number of non-terminated pods targeted by this Alertmanager 438 | // cluster that have the desired version spec. 439 | UpdatedReplicas int32 `json:"updatedReplicas"` 440 | // Total number of available pods (ready for at least minReadySeconds) 441 | // targeted by this Alertmanager cluster. 442 | AvailableReplicas int32 `json:"availableReplicas"` 443 | // Total number of unavailable pods targeted by this Alertmanager cluster. 444 | UnavailableReplicas int32 `json:"unavailableReplicas"` 445 | } 446 | 447 | // A selector for selecting namespaces either selecting all namespaces or a 448 | // list of namespaces. 449 | // +k8s:openapi-gen=true 450 | type NamespaceSelector struct { 451 | // Boolean describing whether all namespaces are selected in contrast to a 452 | // list restricting them. 453 | Any bool `json:"any,omitempty"` 454 | // List of namespace names. 455 | MatchNames []string `json:"matchNames,omitempty"` 456 | 457 | // TODO(fabxc): this should embed metav1.LabelSelector eventually. 458 | // Currently the selector is only used for namespaces which require more complex 459 | // implementation to support label selections. 460 | } 461 | -------------------------------------------------------------------------------- /pkg/cli-utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package crdvalidation 16 | 17 | import ( 18 | "encoding/json" 19 | "flag" 20 | "os" 21 | "strings" 22 | 23 | "github.com/ghodss/yaml" 24 | extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 27 | ) 28 | 29 | // Config stores the user configuration input 30 | type Config struct { 31 | SpecDefinitionName string 32 | EnableValidation bool 33 | OutputFormat string 34 | Labels Labels 35 | Annotations Labels 36 | ResourceScope string 37 | Group string 38 | Kind string 39 | Version string 40 | Plural string 41 | SpecReplicasPath string 42 | StatusReplicasPath string 43 | LabelSelectorPath string 44 | Categories []string 45 | ShortNames []string 46 | GetOpenAPIDefinitions GetAPIDefinitions 47 | } 48 | 49 | type Labels struct { 50 | LabelsString string 51 | LabelsMap map[string]string 52 | } 53 | 54 | // Implement the flag.Value interface 55 | func (labels *Labels) String() string { 56 | return labels.LabelsString 57 | } 58 | 59 | // Merge labels create a new map with labels merged. 60 | func (labels *Labels) Merge(otherLabels map[string]string) map[string]string { 61 | mergedLabels := map[string]string{} 62 | 63 | for key, value := range otherLabels { 64 | mergedLabels[key] = value 65 | } 66 | 67 | for key, value := range labels.LabelsMap { 68 | mergedLabels[key] = value 69 | } 70 | return mergedLabels 71 | } 72 | 73 | // Implement the flag.Set interface 74 | func (labels *Labels) Set(value string) error { 75 | m := map[string]string{} 76 | if value != "" { 77 | splited := strings.Split(value, ",") 78 | for _, pair := range splited { 79 | sp := strings.Split(pair, "=") 80 | m[sp[0]] = sp[1] 81 | } 82 | } 83 | (*labels).LabelsMap = m 84 | (*labels).LabelsString = value 85 | return nil 86 | } 87 | 88 | func NewCustomResourceDefinition(config Config) *extensionsobj.CustomResourceDefinition { 89 | 90 | crd := &extensionsobj.CustomResourceDefinition{ 91 | ObjectMeta: metav1.ObjectMeta{ 92 | Name: config.Plural + "." + config.Group, 93 | Labels: config.Labels.LabelsMap, 94 | Annotations: config.Annotations.LabelsMap, 95 | }, 96 | TypeMeta: CustomResourceDefinitionTypeMeta, 97 | Spec: extensionsobj.CustomResourceDefinitionSpec{ 98 | Group: config.Group, 99 | Version: config.Version, 100 | Scope: extensionsobj.ResourceScope(config.ResourceScope), 101 | Names: extensionsobj.CustomResourceDefinitionNames{ 102 | Plural: config.Plural, 103 | Kind: config.Kind, 104 | Categories: config.Categories, 105 | ShortNames: config.ShortNames, 106 | }, 107 | Subresources: &extensionsobj.CustomResourceSubresources{ 108 | Status: &extensionsobj.CustomResourceSubresourceStatus { 109 | }, 110 | Scale: &extensionsobj.CustomResourceSubresourceScale { 111 | SpecReplicasPath: config.SpecReplicasPath, 112 | StatusReplicasPath: config.StatusReplicasPath, 113 | LabelSelectorPath: &config.LabelSelectorPath, 114 | }, 115 | }, 116 | }, 117 | } 118 | 119 | if config.SpecDefinitionName != "" && config.EnableValidation == true { 120 | crd.Spec.Validation = GetCustomResourceValidation(config.SpecDefinitionName, config.GetOpenAPIDefinitions) 121 | } 122 | 123 | return crd 124 | } 125 | 126 | func MarshallCrd(crd *extensionsobj.CustomResourceDefinition, outputFormat string) error { 127 | jsonBytes, err := json.Marshal(crd) 128 | if err != nil { 129 | return err 130 | } 131 | 132 | var r unstructured.Unstructured 133 | if err := json.Unmarshal(jsonBytes, &r.Object); err != nil { 134 | return err 135 | } 136 | 137 | unstructured.RemoveNestedField(r.Object, "status") 138 | 139 | jsonBytes, err = json.MarshalIndent(r.Object, "", " ") 140 | if err != nil { 141 | return err 142 | } 143 | 144 | if outputFormat == "json" { 145 | _, err = os.Stdout.Write(jsonBytes) 146 | if err != nil { 147 | return err 148 | } 149 | } else { 150 | yamlBytes, err := yaml.JSONToYAML(jsonBytes) 151 | if err != nil { 152 | return err 153 | } 154 | 155 | _, err = os.Stdout.Write([]byte("---\n")) 156 | if err != nil { 157 | return err 158 | } 159 | 160 | _, err = os.Stdout.Write(yamlBytes) 161 | if err != nil { 162 | return err 163 | } 164 | } 165 | 166 | return nil 167 | } 168 | 169 | // InitFlags prepares command line flags parser 170 | func InitFlags(cfg *Config, flagset *flag.FlagSet) *flag.FlagSet { 171 | flagset.Var(&cfg.Labels, "labels", "Labels") 172 | flagset.Var(&cfg.Annotations, "annotations", "Annotations") 173 | flagset.BoolVar(&cfg.EnableValidation, "with-validation", true, "Add CRD validation field, default: true") 174 | flagset.StringVar(&cfg.Group, "apigroup", "custom.example.com", "CRD api group") 175 | flagset.StringVar(&cfg.SpecDefinitionName, "spec-name", "", "CRD spec definition name") 176 | flagset.StringVar(&cfg.OutputFormat, "output", "yaml", "output format: json|yaml") 177 | flagset.StringVar(&cfg.Kind, "kind", "", "CRD Kind") 178 | flagset.StringVar(&cfg.ResourceScope, "scope", string(extensionsobj.NamespaceScoped), "CRD scope: 'Namespaced' | 'Cluster'. Default: Namespaced") 179 | flagset.StringVar(&cfg.Version, "version", "v1", "CRD version, default: 'v1'") 180 | flagset.StringVar(&cfg.Plural, "plural", "", "CRD plural name") 181 | flagset.StringVar(&cfg.SpecReplicasPath, "spec-replicas-path", ".spec.replicas", "CRD spec replicas path") 182 | flagset.StringVar(&cfg.StatusReplicasPath, "status-replicas-path", ".status.replicas", "CRD status replicas path") 183 | flagset.StringVar(&cfg.LabelSelectorPath, "label-selector-path", ".status.labelSelector", "CRD label selector path") 184 | return flagset 185 | } 186 | -------------------------------------------------------------------------------- /pkg/convert_types.go: -------------------------------------------------------------------------------- 1 | package crdvalidation 2 | 3 | import ( 4 | "fmt" 5 | spec "github.com/go-openapi/spec" 6 | extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 7 | common "k8s.io/kube-openapi/pkg/common" 8 | ) 9 | 10 | // SchemaPropsToJSONPropsArray converts []Schema to []JSONSchemaProps 11 | func SchemaPropsToJSONPropsArray(schemas []spec.Schema, openapiSpec map[string]common.OpenAPIDefinition, nested bool) []extensionsobj.JSONSchemaProps { 12 | var s []extensionsobj.JSONSchemaProps 13 | for _, schema := range schemas { 14 | s = append(s, *SchemaPropsToJSONProps(&schema, openapiSpec, nested)) 15 | } 16 | return s 17 | } 18 | 19 | // StringOrArrayToString converts StringOrArray to string 20 | func StringOrArrayToString(strOrArray spec.StringOrArray) string { 21 | if len(strOrArray) > 0 { 22 | return strOrArray[0] 23 | } 24 | return "" 25 | } 26 | 27 | // EnumJSON converts []interface{} to []JSON 28 | func EnumJSON(enum []interface{}) []extensionsobj.JSON { 29 | var s []extensionsobj.JSON 30 | for _, elt := range enum { 31 | s = append(s, extensionsobj.JSON{ 32 | Raw: []byte(fmt.Sprintf("%v", elt)), 33 | }) 34 | } 35 | return s 36 | } 37 | 38 | // SchemaOrArrayToJSONItems converts *SchemaOrArray to *JSONSchemaPropsOrArray 39 | func SchemaOrArrayToJSONItems(schemaOrArray *spec.SchemaOrArray, openapiSpec map[string]common.OpenAPIDefinition, nested bool) *extensionsobj.JSONSchemaPropsOrArray { 40 | var array *extensionsobj.JSONSchemaPropsOrArray 41 | if schemaOrArray == nil { 42 | return array 43 | } 44 | return &extensionsobj.JSONSchemaPropsOrArray{ 45 | Schema: SchemaPropsToJSONProps(schemaOrArray.Schema, openapiSpec, nested), 46 | JSONSchemas: SchemaPropsToJSONPropsArray(schemaOrArray.Schemas, openapiSpec, nested), 47 | } 48 | } 49 | 50 | // SchemaOrBoolToJSONProps converts *SchemaOrBool to *JSONSchemaPropsOrBool 51 | func SchemaOrBoolToJSONProps(schemaOrBool *spec.SchemaOrBool, openapiSpec map[string]common.OpenAPIDefinition, nested bool) *extensionsobj.JSONSchemaPropsOrBool { 52 | var s *extensionsobj.JSONSchemaPropsOrBool 53 | if schemaOrBool == nil { 54 | return s 55 | } 56 | return &extensionsobj.JSONSchemaPropsOrBool{ 57 | Schema: SchemaPropsToJSONProps(schemaOrBool.Schema, openapiSpec, nested), 58 | Allows: schemaOrBool.Allows, 59 | } 60 | } 61 | 62 | // SchemPropsMapToJSONMap converts map[string]Schema to map[string]JSONSchemaProps 63 | func SchemPropsMapToJSONMap(schemaMap map[string]spec.Schema, openapiSpec map[string]common.OpenAPIDefinition, nested bool) map[string]extensionsobj.JSONSchemaProps { 64 | var m map[string]extensionsobj.JSONSchemaProps 65 | m = make(map[string]extensionsobj.JSONSchemaProps) 66 | for key, schema := range schemaMap { 67 | m[key] = *SchemaPropsToJSONProps(&schema, openapiSpec, nested) 68 | } 69 | return m 70 | } 71 | 72 | // SchemaPropsToJSONProps converts a SchemaProps to a JSONProps 73 | func SchemaPropsToJSONProps(schema *spec.Schema, openapiSpec map[string]common.OpenAPIDefinition, nested bool) *extensionsobj.JSONSchemaProps { 74 | var props *extensionsobj.JSONSchemaProps 75 | if schema == nil { 76 | return props 77 | } 78 | schemaProps := &schema.SchemaProps 79 | 80 | var ref *string 81 | if schemaProps.Ref.String() != "" { 82 | if nested { 83 | propref := openapiSpec[schemaProps.Ref.String()].Schema 84 | // If nested just return a pointer to the reference 85 | return SchemaPropsToJSONProps(&propref, openapiSpec, nested) 86 | } 87 | ref = new(string) 88 | *ref = schemaProps.Ref.String() 89 | } 90 | 91 | props = &extensionsobj.JSONSchemaProps{ 92 | Ref: ref, 93 | ID: schemaProps.ID, 94 | Schema: extensionsobj.JSONSchemaURL(string(schema.Schema)), 95 | Description: schemaProps.Description, 96 | Type: StringOrArrayToString(schemaProps.Type), 97 | Format: schemaProps.Format, 98 | Title: schemaProps.Title, 99 | Maximum: schemaProps.Maximum, 100 | ExclusiveMaximum: schemaProps.ExclusiveMaximum, 101 | Minimum: schemaProps.Minimum, 102 | ExclusiveMinimum: schemaProps.ExclusiveMinimum, 103 | MaxLength: schemaProps.MaxLength, 104 | MinLength: schemaProps.MinLength, 105 | Pattern: schemaProps.Pattern, 106 | MaxItems: schemaProps.MaxItems, 107 | MinItems: schemaProps.MinItems, 108 | UniqueItems: schemaProps.UniqueItems, 109 | MultipleOf: schemaProps.MultipleOf, 110 | Enum: EnumJSON(schemaProps.Enum), 111 | MaxProperties: schemaProps.MaxProperties, 112 | MinProperties: schemaProps.MinProperties, 113 | Required: schemaProps.Required, 114 | Items: SchemaOrArrayToJSONItems(schemaProps.Items, openapiSpec, nested), 115 | AllOf: SchemaPropsToJSONPropsArray(schemaProps.AllOf, openapiSpec, nested), 116 | OneOf: SchemaPropsToJSONPropsArray(schemaProps.OneOf, openapiSpec, nested), 117 | AnyOf: SchemaPropsToJSONPropsArray(schemaProps.AnyOf, openapiSpec, nested), 118 | Not: SchemaPropsToJSONProps(schemaProps.Not, openapiSpec, nested), 119 | Properties: SchemPropsMapToJSONMap(schemaProps.Properties, openapiSpec, nested), 120 | // @TODO(01-25-2018) Field not accepted by the current CRD Validation Spec 121 | // AdditionalProperties: SchemaOrBoolToJSONProps(schemaProps.AdditionalProperties, openapiSpec, nested), 122 | PatternProperties: SchemPropsMapToJSONMap(schemaProps.PatternProperties, openapiSpec, nested), 123 | AdditionalItems: SchemaOrBoolToJSONProps(schemaProps.AdditionalItems, openapiSpec, nested), 124 | } 125 | return props 126 | } 127 | -------------------------------------------------------------------------------- /pkg/crdvalidation.go: -------------------------------------------------------------------------------- 1 | package crdvalidation 2 | 3 | import ( 4 | spec "github.com/go-openapi/spec" 5 | extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 6 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 | common "k8s.io/kube-openapi/pkg/common" 8 | ) 9 | 10 | // CustomResourceDefinitionTypeMeta set the default kind/apiversion of CRD 11 | var CustomResourceDefinitionTypeMeta = metav1.TypeMeta{ 12 | Kind: "CustomResourceDefinition", 13 | APIVersion: "apiextensions.k8s.io/v1beta1", 14 | } 15 | 16 | // OpenAPIRefCallBack returns a jsonref using the input string without modification 17 | func OpenAPIRefCallBack(name string) spec.Ref { 18 | return spec.MustCreateRef(name) 19 | } 20 | 21 | // GetAPIDefinition is a function returning a map with all Definition 22 | type GetAPIDefinitions func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition 23 | 24 | // GetCustomResourceValidations returns a CRD validation spec map. It took the openapi generated definition from kube-openapi as argument 25 | func GetCustomResourceValidations(fn GetAPIDefinitions) map[string]*extensionsobj.CustomResourceValidation { 26 | openapiSpec := fn(OpenAPIRefCallBack) 27 | var definitions map[string]*extensionsobj.CustomResourceValidation 28 | definitions = make(map[string]*extensionsobj.CustomResourceValidation) 29 | for key, definition := range openapiSpec { 30 | schema := definition.Schema 31 | definitions[key] = &extensionsobj.CustomResourceValidation{ 32 | OpenAPIV3Schema: SchemaPropsToJSONProps(&schema, openapiSpec, true), 33 | } 34 | } 35 | return definitions 36 | } 37 | 38 | // GetCustomResourceValidation returns the validation definition for a CRD name 39 | func GetCustomResourceValidation(name string, fn func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition) *extensionsobj.CustomResourceValidation { 40 | openapiSpec := fn(OpenAPIRefCallBack) 41 | fixKnownTypes(openapiSpec) 42 | schema := openapiSpec[name].Schema 43 | crv := &extensionsobj.CustomResourceValidation{ 44 | OpenAPIV3Schema: SchemaPropsToJSONProps(&schema, openapiSpec, true), 45 | } 46 | crv.OpenAPIV3Schema.Description = "" 47 | crv.OpenAPIV3Schema.Required = nil 48 | return crv 49 | } 50 | 51 | // ref: https://github.com/kubernetes/kubernetes/issues/62329 52 | func fixKnownTypes(openapiSpec map[string]common.OpenAPIDefinition) { 53 | openapiSpec["k8s.io/apimachinery/pkg/util/intstr.IntOrString"] = common.OpenAPIDefinition{ 54 | Schema: spec.Schema{ 55 | SchemaProps: spec.SchemaProps{ 56 | AnyOf: []spec.Schema{ 57 | { 58 | SchemaProps: spec.SchemaProps{ 59 | Type: []string{"string"}, 60 | }, 61 | }, 62 | { 63 | SchemaProps: spec.SchemaProps{ 64 | Type: []string{"integer"}, 65 | }, 66 | }, 67 | }, 68 | }, 69 | }, 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /pkg/crdvalidation_test.go: -------------------------------------------------------------------------------- 1 | package crdvalidation 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | 8 | spec "github.com/go-openapi/spec" 9 | extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 10 | common "k8s.io/kube-openapi/pkg/common" 11 | "testing" 12 | ) 13 | 14 | func TestConvertSchematoJsonProp(t *testing.T) { 15 | 16 | ref := new(string) 17 | *ref = "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta" 18 | schema := spec.Schema{ 19 | SchemaProps: spec.SchemaProps{ 20 | Description: "Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata", 21 | Ref: OpenAPIRefCallBack(*ref), 22 | }, 23 | } 24 | 25 | expected := extensionsobj.JSONSchemaProps{ 26 | Description: "Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata", 27 | Ref: ref, 28 | } 29 | var def map[string]common.OpenAPIDefinition 30 | props := SchemaPropsToJsonProps(&schema, def, false) 31 | 32 | if props.Description != expected.Description { 33 | t.Errorf("Description: expected %s, got %s", schema.Description, expected.Description) 34 | } 35 | 36 | if *props.Ref != schema.Ref.String() { 37 | t.Errorf("Ref: expected '%s', got '%s'", schema.Ref.String(), *props.Ref) 38 | } 39 | } 40 | 41 | func TestConvertFullSchematoJsonProp(t *testing.T) { 42 | schema := spec.Schema{SchemaProps: spec.SchemaProps{ 43 | Description: "Describes an Alertmanager cluster.", 44 | Properties: map[string]spec.Schema{ 45 | "kind": { 46 | SchemaProps: spec.SchemaProps{ 47 | Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", 48 | Type: []string{"string"}, 49 | Format: "", 50 | }, 51 | }, 52 | "items": { 53 | SchemaProps: spec.SchemaProps{ 54 | Description: "List of Alertmanagers", 55 | Type: []string{"array"}, 56 | Items: &spec.SchemaOrArray{ 57 | Schema: &spec.Schema{ 58 | SchemaProps: spec.SchemaProps{ 59 | Ref: OpenAPIRefCallBack("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Alertmanager"), 60 | }, 61 | }, 62 | }, 63 | }, 64 | }, 65 | "metadata": { 66 | SchemaProps: spec.SchemaProps{ 67 | Description: "Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata", 68 | Ref: OpenAPIRefCallBack("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), 69 | }, 70 | }, 71 | }, 72 | }, 73 | } 74 | var def map[string]common.OpenAPIDefinition 75 | props := SchemaPropsToJsonProps(&schema, def, false) 76 | jsonBytes, err := json.MarshalIndent(props, "", " ") 77 | if err != nil { 78 | fmt.Println("error:", err) 79 | } 80 | os.Stdout.Write(jsonBytes) 81 | 82 | } 83 | --------------------------------------------------------------------------------