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  }