github.com/SamarSidharth/kpt@v0.0.0-20231122062228-c7d747ae3ace/pkg/live/rgpath.go (about) 1 // Copyright 2020 The kpt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package live 16 17 import ( 18 "encoding/json" 19 20 "github.com/GoogleContainerTools/kpt/internal/util/pathutil" 21 rgfilev1alpha1 "github.com/GoogleContainerTools/kpt/pkg/api/resourcegroup/v1alpha1" 22 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 23 "sigs.k8s.io/cli-utils/pkg/manifestreader" 24 "sigs.k8s.io/kustomize/kyaml/kio" 25 "sigs.k8s.io/kustomize/kyaml/kio/filters" 26 "sigs.k8s.io/kustomize/kyaml/kio/kioutil" 27 "sigs.k8s.io/kustomize/kyaml/yaml" 28 ) 29 30 // ResourceGroupPathManifestReader encapsulates the default path 31 // manifest reader. 32 type ResourceGroupPathManifestReader struct { 33 PkgPath string 34 35 manifestreader.ReaderOptions 36 } 37 38 // Read reads the manifests and returns them as Info objects. 39 // Generates and adds a ResourceGroup inventory object from 40 // Kptfile data. If unable to generate the ResourceGroup inventory 41 // object from the Kptfile, it is NOT an error. 42 func (r *ResourceGroupPathManifestReader) Read() ([]*unstructured.Unstructured, error) { 43 absPkgPath, _, err := pathutil.ResolveAbsAndRelPaths(r.PkgPath) 44 if err != nil { 45 return nil, err 46 } 47 48 var objs []*unstructured.Unstructured 49 nodes, err := (&kio.LocalPackageReader{ 50 PackagePath: absPkgPath, 51 WrapBareSeqNode: true, 52 }).Read() 53 if err != nil { 54 return objs, err 55 } 56 57 for _, n := range nodes { 58 if err := removeAnnotations(n, kioutil.IndexAnnotation, kioutil.LegacyIndexAnnotation); err != nil { // nolint:staticcheck 59 return objs, err 60 } 61 u, err := kyamlNodeToUnstructured(n) 62 if err != nil { 63 return objs, err 64 } 65 66 // Skip if current file is a ResourceGroup resource. We do not want to apply/delete any ResourceGroup CRs when we 67 // run any `kpt live` commands on a package. Instead, we have specific logic in place for handling ResourceGroups in 68 // the live cluster. 69 if u.GroupVersionKind() == rgfilev1alpha1.ResourceGroupGVK() { 70 continue 71 } 72 objs = append(objs, u) 73 } 74 75 objs = filterLocalConfig(objs) 76 err = manifestreader.SetNamespaces(r.Mapper, objs, r.Namespace, r.EnforceNamespace) 77 return objs, err 78 } 79 80 // removeAnnotations removes the specified kioutil annotations from the resource. 81 func removeAnnotations(n *yaml.RNode, annotations ...kioutil.AnnotationKey) error { 82 for _, a := range annotations { 83 err := n.PipeE(yaml.ClearAnnotation(a)) 84 if err != nil { 85 return err 86 } 87 } 88 return nil 89 } 90 91 // kyamlNodeToUnstructured take a resource represented as a kyaml RNode and 92 // turns it into an Unstructured object. 93 // 94 //nolint:interfacer 95 func kyamlNodeToUnstructured(n *yaml.RNode) (*unstructured.Unstructured, error) { 96 b, err := n.MarshalJSON() 97 if err != nil { 98 return nil, err 99 } 100 101 var m map[string]interface{} 102 err = json.Unmarshal(b, &m) 103 if err != nil { 104 return nil, err 105 } 106 107 return &unstructured.Unstructured{ 108 Object: m, 109 }, nil 110 } 111 112 const NoLocalConfigAnnoVal = "false" 113 114 // filterLocalConfig returns a new slice of Unstructured where all resources 115 // that are designated as local config have been filtered out. It does this 116 // by looking at the config.kubernetes.io/local-config annotation. Any value 117 // except "false" is considered to mean the resource is local config. 118 // Note(droot): Since we stopped giving special treatment to functionConfigs 119 // "false" value for the local-config annotation doesn't make much sense. 120 // With that we can probably enable just presence of local-config annotation 121 // as a way to mark that config is local. Can get rid of confusion as pointed out in the 122 // issue --> https://github.com/GoogleContainerTools/kpt/issues/2767 123 func filterLocalConfig(objs []*unstructured.Unstructured) []*unstructured.Unstructured { 124 var filteredObjs []*unstructured.Unstructured 125 for _, obj := range objs { 126 annoVal, found := obj.GetAnnotations()[filters.LocalConfigAnnotation] 127 if found && annoVal != NoLocalConfigAnnoVal { 128 continue 129 } 130 filteredObjs = append(filteredObjs, obj) 131 } 132 return filteredObjs 133 }