github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/deploy/util/util.go (about) 1 /* 2 Copyright 2019 The Skaffold 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 util 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "strings" 23 24 "k8s.io/apimachinery/pkg/runtime/schema" 25 "k8s.io/client-go/discovery" 26 k8s "k8s.io/client-go/kubernetes" 27 fakekubeclientset "k8s.io/client-go/kubernetes/fake" 28 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/types" 31 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" 32 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 33 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/instrumentation" 34 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" 35 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/manifest" 36 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 37 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util/stringset" 38 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/yaml" 39 ) 40 41 // ApplyDefaultRepo applies the default repo to a given image tag. 42 func ApplyDefaultRepo(globalConfig string, defaultRepo *string, tag string) (string, error) { 43 repo, err := config.GetDefaultRepo(globalConfig, defaultRepo) 44 if err != nil { 45 return "", fmt.Errorf("getting default repo: %w", err) 46 } 47 48 multiLevel, err := config.GetMultiLevelRepo(globalConfig) 49 if err != nil { 50 return "", fmt.Errorf("getting multi-level repo support: %w", err) 51 } 52 53 newTag, err := docker.SubstituteDefaultRepoIntoImage(repo, multiLevel, tag) 54 if err != nil { 55 return "", fmt.Errorf("applying default repo to %q: %w", tag, err) 56 } 57 58 return newTag, nil 59 } 60 61 // Update which images are logged, if the image is present in the provided deployer's artifacts. 62 func AddTagsToPodSelector(artifacts []graph.Artifact, deployerArtifacts []graph.Artifact, podSelector *kubernetes.ImageList) { 63 m := map[string]bool{} 64 for _, a := range deployerArtifacts { 65 m[a.ImageName] = true 66 } 67 for _, artifact := range artifacts { 68 imageName := docker.SanitizeImageName(artifact.ImageName) 69 if _, ok := m[imageName]; ok { 70 podSelector.Add(artifact.Tag) 71 } 72 } 73 } 74 75 func MockK8sClient(string) (k8s.Interface, error) { 76 return fakekubeclientset.NewSimpleClientset(), nil 77 } 78 79 func ConsolidateNamespaces(original, new []string) []string { 80 if len(new) == 0 { 81 return original 82 } 83 namespaces := stringset.New() 84 namespaces.Insert(append(original, new...)...) 85 namespaces.Delete("") // if we have provided namespaces, remove the empty "default" namespace 86 return namespaces.ToList() 87 } 88 89 // GroupVersionResource returns the first `GroupVersionResource` for the given `GroupVersionKind`. 90 func GroupVersionResource(disco discovery.DiscoveryInterface, gvk schema.GroupVersionKind) (bool, schema.GroupVersionResource, error) { 91 resources, err := disco.ServerResourcesForGroupVersion(gvk.GroupVersion().String()) 92 if err != nil { 93 return false, schema.GroupVersionResource{}, fmt.Errorf("getting server resources for group version: %w", err) 94 } 95 96 for _, r := range resources.APIResources { 97 if r.Kind == gvk.Kind { 98 return r.Namespaced, schema.GroupVersionResource{ 99 Group: gvk.Group, 100 Version: gvk.Version, 101 Resource: r.Name, 102 }, nil 103 } 104 } 105 106 return false, schema.GroupVersionResource{}, fmt.Errorf("could not find resource for %s", gvk.String()) 107 } 108 109 func ConsolidateTransformConfiguration(cfg types.Config) (map[schema.GroupKind]latest.ResourceFilter, map[schema.GroupKind]latest.ResourceFilter, error) { 110 // TODO(aaron-prindle) currently this also modifies the flag & config to support a JSON path syntax for input. 111 // this should be done elsewhere eventually 112 113 transformableAllowlist := map[schema.GroupKind]latest.ResourceFilter{} 114 transformableDenylist := map[schema.GroupKind]latest.ResourceFilter{} 115 // add default values 116 for _, rf := range manifest.TransformAllowlist { 117 groupKind := schema.ParseGroupKind(rf.GroupKind) 118 transformableAllowlist[groupKind] = ConvertJSONPathIndex(rf) 119 } 120 for _, rf := range manifest.TransformDenylist { 121 groupKind := schema.ParseGroupKind(rf.GroupKind) 122 transformableDenylist[groupKind] = ConvertJSONPathIndex(rf) 123 } 124 125 // add user schema values, override defaults 126 for _, rf := range cfg.TransformAllowList() { 127 instrumentation.AddResourceFilter("schema", "allow") 128 groupKind := schema.ParseGroupKind(rf.GroupKind) 129 transformableAllowlist[groupKind] = ConvertJSONPathIndex(rf) 130 delete(transformableDenylist, groupKind) 131 } 132 for _, rf := range cfg.TransformDenyList() { 133 instrumentation.AddResourceFilter("schema", "deny") 134 groupKind := schema.ParseGroupKind(rf.GroupKind) 135 transformableDenylist[groupKind] = ConvertJSONPathIndex(rf) 136 delete(transformableAllowlist, groupKind) 137 } 138 139 // add user flag values, override user schema values and defaults 140 // TODO(aaron-prindle) see if workdir needs to be considered in this read 141 if cfg.TransformRulesFile() != "" { 142 transformRulesFromFile, err := ioutil.ReadFile(cfg.TransformRulesFile()) 143 if err != nil { 144 return nil, nil, err 145 } 146 rsc := latest.ResourceSelectorConfig{} 147 err = yaml.Unmarshal(transformRulesFromFile, &rsc) 148 if err != nil { 149 return nil, nil, err 150 } 151 for _, rf := range rsc.Allow { 152 instrumentation.AddResourceFilter("cli-flag", "allow") 153 groupKind := schema.ParseGroupKind(rf.GroupKind) 154 transformableAllowlist[groupKind] = ConvertJSONPathIndex(rf) 155 delete(transformableDenylist, groupKind) 156 } 157 158 for _, rf := range rsc.Deny { 159 instrumentation.AddResourceFilter("cli-flag", "deny") 160 groupKind := schema.ParseGroupKind(rf.GroupKind) 161 transformableDenylist[groupKind] = ConvertJSONPathIndex(rf) 162 delete(transformableAllowlist, groupKind) 163 } 164 } 165 166 return transformableAllowlist, transformableDenylist, nil 167 } 168 169 func ConvertJSONPathIndex(rf latest.ResourceFilter) latest.ResourceFilter { 170 nrf := latest.ResourceFilter{} 171 nrf.GroupKind = rf.GroupKind 172 173 if len(rf.Labels) > 0 { 174 nlabels := []string{} 175 for _, str := range rf.Labels { 176 if str == ".*" { 177 nlabels = append(nlabels, str) 178 continue 179 } 180 nstr := strings.ReplaceAll(str, ".*", "") 181 nlabels = append(nlabels, nstr) 182 } 183 nrf.Labels = nlabels 184 } 185 186 if len(rf.Image) > 0 { 187 nimage := []string{} 188 for _, str := range rf.Image { 189 if str == ".*" { 190 nimage = append(nimage, str) 191 continue 192 } 193 nstr := strings.ReplaceAll(str, ".*", "") 194 nimage = append(nimage, nstr) 195 } 196 nrf.Image = nimage 197 } 198 199 return nrf 200 }