1111// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212// See the License for the specific language governing permissions and
1313// limitations under the License.
14- //
1514
16- package translate
15+ package crds
1716
1817import (
1918 "bytes"
@@ -24,64 +23,13 @@ import (
2423 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2524)
2625
27- // crdTranslator implements Translator to translate from a given CRD to and from
28- // a given SDK version using the same upstream OpenAPI schema
29- type crdTranslator struct {
30- majorVersion string
31- jsonSchema * jsonschema.Schema
32- annotations map [string ]string
33- }
34-
35- func (tr * crdTranslator ) Annotation (annotation string ) string {
36- return tr .annotations [annotation ]
37- }
38-
39- func (tr * crdTranslator ) MajorVersion () string {
40- return tr .majorVersion
41- }
42-
43- func (tr * crdTranslator ) Validate (unstructuredObj map [string ]any ) error {
44- if err := tr .jsonSchema .Validate (unstructuredObj ); err != nil {
45- return fmt .Errorf ("object validation failed against CRD schema: %w" , err )
46- }
47- return nil
48- }
49-
50- // NewTranslator creates a translator for a particular CRD and major version pairs,
51- // and with a particular set of known Kubernetes object dependencies.
52- //
53- // Given the following example resource:
54- //
55- // apiVersion: atlas.generated.mongodb.com/v1
56- // kind: SearchIndex
57- // metadata:
58- // name: search-index
59- // spec:
60- // v20250312:
61- //
62- // In the above case crdVersion is "v1" and majorVersion is "v20250312".
63- func NewTranslator (crd * apiextensionsv1.CustomResourceDefinition , crdVersion string , majorVersion string ) (Translator , error ) {
64- specVersion := selectVersion (& crd .Spec , crdVersion )
65- if err := assertMajorVersion (specVersion , crd .Spec .Names .Kind , majorVersion ); err != nil {
66- return nil , fmt .Errorf ("failed to assert major version %s in CRD: %w" , majorVersion , err )
67- }
68- schema , err := compileCRDSchema (specVersion .Schema .OpenAPIV3Schema )
69- if err != nil {
70- return nil , fmt .Errorf ("failed to compile schema: %w" , err )
71- }
72- return & crdTranslator {
73- majorVersion : majorVersion ,
74- jsonSchema : schema ,
75- annotations : crd .Annotations ,
76- }, nil
77- }
78-
79- func assertMajorVersion (specVersion * apiextensionsv1.CustomResourceDefinitionVersion , kind string , majorVersion string ) error {
80- props , err := getOpenAPIProperties (kind , specVersion )
26+ // AssertMajorVersion checks the given majorVersion exists for the given kind and CRD version
27+ func AssertMajorVersion (specVersion * apiextensionsv1.CustomResourceDefinitionVersion , kind string , majorVersion string ) error {
28+ props , err := GetOpenAPIProperties (kind , specVersion )
8129 if err != nil {
8230 return fmt .Errorf ("failed to enumerate CRD schema properties: %w" , err )
8331 }
84- specProps , err := getSpecPropertiesFor (kind , props , "spec" )
32+ specProps , err := GetSpecPropertiesFor (kind , props , "spec" )
8533 if err != nil {
8634 return fmt .Errorf ("failed to enumerate CRD spec properties: %w" , err )
8735 }
@@ -92,7 +40,8 @@ func assertMajorVersion(specVersion *apiextensionsv1.CustomResourceDefinitionVer
9240 return nil
9341}
9442
95- func compileCRDSchema (openAPISchema * apiextensionsv1.JSONSchemaProps ) (* jsonschema.Schema , error ) {
43+ // CompileCRDSchema compiles the given JSON schema properties
44+ func CompileCRDSchema (openAPISchema * apiextensionsv1.JSONSchemaProps ) (* jsonschema.Schema , error ) {
9645 schemaBytes , err := json .Marshal (openAPISchema )
9746 if err != nil {
9847 return nil , fmt .Errorf ("failed to marshal CRD schema to JSON: %w" , err )
@@ -108,8 +57,8 @@ func compileCRDSchema(openAPISchema *apiextensionsv1.JSONSchemaProps) (*jsonsche
10857 return schema , nil
10958}
11059
111- // selectVersion returns the version from the CRD spec that matches the given version string
112- func selectVersion (spec * apiextensionsv1.CustomResourceDefinitionSpec , version string ) * apiextensionsv1.CustomResourceDefinitionVersion {
60+ // SelectVersion returns the version from the CRD spec that matches the given version string
61+ func SelectVersion (spec * apiextensionsv1.CustomResourceDefinitionSpec , version string ) * apiextensionsv1.CustomResourceDefinitionVersion {
11362 if len (spec .Versions ) == 0 {
11463 return nil
11564 }
@@ -124,7 +73,8 @@ func selectVersion(spec *apiextensionsv1.CustomResourceDefinitionSpec, version s
12473 return nil
12574}
12675
127- func getOpenAPIProperties (kind string , version * apiextensionsv1.CustomResourceDefinitionVersion ) (map [string ]apiextensionsv1.JSONSchemaProps , error ) {
76+ // GetOpenAPIProperties digs up the schema properties of a given kind on a given CRD version
77+ func GetOpenAPIProperties (kind string , version * apiextensionsv1.CustomResourceDefinitionVersion ) (map [string ]apiextensionsv1.JSONSchemaProps , error ) {
12878 if version == nil {
12979 return nil , fmt .Errorf ("missing version (nil) from %v spec" , kind )
13080 }
@@ -140,7 +90,8 @@ func getOpenAPIProperties(kind string, version *apiextensionsv1.CustomResourceDe
14090 return version .Schema .OpenAPIV3Schema .Properties , nil
14191}
14292
143- func getSpecPropertiesFor (kind string , props map [string ]apiextensionsv1.JSONSchemaProps , field string ) (map [string ]apiextensionsv1.JSONSchemaProps , error ) {
93+ // GetSpecPropertiesFor takes the properties value of a given field of a kind's properties set
94+ func GetSpecPropertiesFor (kind string , props map [string ]apiextensionsv1.JSONSchemaProps , field string ) (map [string ]apiextensionsv1.JSONSchemaProps , error ) {
14495 prop , ok := props [field ]
14596 if ! ok {
14697 return nil , fmt .Errorf ("kind %q spec is missing field %q on" , kind , field )
0 commit comments