1/* 2Copyright 2018 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package config 18 19import ( 20 "strings" 21 22 "sigs.k8s.io/kustomize/pkg/gvk" 23) 24 25// NameBackReferences is an association between a gvk.GVK and a list 26// of FieldSpec instances that could refer to it. 27// 28// It is used to handle name changes, and can be thought of as a 29// a contact list. If you change your own contact info (name, 30// phone number, etc.), you must tell your contacts or they won't 31// know about the change. 32// 33// For example, ConfigMaps can be used by Pods and everything that 34// contains a Pod; Deployment, Job, StatefulSet, etc. To change 35// the name of a ConfigMap instance from 'alice' to 'bob', one 36// must visit all objects that could refer to the ConfigMap, see if 37// they mention 'alice', and if so, change the reference to 'bob'. 38// 39// The NameBackReferences instance to aid in this could look like 40// { 41// kind: ConfigMap 42// version: v1 43// FieldSpecs: 44// - kind: Pod 45// version: v1 46// path: spec/volumes/configMap/name 47// - kind: Deployment 48// path: spec/template/spec/volumes/configMap/name 49// - kind: Job 50// path: spec/template/spec/volumes/configMap/name 51// (etc.) 52// } 53type NameBackReferences struct { 54 gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` 55 FieldSpecs fsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"` 56} 57 58func (n NameBackReferences) String() string { 59 var r []string 60 for _, f := range n.FieldSpecs { 61 r = append(r, f.String()) 62 } 63 return n.Gvk.String() + ": (\n" + 64 strings.Join(r, "\n") + "\n)" 65} 66 67type nbrSlice []NameBackReferences 68 69func (s nbrSlice) Len() int { return len(s) } 70func (s nbrSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 71func (s nbrSlice) Less(i, j int) bool { 72 return s[i].Gvk.IsLessThan(s[j].Gvk) 73} 74 75func (s nbrSlice) mergeAll(o nbrSlice) (result nbrSlice, err error) { 76 result = s 77 for _, r := range o { 78 result, err = result.mergeOne(r) 79 if err != nil { 80 return nil, err 81 } 82 } 83 return result, nil 84} 85 86func (s nbrSlice) mergeOne(other NameBackReferences) (nbrSlice, error) { 87 var result nbrSlice 88 var err error 89 found := false 90 for _, c := range s { 91 if c.Gvk.Equals(other.Gvk) { 92 c.FieldSpecs, err = c.FieldSpecs.mergeAll(other.FieldSpecs) 93 if err != nil { 94 return nil, err 95 } 96 found = true 97 } 98 result = append(result, c) 99 } 100 101 if !found { 102 result = append(result, other) 103 } 104 return result, nil 105} 106