github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/deploy/kustomize/util.go (about)

     1  /*
     2  Copyright 2020 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 kustomize
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
    26  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/yaml"
    27  )
    28  
    29  // DependenciesForKustomization finds common kustomize artifacts relative to the
    30  // provided working dir, and collects them into a list of files to be passed
    31  // to the file watcher.
    32  func DependenciesForKustomization(dir string) ([]string, error) {
    33  	var deps []string
    34  
    35  	path, err := FindKustomizationConfig(dir)
    36  	if err != nil {
    37  		// No kustomization config found so assume it's remote and stop traversing
    38  		return deps, nil
    39  	}
    40  
    41  	buf, err := ioutil.ReadFile(path)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	content := kustomization{}
    47  	if err := yaml.Unmarshal(buf, &content); err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	deps = append(deps, path)
    52  
    53  	candidates := append(content.Bases, content.Resources...)
    54  	candidates = append(candidates, content.Components...)
    55  
    56  	for _, candidate := range candidates {
    57  		// If the file doesn't exist locally, we can assume it's a remote file and
    58  		// skip it, since we can't monitor remote files. Kustomize itself will
    59  		// handle invalid/missing files.
    60  		local, mode := pathExistsLocally(candidate, dir)
    61  		if !local {
    62  			continue
    63  		}
    64  
    65  		if mode.IsDir() {
    66  			candidateDeps, err := DependenciesForKustomization(filepath.Join(dir, candidate))
    67  			if err != nil {
    68  				return nil, err
    69  			}
    70  			deps = append(deps, candidateDeps...)
    71  		} else {
    72  			deps = append(deps, filepath.Join(dir, candidate))
    73  		}
    74  	}
    75  
    76  	for _, patch := range content.PatchesStrategicMerge {
    77  		if patch.Path != "" {
    78  			deps = append(deps, filepath.Join(dir, patch.Path))
    79  		}
    80  	}
    81  
    82  	deps = append(deps, util.AbsolutePaths(dir, content.CRDs)...)
    83  
    84  	for _, patch := range content.Patches {
    85  		if patch.Path != "" {
    86  			deps = append(deps, filepath.Join(dir, patch.Path))
    87  		}
    88  	}
    89  
    90  	for _, jsonPatch := range content.PatchesJSON6902 {
    91  		if jsonPatch.Path != "" {
    92  			deps = append(deps, filepath.Join(dir, jsonPatch.Path))
    93  		}
    94  	}
    95  
    96  	for _, generator := range content.ConfigMapGenerator {
    97  		deps = append(deps, util.AbsolutePaths(dir, generator.Files)...)
    98  		envs := generator.Envs
    99  		if generator.Env != "" {
   100  			envs = append(envs, generator.Env)
   101  		}
   102  		deps = append(deps, util.AbsolutePaths(dir, envs)...)
   103  	}
   104  
   105  	for _, generator := range content.SecretGenerator {
   106  		deps = append(deps, util.AbsolutePaths(dir, generator.Files)...)
   107  		envs := generator.Envs
   108  		if generator.Env != "" {
   109  			envs = append(envs, generator.Env)
   110  		}
   111  		deps = append(deps, util.AbsolutePaths(dir, envs)...)
   112  	}
   113  
   114  	return deps, nil
   115  }
   116  
   117  // FindKustomizationConfig finds the kustomization config relative to the provided dir.
   118  // A Kustomization config must be at the root of the directory. Kustomize will
   119  // error if more than one of these files exists so order doesn't matter.
   120  func FindKustomizationConfig(dir string) (string, error) {
   121  	for _, candidate := range KustomizeFilePaths {
   122  		if local, _ := pathExistsLocally(candidate, dir); local {
   123  			return filepath.Join(dir, candidate), nil
   124  		}
   125  	}
   126  	return "", fmt.Errorf("no Kustomization configuration found in directory: %s", dir)
   127  }
   128  
   129  // BuildCommandArgs returns a list of build args to be passed to kustomize.
   130  func BuildCommandArgs(buildArgs []string, kustomizePath string) []string {
   131  	var args []string
   132  
   133  	if len(buildArgs) > 0 {
   134  		for _, v := range buildArgs {
   135  			parts := strings.Split(v, " ")
   136  			args = append(args, parts...)
   137  		}
   138  	}
   139  
   140  	if len(kustomizePath) > 0 {
   141  		args = append(args, kustomizePath)
   142  	}
   143  
   144  	return args
   145  }