github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/specs/customresourcedefinition_test.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package specs_test 5 6 import ( 7 "strings" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 12 apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 13 "k8s.io/utils/pointer" 14 15 k8sspecs "github.com/juju/juju/caas/kubernetes/provider/specs" 16 "github.com/juju/juju/testing" 17 ) 18 19 type crdSuite struct { 20 testing.BaseSuite 21 } 22 23 var _ = gc.Suite(&crdSuite{}) 24 25 func (s *crdSuite) TestK8sCustomResourceDefinitionV1Beta1(c *gc.C) { 26 specV1Beta1 := ` 27 name: tfjobs.kubeflow.org 28 labels: 29 foo: bar 30 juju-global-resource-lifecycle: model 31 spec: 32 group: kubeflow.org 33 scope: Cluster 34 names: 35 kind: TFJob 36 singular: tfjob 37 plural: tfjobs 38 version: v1 39 versions: 40 - name: v1 41 served: true 42 storage: true 43 - name: v1beta2 44 served: true 45 storage: false 46 conversion: 47 strategy: None 48 preserveUnknownFields: false 49 additionalPrinterColumns: 50 - name: Worker 51 type: integer 52 description: Worker attribute. 53 jsonPath: .spec.tfReplicaSpecs.Worker 54 validation: 55 openAPIV3Schema: 56 properties: 57 spec: 58 properties: 59 tfReplicaSpecs: 60 properties: 61 Worker: 62 properties: 63 replicas: 64 type: integer 65 minimum: 1 66 PS: 67 properties: 68 replicas: 69 type: integer 70 minimum: 1 71 Chief: 72 properties: 73 replicas: 74 type: integer 75 minimum: 1 76 maximum: 1 77 ` 78 var obj k8sspecs.K8sCustomResourceDefinition 79 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1Beta1), len(specV1Beta1)).Decode(&obj) 80 c.Assert(err, jc.ErrorIsNil) 81 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sCustomResourceDefinition{ 82 Meta: k8sspecs.Meta{ 83 Name: "tfjobs.kubeflow.org", 84 Labels: map[string]string{ 85 "foo": "bar", 86 "juju-global-resource-lifecycle": "model", 87 }, 88 }, 89 Spec: k8sspecs.K8sCustomResourceDefinitionSpec{ 90 Version: k8sspecs.K8sCustomResourceDefinitionV1Beta1, 91 SpecV1Beta1: apiextensionsv1beta1.CustomResourceDefinitionSpec{ 92 Group: "kubeflow.org", 93 Version: "v1", 94 Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ 95 {Name: "v1", Served: true, Storage: true}, 96 {Name: "v1beta2", Served: true, Storage: false}, 97 }, 98 Scope: "Cluster", 99 PreserveUnknownFields: pointer.BoolPtr(false), 100 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ 101 Kind: "TFJob", 102 Plural: "tfjobs", 103 Singular: "tfjob", 104 }, 105 Conversion: &apiextensionsv1beta1.CustomResourceConversion{ 106 Strategy: apiextensionsv1beta1.NoneConverter, 107 }, 108 AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ 109 { 110 Name: "Worker", 111 Type: "integer", 112 Description: "Worker attribute.", 113 JSONPath: ".spec.tfReplicaSpecs.Worker", 114 }, 115 }, 116 Validation: &apiextensionsv1beta1.CustomResourceValidation{ 117 OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{ 118 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 119 "spec": { 120 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 121 "tfReplicaSpecs": { 122 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 123 "PS": { 124 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 125 "replicas": { 126 Type: "integer", Minimum: pointer.Float64Ptr(1), 127 }, 128 }, 129 }, 130 "Chief": { 131 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 132 "replicas": { 133 Type: "integer", 134 Minimum: pointer.Float64Ptr(1), 135 Maximum: pointer.Float64Ptr(1), 136 }, 137 }, 138 }, 139 "Worker": { 140 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 141 "replicas": { 142 Type: "integer", 143 Minimum: pointer.Float64Ptr(1), 144 }, 145 }, 146 }, 147 }, 148 }, 149 }, 150 }, 151 }, 152 }, 153 }, 154 }, 155 }, 156 }) 157 } 158 159 func (s *crdSuite) TestK8sCustomResourceDefinitionV1(c *gc.C) { 160 specV1 := ` 161 name: certificates.networking.internal.knative.dev 162 labels: 163 knative.dev/crd-install: "true" 164 serving.knative.dev/release: "v0.19.0" 165 spec: 166 scope: Namespaced 167 group: networking.internal.knative.dev 168 names: 169 kind: Certificate 170 plural: certificates 171 singular: certificate 172 categories: 173 - knative-internal 174 - networking 175 shortNames: 176 - kcert 177 versions: 178 - name: v1alpha1 179 served: true 180 storage: true 181 subresources: 182 status: {} 183 schema: 184 openAPIV3Schema: 185 type: object 186 # this is a work around so we don't need to flush out the 187 # schema for each version at this time 188 # 189 # see issue: https://github.com/knative/serving/issues/912 190 x-kubernetes-preserve-unknown-fields: true 191 additionalPrinterColumns: 192 - name: Ready 193 type: string 194 jsonPath: ".status.conditions[?(@.type==\"Ready\")].status" 195 - name: Reason 196 type: string 197 jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason" 198 ` 199 var obj k8sspecs.K8sCustomResourceDefinition 200 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1), len(specV1)).Decode(&obj) 201 c.Assert(err, jc.ErrorIsNil) 202 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sCustomResourceDefinition{ 203 Meta: k8sspecs.Meta{ 204 Name: "certificates.networking.internal.knative.dev", 205 Labels: map[string]string{ 206 "knative.dev/crd-install": "true", 207 "serving.knative.dev/release": "v0.19.0", 208 }, 209 }, 210 Spec: k8sspecs.K8sCustomResourceDefinitionSpec{ 211 Version: k8sspecs.K8sCustomResourceDefinitionV1, 212 SpecV1: apiextensionsv1.CustomResourceDefinitionSpec{ 213 Scope: apiextensionsv1.NamespaceScoped, 214 Group: "networking.internal.knative.dev", 215 Names: apiextensionsv1.CustomResourceDefinitionNames{ 216 Kind: "Certificate", 217 Plural: "certificates", 218 Singular: "certificate", 219 Categories: []string{ 220 "knative-internal", 221 "networking", 222 }, 223 ShortNames: []string{ 224 "kcert", 225 }, 226 }, 227 Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ 228 { 229 Name: "v1alpha1", 230 Served: true, 231 Storage: true, 232 Subresources: &apiextensionsv1.CustomResourceSubresources{ 233 Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, 234 }, 235 Schema: &apiextensionsv1.CustomResourceValidation{ 236 OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ 237 Type: "object", 238 XPreserveUnknownFields: pointer.BoolPtr(true), 239 }, 240 }, 241 AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{ 242 { 243 Name: "Ready", 244 Type: "string", 245 JSONPath: ".status.conditions[?(@.type==\"Ready\")].status", 246 }, 247 { 248 Name: "Reason", 249 Type: "string", 250 JSONPath: ".status.conditions[?(@.type==\"Ready\")].reason", 251 }, 252 }, 253 }, 254 }, 255 }, 256 }, 257 }) 258 }