github.com/alex123012/deckhouse-controller-tools@v0.0.0-20230510090815-d594daf1af8c/pkg/crd/markers/topology.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package markers 18 19 import ( 20 "fmt" 21 22 apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 23 "sigs.k8s.io/controller-tools/pkg/markers" 24 ) 25 26 // TopologyMarkers specify topology markers (i.e. markers that describe if a 27 // list behaves as an associative-list or a set, if a map is atomic or not). 28 var TopologyMarkers = []*definitionWithHelp{ 29 must(markers.MakeDefinition("listMapKey", markers.DescribesField, ListMapKey(""))). 30 WithHelp(ListMapKey("").Help()), 31 must(markers.MakeDefinition("listMapKey", markers.DescribesType, ListMapKey(""))). 32 WithHelp(ListMapKey("").Help()), 33 must(markers.MakeDefinition("listType", markers.DescribesField, ListType(""))). 34 WithHelp(ListType("").Help()), 35 must(markers.MakeDefinition("listType", markers.DescribesType, ListType(""))). 36 WithHelp(ListType("").Help()), 37 must(markers.MakeDefinition("mapType", markers.DescribesField, MapType(""))). 38 WithHelp(MapType("").Help()), 39 must(markers.MakeDefinition("mapType", markers.DescribesType, MapType(""))). 40 WithHelp(MapType("").Help()), 41 must(markers.MakeDefinition("structType", markers.DescribesField, StructType(""))). 42 WithHelp(StructType("").Help()), 43 must(markers.MakeDefinition("structType", markers.DescribesType, StructType(""))). 44 WithHelp(StructType("").Help()), 45 } 46 47 func init() { 48 AllDefinitions = append(AllDefinitions, TopologyMarkers...) 49 } 50 51 // +controllertools:marker:generateHelp:category="CRD processing" 52 53 // ListType specifies the type of data-structure that the list 54 // represents (map, set, atomic). 55 // 56 // Possible data-structure types of a list are: 57 // 58 // - "map": it needs to have a key field, which will be used to build an 59 // associative list. A typical example is a the pod container list, 60 // which is indexed by the container name. 61 // 62 // - "set": Fields need to be "scalar", and there can be only one 63 // occurrence of each. 64 // 65 // - "atomic": All the fields in the list are treated as a single value, 66 // are typically manipulated together by the same actor. 67 type ListType string 68 69 // +controllertools:marker:generateHelp:category="CRD processing" 70 71 // ListMapKey specifies the keys to map listTypes. 72 // 73 // It indicates the index of a map list. They can be repeated if multiple keys 74 // must be used. It can only be used when ListType is set to map, and the keys 75 // should be scalar types. 76 type ListMapKey string 77 78 // +controllertools:marker:generateHelp:category="CRD processing" 79 80 // MapType specifies the level of atomicity of the map; 81 // i.e. whether each item in the map is independent of the others, 82 // or all fields are treated as a single unit. 83 // 84 // Possible values: 85 // 86 // - "granular": items in the map are independent of each other, 87 // and can be manipulated by different actors. 88 // This is the default behavior. 89 // 90 // - "atomic": all fields are treated as one unit. 91 // Any changes have to replace the entire map. 92 type MapType string 93 94 // +controllertools:marker:generateHelp:category="CRD processing" 95 96 // StructType specifies the level of atomicity of the struct; 97 // i.e. whether each field in the struct is independent of the others, 98 // or all fields are treated as a single unit. 99 // 100 // Possible values: 101 // 102 // - "granular": fields in the struct are independent of each other, 103 // and can be manipulated by different actors. 104 // This is the default behavior. 105 // 106 // - "atomic": all fields are treated as one unit. 107 // Any changes have to replace the entire struct. 108 type StructType string 109 110 func (l ListType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 111 if schema.Type != "array" { 112 return fmt.Errorf("must apply listType to an array, found %s", schema.Type) 113 } 114 if l != "map" && l != "atomic" && l != "set" { 115 return fmt.Errorf(`ListType must be either "map", "set" or "atomic"`) 116 } 117 p := string(l) 118 schema.XListType = &p 119 return nil 120 } 121 122 func (l ListType) ApplyFirst() {} 123 124 func (l ListMapKey) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 125 if schema.Type != "array" { 126 return fmt.Errorf("must apply listMapKey to an array, found %s", schema.Type) 127 } 128 if schema.XListType == nil || *schema.XListType != "map" { 129 return fmt.Errorf("must apply listMapKey to an associative-list") 130 } 131 schema.XListMapKeys = append(schema.XListMapKeys, string(l)) 132 return nil 133 } 134 135 func (m MapType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 136 if schema.Type != "object" { 137 return fmt.Errorf("must apply mapType to an object") 138 } 139 140 if m != "atomic" && m != "granular" { 141 return fmt.Errorf(`MapType must be either "granular" or "atomic"`) 142 } 143 144 p := string(m) 145 schema.XMapType = &p 146 147 return nil 148 } 149 150 func (s StructType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 151 if schema.Type != "object" && schema.Type != "" { 152 return fmt.Errorf("must apply structType to an object; either explicitly set or defaulted through an empty schema type") 153 } 154 155 if s != "atomic" && s != "granular" { 156 return fmt.Errorf(`StructType must be either "granular" or "atomic"`) 157 } 158 159 p := string(s) 160 schema.XMapType = &p 161 162 return nil 163 }