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  }