github.com/minio/controller-tools@v0.4.7/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 "github.com/minio/controller-tools/pkg/markers" 23 apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 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("listType", markers.DescribesField, ListType(""))). 32 WithHelp(ListType("").Help()), 33 must(markers.MakeDefinition("mapType", markers.DescribesField, MapType(""))). 34 WithHelp(MapType("").Help()), 35 must(markers.MakeDefinition("structType", markers.DescribesField, StructType(""))). 36 WithHelp(StructType("").Help()), 37 } 38 39 func init() { 40 AllDefinitions = append(AllDefinitions, TopologyMarkers...) 41 } 42 43 // +controllertools:marker:generateHelp:category="CRD processing" 44 45 // ListType specifies the type of data-structure that the list 46 // represents (map, set, atomic). 47 // 48 // Possible data-structure types of a list are: 49 // 50 // - "map": it needs to have a key field, which will be used to build an 51 // associative list. A typical example is a the pod container list, 52 // which is indexed by the container name. 53 // 54 // - "set": Fields need to be "scalar", and there can be only one 55 // occurrence of each. 56 // 57 // - "atomic": All the fields in the list are treated as a single value, 58 // are typically manipulated together by the same actor. 59 type ListType string 60 61 // +controllertools:marker:generateHelp:category="CRD processing" 62 63 // ListMapKey specifies the keys to map listTypes. 64 // 65 // It indicates the index of a map list. They can be repeated if multiple keys 66 // must be used. It can only be used when ListType is set to map, and the keys 67 // should be scalar types. 68 type ListMapKey string 69 70 // +controllertools:marker:generateHelp:category="CRD processing" 71 72 // MapType specifies the level of atomicity of the map; 73 // i.e. whether each item in the map is independent of the others, 74 // or all fields are treated as a single unit. 75 // 76 // Possible values: 77 // 78 // - "granular": items in the map are independent of each other, 79 // and can be manipulated by different actors. 80 // This is the default behavior. 81 // 82 // - "atomic": all fields are treated as one unit. 83 // Any changes have to replace the entire map. 84 type MapType string 85 86 // +controllertools:marker:generateHelp:category="CRD processing" 87 88 // StructType specifies the level of atomicity of the struct; 89 // i.e. whether each field in the struct is independent of the others, 90 // or all fields are treated as a single unit. 91 // 92 // Possible values: 93 // 94 // - "granular": fields in the struct are independent of each other, 95 // and can be manipulated by different actors. 96 // This is the default behavior. 97 // 98 // - "atomic": all fields are treated as one unit. 99 // Any changes have to replace the entire struct. 100 type StructType string 101 102 func (l ListType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 103 if schema.Type != "array" { 104 return fmt.Errorf("must apply listType to an array") 105 } 106 if l != "map" && l != "atomic" && l != "set" { 107 return fmt.Errorf(`ListType must be either "map", "set" or "atomic"`) 108 } 109 p := string(l) 110 schema.XListType = &p 111 return nil 112 } 113 114 func (l ListType) ApplyFirst() {} 115 116 func (l ListMapKey) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 117 if schema.Type != "array" { 118 return fmt.Errorf("must apply listMapKey to an array") 119 } 120 if schema.XListType == nil || *schema.XListType != "map" { 121 return fmt.Errorf("must apply listMapKey to an associative-list") 122 } 123 schema.XListMapKeys = append(schema.XListMapKeys, string(l)) 124 return nil 125 } 126 127 func (m MapType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 128 if schema.Type != "object" { 129 return fmt.Errorf("must apply mapType to an object") 130 } 131 132 if m != "atomic" && m != "granular" { 133 return fmt.Errorf(`MapType must be either "granular" or "atomic"`) 134 } 135 136 p := string(m) 137 schema.XMapType = &p 138 139 return nil 140 } 141 142 func (s StructType) ApplyToSchema(schema *apiext.JSONSchemaProps) error { 143 if schema.Type != "object" && schema.Type != "" { 144 return fmt.Errorf("must apply structType to an object; either explicitly set or defaulted through an empty schema type") 145 } 146 147 if s != "atomic" && s != "granular" { 148 return fmt.Errorf(`StructType must be either "granular" or "atomic"`) 149 } 150 151 p := string(s) 152 schema.XMapType = &p 153 154 return nil 155 }