sigs.k8s.io/cluster-api@v1.6.3/internal/controllers/topology/cluster/structuredmerge/options.go (about) 1 /* 2 Copyright 2022 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 structuredmerge 18 19 import ( 20 "sigs.k8s.io/controller-runtime/pkg/client" 21 22 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 23 "sigs.k8s.io/cluster-api/internal/contract" 24 "sigs.k8s.io/cluster-api/internal/util/ssa" 25 ) 26 27 var ( 28 // defaultAllowedPaths are the allowed paths for all objects except Clusters. 29 defaultAllowedPaths = []contract.Path{ 30 // apiVersion, kind, name and namespace are required field for a server side apply intent. 31 {"apiVersion"}, 32 {"kind"}, 33 {"metadata", "name"}, 34 {"metadata", "namespace"}, 35 // uid is optional for a server side apply intent but sets the expectation of an object getting created or a specific one updated. 36 {"metadata", "uid"}, 37 // the topology controller controls/has an opinion for labels, annotation, ownerReferences and spec only. 38 {"metadata", "labels"}, 39 {"metadata", "annotations"}, 40 {"metadata", "ownerReferences"}, 41 {"spec"}, 42 } 43 44 // allowedPathsCluster are the allowed paths specific for Clusters. 45 // The cluster object is not created by the topology controller and already contains fields which are 46 // not supposed for the topology controller to have an opinion on / take (co-)ownership of. 47 // Because of that the allowedPaths are different to other objects. 48 // NOTE: This is mostly the same as defaultAllowedPaths but having more restrictions. 49 allowedPathsCluster = []contract.Path{ 50 // apiVersion, kind, name and namespace are required field for a server side apply intent. 51 {"apiVersion"}, 52 {"kind"}, 53 {"metadata", "name"}, 54 {"metadata", "namespace"}, 55 // uid is optional for a server side apply intent but sets the expectation of an object getting created or a specific one updated. 56 {"metadata", "uid"}, 57 // the topology controller controls/has an opinion for the labels ClusterNameLabel 58 // and ClusterTopologyOwnedLabel as well as infrastructureRef and controlPlaneRef in spec. 59 {"metadata", "labels", clusterv1.ClusterNameLabel}, 60 {"metadata", "labels", clusterv1.ClusterTopologyOwnedLabel}, 61 {"spec", "infrastructureRef"}, 62 {"spec", "controlPlaneRef"}, 63 } 64 ) 65 66 // HelperOption is some configuration that modifies options for Helper. 67 type HelperOption interface { 68 // ApplyToHelper applies this configuration to the given helper options. 69 ApplyToHelper(*HelperOptions) 70 } 71 72 // HelperOptions contains options for Helper. 73 type HelperOptions struct { 74 ssa.FilterObjectInput 75 } 76 77 // newHelperOptions returns initialized HelperOptions. 78 func newHelperOptions(target client.Object, opts ...HelperOption) *HelperOptions { 79 helperOptions := &HelperOptions{ 80 FilterObjectInput: ssa.FilterObjectInput{ 81 AllowedPaths: defaultAllowedPaths, 82 IgnorePaths: []contract.Path{}, 83 }, 84 } 85 // Overwrite the allowedPaths for Cluster objects to prevent the topology controller 86 // to take ownership of fields it is not supposed to. 87 if _, ok := target.(*clusterv1.Cluster); ok { 88 helperOptions.AllowedPaths = allowedPathsCluster 89 } 90 helperOptions = helperOptions.ApplyOptions(opts) 91 return helperOptions 92 } 93 94 // ApplyOptions applies the given patch options on these options, 95 // and then returns itself (for convenient chaining). 96 func (o *HelperOptions) ApplyOptions(opts []HelperOption) *HelperOptions { 97 for _, opt := range opts { 98 opt.ApplyToHelper(o) 99 } 100 return o 101 } 102 103 // IgnorePaths instruct the Helper to ignore given paths when computing a patch. 104 // NOTE: ignorePaths are used to filter out fields nested inside allowedPaths, e.g. 105 // spec.ControlPlaneEndpoint. 106 type IgnorePaths []contract.Path 107 108 // ApplyToHelper applies this configuration to the given helper options. 109 func (i IgnorePaths) ApplyToHelper(opts *HelperOptions) { 110 opts.IgnorePaths = i 111 }