Compare commits

...

54 Commits

Author SHA1 Message Date
Jeff Regan
d37f47f0e7 Update OWNERS_ALIASES 2021-04-22 21:13:46 -07:00
Jeff Regan
705c6ad5ce Merge pull request #3834 from monopole/pinPluginsToV0.0.0
Pin plugins to v0.0.0
2021-04-22 17:20:18 -07:00
monopole
94f8d4ec63 Pin plugins to v0.0.0 2021-04-22 17:06:33 -07:00
Francesc Campoy
225bae8491 Make fsNode handle correctly consecutive reads and writes (#3820)
* Make fsNode handle correctly consecutive reads and writes

* Check for directories in ReadFile and add some error checks

* Update comment

* Improved docs and added better test

* Move test into its own file protected by built constraint

* Use manual test since iotest.TestReader is only available in Go 1.16
2021-04-22 16:50:01 -07:00
Jeff Regan
06add3ab35 Merge pull request #3737 from natasha41575/ReplacementTransformer
replacement transformer that uses the new replacement filter
2021-04-22 11:22:51 -07:00
Jeff Regan
f93cee9440 Merge pull request #3813 from monopole/unpinEverything
Back to dev mode; unpin the modules.
2021-04-16 03:12:33 -07:00
Kubernetes Prow Robot
21e65990c1 Merge pull request #3795 from jlandowner/master
Support immutable attribute on generators
2021-04-15 22:36:22 -07:00
monopole
38e9c34f08 Back to dev mode; unpin the modules. 2021-04-15 22:15:57 -07:00
Natasha Sarkar
038bc7713b add replacement transformer 2021-04-15 14:12:33 -07:00
Jeff Regan
a5914abad8 Merge pull request #3811 from monopole/pinToApi
Pin to api v0.8.8
2021-04-15 13:32:54 -07:00
monopole
3f2b98ff01 Pin to api v0.8.8 2021-04-15 13:21:06 -07:00
Jeff Regan
aa1dd9ddc2 Merge pull request #3810 from monopole/mergo_0.3.5
Back to mergo v0.3.5
2021-04-15 13:11:16 -07:00
monopole
5ba45f1ef8 Back to mergo v0.3.5 2021-04-15 12:48:20 -07:00
Jeff Regan
f3752dc75c Update args.go 2021-04-15 12:31:29 -07:00
Jeff Regan
d5f4da1261 Merge pull request #3809 from monopole/unpinEverything
Back to development mode; unpin the modules
2021-04-15 09:13:28 -07:00
Kubernetes Prow Robot
7680392d96 Merge pull request #3808 from fenggw-fnst/work
Fix typo
2021-04-14 20:21:49 -07:00
monopole
d8015d3c93 Back to development mode; unpin the modules 2021-04-14 20:08:13 -07:00
Jeff Regan
7487e2f9cb Merge pull request #3807 from monopole/pinToApi
Pin to api v0.8.7
2021-04-14 20:03:46 -07:00
Guangwen Feng
4b8bc7d6ba Fix typo
Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
2021-04-15 10:55:28 +08:00
monopole
59af49522e Pin to api v0.8.7 2021-04-14 19:47:59 -07:00
Jeff Regan
72d3eb15e0 Update remoteBuild.md 2021-04-14 19:26:42 -07:00
Jeff Regan
14e31de6b1 Merge pull request #3806 from monopole/unpinApi
Unpin the api
2021-04-14 19:03:18 -07:00
monopole
162b8f3d37 Unpin the api 2021-04-14 18:44:16 -07:00
Kubernetes Prow Robot
003cf61a48 Merge pull request #3805 from KnVerey/downgrade-mergo
Downgrade mergo to v0.3.7
2021-04-14 16:11:51 -07:00
Katrina Verey
74f0df8b9d Downgrade mergo to v0.3.7 2021-04-14 14:58:02 -07:00
Jeff Regan
0df531e7c6 Merge pull request #3802 from monopole/pinToApi
Pin to api v0.8.6
2021-04-13 12:22:20 -07:00
monopole
e3ce61647f Pin to api v0.8.6 2021-04-13 12:05:52 -07:00
Jeff Regan
768132f65f Merge pull request #3801 from monopole/pinToCmdConfig
Pin to cmd/config v0.9.10
2021-04-13 11:37:55 -07:00
monopole
6a708bcc23 Pin to cmd/config v0.9.10 2021-04-13 11:24:17 -07:00
Jeff Regan
d8182f8d81 Merge pull request #3800 from monopole/fixGoModNit
Fix go.sum nit
2021-04-13 11:19:21 -07:00
monopole
99b6a5920e Fix go.sum nit 2021-04-13 11:15:36 -07:00
Jeff Regan
8877c81468 Merge pull request #3799 from monopole/pinToKyaml_v0.10.17
Pin to kyaml@v0.10.17
2021-04-13 11:01:50 -07:00
monopole
88911bbb61 Pin to kyaml@v0.10.17 2021-04-13 10:31:18 -07:00
jlandowner
82ff64c374 Support immutable attribute on generators 2021-04-13 01:02:58 +00:00
Jeff Regan
01c477570a Merge pull request #3750 from minchao/fix-wordpress-init-command
Fix init command in wordpress example
2021-04-12 16:46:19 -07:00
Kubernetes Prow Robot
f8dad80a79 Merge pull request #3784 from monopole/flagEnableHelm
Add flag --enable-helm
2021-04-12 13:52:15 -07:00
monopole
240cda089a Add flag --enable-helm 2021-04-12 13:40:21 -07:00
Kubernetes Prow Robot
c94c193b5b Merge pull request #3793 from jeremyrickard/better-update-handling
Add check of UpdateExpectedFromActual before skipping test
2021-04-12 12:52:15 -07:00
Jeremy
9989b5fc84 Add check of UpdateExpectedFromActual before skipping test
Signed-off-by: Jeremy <jeremyrrickard@gmail.com>
2021-04-12 13:12:53 -06:00
Jeff Regan
aeba50488b Merge pull request #3792 from monopole/nits
Fix nits, add internal GetRoot func.
2021-04-12 07:53:00 -07:00
monopole
9c43518a15 Fix nits, add internal GetRoot func. 2021-04-12 07:51:01 -07:00
Jeff Regan
9d50890174 Merge pull request #3790 from monopole/enhanceHarness
Enhance the enhanced test harness.
2021-04-11 18:50:00 -07:00
monopole
3af1ae4159 Enhance test harness. 2021-04-11 18:14:30 -07:00
Kubernetes Prow Robot
5100568b0c Merge pull request #3788 from monopole/helmPrep
upgrade to helm 3.5.4 and imdario/mergo v0.3.12
2021-04-09 15:52:22 -07:00
monopole
aa5b4814d6 upgrade to helm 3.5.4 and imdario/mergo v0.3.12 2021-04-09 15:05:41 -07:00
Kubernetes Prow Robot
264b3ff338 Merge pull request #3773 from natasha41575/ReplacementFieldOptions
use field options to refine replacements
2021-04-09 12:15:16 -07:00
Natasha Sarkar
a40c74e545 use field options to refine replacements 2021-04-09 11:15:49 -07:00
Kubernetes Prow Robot
f61b075d3b Merge pull request #3775 from Shell32-Natsu/kyaml-filter
Enable LocalPackageReader to ignore specific path
2021-04-08 09:52:03 -07:00
Donny Xia
629d822604 Merge pull request #3783 from natasha41575/AddNatasha
add natasha to maintainers
2021-04-08 09:39:55 -07:00
Jeff Regan
bf64f109b9 Merge pull request #3782 from natasha41575/ReplacementRejectField
add use of rejects field in replacement filter
2021-04-08 09:15:53 -07:00
Natasha Sarkar
5f93fc53f4 add natasha to maintainers 2021-04-07 17:08:30 -07:00
Natasha Sarkar
0fe3f303e8 add use of rejects field in replacement filter 2021-04-07 16:00:18 -07:00
Donny Xia
7825050b18 Enable LocalPackageReader to ignore specific path 2021-04-05 12:46:20 -07:00
minchao
e6b52e7295 Fix init command in wordpress example 2021-03-24 11:19:53 +08:00
90 changed files with 3327 additions and 967 deletions

View File

@@ -96,7 +96,7 @@ $(MYGOBIN)/prchecker:
go install .
# Build from local source.
$(MYGOBIN)/kustomize:
$(MYGOBIN)/kustomize: build-kustomize-api
cd kustomize; \
go install .
@@ -105,7 +105,7 @@ install-tools: \
$(MYGOBIN)/goimports \
$(MYGOBIN)/golangci-lint-kustomize \
$(MYGOBIN)/gorepomod \
$(MYGOBIN)/helm \
$(MYGOBIN)/helmV3 \
$(MYGOBIN)/k8scopy \
$(MYGOBIN)/mdrip \
$(MYGOBIN)/pluginator \
@@ -150,6 +150,7 @@ _builtinplugins = \
PatchStrategicMergeTransformer.go \
PatchTransformer.go \
PrefixSuffixTransformer.go \
ReplacementTransformer.go \
ReplicaCountTransformer.go \
SecretGenerator.go \
ValueAddTransformer.go \
@@ -176,6 +177,7 @@ $(pGen)/PatchJson6902Transformer.go: $(pSrc)/patchjson6902transformer/PatchJson6
$(pGen)/PatchStrategicMergeTransformer.go: $(pSrc)/patchstrategicmergetransformer/PatchStrategicMergeTransformer.go
$(pGen)/PatchTransformer.go: $(pSrc)/patchtransformer/PatchTransformer.go
$(pGen)/PrefixSuffixTransformer.go: $(pSrc)/prefixsuffixtransformer/PrefixSuffixTransformer.go
$(pGen)/ReplacementTransformer.go: $(pSrc)/replacementtransformer/ReplacementTransformer.go
$(pGen)/ReplicaCountTransformer.go: $(pSrc)/replicacounttransformer/ReplicaCountTransformer.go
$(pGen)/SecretGenerator.go: $(pSrc)/secretgenerator/SecretGenerator.go
$(pGen)/ValueAddTransformer.go: $(pSrc)/valueaddtransformer/ValueAddTransformer.go
@@ -323,17 +325,13 @@ $(MYGOBIN)/helmV3:
( \
set -e; \
d=$(shell mktemp -d); cd $$d; \
tgzFile=helm-v3.4.0-linux-amd64.tar.gz; \
tgzFile=helm-v3.5.3-linux-amd64.tar.gz; \
wget https://get.helm.sh/$$tgzFile; \
tar -xvzf $$tgzFile; \
mv linux-amd64/helm $(MYGOBIN)/helmV3; \
rm -rf $$d \
)
# Default version of helm is v3.
$(MYGOBIN)/helm: $(MYGOBIN)/helmV3
ln -s $(MYGOBIN)/helmV3 $(MYGOBIN)/helm
$(MYGOBIN)/kind:
( \
set -e; \

View File

@@ -1,14 +1,14 @@
aliases:
kustomize-admins:
- knverey
- monopole
- pwittrock
kustomize-maintainers:
- droot
- justinsb
- liujingfang1
- mengqiy
- monopole
- pwittrock
- mortent
- natasha41575
- phanimarupaka
- pwittrock
- Shell32-Natsu

View File

@@ -6,7 +6,6 @@ package builtins
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
@@ -16,7 +15,6 @@ import (
"github.com/imdario/mergo"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
@@ -25,201 +23,234 @@ import (
// HelmChartInflationGeneratorPlugin is a plugin to generate resources
// from a remote or local helm chart.
type HelmChartInflationGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
runHelmCommand func([]string) ([]byte, error)
types.HelmChartArgs
h *resmap.PluginHelpers
types.HelmGlobals
types.HelmChart
tmpDir string
}
var KustomizePlugin HelmChartInflationGeneratorPlugin
const (
valuesMergeOptionMerge = "merge"
valuesMergeOptionOverride = "override"
valuesMergeOptionReplace = "replace"
)
var legalMergeOptions = []string{
valuesMergeOptionMerge,
valuesMergeOptionOverride,
valuesMergeOptionReplace,
}
// Config uses the input plugin configurations `config` to setup the generator
// options
func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) error {
func (p *HelmChartInflationGeneratorPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
if h.GeneralConfig() == nil {
return fmt.Errorf("unable to access general config")
}
if !h.GeneralConfig().HelmConfig.Enabled {
return fmt.Errorf("must specify --enable-helm")
}
if h.GeneralConfig().HelmConfig.Command == "" {
return fmt.Errorf("must specify --helm-command")
}
p.h = h
err := yaml.Unmarshal(config, p)
if err != nil {
return err
if err = yaml.Unmarshal(config, p); err != nil {
return
}
tmpDir, err := filesys.NewTmpConfirmedDir()
if err != nil {
return err
}
p.tmpDir = string(tmpDir)
if p.ChartName == "" {
return fmt.Errorf("chartName cannot be empty")
}
if p.ChartHome == "" {
p.ChartHome = filepath.Join(p.tmpDir, "chart")
}
if p.ChartRepoName == "" {
p.ChartRepoName = "stable"
}
if p.HelmBin == "" {
p.HelmBin = "helm"
}
if p.HelmHome == "" {
p.HelmHome = filepath.Join(p.tmpDir, ".helm")
}
if p.Values == "" {
p.Values = filepath.Join(p.ChartHome, p.ChartName, "values.yaml")
}
if p.ValuesMerge == "" {
p.ValuesMerge = "override"
}
// runHelmCommand will run `helm` command with args provided. Return stdout
// and error if there is any.
p.runHelmCommand = func(args []string) ([]byte, error) {
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
cmd := exec.Command(p.HelmBin, args...)
cmd.Stdout = stdout
cmd.Stderr = stderr
cmd.Env = append(os.Environ(),
fmt.Sprintf("HELM_CONFIG_HOME=%s", p.HelmHome),
fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.HelmHome),
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.HelmHome),
)
err := cmd.Run()
if err != nil {
return stdout.Bytes(),
errors.Wrap(
fmt.Errorf("failed to run command %s %s", p.HelmBin, strings.Join(args, " ")),
stderr.String(),
)
}
return stdout.Bytes(), nil
}
return nil
return p.validateArgs()
}
// EncodeValues for writing
func (p *HelmChartInflationGeneratorPlugin) EncodeValues(w io.Writer) error {
d, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
_, err = w.Write(d)
if err != nil {
return err
}
return nil
}
// useValuesLocal process (merge) inflator config provided values with chart default values.yaml
func (p *HelmChartInflationGeneratorPlugin) useValuesLocal() error {
// not override, merge, none
if !(p.ValuesMerge == "none" || p.ValuesMerge == "no" || p.ValuesMerge == "false") {
var pValues []byte
var err error
if filepath.IsAbs(p.Values) {
pValues, err = ioutil.ReadFile(p.Values)
} else {
pValues, err = p.h.Loader().Load(p.Values)
}
if err != nil {
return err
}
chValues := make(map[string]interface{})
err = yaml.Unmarshal(pValues, &chValues)
if err != nil {
return err
}
if p.ValuesMerge == "override" {
err = mergo.Merge(&chValues, p.ValuesLocal, mergo.WithOverride)
if err != nil {
return err
}
}
if p.ValuesMerge == "merge" {
err = mergo.Merge(&chValues, p.ValuesLocal)
if err != nil {
return err
}
}
p.ValuesLocal = chValues
}
b, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
}
p.Values = path
return nil
}
// copyValues will copy the relative values file into the temp directory
// to avoid messing up with CWD.
func (p *HelmChartInflationGeneratorPlugin) copyValues() error {
// only copy when the values path is not absolute
if filepath.IsAbs(p.Values) {
// This uses the real file system since tmpDir may be used
// by the helm subprocess. Cannot use a chroot jail or fake
// filesystem since we allow the user to use previously
// downloaded charts. This is safe since this plugin is
// owned by kustomize.
func (p *HelmChartInflationGeneratorPlugin) establishTmpDir() (err error) {
if p.tmpDir != "" {
// already done.
return nil
}
// we must use use loader to read values file
b, err := p.h.Loader().Load(p.Values)
if err != nil {
p.tmpDir, err = ioutil.TempDir("", "kustomize-helm-")
return err
}
func (p *HelmChartInflationGeneratorPlugin) validateArgs() (err error) {
if p.Name == "" {
return fmt.Errorf("chart name cannot be empty")
}
// ChartHome might be consulted by the plugin (to read
// values files below it), so it must be located under
// the loader root (unless root restrictions are
// disabled, in which case this can be an absolute path).
if p.ChartHome == "" {
p.ChartHome = "charts"
}
// The ValuesFile may be consulted by the plugin, so it must
// be under the loader root (unless root restrictions are
// disabled).
if p.ValuesFile == "" {
p.ValuesFile = filepath.Join(p.ChartHome, p.Name, "values.yaml")
}
if err = p.errIfIllegalValuesMerge(); err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
// ConfigHome is not loaded by the plugin, and can be located anywhere.
if p.ConfigHome == "" {
if err = p.establishTmpDir(); err != nil {
return errors.Wrap(
err, "unable to create tmp dir for HELM_CONFIG_HOME")
}
p.ConfigHome = filepath.Join(p.tmpDir, "helm")
}
p.Values = path
return nil
}
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(b []byte) (string, error) {
path := filepath.Join(p.ChartHome, p.ChartName, "kustomize-values.yaml")
err := ioutil.WriteFile(path, b, 0644)
func (p *HelmChartInflationGeneratorPlugin) errIfIllegalValuesMerge() error {
if p.ValuesMerge == "" {
// Use the default.
p.ValuesMerge = valuesMergeOptionOverride
return nil
}
for _, opt := range legalMergeOptions {
if p.ValuesMerge == opt {
return nil
}
}
return fmt.Errorf("valuesMerge must be one of %v", legalMergeOptions)
}
func (p *HelmChartInflationGeneratorPlugin) absChartHome() string {
if filepath.IsAbs(p.ChartHome) {
return p.ChartHome
}
return filepath.Join(p.h.Loader().Root(), p.ChartHome)
}
func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
args []string) ([]byte, error) {
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
cmd := exec.Command(p.h.GeneralConfig().HelmConfig.Command, args...)
cmd.Stdout = stdout
cmd.Stderr = stderr
env := []string{
fmt.Sprintf("HELM_CONFIG_HOME=%s", p.ConfigHome),
fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.ConfigHome),
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.ConfigHome)}
cmd.Env = append(os.Environ(), env...)
err := cmd.Run()
if err != nil {
helm := p.h.GeneralConfig().HelmConfig.Command
err = errors.Wrap(
fmt.Errorf(
"unable to run: '%s %s' with env=%s (is '%s' installed?)",
helm, strings.Join(args, " "), env, helm),
stderr.String(),
)
}
return stdout.Bytes(), err
}
// createNewMergedValuesFile replaces/merges original values file with ValuesInline.
func (p *HelmChartInflationGeneratorPlugin) createNewMergedValuesFile() (
path string, err error) {
if p.ValuesMerge == valuesMergeOptionMerge ||
p.ValuesMerge == valuesMergeOptionOverride {
if err = p.replaceValuesInline(); err != nil {
return "", err
}
}
var b []byte
b, err = yaml.Marshal(p.ValuesInline)
if err != nil {
return "", err
}
return path, nil
return p.writeValuesBytes(b)
}
func (p *HelmChartInflationGeneratorPlugin) replaceValuesInline() error {
pValues, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return err
}
chValues := make(map[string]interface{})
if err = yaml.Unmarshal(pValues, &chValues); err != nil {
return err
}
switch p.ValuesMerge {
case valuesMergeOptionOverride:
err = mergo.Merge(
&chValues, p.ValuesInline, mergo.WithOverride)
case valuesMergeOptionMerge:
err = mergo.Merge(&chValues, p.ValuesInline)
}
p.ValuesInline = chValues
return err
}
// copyValuesFile to avoid branching. TODO: get rid of this.
func (p *HelmChartInflationGeneratorPlugin) copyValuesFile() (string, error) {
b, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return "", err
}
return p.writeValuesBytes(b)
}
// Write a absolute path file in the tmp file system.
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(
b []byte) (string, error) {
if err := p.establishTmpDir(); err != nil {
return "", fmt.Errorf("cannot create tmp dir to write helm values")
}
path := filepath.Join(p.tmpDir, p.Name+"-kustomize-values.yaml")
return path, ioutil.WriteFile(path, b, 0644)
}
func (p *HelmChartInflationGeneratorPlugin) cleanup() {
if p.tmpDir != "" {
os.RemoveAll(p.tmpDir)
}
}
// Generate implements generator
func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
// cleanup
defer os.RemoveAll(p.tmpDir)
// check helm version. we only support V3
err := p.checkHelmVersion()
if err != nil {
func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err error) {
defer p.cleanup()
if err = p.checkHelmVersion(); err != nil {
return nil, err
}
// pull the chart
if !p.checkLocalChart() {
_, err := p.runHelmCommand(p.getPullCommandArgs())
if err != nil {
if path, exists := p.chartExistsLocally(); !exists {
if p.Repo == "" {
return nil, fmt.Errorf(
"no repo specified for pull, no chart found at '%s'", path)
}
if _, err := p.runHelmCommand(p.pullCommand()); err != nil {
return nil, err
}
}
// inflator config valuesLocal
if len(p.ValuesLocal) > 0 {
err := p.useValuesLocal()
if err != nil {
return nil, err
}
if len(p.ValuesInline) > 0 {
p.ValuesFile, err = p.createNewMergedValuesFile()
} else {
err := p.copyValues()
if err != nil {
return nil, err
}
p.ValuesFile, err = p.copyValuesFile()
}
// render the charts
stdout, err := p.runHelmCommand(p.getTemplateCommandArgs())
if err != nil {
return nil, err
}
var stdout []byte
stdout, err = p.runHelmCommand(p.templateCommand())
if err != nil {
return nil, err
}
rm, rmfErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
if rmfErr == nil {
rm, err = p.h.ResmapFactory().NewResMapFromBytes(stdout)
if err == nil {
return rm, nil
}
// try to remove the contents before first "---" because
@@ -228,50 +259,49 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
if idx := strings.Index(stdoutStr, "---"); idx != -1 {
return p.h.ResmapFactory().NewResMapFromBytes([]byte(stdoutStr[idx:]))
}
return nil, rmfErr
return nil, err
}
func (p *HelmChartInflationGeneratorPlugin) getTemplateCommandArgs() []string {
func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
args := []string{"template"}
if p.ReleaseName != "" {
args = append(args, p.ReleaseName)
}
args = append(args, filepath.Join(p.ChartHome, p.ChartName))
if p.ReleaseNamespace != "" {
args = append(args, "--namespace", p.ReleaseNamespace)
args = append(args, filepath.Join(p.absChartHome(), p.Name))
if p.ValuesFile != "" {
args = append(args, "--values", p.ValuesFile)
}
if p.Values != "" {
args = append(args, "--values", p.Values)
if p.ReleaseName == "" {
// AFAICT, this doesn't work as intended due to a bug in helm.
// See https://github.com/helm/helm/issues/6019
// I've tried placing the flag before and after the name argument.
args = append(args, "--generate-name")
}
args = append(args, p.ExtraArgs...)
return args
}
func (p *HelmChartInflationGeneratorPlugin) getPullCommandArgs() []string {
args := []string{"pull", "--untar", "--untardir", p.ChartHome}
chartName := fmt.Sprintf("%s/%s", p.ChartRepoName, p.ChartName)
if p.ChartVersion != "" {
args = append(args, "--version", p.ChartVersion)
func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
args := []string{
"pull",
"--untar",
"--untardir", p.absChartHome(),
"--repo", p.Repo,
p.Name}
if p.Version != "" {
args = append(args, "--version", p.Version)
}
if p.ChartRepoURL != "" {
args = append(args, "--repo", p.ChartRepoURL)
chartName = p.ChartName
}
args = append(args, chartName)
return args
}
// checkLocalChart will return true if the chart does exist in
// chartExistsLocally will return true if the chart does exist in
// local chart home.
func (p *HelmChartInflationGeneratorPlugin) checkLocalChart() bool {
path := filepath.Join(p.ChartHome, p.ChartName)
func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool) {
path := filepath.Join(p.absChartHome(), p.Name)
s, err := os.Stat(path)
if err != nil {
return false
return "", false
}
return s.IsDir()
return path, s.IsDir()
}
// checkHelmVersion will return an error if the helm version is not V3

View File

@@ -0,0 +1,65 @@
// Code generated by pluginator on ReplacementTransformer; DO NOT EDIT.
// pluginator {unknown 1970-01-01T00:00:00Z }
package builtins
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/replacement"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/yaml"
)
// Replace values in targets with values from a source
type ReplacementTransformerPlugin struct {
ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"`
}
func (p *ReplacementTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.ReplacementList = []types.ReplacementField{}
if err := yaml.Unmarshal(c, p); err != nil {
return err
}
for _, r := range p.ReplacementList {
if r.Path != "" && (r.Source != nil || len(r.Targets) != 0) {
return fmt.Errorf("cannot specify both path and inline replacement")
}
if r.Path != "" {
// load the replacement from the path
content, err := h.Loader().Load(r.Path)
if err != nil {
return err
}
repl := types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl)
} else {
// replacement information is already loaded
p.Replacements = append(p.Replacements, r.Replacement)
}
}
return nil
}
func (p *ReplacementTransformerPlugin) Transform(m resmap.ResMap) (err error) {
var nodes []*kyaml.RNode
for _, r := range m.Resources() {
nodes = append(nodes, r.Node())
}
_, err = replacement.Filter{
Replacements: p.Replacements,
}.Filter(nodes)
return err
}
func NewReplacementTransformerPlugin() resmap.TransformerPlugin {
return &ReplacementTransformerPlugin{}
}

View File

@@ -6,6 +6,7 @@ package filesys
import (
"bytes"
"fmt"
"io"
"log"
"os"
"path/filepath"
@@ -37,9 +38,9 @@ type fsNode struct {
// if this node is a file, this is the content.
content []byte
// if this node is a file, this tracks whether or
// not it is "open".
open bool
// if offset is not nil the file is open and it tracks
// the current file offset.
offset *int
}
// MakeEmptyDirInMemory returns an empty directory.
@@ -119,6 +120,9 @@ func (n *fsNode) addFile(name string, c []byte) (result *fsNode, err error) {
result, ok := parent.dir[fileName]
if ok {
// File already exists; overwrite it.
if result.offset != nil {
return nil, fmt.Errorf("cannot add already opened file '%s'", n.Path())
}
result.content = c
return result, nil
}
@@ -133,7 +137,12 @@ func (n *fsNode) addFile(name string, c []byte) (result *fsNode, err error) {
// Create implements FileSystem.
// Create makes an empty file.
func (n *fsNode) Create(path string) (result File, err error) {
return n.AddFile(path, []byte{})
f, err := n.AddFile(path, nil)
if err != nil {
return f, err
}
f.offset = new(int)
return f, nil
}
// WriteFile implements FileSystem.
@@ -154,6 +163,7 @@ func (n *fsNode) AddFile(
}
func (n *fsNode) addDir(path string) (result *fsNode, err error) {
parent := n
dName, subDirName := mySplit(path)
if dName != "" {
@@ -348,7 +358,17 @@ func (n *fsNode) Size() int64 {
}
// Open implements FileSystem.
// Open opens the node for reading (just marks it).
// Open opens the node in read-write mode and sets the offset its start.
// Writing right after opening the file will replace the original content
// and move the offset forward, as with a file opened with O_RDWR | O_CREATE.
//
// As an example, let's consider a file with content "content":
// - open: sets offset to start, content is "content"
// - write "@": offset increases by one, the content is now "@ontent"
// - read the rest: since offset is 1, the read operation returns "ontent"
// - write "$": offset is at EOF, so "$" is appended and content is now "@ontent$"
// - read the rest: returns 0 bytes and EOF
// - close: the content is still "@ontent$"
func (n *fsNode) Open(path string) (File, error) {
result, err := n.Find(path)
if err != nil {
@@ -357,13 +377,19 @@ func (n *fsNode) Open(path string) (File, error) {
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to open it", path)
}
result.open = true
if result.offset != nil {
return nil, fmt.Errorf("cannot open previously opened file '%s'", path)
}
result.offset = new(int)
return result, nil
}
// Close marks the node closed.
func (n *fsNode) Close() error {
n.open = false
if n.offset == nil {
return fmt.Errorf("cannot close already closed file '%s'", n.Path())
}
n.offset = nil
return nil
}
@@ -376,9 +402,12 @@ func (n *fsNode) ReadFile(path string) (c []byte, err error) {
if result == nil {
return nil, fmt.Errorf("cannot find '%s' to read it", path)
}
if result.isNodeADir() {
return nil, fmt.Errorf("cannot read content from non-file '%s'", n.Path())
}
c = make([]byte, len(result.content))
_, err = result.Read(c)
return c, err
copy(c, result.content)
return c, nil
}
// Read returns the content of the file node.
@@ -387,7 +416,19 @@ func (n *fsNode) Read(d []byte) (c int, err error) {
return 0, fmt.Errorf(
"cannot read content from non-file '%s'", n.Path())
}
return copy(d, n.content), nil
if n.offset == nil {
return 0, fmt.Errorf("cannot read from closed file '%s'", n.Path())
}
rest := n.content[*n.offset:]
if len(d) < len(rest) {
rest = rest[:len(d)]
} else {
err = io.EOF
}
copy(d, rest)
*n.offset += len(rest)
return len(rest), err
}
// Write saves the contents of the argument to the file node.
@@ -396,8 +437,12 @@ func (n *fsNode) Write(p []byte) (c int, err error) {
return 0, fmt.Errorf(
"cannot write content to non-file '%s'", n.Path())
}
n.content = make([]byte, len(p))
return copy(n.content, p), nil
if n.offset == nil {
return 0, fmt.Errorf("cannot write to closed file '%s'", n.Path())
}
n.content = append(n.content[:*n.offset], p...)
*n.offset = len(n.content)
return len(p), nil
}
// ContentMatches returns true if v matches fake file's content.

View File

@@ -5,6 +5,9 @@ package filesys
import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"sort"
@@ -91,7 +94,6 @@ func TestMakeFsInMemory(t *testing.T) {
func runBasicOperations(
t *testing.T, tName string, isFSysRooted bool,
cases []pathCase, fSys FileSystem) {
buff := make([]byte, 500)
for _, c := range cases {
err := fSys.WriteFile(c.arg, []byte(content))
if c.errStr != "" {
@@ -128,26 +130,40 @@ func runBasicOperations(
if fi.Name() != c.name {
t.Fatalf("%s; expected name '%s', got '%s'", c.what, c.name, fi.Name())
}
count, err := f.Read(buff)
buff, err := ioutil.ReadAll(f)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if string(buff[:count]) != content {
if string(buff) != content {
t.Fatalf("%s; unexpected buff '%s'", c.what, buff)
}
count, err = f.Write([]byte(shortContent))
count, err := f.Write([]byte(shortContent))
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if count != len(shortContent) {
t.Fatalf("%s; unexpected count: %d", c.what, len(shortContent))
}
if err := f.Close(); err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
stuff, err = fSys.ReadFile(c.path)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
both := content + shortContent
if string(stuff) != both {
t.Fatalf("%s; unexpected content '%s', expected '%s'", c.what, stuff, both)
}
if err := fSys.WriteFile(c.path, []byte(shortContent)); err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
stuff, err = fSys.ReadFile(c.path)
if err != nil {
t.Fatalf("%s; unexpected error: %v", c.what, err)
}
if string(stuff) != shortContent {
t.Fatalf("%s; unexpected content '%s'", c.what, stuff)
t.Fatalf("%s; unexpected content '%s', expected '%s'", c.what, stuff, shortContent)
}
}
@@ -589,6 +605,7 @@ func TestGlob(t *testing.T) {
}
func assertEqualStringSlices(t *testing.T, expected, actual []string, message string) {
t.Helper()
if len(expected) != len(actual) {
t.Fatalf(
"%s; unequal sizes; len(expected)=%d, len(actual)=%d\n%+v\n%+v\n",
@@ -786,3 +803,52 @@ func TestCleanedAbs(t *testing.T) {
}
}
}
func TestFileOps(t *testing.T) {
const path = "foo.txt"
content := strings.Repeat("longest content", 100)
fs := MakeFsInMemory()
f, err := fs.Create(path)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, err := fs.Open(path); err == nil {
t.Fatalf("expected already opened error, got nil")
}
if _, err := fmt.Fprint(f, content); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := f.Close(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := f.Close(); err == nil {
t.Fatalf("expected already closed error, got nil")
}
f, err = fs.Open(path)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
defer f.Close()
for {
buf := make([]byte, rand.Intn(10))
n, err := f.Read(buf)
if err != nil && err != io.EOF {
t.Fatalf("unexpected error: %v", err)
}
if content[:n] != string(buf[:n]) {
t.Fatalf("unexpected read: expected %q got %q", content[:n], buf[:n])
}
content = content[n:]
if err != io.EOF {
continue
}
if len(content) == 0 {
break
}
t.Fatalf("unexpected EOF: remaining %d bytes", len(content))
}
}

View File

@@ -13,7 +13,7 @@ import (
)
type Filter struct {
Replacements []types.Replacement
Replacements []types.Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"`
}
// Filter replaces values of targets with values from sources
@@ -43,8 +43,8 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.T
t.FieldPaths = []string{types.DefaultReplacementFieldPath}
}
for _, n := range nodes {
// TODO (#3492): Don't include matches listed in the `reject` field
if t.Select.KrmId.Match(getKrmId(n)) {
nodeId := getKrmId(n)
if t.Select.KrmId.Match(nodeId) && !rejectId(t.Reject, nodeId) {
err := applyToNode(n, value, t)
if err != nil {
return nil, err
@@ -55,20 +55,61 @@ func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targets []*types.T
return nodes, nil
}
func rejectId(rejects []*types.Selector, nodeId *types.KrmId) bool {
for _, r := range rejects {
if r.KrmId.Match(nodeId) {
return true
}
}
return false
}
func applyToNode(node *yaml.RNode, value *yaml.RNode, target *types.TargetSelector) error {
for _, fp := range target.FieldPaths {
t, err := node.Pipe(yaml.Lookup(strings.Split(fp, ".")...))
fieldPath := strings.Split(fp, ".")
var t *yaml.RNode
var err error
if target.Options != nil && target.Options.Create {
t, err = node.Pipe(yaml.LookupCreate(value.YNode().Kind, fieldPath...))
} else {
t, err = node.Pipe(yaml.Lookup(fieldPath...))
}
if err != nil {
return err
}
if t != nil {
// TODO (#3492): Use the field options to refine interpretation of the field
t.SetYNode(value.YNode())
if err = setTargetValue(target.Options, t, value); err != nil {
return err
}
}
}
return nil
}
func setTargetValue(options *types.FieldOptions, t *yaml.RNode, value *yaml.RNode) error {
if options != nil && options.Delimiter != "" {
if t.YNode().Kind != yaml.ScalarNode {
return fmt.Errorf("delimiter option can only be used with scalar nodes")
}
tv := strings.Split(t.YNode().Value, options.Delimiter)
v := yaml.GetValue(value)
// TODO: Add a way to remove an element
switch {
case options.Index < 0: // prefix
tv = append([]string{v}, tv...)
case options.Index >= len(tv): // suffix
tv = append(tv, v)
default: // replace an element
tv[options.Index] = v
}
value.YNode().Value = strings.Join(tv, options.Delimiter)
}
t.SetYNode(value.YNode())
return nil
}
func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, error) {
source, err := selectSourceNode(nodes, r.Source)
if err != nil {
@@ -84,10 +125,28 @@ func getReplacement(nodes []*yaml.RNode, r *types.Replacement) (*yaml.RNode, err
if err != nil {
return nil, err
}
// TODO (#3492): Use the field options to refine interpretation of the field
if !rn.IsNilOrEmpty() {
return getRefinedValue(r.Source.Options, rn)
}
return rn, nil
}
func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, error) {
if options == nil || options.Delimiter == "" {
return rn, nil
}
if rn.YNode().Kind != yaml.ScalarNode {
return nil, fmt.Errorf("delimiter option can only be used with scalar nodes")
}
value := strings.Split(yaml.GetValue(rn), options.Delimiter)
if options.Index >= len(value) || options.Index < 0 {
return nil, fmt.Errorf("options.index %d is out of bounds for value %s", options.Index, yaml.GetValue(rn))
}
n := rn.Copy()
n.YNode().Value = value[options.Index]
return n, nil
}
// selectSourceNode finds the node that matches the selector, returning
// an error if multiple or none are found
func selectSourceNode(nodes []*yaml.RNode, selector *types.SourceSelector) (*yaml.RNode, error) {

View File

@@ -23,33 +23,7 @@ func TestFilter(t *testing.T) {
input: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy3
name: deploy
spec:
template:
spec:
@@ -62,19 +36,19 @@ spec:
replacements: `replacements:
- source:
kind: Deployment
name: deploy2
name: deploy
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
name: deploy1
name: deploy
fieldPaths:
- spec.template.spec.containers.1.image
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
name: deploy
spec:
template:
spec:
@@ -83,32 +57,6 @@ spec:
name: nginx-tagged
- image: nginx:1.7.9
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
},
"complex type": {
@@ -583,6 +531,813 @@ spec:
name: postgresdb
`,
},
"reject 1": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
replacements: `replacements:
- source:
kind: Deployment
name: deploy2
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
reject:
- name: deploy2
- name: deploy3
fieldPaths:
- spec.template.spec.containers.1.image
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:1.7.9
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
},
"reject 2": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: StatefulSet
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
replacements: `replacements:
- source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
version: v1
reject:
- kind: Deployment
name: my-name
fieldPaths:
- spec.template.spec.containers.1.image
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: StatefulSet
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:1.7.9
name: postgresdb
`,
},
// the only difference in the inputs between this and the previous test
// is the dash before `name: my-name` on line 733
"reject 3": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: StatefulSet
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
replacements: `replacements:
- source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
version: v1
reject:
- kind: Deployment
- name: my-name
fieldPaths:
- spec.template.spec.containers.1.image
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: StatefulSet
metadata:
name: my-name
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
},
"partial string replacement - replace": {
input: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
replacements: `replacements:
- source:
kind: Deployment
name: deploy2
fieldPath: spec.template.spec.containers.0.image
options:
delimiter: ':'
targets:
- select:
kind: Deployment
name: deploy1
fieldPaths:
- spec.template.spec.containers.1.image
options:
delimiter: ':'
`,
expected: `apiVersion: v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:1.8.0
name: postgresdb
---
apiVersion: v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx-tagged
- image: postgres:1.8.0
name: postgresdb
`,
},
"partial string replacement - prefix": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group/config
`,
replacements: `replacements:
- source:
kind: Pod
name: pod1
fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 0
targets:
- select:
kind: Pod
name: pod2
fieldPaths:
- spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: -1
`,
expected: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group/config
`,
},
"partial string replacement - suffix": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group/config
`,
replacements: `replacements:
- source:
kind: Pod
name: pod2
fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 1
targets:
- select:
kind: Pod
name: pod1
fieldPaths:
- spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 2
`,
expected: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group/config
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group/config
`,
},
"partial string replacement - last element": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group1
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2
`,
replacements: `replacements:
- source:
kind: Pod
name: pod2
fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 0
targets:
- select:
kind: Pod
name: pod1
fieldPaths:
- spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 1
`,
expected: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group2
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2
`,
},
"partial string replacement - first element": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group1/config
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2
`,
replacements: `replacements:
- source:
kind: Pod
name: pod2
fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 0
targets:
- select:
kind: Pod
name: pod1
fieldPaths:
- spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 0
`,
expected: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2/config
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2
`,
},
"options.index out of bounds": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: my/group1
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
volumes:
- projected:
sources:
- configMap:
name: myconfigmap
items:
- key: config
path: group2
`,
replacements: `replacements:
- source:
kind: Pod
name: pod2
fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: -1
targets:
- select:
kind: Pod
name: pod1
fieldPaths:
- spec.volumes.0.projected.sources.0.configMap.items.0.path
options:
delimiter: '/'
index: 1
`,
expectedErr: "options.index -1 is out of bounds for value group2",
},
"create": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
`,
replacements: `replacements:
- source:
kind: Pod
name: pod
fieldPath: spec.containers
targets:
- select:
name: deploy1
fieldPaths:
- spec.template.spec.containers
options:
create: true
- source:
kind: Pod
name: pod
fieldPath: spec.containers
targets:
- select:
name: deploy2
fieldPaths:
- spec.template.spec.containers
`,
expected: `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
`,
},
"complex type with delimiter in source": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers: {}
`,
replacements: `replacements:
- source:
kind: Pod
name: pod
fieldPath: spec.containers
options:
delimiter: "/"
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers
`,
expectedErr: "delimiter option can only be used with scalar nodes",
},
"complex type with delimiter in target": {
input: `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers: {}
`,
replacements: `replacements:
- source:
kind: Pod
name: pod
fieldPath: spec.containers
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers
options:
delimiter: "/"
`,
expectedErr: "delimiter option can only be used with scalar nodes",
},
}
for tn, tc := range testCases {

View File

@@ -11,6 +11,8 @@ require (
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.4.0
gopkg.in/yaml.v2 v2.4.0
sigs.k8s.io/kustomize/kyaml v0.10.16
sigs.k8s.io/kustomize/kyaml v0.10.17
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/kyaml => ../kyaml

View File

@@ -264,7 +264,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -269,7 +269,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
sigs.k8s.io/kustomize/kyaml v0.10.17 h1:4zrV0ym5AYa0e512q7K3Wp1u7mzoWW0xR3UHJcGWGIg=
sigs.k8s.io/kustomize/kyaml v0.10.17/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -41,5 +41,6 @@ func MakeConfigMap(
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
setImmutable(rn, args.Options)
return rn, nil
}

View File

@@ -163,6 +163,7 @@ data:
"river": "Missouri",
"city": "Iowa City",
},
Immutable: true,
},
},
},
@@ -183,6 +184,7 @@ data:
b: y
c: Hello World
d: "true"
immutable: true
`,
},
},

View File

@@ -54,5 +54,6 @@ func MakeSecret(
return nil, err
}
copyLabelsAndAnnotations(rn, args.Options)
setImmutable(rn, args.Options)
return rn, nil
}

View File

@@ -170,6 +170,7 @@ data:
"river": "Missouri",
"city": "Iowa City",
},
Immutable: true,
},
},
},
@@ -191,6 +192,7 @@ data:
b: eQ==
c: SGVsbG8gV29ybGQ=
d: dHJ1ZQ==
immutable: true
`,
},
},

View File

@@ -76,3 +76,16 @@ func copyLabelsAndAnnotations(
}
return nil
}
func setImmutable(
rn *yaml.RNode, opts *types.GeneratorOptions) error {
if opts == nil {
return nil
}
if opts.Immutable {
if _, err := rn.Pipe(yaml.SetField("immutable", yaml.NewScalarRNode("true"))); err != nil {
return err
}
}
return nil
}

View File

@@ -24,11 +24,12 @@ func _() {
_ = x[SecretGenerator-13]
_ = x[ValueAddTransformer-14]
_ = x[HelmChartInflationGenerator-15]
_ = x[ReplacementTransformer-16]
}
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGenerator"
const _BuiltinPluginType_name = "UnknownAnnotationsTransformerConfigMapGeneratorHashTransformerImageTagTransformerLabelTransformerLegacyOrderTransformerNamespaceTransformerPatchJson6902TransformerPatchStrategicMergeTransformerPatchTransformerPrefixSuffixTransformerReplicaCountTransformerSecretGeneratorValueAddTransformerHelmChartInflationGeneratorReplacementTransformer"
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316}
var _BuiltinPluginType_index = [...]uint16{0, 7, 29, 47, 62, 81, 97, 119, 139, 163, 193, 209, 232, 255, 270, 289, 316, 338}
func (i BuiltinPluginType) String() string {
if i < 0 || i >= BuiltinPluginType(len(_BuiltinPluginType_index)-1) {

View File

@@ -28,6 +28,7 @@ const (
SecretGenerator
ValueAddTransformer
HelmChartInflationGenerator
ReplacementTransformer
)
var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
@@ -72,6 +73,7 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
PatchStrategicMergeTransformer: builtins.NewPatchStrategicMergeTransformerPlugin,
PatchTransformer: builtins.NewPatchTransformerPlugin,
PrefixSuffixTransformer: builtins.NewPrefixSuffixTransformerPlugin,
ReplacementTransformer: builtins.NewReplacementTransformerPlugin,
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
ValueAddTransformer: builtins.NewValueAddTransformerPlugin,
}

View File

@@ -45,7 +45,8 @@ s/$BAR/bar baz/g
})
pluginConfig.RemoveBuildAnnotations()
loader := pLdr.NewLoader(types.DisabledPluginConfig(), rf, fSys)
pc := types.DisabledPluginConfig()
loader := pLdr.NewLoader(pc, rf, fSys)
pluginPath, err := loader.AbsolutePluginPath(pluginConfig.OrgId())
if err != nil {
t.Fatalf("unexpected err: %v", err)
@@ -61,7 +62,9 @@ s/$BAR/bar baz/g
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
p.Config(resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf), yaml)
p.Config(
resmap.NewPluginHelpers(ldr, pvd.GetFieldValidator(), rf, pc),
yaml)
expected := "someteam.example.com/v1/sedtransformer/SedTransformer"
if !strings.HasSuffix(p.Path(), expected) {

View File

@@ -42,6 +42,11 @@ func NewLoader(
return &Loader{pc: pc, rf: rf, fs: fs}
}
// Config provides the global (not plugin specific) PluginConfig data.
func (l *Loader) Config() *types.PluginConfig {
return l.pc
}
func (l *Loader) LoadGenerators(
ldr ifc.Loader, v ifc.Validator, rm resmap.ResMap) ([]resmap.Generator, error) {
var result []resmap.Generator
@@ -188,7 +193,7 @@ func (l *Loader) loadAndConfigurePlugin(
if err != nil {
return nil, errors.Wrapf(err, "marshalling yaml from res %s", res.OrgId())
}
err = c.Config(resmap.NewPluginHelpers(ldr, v, l.rf), yaml)
err = c.Config(resmap.NewPluginHelpers(ldr, v, l.rf, l.pc), yaml)
if err != nil {
return nil, errors.Wrapf(
err, "plugin %s fails configuration", res.OrgId())

View File

@@ -443,7 +443,10 @@ func (kt *KustTarget) configureBuiltinPlugin(
err, "builtin %s marshal", bpt)
}
}
err = p.Config(resmap.NewPluginHelpers(kt.ldr, kt.validator, kt.rFactory), y)
err = p.Config(
resmap.NewPluginHelpers(
kt.ldr, kt.validator, kt.rFactory, kt.pLdr.Config()),
y)
if err != nil {
return errors.Wrapf(
err, "trouble configuring builtin %s with config: `\n%s`", bpt, string(y))

View File

@@ -57,6 +57,7 @@ func (kt *KustTarget) configureBuiltinTransformers(
builtinhelpers.PatchJson6902Transformer,
builtinhelpers.ReplicaCountTransformer,
builtinhelpers.ImageTagTransformer,
builtinhelpers.ReplacementTransformer,
} {
r, err := transformerConfigurators[bpt](
kt, bpt, builtinhelpers.TransformerFactories[bpt], tc)
@@ -112,16 +113,22 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func(
return
},
builtinhelpers.HelmChartInflationGenerator: func(kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
builtinhelpers.HelmChartInflationGenerator: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f gFactory) (
result []resmap.Generator, err error) {
var c struct {
types.HelmChartArgs
types.HelmGlobals
types.HelmChart
}
for _, args := range kt.kustomization.HelmChartInflationGenerator {
c.HelmChartArgs = args
var globals types.HelmGlobals
if kt.kustomization.HelmGlobals != nil {
globals = *kt.kustomization.HelmGlobals
}
for _, chart := range kt.kustomization.HelmCharts {
c.HelmGlobals = globals
c.HelmChart = chart
p := f()
err := kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
if err = kt.configureBuiltinPlugin(p, c, bpt); err != nil {
return nil, err
}
result = append(result, p)
@@ -317,6 +324,21 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func(
}
return
},
builtinhelpers.ReplacementTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, _ *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {
var c struct {
Replacements []types.ReplacementField
}
c.Replacements = kt.kustomization.Replacements
p := f()
err = kt.configureBuiltinPlugin(p, c, bpt)
if err != nil {
return nil, err
}
result = append(result, p)
return result, nil
},
builtinhelpers.ReplicaCountTransformer: func(
kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) (
result []resmap.Transformer, err error) {

View File

@@ -3,14 +3,13 @@
package krusty_test
/*
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
var expected string = `
const expectedHelm = `
apiVersion: v1
data:
rcon-password: Q0hBTkdFTUUh
@@ -18,36 +17,19 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-1.2.0
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
type: Opaque
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
volume.alpha.kubernetes.io/storage-class: default
labels:
app: test-minecraft
chart: minecraft-1.2.0
heritage: Helm
release: test
name: test-minecraft-datadir
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
app: test-minecraft
chart: minecraft-1.2.0
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
@@ -59,45 +41,43 @@ spec:
targetPort: minecraft
selector:
app: test-minecraft
type: LoadBalancer
type: ClusterIP
`
func TestHelmChartInflationGenerator(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
func TestHelmChartInflationGeneratorOld(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
th.WriteK(th.GetRoot(), `
helmChartInflationGenerator:
- chartName: minecraft
chartRepoUrl: https://kubernetes-charts.storage.googleapis.com
chartVersion: v1.2.0
chartRepoUrl: https://itzg.github.io/minecraft-server-charts
chartVersion: 3.1.3
releaseName: test
releaseNamespace: testNamespace
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, expectedHelm)
}
func TestHelmChartInflationGenerator(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
func TestHelmChartInflationGeneratorAsPlugin(t *testing.T) {
th := kusttest_test.MakeHarness(t)
th.WriteK("/app", `
generators:
- helm.yaml
th.WriteK(th.GetRoot(), `
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
releaseName: test
`)
th.WriteF("/app/helm.yaml", `
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMap
chartName: minecraft
chartRepoUrl: https://kubernetes-charts.storage.googleapis.com
chartVersion: v1.2.0
releaseName: test
releaseNamespace: testNamespace
`)
m := th.Run("/app", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, expectedHelm)
}
*/

View File

@@ -0,0 +1,271 @@
package krusty_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
// end to end tests to demonstrate functionality of ReplacementTransformer
func TestReplacementsField(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK(".", `
resources:
- resource.yaml
replacements:
- source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image
`)
th.WriteF("resource.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
expected := `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}
func TestReplacementsFieldWithPath(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteK(".", `
resources:
- resource.yaml
replacements:
- path: replacement.yaml
`)
th.WriteF("replacement.yaml",
`
source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image
`)
th.WriteF("resource.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
expected := `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, expected)
}
func TestReplacementTransformerWithDiamondShape(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t)
defer th.Reset()
th.WriteF("base/deployment.yaml",
`
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: nginx:1.7.9
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
`)
th.WriteF("base/kustomization.yaml",
`
resources:
- deployment.yaml
`)
th.WriteF("a/kustomization.yaml",
`
namePrefix: a-
resources:
- ../base
replacements:
- path: replacement.yaml
`)
th.WriteF("a/replacement.yaml",
`
source:
name: a-sourceA
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
name: a-deploy
fieldPaths:
- spec.template.spec.containers.[name=nginx].image
`)
th.WriteF("b/kustomization.yaml",
`
namePrefix: b-
resources:
- ../base
replacements:
- path: replacement.yaml
`)
th.WriteF("b/replacement.yaml",
`
source:
name: b-sourceB
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
name: b-deploy
fieldPaths:
- spec.template.spec.containers.[name=nginx].image
`)
th.WriteF("combined/kustomization.yaml",
`
resources:
- ../a
- ../b
`)
m := th.Run("combined", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-deploy
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: a-sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-deploy
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-sourceA
spec:
template:
spec:
containers:
- image: nginx:newtagA
name: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: b-sourceB
spec:
template:
spec:
containers:
- image: nginx:newtagB
name: nginx
`)
}

View File

@@ -319,7 +319,6 @@ func (fl *fileLoader) Load(path string) ([]byte, error) {
}
return body, nil
}
if !filepath.IsAbs(path) {
path = fl.root.Join(path)
}

View File

@@ -54,7 +54,6 @@ func MakeFakeFs(td []testData) filesys.FileSystem {
func makeLoader() *fileLoader {
return NewFileLoaderAtRoot(MakeFakeFs(testCases))
}
func TestLoaderLoad(t *testing.T) {

View File

@@ -33,8 +33,10 @@ type Configurable interface {
}
// NewPluginHelpers makes an instance of PluginHelpers.
func NewPluginHelpers(ldr ifc.Loader, v ifc.Validator, rf *Factory) *PluginHelpers {
return &PluginHelpers{ldr: ldr, v: v, rf: rf}
func NewPluginHelpers(
ldr ifc.Loader, v ifc.Validator, rf *Factory,
pc *types.PluginConfig) *PluginHelpers {
return &PluginHelpers{ldr: ldr, v: v, rf: rf, pc: pc}
}
// PluginHelpers holds things that any or all plugins might need.
@@ -44,6 +46,11 @@ type PluginHelpers struct {
ldr ifc.Loader
v ifc.Validator
rf *Factory
pc *types.PluginConfig
}
func (c *PluginHelpers) GeneralConfig() *types.PluginConfig {
return c.pc
}
func (c *PluginHelpers) Loader() ifc.Loader {

View File

@@ -57,6 +57,10 @@ func (r *Resource) AsRNode() *kyaml.RNode {
return r.node.Copy()
}
func (r *Resource) Node() *kyaml.RNode {
return r.node
}
func (r *Resource) ResetPrimaryData(incoming *Resource) {
r.node = incoming.node.Copy()
}

View File

@@ -42,27 +42,36 @@ func (th Harness) GetFSys() filesys.FileSystem {
}
func (th Harness) WriteK(path string, content string) {
th.fSys.WriteFile(
err := th.fSys.WriteFile(
filepath.Join(
path,
konfig.DefaultKustomizationFileName()), []byte(`
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`+content))
if err != nil {
th.t.Fatalf("unexpected error while writing Kustomization to %s: %v", path, err)
}
}
func (th Harness) WriteC(path string, content string) {
th.fSys.WriteFile(
err := th.fSys.WriteFile(
filepath.Join(
path,
konfig.DefaultKustomizationFileName()), []byte(`
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
`+content))
if err != nil {
th.t.Fatalf("unexpected error while writing Component to %s: %v", path, err)
}
}
func (th Harness) WriteF(path string, content string) {
th.fSys.WriteFile(path, []byte(content))
err := th.fSys.WriteFile(path, []byte(content))
if err != nil {
th.t.Fatalf("unexpected error while writing file to %s: %v", path, err)
}
}
func (th Harness) MakeDefaultOptions() krusty.Options {

View File

@@ -4,6 +4,10 @@
package kusttest_test
import (
"io/ioutil"
"os"
"os/exec"
"strings"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
@@ -33,36 +37,77 @@ type HarnessEnhanced struct {
// A file loader using the Harness.fSys to read test data.
ldr ifc.Loader
// If true, wipe the ifc.loader root (not the plugin loader root)
// as part of cleanup.
shouldWipeLdrRoot bool
// A plugin loader that loads plugins from a (real) file system.
pl *pLdr.Loader
}
func MakeEnhancedHarness(t *testing.T) *HarnessEnhanced {
pte := newPluginTestEnv(t).set()
r := makeBaseEnhancedHarness(t)
r.Harness = MakeHarnessWithFs(t, filesys.MakeFsInMemory())
// Point the Harness's file loader to the root ('/')
// of the in-memory file system.
r.ResetLoaderRoot(filesys.Separator)
return r
}
pc := types.EnabledPluginConfig(types.BploLoadFromFileSys)
pc.FnpLoadingOptions.EnableStar = true
p := provider.NewDefaultDepProvider()
resourceFactory := p.GetResourceFactory()
resmapFactory := resmap.NewFactory(resourceFactory)
func MakeEnhancedHarnessWithTmpRoot(t *testing.T) *HarnessEnhanced {
r := makeBaseEnhancedHarness(t)
fSys := filesys.MakeFsOnDisk()
r.Harness = MakeHarnessWithFs(t, fSys)
tmpDir, err := ioutil.TempDir("", "kust-testing-")
if err != nil {
panic("test harness cannot make tmp dir: " + err.Error())
}
r.ldr, err = fLdr.NewLoader(fLdr.RestrictionRootOnly, tmpDir, fSys)
if err != nil {
panic("test harness cannot make ldr at tmp dir: " + err.Error())
}
r.shouldWipeLdrRoot = true
return r
}
result := &HarnessEnhanced{
Harness: MakeHarness(t),
pte: pte,
rf: resmapFactory,
// The plugin configs are always located on disk, regardless of the test harness's FS
pl: pLdr.NewLoader(pc, resmapFactory, filesys.MakeFsOnDisk())}
func makeBaseEnhancedHarness(t *testing.T) *HarnessEnhanced {
rf := resmap.NewFactory(
provider.NewDefaultDepProvider().GetResourceFactory())
return &HarnessEnhanced{
pte: newPluginTestEnv(t).set(),
rf: rf,
pl: pLdr.NewLoader(
types.EnabledPluginConfig(types.BploLoadFromFileSys),
rf,
// Plugin configs are always located on disk,
// regardless of the test harness's FS
filesys.MakeFsOnDisk())}
}
// Point the file loader to the root ('/') of the in-memory file system.
result.ResetLoaderRoot(filesys.Separator)
func (th *HarnessEnhanced) ErrIfNoHelm() error {
_, err := exec.LookPath(th.GetPluginConfig().HelmConfig.Command)
return err
}
return result
func (th *HarnessEnhanced) GetRoot() string {
return th.ldr.Root()
}
func (th *HarnessEnhanced) Reset() {
if th.shouldWipeLdrRoot {
if !strings.HasPrefix(th.ldr.Root(), os.TempDir()) {
// sanity check.
panic("something strange about th.ldr.Root() = " + th.ldr.Root())
}
os.RemoveAll(th.ldr.Root())
}
th.pte.reset()
}
func (th *HarnessEnhanced) GetPluginConfig() *types.PluginConfig {
return th.pl.Config()
}
func (th *HarnessEnhanced) PrepBuiltin(k string) *HarnessEnhanced {
return th.BuildGoPlugin(konfig.BuiltinPluginPackage, "", k)
}
@@ -105,7 +150,7 @@ func (th *HarnessEnhanced) LoadAndRunGenerator(
}
rm, err := g.Generate()
if err != nil {
th.t.Fatalf("Err: %v", err)
th.t.Fatalf("generate err: %v", err)
}
rm.RemoveBuildAnnotations()
return rm

View File

@@ -15,6 +15,9 @@ type GeneratorOptions struct {
// suffix to the names of generated resources that is a hash of the
// resource contents.
DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"`
// Immutable if true add to all generated resources.
Immutable bool `json:"immutable,omitempty" yaml:"immutable,omitempty"`
}
// MergeGlobalOptionsIntoLocal merges two instances of GeneratorOptions.
@@ -42,6 +45,9 @@ func MergeGlobalOptionsIntoLocal(
if globalOpts.DisableNameSuffixHash {
localOpts.DisableNameSuffixHash = true
}
if globalOpts.Immutable {
localOpts.Immutable = true
}
return localOpts
}

View File

@@ -34,6 +34,7 @@ func TestMergeGlobalOptionsIntoLocal(t *testing.T) {
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
Immutable: false,
},
},
{
@@ -47,6 +48,7 @@ func TestMergeGlobalOptionsIntoLocal(t *testing.T) {
Labels: map[string]string{"pet": "dog"},
Annotations: map[string]string{"fruit": "apple"},
DisableNameSuffixHash: false,
Immutable: false,
},
},
{
@@ -76,42 +78,52 @@ func TestMergeGlobalOptionsIntoLocal(t *testing.T) {
"tesla": "Y",
},
DisableNameSuffixHash: false,
Immutable: false,
},
},
{
name: "global disable trumps local",
local: &GeneratorOptions{
DisableNameSuffixHash: false,
Immutable: false,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
},
{
name: "local disable works",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: false,
Immutable: false,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
},
{
name: "everyone wants disable",
local: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
global: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
expected: &GeneratorOptions{
DisableNameSuffixHash: true,
Immutable: true,
},
},
}

View File

@@ -3,14 +3,77 @@
package types
// HelmChartArgs contains the metadata of how to generate a secret.
type HelmGlobals struct {
// ChartHome is a file path, relative to the kustomization root,
// to a directory containing a subdirectory for each chart to be
// included in the kustomization.
// The default value of this field is "charts".
// So, for example, kustomize looks for the minecraft chart
// at {kustomizationRoot}/{ChartHome}/minecraft.
// If the chart is there at build time, kustomize will use it as found,
// and not check version numbers or dates.
// If the chart is not there, kustomize will attempt to pull it
// using the version number specified in the kustomization file,
// and put it there. To suppress the pull attempt, simply assure
// that the chart is already there.
ChartHome string `json:"chartHome,omitempty" yaml:"chartHome,omitempty"`
// ConfigHome defines a value that kustomize should pass to helm via
// the HELM_CONFIG_HOME environment variable. kustomize doesn't attempt
// to read or write this directory.
// If omitted, {tmpDir}/helm is used, where {tmpDir} is some temporary
// directory created by kustomize for the benefit of helm.
// Likewise, kustomize sets
// HELM_CACHE_HOME={ConfigHome}/.cache
// HELM_DATA_HOME={ConfigHome}/.data
// for the helm subprocess.
ConfigHome string `json:"configHome,omitempty" yaml:"configHome,omitempty"`
}
type HelmChart struct {
// Name is the name of the chart, e.g. 'minecraft'.
Name string `json:"name,omitempty" yaml:"name,omitempty"`
// Version is the version of the chart, e.g. '3.1.3'
Version string `json:"version,omitempty" yaml:"version,omitempty"`
// Repo is a URL locating the chart on the internet.
// This is the argument to helm's `--repo` flag, e.g.
// `https://itzg.github.io/minecraft-server-charts`.
Repo string `json:"repo,omitempty" yaml:"repo,omitempty"`
// ReleaseName replaces RELEASE-NAME in chart template output,
// making a particular inflation of a chart unique with respect to
// other inflations of the same chart in a cluster. It's the first
// argument to the helm `install` and `template` commands, i.e.
// helm install {RELEASE-NAME} {chartName}
// helm template {RELEASE-NAME} {chartName}
// If omitted, the flag --generate-name is passed to 'helm template'.
ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"`
// ValuesFile is local file path to a values file to use _instead of_
// the default values that accompanied the chart.
// The default values are in '{ChartHome}/{Name}/values.yaml'.
ValuesFile string `json:"valuesFile,omitempty" yaml:"valuesFile,omitempty"`
// ValuesInline holds value mappings specified directly,
// rather than in a separate file.
ValuesInline map[string]interface{} `json:"valuesInline,omitempty" yaml:"valuesInline,omitempty"`
// ValuesMerge specifies how to treat ValuesInline with respect to Values.
// Legal values: 'merge', 'override', 'replace'.
// Defaults to 'override'.
ValuesMerge string `json:"valuesMerge,omitempty" yaml:"valuesMerge,omitempty"`
}
// HelmChartArgs contains arguments to helm.
// Deprecated. Use HelmGlobals and HelmChart instead.
type HelmChartArgs struct {
ChartName string `json:"chartName,omitempty" yaml:"chartName,omitempty"`
ChartVersion string `json:"chartVersion,omitempty" yaml:"chartVersion,omitempty"`
ChartRepoURL string `json:"chartRepoUrl,omitempty" yaml:"chartRepoUrl,omitempty"`
ChartHome string `json:"chartHome,omitempty" yaml:"chartHome,omitempty"`
// Use chartRelease to keep compatible with old exec plugin
ChartRepoName string `json:"chartRelease,omitempty" yaml:"chartRelease,omitempty"`
ChartName string `json:"chartName,omitempty" yaml:"chartName,omitempty"`
ChartVersion string `json:"chartVersion,omitempty" yaml:"chartVersion,omitempty"`
ChartRepoURL string `json:"chartRepoUrl,omitempty" yaml:"chartRepoUrl,omitempty"`
ChartHome string `json:"chartHome,omitempty" yaml:"chartHome,omitempty"`
ChartRepoName string `json:"chartRepoName,omitempty" yaml:"chartRepoName,omitempty"`
HelmBin string `json:"helmBin,omitempty" yaml:"helmBin,omitempty"`
HelmHome string `json:"helmHome,omitempty" yaml:"helmHome,omitempty"`
Values string `json:"values,omitempty" yaml:"values,omitempty"`
@@ -20,3 +83,32 @@ type HelmChartArgs struct {
ReleaseNamespace string `json:"releaseNamespace,omitempty" yaml:"releaseNamespace,omitempty"`
ExtraArgs []string `json:"extraArgs,omitempty" yaml:"extraArgs,omitempty"`
}
// SplitHelmParameters splits helm parameters into
// per-chart params and global chart-independent parameters.
func SplitHelmParameters(
oldArgs []HelmChartArgs) (charts []HelmChart, globals HelmGlobals) {
for _, old := range oldArgs {
charts = append(charts, makeHelmChartFromHca(&old))
if old.HelmHome != "" {
// last non-empty wins
globals.ConfigHome = old.HelmHome
}
if old.ChartHome != "" {
// last non-empty wins
globals.ChartHome = old.ChartHome
}
}
return charts, globals
}
func makeHelmChartFromHca(old *HelmChartArgs) (c HelmChart) {
c.Name = old.ChartName
c.Version = old.ChartVersion
c.Repo = old.ChartRepoURL
c.ValuesFile = old.Values
c.ValuesInline = old.ValuesLocal
c.ValuesMerge = old.ValuesMerge
c.ReleaseName = old.ReleaseName
return
}

View File

@@ -74,6 +74,10 @@ type Kustomization struct {
// patch, but this operator is simpler to specify.
Images []Image `json:"images,omitempty" yaml:"images,omitempty"`
// Replacements is a list of replacements, which will copy nodes from a
// specified source to N specified targets.
Replacements []ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
// Replicas is a list of {resourcename, count} that allows for simpler replica
// specification. This can also be done with a patch.
Replicas []Replica `json:"replicas,omitempty" yaml:"replicas,omitempty"`
@@ -129,9 +133,14 @@ type Kustomization struct {
// the map will have a suffix hash generated from its contents.
SecretGenerator []SecretArgs `json:"secretGenerator,omitempty" yaml:"secretGenerator,omitempty"`
// HelmGlobals contains helm configuration that isn't chart specific.
HelmGlobals *HelmGlobals `json:"helmGlobals,omitempty" yaml:"helmGlobals,omitempty"`
// HelmCharts is a list of helm chart configuration instances.
HelmCharts []HelmChart `json:"helmCharts,omitempty" yaml:"helmCharts,omitempty"`
// HelmChartInflationGenerator is a list of helm chart configurations.
// The resulting resource is a normal operand rendered from
// a remote chart by `helm template`
// Deprecated. Auto-converted to HelmGlobals and HelmCharts.
HelmChartInflationGenerator []HelmChartArgs `json:"helmChartInflationGenerator,omitempty" yaml:"helmChartInflationGenerator,omitempty"`
// GeneratorOptions modify behavior of all ConfigMap and Secret generators.
@@ -185,6 +194,15 @@ func (k *Kustomization) FixKustomizationPostUnmarshalling() {
k.SecretGenerator[i].EnvSource = ""
}
}
charts, globals := SplitHelmParameters(k.HelmChartInflationGenerator)
if k.HelmGlobals == nil {
if globals.ChartHome != "" || globals.ConfigHome != "" {
k.HelmGlobals = &globals
}
}
k.HelmCharts = append(k.HelmCharts, charts...)
// Wipe it for the fix command.
k.HelmChartInflationGenerator = nil
}
// FixKustomizationPreMarshalling fixes things

View File

@@ -3,6 +3,11 @@
package types
type HelmConfig struct {
Enabled bool
Command string
}
// PluginConfig holds plugin configuration.
type PluginConfig struct {
// PluginRestrictions distinguishes plugin restrictions.
@@ -13,10 +18,18 @@ type PluginConfig struct {
// FnpLoadingOptions sets the way function-based plugin behaviors.
FnpLoadingOptions FnPluginLoadingOptions
// HelmConfig contains metadata needed for allowing and running helm.
HelmConfig HelmConfig
}
func EnabledPluginConfig(b BuiltinPluginLoadingOptions) *PluginConfig {
return MakePluginConfig(PluginRestrictionsNone, b)
func EnabledPluginConfig(b BuiltinPluginLoadingOptions) (pc *PluginConfig) {
pc = MakePluginConfig(PluginRestrictionsNone, b)
pc.FnpLoadingOptions.EnableStar = true
pc.HelmConfig.Enabled = true
// If this command is not on PATH, tests needing it should skip.
pc.HelmConfig.Command = "helmV3"
return
}
func DisabledPluginConfig() *PluginConfig {

View File

@@ -33,9 +33,7 @@ type TargetSelector struct {
Select *Selector `json:"select" yaml:"select"`
// From the allowed set, remove objects that match this.
// TODO (#3492): Remove matches listed in the `reject` field
// Currently this field is unused
Reject *Selector `json:"reject" yaml:"reject"`
Reject []*Selector `json:"reject" yaml:"reject"`
// Structured field paths expected in each allowed object.
FieldPaths []string `json:"fieldPaths" yaml:"fieldPaths"`
@@ -45,8 +43,6 @@ type TargetSelector struct {
}
// FieldOptions refine the interpretation of FieldPaths.
// TODO (#3492): Implement use of these options, they are
// currently unused
type FieldOptions struct {
// Used to split/join the field.
Delimiter string `json:"delimiter" yaml:"delimiter"`
@@ -54,8 +50,9 @@ type FieldOptions struct {
// Which position in the split to consider.
Index int `json:"index" yaml:"index"`
// None, Base64, URL, Hex, etc.
Encoding string `json:"encoding" yaml:"index"`
// TODO (#3492): Implement use of this option
// None, Base64, URL, Hex, etc
Encoding string `json:"encoding" yaml:"encoding"`
// If field missing, add it.
Create bool `json:"create" yaml:"create"`

View File

@@ -0,0 +1,6 @@
package types
type ReplacementField struct {
Replacement `json:",inline,omitempty" yaml:",inline,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
}

View File

@@ -16,5 +16,7 @@ require (
golang.org/x/text v0.3.4 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/inf.v0 v0.9.1
sigs.k8s.io/kustomize/kyaml v0.10.16
sigs.k8s.io/kustomize/kyaml v0.10.17
)
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml

View File

@@ -290,5 +290,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=

View File

@@ -33,8 +33,9 @@ var (
"docs",
"examples",
"hack",
"site",
"plugin",
"releasing",
"site",
}
)

View File

@@ -6,8 +6,10 @@ require (
github.com/rakyll/statik v0.1.7
github.com/spf13/cobra v1.0.0
github.com/stretchr/testify v1.4.0
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/kyaml v0.10.16
sigs.k8s.io/kustomize/api v0.8.8
sigs.k8s.io/kustomize/kyaml v0.10.17
)
replace sigs.k8s.io/kustomize/api => ../../api
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml

View File

@@ -267,7 +267,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -8,6 +8,7 @@ import (
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/fn/framework"
)
@@ -17,7 +18,7 @@ func main() {
p := provider.NewDefaultDepProvider()
resmapFactory := resmap.NewFactory(p.GetResourceFactory())
pluginHelpers := resmap.NewPluginHelpers(
nil, p.GetFieldValidator(), resmapFactory)
nil, p.GetFieldValidator(), resmapFactory, types.DisabledPluginConfig())
processor := framework.ResourceListProcessorFunc(func(resourceList *framework.ResourceList) error {
resMap, err := resmapFactory.NewResMapFromRNodeSlice(resourceList.Items)

View File

@@ -1,49 +1,63 @@
# kustomization of a helm chart
[`helm`]: https://helm.sh
[last mile]: https://testingclouds.wordpress.com/2018/07/20/844/
[stable chart]: https://github.com/helm/charts/tree/master/stable
[helm charts]: https://github.com/helm/charts
[_minecraft_]: https://github.com/helm/charts/tree/master/stable/minecraft
[artifact hub]: https://artifacthub.io
[_minecraft_]: https://artifacthub.io/packages/helm/minecraft-server-charts/minecraft
[plugin]: ../docs/plugins
[built]: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization
[Helm charts] aren't natively read by kustomize, but
kustomize has a builtin HelmChartInflationGenerator that allows one to
access helm charts.
Kustomize is [built] from _generators_ and
_transformers_; the former make kubernetes YAML, the
latter transform said YAML.
One pattern combining kustomize and helm is
the [last mile] modification, where
one uses an inflated chart as a base, then
modifies it on the way to the cluster using
kustomize.
Kustomize, via the `helmCharts` field, has the ability to
use the [`helm`] command line program in a subprocess to
inflate a helm chart, generating YAML as part of (or as the
entirety of) a kustomize base.
The example arbitrarily uses [_minecraft_] in [stable chart] repository,
but should work for any chart in any valid chart repository.
This YAML can then be modified either in the base directly
(transformers always run _after_ generators), or via
a kustomize overlay.
Either approach can be viewed as [last mile] modification
of the chart output before applying it to a cluster.
The example below arbitrarily uses the
[_minecraft_] chart pulled from the [artifact hub]
chart repository.
## Preparation
This example defines the `helm` command as
<!-- @defineHelmCommand @testHelm -->
```
helmCommand=~/go/bin/helmV3
```
This value is needed for testing this example in CI/CD.
A user doesn't need this if their binary is called
`helm` and is on their shell's `PATH`.
The following example assumes you have `helm`
on your `$PATH`. The plugin only supports helm V3 or later.
Make a place to work:
<!-- @makeWorkplace @helmtest -->
<!-- @makeWorkplace @testHelm -->
```
DEMO_HOME=$(mktemp -d)
mkdir -p $DEMO_HOME/base
mkdir -p $DEMO_HOME/dev
mkdir -p $DEMO_HOME/prod
mkdir -p $DEMO_HOME/base $DEMO_HOME/dev $DEMO_HOME/prod
```
## Use a remote chart
## Define some variants
Define a kustomization representing your _development_
variant (aka environment).
variant.
This could involve any number of kustomizations (see
other examples), but in this case just add the name
prefix `dev-` to all resources:
<!-- @writeKustDev @helmtest -->
prefix '`dev-`' to all resources:
<!-- @writeKustDev @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/dev/kustomization.yaml
namePrefix: dev-
@@ -53,10 +67,9 @@ EOF
```
Likewise define a _production_ variant, with a name
prefix `prod-`:
<!-- @writeKustProd @helmtest -->
prefix '`prod-`':
<!-- @writeKustProd @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/prod/kustomization.yaml
namePrefix: prod-
@@ -67,45 +80,34 @@ EOF
These two variants refer to a common base.
Define this base:
<!-- @writeKustDev @helmtest -->
Define this base the usual way by creating a
`kustomization` file:
<!-- @writeKustBase @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/base/kustomization.yaml
generators:
- chartInflator.yaml
helmCharts:
- name: minecraft
valuesInline:
minecraftServer:
eula: true
difficulty: hard
rcon:
enabled: true
releaseName: moria
version: 3.1.3
repo: https://itzg.github.io/minecraft-server-charts
EOF
```
The base refers to a generator configuration file
called `chartInflator.yaml`.
The only thing in this particular file is a `helmCharts`
field, specifying a single chart.
This file lets one specify the name of a [stable chart],
and other things like a path to a values file, defaulting
to the `values.yaml` that comes with the chart.
Create the config file `chartInflator.yaml`, specifying
the arbitrarily chosen chart name _minecraft_ and the repository
url that will be used to find the chart:
<!-- @writeGeneratorConfig @helmtest -->
```
cat <<'EOF' >$DEMO_HOME/base/chartInflator.yaml
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: notImportantHere
chartName: minecraft
chartRepoUrl: https://kubernetes-charts.storage.googleapis.com
EOF
```
The `valuesInline` field overrides some native chart values.
Check the directory layout:
<!-- @tree -->
```
tree $DEMO_HOME
```
@@ -115,155 +117,249 @@ Expect something like:
> ```
> /tmp/whatever
> ├── base
>    ├── chartInflator.yaml
> │   └── kustomization.yaml
> └── kustomization.yaml
> ├── dev
>    └── kustomization.yaml
> └── kustomization.yaml
> └── prod
> └── kustomization.yaml
> ```
Define a helper function to run kustomize with the
correct environment and flags for plugins:
### Helm related flags
<!-- @defineKustomizeIt @helmtest -->
Attempt to build the `base`:
<!-- @checkFailure @testHelm -->
```
cmd="kustomize build --helm-command $helmCommand $DEMO_HOME/base"
if ($cmd); then
echo "Build should fail!" && false # Force test to fail.
else
echo "Build failed because no --enable-helm flag (desired outcome)."
fi
```
This `build` fails and complains about a missing
`--enable-helm` flag.
The flag `--enable-helm` exists to have the user
acknowledge that kustomize is running an external program as
part of the `build` step. It's like the
`--enable-plugins` flag, but with a helm focus.
The flag `--helm-command` has a default value (`helm` of
course) so it's not suitable as an enablement flag. A user
with `helm` on their `PATH` need not awkwardly specify
`'--helm-command helm'`.
Given the above, define a helper function to run `kustomize` with the
flags required for `helm` use in this demo:
<!-- @defineKustomizeIt @testHelm -->
```
function kustomizeIt {
XDG_CONFIG_HOME=$DEMO_HOME \
kustomize build --enable_alpha_plugins \
kustomize build \
--enable-helm \
--helm-command $helmCommand \
$DEMO_HOME/$1
}
```
### Build the base and the variants
Finally, build the `prod` variant. Notice that all
resource names now have the `prod-` prefix:
<!-- @doProd @helmtest -->
```
clear
kustomizeIt prod
```
Compare `dev` to `prod`:
<!-- @doCompare -->
```
diff <(kustomizeIt dev) <(kustomizeIt prod) | more
```
To see the unmodified but inflated chart, run kustomize
on the base. Every invocation here is re-downloading
and re-inflating the chart.
<!-- @showBase @helmtest -->
Now build the `base`:
<!-- @showBase @testHelm -->
```
kustomizeIt base
```
## Use a local chart
This works, and you see an inflated chart complete
with a `Secret`, `Service`, `Deployment`, etc.
The example above fetches a new copy of the chart
and render it with each kustomize
build, because a local chart home isn't specified
in the configuration.
To suppress fetching, specify a _chart home_
explicitly, and just make sure the chart is already
there.
To demo this so that it won't interfere with your
existing helm environment, do this:
**This demo uses Helm V3**
<!-- @helmInit @helmtest -->
```
helmHome=$DEMO_HOME/dothelm
chartHome=$DEMO_HOME/base/charts
repoUrl=https://kubernetes-charts.storage.googleapis.com
function doHelm {
helm --home $helmHome $@
}
```
Now download a chart; again use _minecraft_
(but you could use anything):
<!-- @fetchChart @helmtest -->
```
doHelm pull --untar \
--untardir $chartHome \
--repo $repoUrl \
minecraft
```
The tree has more stuff now; helm config data
and a complete copy of the chart:
As a side effect of this build, kustomize pulled the chart
and placed it in the `charts` subdirectory of the base.
Take a look:
<!-- @tree -->
```
tree $DEMO_HOME
```
Add a `chartHome` field to the generator config file so
that it knows where to find the local chart:
If the chart had already been there, kustomize would
not have tried to pull it.
<!-- @modifyGenConfig @helmtest -->
To change the location of the charts, use this
in your kustomization file:
> ```
> helmGlobals:
> chartHome: charts
> ```
Change `charts` as desired, but it's best to keep it
in (or below) the same directory as the `kustomization.yaml` file.
If it's outside the kustomization root, the `build` command will
fail unless given the flag `'--load-restrictor=none'` to
disable file loading restrictions.
Now build the two variants `dev` and `prod`
and compare their differences:
<!-- @doCompare -->
```
echo "chartHome: $chartHome" >>$DEMO_HOME/base/chartInflator.yaml
diff <(kustomizeIt dev) <(kustomizeIt prod) | more
```
Change the values file, to show that the results
generated below are from the _locally_ stored chart:
This shows so-called _last mile hydration_ of two variants
made from a common base that happens to be generated from a
helm chart.
<!-- @valueChange @helmtest -->
## How does the pull work?
The command kustomize used to download the chart
is something like
> ```
> $helmCommand pull \
> --untar \
> --untardir $DEMO_HOME/base/charts \
> --repo https://itzg.github.io/minecraft-server-charts \
> --version 3.1.3 \
> minecraft
> ```
The first use of kustomize above (when the `base` was
expanded) fetched the chart and placed it in the `charts`
directory next to the `kustomization.yaml` file.
This chart was reused, _not_ re-fetched, with the variant
expansions `prod` and `dev`.
If a chart exists, kustomize will not overwrite it (so to
suppress a pull, simply assure the chart is already in your
kustomization root). kustomize won't check dates or version
numbers or do anything that smells like cache management.
> kustomize is a YAML manipulator. It's not a manager
> of a cache of things downloaded from the internet.
## The pull happens once.
To show that the locally stored chart is being re-used, modify
its _values_ file.
First make note of the password encoded in the production
inflation:
<!-- @checkPassword @testHelm -->
```
sed -i 's/CHANGEME!/SOMETHINGELSE/' $chartHome/minecraft/values.yaml
sed -i 's/LoadBalancer/NodePort/' $chartHome/minecraft/values.yaml
test 1 == $(kustomizeIt prod | grep -c "rcon-password: Q0hBTkdFTUUh")
```
Finally, built it
The above command succeeds if the value of the generated
password is as shown (`Q0hBTkdFTUUh`).
<!-- @finalProd @helmtest -->
Now change the password in the local values file:
<!-- @valueChange @testHelm -->
```
kustomizeIt prod
values=$DEMO_HOME/base/charts/minecraft/values.yaml
grep CHANGEME $values
sed -i 's/CHANGEME/SOMETHING_ELSE/' $values
grep SOMETHING_ELSE $values
```
and observe the change from `LoadBalancer` to `NodePort`, and
the change in the encoded password.
Run the build, and confirm that the same `rcon-password`
field in the output has a new value, confirming that the
chart used was a _local_ chart, not a chart freshly
downloaded from the internet:
Clean the directory.
<!-- @showBase @helmtest -->
<!-- @checkPassword2 @testHelm -->
```
test 1 == $(kustomizeIt prod | grep -c "rcon-password: U09NRVRISU5HX0VMU0Uh")
```
Finally, clean up:
<!-- @showBase @testHelm -->
```
rm -r $DEMO_HOME
```
## How to migrate from old plugin to builtin plugin
## Performance
[bash-based helm chart inflator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/chartinflator
[go-based builtin helm chart inflator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/builtin/helmchartinflationgenerator
To recap, the helm-related kustomization fields make
kustomize run
The [bash-based helm chart inflator] is intended as an example of using bash
to write a generator plugin.
> ```
> helm pull ...
> helm template ...
> ```
It proved to be popular for inflating helm charts,
so there's now a [go-based builtin helm chart inflator].
_as a convenience for the user_ to generate YAML from a helm chart.
This newer generator is supported as part of the core code, so anyone using the
old bash-based example plugin would probably benefit from switching to the
newer built-in plugin.
Helm's `pull` command downloads the chart. Helm's `template`
command inflates the chart template, spitting the inflated
template to stdout (where kustomize captures it) rather than
immediately sending it to a cluster as `helm install`
would.
Be advised that at the time of writing, the built-in plugin only supports helm v3.
To improve performance, a user can retain the chart after
the first pull, and commit the chart to their configuration
repository (below the `kustomization.yaml` file that refers
to it). kustomize only tries to pull the chart if it's not
already there.
To further improve performance, a user can inflate the
chart themselves at the command line, e.g.
> ```
> helm template {releaseName} \
> --values {valuesFile} \
> --version {version} \
> --repo {repo} \
> {chartName} > {chartName}.yaml
> ```
then commit the resulting `{chartName}.yaml` file to a git
repo as a configuration base, mentioning that file as a
`resource` in a `kustomization.yaml` file, e.g.
> ```
> resources:
> - minecraft_v3.1.3_Chart.yaml
> ```
The user should choose when or if to refresh their local
copy of the chart's inflation. kustomize would have no
awareness that the YAML was generated by helm, and kustomize
wouldn't run `helm` during the `build`. This is analogous
to `Go` module vendoring.
### But it's not really about performance.
Although the `helm` related fields discussed above are handy
for experimentation and development, it's best to avoid them
in production.
The same argument applies to using _remote_ git URL's in
other kustomization fields. Handy for experimentation,
but ill-advised in production.
It's irresponsible to depend on a remote configuration
that's _not under your control_. Annoying enablement flags
like `'--enable-helm'` are intended to _remind_ one of a
risk, but offer zero protection from risk. Further, they
are useless are reminders, since __annoying things are
immediately scripted away and forgotten__, as was done above
in the `kustomizeIt` shell function.
## Best practice
Don't use remote configuration that you don't control in
production.
Maintain a _local, inflated fork_ of a remote configuration,
and have a human rebase / reinflate that fork from time to
time to capture upstream changes.

View File

@@ -145,7 +145,7 @@ diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
```
If you prefer YAML to JSON, the patch can be expressed
in YAML format (neverthless following [JSON patch] rules):
in YAML format (nevertheless following [JSON patch] rules):
<!-- @writeYamlPatch @testAgainstLatestRelease -->
```

View File

@@ -82,23 +82,17 @@ Here are some example urls
```
DEMO_HOME=$(mktemp -d)
cat <<EOF >$DEMO_HOME/kustomization.yaml
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
resources:
# a repo with a root level kustomization.yaml
- github.com/Liujingfang1/mysql
# a repo with a root level kustomization.yaml on branch test
- github.com/Liujingfang1/mysql?ref=test
# a subdirectory in a repo on branch repoUrl2
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=repoUrl2
# a subdirectory in a repo on commit `7050a45134e9848fca214ad7e7007e96e5042c03`
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=7050a45134e9848fca214ad7e7007e96e5042c03
# a subdirectory in a remote archive
- https://github.com/kustless/kustomize-examples/archive/master.zip//kustomize-examples-master
EOF
```

View File

@@ -86,9 +86,8 @@ The patch has following content
> initContainers:
> - name: init-command
> image: debian
> command:
> - "echo $(WORDPRESS_SERVICE)"
> - "echo $(MYSQL_SERVICE)"
> command: ["/bin/sh"]
> args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
> containers:
> - name: wordpress
> env:
@@ -138,11 +137,13 @@ Expect this in the output:
> ```
> (truncated)
> ...
> initContainers:
> - command:
> - echo demo-wordpress
> - echo demo-mysql
> image: debian
> name: init-command
> initContainers:
> - args:
> - -c
> - echo demo-wordpress; echo demo-mysql
> command:
> - /bin/sh
> image: debian
> name: init-command
>
> ```

View File

@@ -8,9 +8,8 @@ spec:
initContainers:
- name: init-command
image: debian
command:
- "echo $(WORDPRESS_SERVICE)"
- "echo $(MYSQL_SERVICE)"
command: ["/bin/sh"]
args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
containers:
- name: wordpress
env:

View File

@@ -86,9 +86,8 @@ curl -s -o "$DEMO_HOME/#1.yaml" \
> initContainers:
> - name: init-command
> image: debian
> command:
> - "echo $(WORDPRESS_SERVICE)"
> - "echo $(MYSQL_SERVICE)"
> command: ["/bin/sh"]
> args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
> containers:
> - name: wordpress
> env:
@@ -138,11 +137,13 @@ kustomize build $DEMO_HOME
> ```yaml
> (truncated)
> ...
> initContainers:
> - command:
> - echo demo-wordpress
> - echo demo-mysql
> image: debian
> name: init-command
> initContainers:
> - args:
> - -c
> - echo demo-wordpress; echo demo-mysql
> command:
> - /bin/sh
> image: debian
> name: init-command
>
> ```

View File

@@ -35,10 +35,11 @@ mdrip --mode test --blockTimeOut 15m \
# TODO: make work for non-linux
if onLinuxAndNotOnRemoteCI; then
echo "On linux, and not on remote CI. Running expensive tests."
# Requires helm.
make $MYGOBIN/helm
mdrip --mode test --label helmtest examples/chart.md
# TODO: remove the HEAD check once --enable-helm flag released.
if [ "$version" == "HEAD" ]; then
make $MYGOBIN/helmV3
mdrip --mode test --label testHelm examples/chart.md
fi
fi
# Force outside logic to rebuild kustomize rather than

View File

@@ -23,7 +23,9 @@ var theFlags struct {
enable struct {
plugins bool
managedByLabel bool
helm bool
}
helmCommand string
loadRestrictor string
reorderOutput string
fnOptions types.FnPluginLoadingOptions
@@ -102,6 +104,7 @@ func NewCmdBuild(
AddFlagEnablePlugins(cmd.Flags())
AddFlagReorderOutput(cmd.Flags())
AddFlagEnableManagedbyLabel(cmd.Flags())
AddFlagEnableHelm(cmd.Flags())
return cmd
}
@@ -132,7 +135,10 @@ func HonorKustomizeFlags(kOpts *krusty.Options) *krusty.Options {
c := types.EnabledPluginConfig(types.BploUseStaticallyLinked)
c.FnpLoadingOptions = theFlags.fnOptions
kOpts.PluginConfig = c
} else {
kOpts.PluginConfig.HelmConfig.Enabled = theFlags.enable.helm
}
kOpts.PluginConfig.HelmConfig.Command = theFlags.helmCommand
kOpts.AddManagedbyLabel = isManagedByLabelEnabled()
return kOpts
}

View File

@@ -0,0 +1,24 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package build
import (
"github.com/spf13/pflag"
)
// AddFlagEnableHelm adds the --enable-helm flag.
// The helm plugin is builtin, meaning it's
// enabled independently of --enable-alpha-plugins.
func AddFlagEnableHelm(set *pflag.FlagSet) {
set.BoolVar(
&theFlags.enable.helm,
"enable-helm",
false,
"Enable use of the Helm chart inflator generator.")
set.StringVar(
&theFlags.helmCommand,
"helm-command",
"helm", // default
"helm command (path to executable)")
}

View File

@@ -7,9 +7,9 @@ require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/cmd/config v0.9.7
sigs.k8s.io/kustomize/kyaml v0.10.16
sigs.k8s.io/kustomize/api v0.8.8
sigs.k8s.io/kustomize/cmd/config v0.9.10
sigs.k8s.io/kustomize/kyaml v0.10.17
sigs.k8s.io/yaml v1.2.0
)
@@ -21,3 +21,5 @@ exclude (
replace sigs.k8s.io/kustomize/api => ../api
replace sigs.k8s.io/kustomize/cmd/config => ../cmd/config
replace sigs.k8s.io/kustomize/kyaml => ../kyaml

View File

@@ -298,7 +298,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/kustomize/kyaml v0.10.16 h1:4rn0PTEK4STOA5kbpz72oGskjpKYlmwru4YRgVQFv+c=
sigs.k8s.io/kustomize/kyaml v0.10.16/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -111,8 +111,8 @@ func (rc *CommandResultsChecker) compare(t *testing.T, path string) {
args := []string{rc.ConfigInputFilename}
expectedOutput, expectedError := getExpected(t, rc.ExpectedOutputFilename, rc.ExpectedErrorFilename)
if expectedError == "" && expectedOutput == "" {
// missing expected
if expectedError == "" && expectedOutput == "" && !rc.UpdateExpectedFromActual {
// missing expected and UpdateExpectedFromActual == false, return and skip this test
return
}
require.NoError(t, err)
@@ -251,8 +251,8 @@ func (rc *ProcessorResultsChecker) compare(t *testing.T, path string) {
require.NoError(t, err)
expectedOutput, expectedError := getExpected(t, rc.ExpectedOutputFilename, rc.ExpectedErrorFilename)
if expectedError == "" && expectedOutput == "" {
// missing expected
if expectedError == "" && expectedOutput == "" && !rc.UpdateExpectedFromActual {
// missing expected and UpdateExpectedFromActual == false, return and skip this test
return
}

View File

@@ -71,6 +71,10 @@ type LocalPackageReadWriter struct {
NoDeleteFiles bool `yaml:"noDeleteFiles,omitempty"`
files sets.String
// FileSkipFunc is a function which returns true if reader should ignore
// the file
FileSkipFunc LocalPackageSkipFileFunc
}
func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) {
@@ -81,6 +85,7 @@ func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) {
ErrorIfNonResources: r.ErrorIfNonResources,
SetAnnotations: r.SetAnnotations,
PackageFileName: r.PackageFileName,
FileSkipFunc: r.FileSkipFunc,
}.Read()
if err != nil {
return nil, errors.Wrap(err)
@@ -133,6 +138,11 @@ func (r *LocalPackageReadWriter) getFiles(nodes []*yaml.RNode) (sets.String, err
return val, nil
}
// LocalPackageSkipFileFunc is a function which returns true if the file
// in the package should be ignored by reader.
// relPath is an OS specific relative path
type LocalPackageSkipFileFunc func(relPath string) bool
// LocalPackageReader reads ResourceNodes from a local package.
type LocalPackageReader struct {
Kind string `yaml:"kind,omitempty"`
@@ -163,6 +173,10 @@ type LocalPackageReader struct {
// SetAnnotations are annotations to set on the Resources as they are read.
SetAnnotations map[string]string `yaml:"setAnnotations,omitempty"`
// FileSkipFunc is a function which returns true if reader should ignore
// the file
FileSkipFunc LocalPackageSkipFileFunc
}
var _ Reader = LocalPackageReader{}
@@ -215,24 +229,24 @@ func (r LocalPackageReader) Read() ([]*yaml.RNode, error) {
if info.IsDir() {
return r.shouldSkipDir(path, ignoreFilesMatcher)
}
if match, err := r.shouldSkipFile(path, ignoreFilesMatcher); err != nil {
// get the relative path to file within the package so we can write the files back out
// to another location.
relPath, err := filepath.Rel(pathRelativeTo, path)
if err != nil {
return errors.WrapPrefixf(err, pathRelativeTo)
}
if match, err := r.shouldSkipFile(path, relPath, ignoreFilesMatcher); err != nil {
return err
} else if !match {
} else if match {
// skip this file
return nil
}
// get the relative path to file within the package so we can write the files back out
// to another location.
path, err = filepath.Rel(pathRelativeTo, path)
r.initReaderAnnotations(relPath, info)
nodes, err := r.readFile(path, info)
if err != nil {
return errors.WrapPrefixf(err, pathRelativeTo)
}
r.initReaderAnnotations(path, info)
nodes, err := r.readFile(filepath.Join(pathRelativeTo, path), info)
if err != nil {
return errors.WrapPrefixf(err, filepath.Join(pathRelativeTo, path))
return errors.WrapPrefixf(err, path)
}
operand = append(operand, nodes...)
return nil
@@ -258,21 +272,25 @@ func (r *LocalPackageReader) readFile(path string, _ os.FileInfo) ([]*yaml.RNode
}
// shouldSkipFile returns true if the file should be skipped
func (r *LocalPackageReader) shouldSkipFile(path string, matcher *ignoreFilesMatcher) (bool, error) {
func (r *LocalPackageReader) shouldSkipFile(path, relPath string, matcher *ignoreFilesMatcher) (bool, error) {
// check if the file is covered by a .krmignore file.
if matcher.matchFile(path) {
return false, nil
return true, nil
}
if r.FileSkipFunc != nil && r.FileSkipFunc(relPath) {
return true, nil
}
// check if the files are in scope
for _, g := range r.MatchFilesGlob {
if match, err := filepath.Match(g, filepath.Base(path)); err != nil {
return false, errors.Wrap(err)
return true, errors.Wrap(err)
} else if match {
return true, nil
return false, nil
}
}
return false, nil
return true, nil
}
// initReaderAnnotations adds the LocalPackageReader Annotations to r.SetAnnotations

View File

@@ -121,6 +121,78 @@ metadata:
}
}
func TestLocalPackageReader_Read_pkgAndSkipFile(t *testing.T) {
s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c"))
defer s.Clean()
s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA)
s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB)
s.WriteFile(t, filepath.Join("c_test.yaml"), readFileC)
s.WriteFile(t, filepath.Join("d_test.yaml"), readFileD)
paths := []struct {
path string
}{
{path: "./"},
{path: s.Root},
}
for _, p := range paths {
rfr := LocalPackageReader{
PackagePath: p.path,
FileSkipFunc: func(relPath string) bool {
return relPath == "d_test.yaml"
},
}
nodes, err := rfr.Read()
if !assert.NoError(t, err) {
return
}
if !assert.Len(t, nodes, 4) {
return
}
expected := []string{
`a: b #first
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'a_test.yaml'
`,
`c: d # second
metadata:
annotations:
config.kubernetes.io/index: '1'
config.kubernetes.io/path: 'a_test.yaml'
`,
`# second thing
e: f
g:
h:
- i # has a list
- j
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'b_test.yaml'
`,
`a: b #third
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'c_test.yaml'
`,
}
for i := range nodes {
val, err := nodes[i].String()
if !assert.NoError(t, err) {
return
}
if !assert.Equal(t, expected[i], val) {
return
}
}
}
}
func TestLocalPackageReader_Read_JSON(t *testing.T) {
s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c"))
defer s.Clean()

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/annotationstransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/configmapgenerator
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/hashtransformer
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../kyaml

View File

@@ -1,11 +1,8 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Helm chart generator
//
// Fetches the given chart from {ChartRepo}/{ChartName},
// and inflates it to stdout, using the given values file.
// This generator expects helm V3 or later.
// Helm chart inflation generator.
// Uses helm V3 to generate k8s YAML from a helm chart.
//go:generate pluginator
package main
@@ -13,7 +10,6 @@ package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
@@ -23,7 +19,6 @@ import (
"github.com/imdario/mergo"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/yaml"
@@ -32,202 +27,235 @@ import (
// HelmChartInflationGeneratorPlugin is a plugin to generate resources
// from a remote or local helm chart.
type HelmChartInflationGeneratorPlugin struct {
h *resmap.PluginHelpers
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
runHelmCommand func([]string) ([]byte, error)
types.HelmChartArgs
h *resmap.PluginHelpers
types.HelmGlobals
types.HelmChart
tmpDir string
}
//noinspection GoUnusedGlobalVariable
var KustomizePlugin HelmChartInflationGeneratorPlugin
const (
valuesMergeOptionMerge = "merge"
valuesMergeOptionOverride = "override"
valuesMergeOptionReplace = "replace"
)
var legalMergeOptions = []string{
valuesMergeOptionMerge,
valuesMergeOptionOverride,
valuesMergeOptionReplace,
}
// Config uses the input plugin configurations `config` to setup the generator
// options
func (p *HelmChartInflationGeneratorPlugin) Config(h *resmap.PluginHelpers, config []byte) error {
func (p *HelmChartInflationGeneratorPlugin) Config(
h *resmap.PluginHelpers, config []byte) (err error) {
if h.GeneralConfig() == nil {
return fmt.Errorf("unable to access general config")
}
if !h.GeneralConfig().HelmConfig.Enabled {
return fmt.Errorf("must specify --enable-helm")
}
if h.GeneralConfig().HelmConfig.Command == "" {
return fmt.Errorf("must specify --helm-command")
}
p.h = h
err := yaml.Unmarshal(config, p)
if err != nil {
return err
if err = yaml.Unmarshal(config, p); err != nil {
return
}
tmpDir, err := filesys.NewTmpConfirmedDir()
if err != nil {
return err
}
p.tmpDir = string(tmpDir)
if p.ChartName == "" {
return fmt.Errorf("chartName cannot be empty")
}
if p.ChartHome == "" {
p.ChartHome = filepath.Join(p.tmpDir, "chart")
}
if p.ChartRepoName == "" {
p.ChartRepoName = "stable"
}
if p.HelmBin == "" {
p.HelmBin = "helm"
}
if p.HelmHome == "" {
p.HelmHome = filepath.Join(p.tmpDir, ".helm")
}
if p.Values == "" {
p.Values = filepath.Join(p.ChartHome, p.ChartName, "values.yaml")
}
if p.ValuesMerge == "" {
p.ValuesMerge = "override"
}
// runHelmCommand will run `helm` command with args provided. Return stdout
// and error if there is any.
p.runHelmCommand = func(args []string) ([]byte, error) {
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
cmd := exec.Command(p.HelmBin, args...)
cmd.Stdout = stdout
cmd.Stderr = stderr
cmd.Env = append(os.Environ(),
fmt.Sprintf("HELM_CONFIG_HOME=%s", p.HelmHome),
fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.HelmHome),
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.HelmHome),
)
err := cmd.Run()
if err != nil {
return stdout.Bytes(),
errors.Wrap(
fmt.Errorf("failed to run command %s %s", p.HelmBin, strings.Join(args, " ")),
stderr.String(),
)
}
return stdout.Bytes(), nil
}
return nil
return p.validateArgs()
}
// EncodeValues for writing
func (p *HelmChartInflationGeneratorPlugin) EncodeValues(w io.Writer) error {
d, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
_, err = w.Write(d)
if err != nil {
return err
}
return nil
}
// useValuesLocal process (merge) inflator config provided values with chart default values.yaml
func (p *HelmChartInflationGeneratorPlugin) useValuesLocal() error {
// not override, merge, none
if !(p.ValuesMerge == "none" || p.ValuesMerge == "no" || p.ValuesMerge == "false") {
var pValues []byte
var err error
if filepath.IsAbs(p.Values) {
pValues, err = ioutil.ReadFile(p.Values)
} else {
pValues, err = p.h.Loader().Load(p.Values)
}
if err != nil {
return err
}
chValues := make(map[string]interface{})
err = yaml.Unmarshal(pValues, &chValues)
if err != nil {
return err
}
if p.ValuesMerge == "override" {
err = mergo.Merge(&chValues, p.ValuesLocal, mergo.WithOverride)
if err != nil {
return err
}
}
if p.ValuesMerge == "merge" {
err = mergo.Merge(&chValues, p.ValuesLocal)
if err != nil {
return err
}
}
p.ValuesLocal = chValues
}
b, err := yaml.Marshal(p.ValuesLocal)
if err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
}
p.Values = path
return nil
}
// copyValues will copy the relative values file into the temp directory
// to avoid messing up with CWD.
func (p *HelmChartInflationGeneratorPlugin) copyValues() error {
// only copy when the values path is not absolute
if filepath.IsAbs(p.Values) {
// This uses the real file system since tmpDir may be used
// by the helm subprocess. Cannot use a chroot jail or fake
// filesystem since we allow the user to use previously
// downloaded charts. This is safe since this plugin is
// owned by kustomize.
func (p *HelmChartInflationGeneratorPlugin) establishTmpDir() (err error) {
if p.tmpDir != "" {
// already done.
return nil
}
// we must use use loader to read values file
b, err := p.h.Loader().Load(p.Values)
if err != nil {
p.tmpDir, err = ioutil.TempDir("", "kustomize-helm-")
return err
}
func (p *HelmChartInflationGeneratorPlugin) validateArgs() (err error) {
if p.Name == "" {
return fmt.Errorf("chart name cannot be empty")
}
// ChartHome might be consulted by the plugin (to read
// values files below it), so it must be located under
// the loader root (unless root restrictions are
// disabled, in which case this can be an absolute path).
if p.ChartHome == "" {
p.ChartHome = "charts"
}
// The ValuesFile may be consulted by the plugin, so it must
// be under the loader root (unless root restrictions are
// disabled).
if p.ValuesFile == "" {
p.ValuesFile = filepath.Join(p.ChartHome, p.Name, "values.yaml")
}
if err = p.errIfIllegalValuesMerge(); err != nil {
return err
}
path, err := p.writeValuesBytes(b)
if err != nil {
return err
// ConfigHome is not loaded by the plugin, and can be located anywhere.
if p.ConfigHome == "" {
if err = p.establishTmpDir(); err != nil {
return errors.Wrap(
err, "unable to create tmp dir for HELM_CONFIG_HOME")
}
p.ConfigHome = filepath.Join(p.tmpDir, "helm")
}
p.Values = path
return nil
}
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(b []byte) (string, error) {
path := filepath.Join(p.ChartHome, p.ChartName, "kustomize-values.yaml")
err := ioutil.WriteFile(path, b, 0644)
func (p *HelmChartInflationGeneratorPlugin) errIfIllegalValuesMerge() error {
if p.ValuesMerge == "" {
// Use the default.
p.ValuesMerge = valuesMergeOptionOverride
return nil
}
for _, opt := range legalMergeOptions {
if p.ValuesMerge == opt {
return nil
}
}
return fmt.Errorf("valuesMerge must be one of %v", legalMergeOptions)
}
func (p *HelmChartInflationGeneratorPlugin) absChartHome() string {
if filepath.IsAbs(p.ChartHome) {
return p.ChartHome
}
return filepath.Join(p.h.Loader().Root(), p.ChartHome)
}
func (p *HelmChartInflationGeneratorPlugin) runHelmCommand(
args []string) ([]byte, error) {
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
cmd := exec.Command(p.h.GeneralConfig().HelmConfig.Command, args...)
cmd.Stdout = stdout
cmd.Stderr = stderr
env := []string{
fmt.Sprintf("HELM_CONFIG_HOME=%s", p.ConfigHome),
fmt.Sprintf("HELM_CACHE_HOME=%s/.cache", p.ConfigHome),
fmt.Sprintf("HELM_DATA_HOME=%s/.data", p.ConfigHome)}
cmd.Env = append(os.Environ(), env...)
err := cmd.Run()
if err != nil {
helm := p.h.GeneralConfig().HelmConfig.Command
err = errors.Wrap(
fmt.Errorf(
"unable to run: '%s %s' with env=%s (is '%s' installed?)",
helm, strings.Join(args, " "), env, helm),
stderr.String(),
)
}
return stdout.Bytes(), err
}
// createNewMergedValuesFile replaces/merges original values file with ValuesInline.
func (p *HelmChartInflationGeneratorPlugin) createNewMergedValuesFile() (
path string, err error) {
if p.ValuesMerge == valuesMergeOptionMerge ||
p.ValuesMerge == valuesMergeOptionOverride {
if err = p.replaceValuesInline(); err != nil {
return "", err
}
}
var b []byte
b, err = yaml.Marshal(p.ValuesInline)
if err != nil {
return "", err
}
return path, nil
return p.writeValuesBytes(b)
}
func (p *HelmChartInflationGeneratorPlugin) replaceValuesInline() error {
pValues, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return err
}
chValues := make(map[string]interface{})
if err = yaml.Unmarshal(pValues, &chValues); err != nil {
return err
}
switch p.ValuesMerge {
case valuesMergeOptionOverride:
err = mergo.Merge(
&chValues, p.ValuesInline, mergo.WithOverride)
case valuesMergeOptionMerge:
err = mergo.Merge(&chValues, p.ValuesInline)
}
p.ValuesInline = chValues
return err
}
// copyValuesFile to avoid branching. TODO: get rid of this.
func (p *HelmChartInflationGeneratorPlugin) copyValuesFile() (string, error) {
b, err := p.h.Loader().Load(p.ValuesFile)
if err != nil {
return "", err
}
return p.writeValuesBytes(b)
}
// Write a absolute path file in the tmp file system.
func (p *HelmChartInflationGeneratorPlugin) writeValuesBytes(
b []byte) (string, error) {
if err := p.establishTmpDir(); err != nil {
return "", fmt.Errorf("cannot create tmp dir to write helm values")
}
path := filepath.Join(p.tmpDir, p.Name+"-kustomize-values.yaml")
return path, ioutil.WriteFile(path, b, 0644)
}
func (p *HelmChartInflationGeneratorPlugin) cleanup() {
if p.tmpDir != "" {
os.RemoveAll(p.tmpDir)
}
}
// Generate implements generator
func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
// cleanup
defer os.RemoveAll(p.tmpDir)
// check helm version. we only support V3
err := p.checkHelmVersion()
if err != nil {
func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err error) {
defer p.cleanup()
if err = p.checkHelmVersion(); err != nil {
return nil, err
}
// pull the chart
if !p.checkLocalChart() {
_, err := p.runHelmCommand(p.getPullCommandArgs())
if err != nil {
if path, exists := p.chartExistsLocally(); !exists {
if p.Repo == "" {
return nil, fmt.Errorf(
"no repo specified for pull, no chart found at '%s'", path)
}
if _, err := p.runHelmCommand(p.pullCommand()); err != nil {
return nil, err
}
}
// inflator config valuesLocal
if len(p.ValuesLocal) > 0 {
err := p.useValuesLocal()
if err != nil {
return nil, err
}
if len(p.ValuesInline) > 0 {
p.ValuesFile, err = p.createNewMergedValuesFile()
} else {
err := p.copyValues()
if err != nil {
return nil, err
}
p.ValuesFile, err = p.copyValuesFile()
}
// render the charts
stdout, err := p.runHelmCommand(p.getTemplateCommandArgs())
if err != nil {
return nil, err
}
var stdout []byte
stdout, err = p.runHelmCommand(p.templateCommand())
if err != nil {
return nil, err
}
rm, rmfErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
if rmfErr == nil {
rm, err = p.h.ResmapFactory().NewResMapFromBytes(stdout)
if err == nil {
return rm, nil
}
// try to remove the contents before first "---" because
@@ -236,50 +264,49 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (resmap.ResMap, error) {
if idx := strings.Index(stdoutStr, "---"); idx != -1 {
return p.h.ResmapFactory().NewResMapFromBytes([]byte(stdoutStr[idx:]))
}
return nil, rmfErr
return nil, err
}
func (p *HelmChartInflationGeneratorPlugin) getTemplateCommandArgs() []string {
func (p *HelmChartInflationGeneratorPlugin) templateCommand() []string {
args := []string{"template"}
if p.ReleaseName != "" {
args = append(args, p.ReleaseName)
}
args = append(args, filepath.Join(p.ChartHome, p.ChartName))
if p.ReleaseNamespace != "" {
args = append(args, "--namespace", p.ReleaseNamespace)
args = append(args, filepath.Join(p.absChartHome(), p.Name))
if p.ValuesFile != "" {
args = append(args, "--values", p.ValuesFile)
}
if p.Values != "" {
args = append(args, "--values", p.Values)
if p.ReleaseName == "" {
// AFAICT, this doesn't work as intended due to a bug in helm.
// See https://github.com/helm/helm/issues/6019
// I've tried placing the flag before and after the name argument.
args = append(args, "--generate-name")
}
args = append(args, p.ExtraArgs...)
return args
}
func (p *HelmChartInflationGeneratorPlugin) getPullCommandArgs() []string {
args := []string{"pull", "--untar", "--untardir", p.ChartHome}
chartName := fmt.Sprintf("%s/%s", p.ChartRepoName, p.ChartName)
if p.ChartVersion != "" {
args = append(args, "--version", p.ChartVersion)
func (p *HelmChartInflationGeneratorPlugin) pullCommand() []string {
args := []string{
"pull",
"--untar",
"--untardir", p.absChartHome(),
"--repo", p.Repo,
p.Name}
if p.Version != "" {
args = append(args, "--version", p.Version)
}
if p.ChartRepoURL != "" {
args = append(args, "--repo", p.ChartRepoURL)
chartName = p.ChartName
}
args = append(args, chartName)
return args
}
// checkLocalChart will return true if the chart does exist in
// chartExistsLocally will return true if the chart does exist in
// local chart home.
func (p *HelmChartInflationGeneratorPlugin) checkLocalChart() bool {
path := filepath.Join(p.ChartHome, p.ChartName)
func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool) {
path := filepath.Join(p.absChartHome(), p.Name)
s, err := os.Stat(path)
if err != nil {
return false
return "", false
}
return s.IsDir()
return path, s.IsDir()
}
// checkHelmVersion will return an error if the helm version is not V3

View File

@@ -1,34 +1,30 @@
package main_test
/*
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"sigs.k8s.io/kustomize/api/filesys"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
//add tests for https://github.com/kubernetes-sigs/kustomize/pull/3713 if you plan to re-enable tests
func TestHelmChartInflationGenerator(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t).
PrepBuiltin("HelmChartInflationGenerator")
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
rm := th.LoadAndRunGenerator(`
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMap
chartName: minecraft
chartRepoUrl: https://charts.helm.sh/stable
chartVersion: v1.2.0
releaseName: test
releaseNamespace: testNamespace
name: myMc
name: minecraft
version: 3.1.3
repo: https://itzg.github.io/minecraft-server-charts
releaseName: moria
`)
th.AssertActualEqualsExpected(rm, `
@@ -38,40 +34,23 @@ data:
kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-1.2.0
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
release: moria
name: moria-minecraft
type: Opaque
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
volume.alpha.kubernetes.io/storage-class: default
labels:
app: test-minecraft
chart: minecraft-1.2.0
heritage: Helm
release: test
name: test-minecraft-datadir
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
app: test-minecraft
chart: minecraft-1.2.0
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
release: moria
name: moria-minecraft
spec:
ports:
- name: minecraft
@@ -79,93 +58,35 @@ spec:
protocol: TCP
targetPort: minecraft
selector:
app: test-minecraft
type: LoadBalancer
app: moria-minecraft
type: ClusterIP
`)
}
func TestHelmChartInflationGeneratorWithValues(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("HelmChartInflationGenerator")
defer th.Reset()
tempDirConfirmed, err := filesys.NewTmpConfirmedDir()
if err != nil {
t.Fatal(err)
}
tempDir := string(tempDirConfirmed)
defer os.RemoveAll(tempDir)
valuesPath := path.Join(tempDir, "values.yaml")
ioutil.WriteFile(valuesPath, []byte(`
minecraftServer:
eula: TRUE
`), 0644)
rm := th.LoadAndRunGenerator(fmt.Sprintf(`
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMap
chartName: minecraft
chartRepoUrl: https://charts.helm.sh/stable
chartVersion: v1.2.0
helmBin: helm
helmHome: %s
chartHome: %s
releaseName: test
releaseNamespace: testNamespace
values: %s
valuesLocal:
resources:
limits:
memory: 512Mi
cpu: 1000m
requests:
memory: 512Mi
cpu: 200m
`, tempDir, tempDir, valuesPath))
th.AssertActualEqualsExpected(rm, `
const expectedInflationFmt = `
apiVersion: v1
data:
rcon-password: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-1.2.0
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
release: moria
name: moria-minecraft
type: Opaque
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
volume.alpha.kubernetes.io/storage-class: default
labels:
app: test-minecraft
chart: minecraft-1.2.0
heritage: Helm
release: test
name: test-minecraft-datadir
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
app: test-minecraft
chart: minecraft-1.2.0
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
release: moria
name: moria-minecraft
spec:
ports:
- name: minecraft
@@ -173,28 +94,48 @@ spec:
protocol: TCP
targetPort: minecraft
selector:
app: test-minecraft
app: moria-minecraft
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: moria
name: moria-minecraft-rcon
spec:
ports:
- name: rcon
port: 25575
protocol: TCP
targetPort: rcon
selector:
app: moria-minecraft
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test-minecraft
chart: minecraft-1.2.0
app: moria-minecraft
chart: minecraft-3.1.3
heritage: Helm
release: test
name: test-minecraft
release: moria
name: moria-minecraft
spec:
selector:
matchLabels:
app: test-minecraft
app: moria-minecraft
strategy:
type: Recreate
template:
metadata:
labels:
app: test-minecraft
app: moria-minecraft
spec:
containers:
- env:
@@ -203,9 +144,9 @@ spec:
- name: TYPE
value: VANILLA
- name: VERSION
value: 1.14.4
value: LATEST
- name: DIFFICULTY
value: easy
value: %s
- name: WHITELIST
value: ""
- name: OPS
@@ -222,7 +163,7 @@ spec:
value: "true"
- name: ENABLE_COMMAND_BLOCK
value: "true"
- name: FORCE_gameMode
- name: FORCE_GAMEMODE
value: "false"
- name: GENERATE_STRUCTURES
value: "true"
@@ -257,47 +198,48 @@ spec:
- name: ONLINE_MODE
value: "true"
- name: MEMORY
value: 512M
value: 1024M
- name: JVM_OPTS
value: ""
- name: JVM_XX_OPTS
value: ""
- name: ENABLE_RCON
value: "true"
- name: RCON_PASSWORD
valueFrom:
secretKeyRef:
key: rcon-password
name: moria-minecraft
image: itzg/minecraft-server:latest
imagePullPolicy: Always
livenessProbe:
exec:
command:
- mcstatus
- localhost:25565
- status
failureThreshold: 10
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 25565
timeoutSeconds: 1
name: test-minecraft
name: moria-minecraft
ports:
- containerPort: 25565
name: minecraft
protocol: TCP
- containerPort: 25575
name: rcon
protocol: TCP
readinessProbe:
exec:
command:
- mcstatus
- localhost:25565
- status
failureThreshold: 10
initialDelaySeconds: 30
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 25565
timeoutSeconds: 1
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 200m
memory: 512Mi
cpu: %dm
memory: %dMi
volumeMounts:
- mountPath: /data
name: datadir
@@ -305,9 +247,110 @@ spec:
fsGroup: 2000
runAsUser: 1000
volumes:
- name: datadir
persistentVolumeClaim:
claimName: test-minecraft-datadir
- emptyDir: {}
name: datadir
`
func TestHelmChartInflationGeneratorWithValuesInlineOverride(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t).
PrepBuiltin("HelmChartInflationGenerator")
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
rm := th.LoadAndRunGenerator(`
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMc
name: minecraft
version: 3.1.3
repo: https://itzg.github.io/minecraft-server-charts
releaseName: moria
valuesInline:
minecraftServer:
eula: true
difficulty: hard
rcon:
enabled: true
`)
th.AssertActualEqualsExpected(
rm, fmt.Sprintf(expectedInflationFmt,
"hard", // difficulty
500, // cpu
512, // memory
))
}
func TestHelmChartInflationGeneratorWithLocalValuesFile(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t).
PrepBuiltin("HelmChartInflationGenerator")
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
th.WriteF(filepath.Join(th.GetRoot(), "myValues.yaml"), `
minecraftServer:
eula: true
difficulty: peaceful
rcon:
enabled: true
resources:
requests:
cpu: 888m
memory: 666Mi
`)
rm := th.LoadAndRunGenerator(`
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMc
name: minecraft
version: 3.1.3
repo: https://itzg.github.io/minecraft-server-charts
releaseName: moria
valuesFile: myValues.yaml
`)
th.AssertActualEqualsExpected(
rm, fmt.Sprintf(expectedInflationFmt,
"peaceful", // difficulty
888, // cpu
666, // memory
))
}
func TestHelmChartInflationGeneratorWithInLineReplace(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t).
PrepBuiltin("HelmChartInflationGenerator")
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
rm := th.LoadAndRunGenerator(`
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: myMc
name: minecraft
version: 3.1.3
repo: https://itzg.github.io/minecraft-server-charts
releaseName: moria
valuesInline:
minecraftServer:
eula: true
difficulty: OMG_PLEASE_NO
rcon:
enabled: true
resources:
requests:
cpu: 555m
memory: 111Mi
valuesMerge: replace
`)
th.AssertActualEqualsExpected(
rm, fmt.Sprintf(expectedInflationFmt,
"OMG_PLEASE_NO", // difficulty
555, // cpu
111, // memory
))
}
*/

View File

@@ -5,7 +5,7 @@ go 1.16
require (
github.com/imdario/mergo v0.3.5
github.com/pkg/errors v0.9.1
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -33,6 +33,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -102,6 +103,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -159,6 +161,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -191,6 +194,7 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/imagetagtransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/labeltransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -4,7 +4,7 @@ go 1.16
require (
github.com/pkg/errors v0.9.1
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
)
replace sigs.k8s.io/kustomize/kyaml => ../../../kyaml

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/namespacetransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -5,7 +5,7 @@ go 1.16
require (
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/pkg/errors v0.9.1
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -4,7 +4,7 @@ go 1.16
require (
github.com/stretchr/testify v1.4.0
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -4,7 +4,7 @@ go 1.16
require (
github.com/evanphx/json-patch v4.5.0+incompatible
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/prefixsuffixtransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -0,0 +1,64 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
//go:generate pluginator
package main
import (
"fmt"
"sigs.k8s.io/kustomize/api/filters/replacement"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"sigs.k8s.io/yaml"
)
// Replace values in targets with values from a source
type plugin struct {
ReplacementList []types.ReplacementField `json:"replacements,omitempty" yaml:"replacements,omitempty"`
Replacements []types.Replacement `json:"omitempty" yaml:"omitempty"`
}
//noinspection GoUnusedGlobalVariable
var KustomizePlugin plugin
func (p *plugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
p.ReplacementList = []types.ReplacementField{}
if err := yaml.Unmarshal(c, p); err != nil {
return err
}
for _, r := range p.ReplacementList {
if r.Path != "" && (r.Source != nil || len(r.Targets) != 0) {
return fmt.Errorf("cannot specify both path and inline replacement")
}
if r.Path != "" {
// load the replacement from the path
content, err := h.Loader().Load(r.Path)
if err != nil {
return err
}
repl := types.Replacement{}
if err := yaml.Unmarshal(content, &repl); err != nil {
return err
}
p.Replacements = append(p.Replacements, repl)
} else {
// replacement information is already loaded
p.Replacements = append(p.Replacements, r.Replacement)
}
}
return nil
}
func (p *plugin) Transform(m resmap.ResMap) (err error) {
var nodes []*kyaml.RNode
for _, r := range m.Resources() {
nodes = append(nodes, r.Node())
}
_, err = replacement.Filter{
Replacements: p.Replacements,
}.Filter(nodes)
return err
}

View File

@@ -0,0 +1,196 @@
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package main_test
import (
"testing"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)
func TestReplacementTransformer(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("ReplacementTransformer")
defer th.Reset()
rm := th.LoadAndRunTransformer(`
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image
`, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
th.AssertActualEqualsExpected(rm, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`)
}
func TestReplacementTransformerFromPath(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("ReplacementTransformer")
defer th.Reset()
th.WriteF("replacement.yaml", `
source:
kind: Deployment
fieldPath: spec.template.spec.containers.0.image
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.1.image`)
rm := th.LoadAndRunTransformer(`
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- path: replacement.yaml
`, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
name: postgresdb
`)
th.AssertActualEqualsExpected(rm, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy
spec:
template:
spec:
containers:
- image: foobar:1
name: replaced-with-digest
- image: foobar:1
name: postgresdb
`)
}
func TestReplacementTransformerComplexType(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("ReplacementTransformer")
defer th.Reset()
rm := th.LoadAndRunTransformer(`
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
kind: Pod
name: pod
fieldPath: spec.containers
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers
`, `
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers: {}
`)
th.AssertActualEqualsExpected(rm, `
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
`)
}

View File

@@ -0,0 +1,13 @@
module sigs.k8s.io/kustomize/plugin/builtin/replacementtransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/kustomize/kyaml v0.10.17
sigs.k8s.io/yaml v1.2.0
)
replace sigs.k8s.io/kustomize/kyaml => ./../../../kyaml
replace sigs.k8s.io/kustomize/api => ./../../../api

View File

@@ -0,0 +1,268 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw=
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/replicacounttransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/secretgenerator
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/valueaddtransformer
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/bashedconfigmap
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/calvinduplicator
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -4,7 +4,7 @@ go 1.16
require (
github.com/pkg/errors v0.9.1
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/printpluginenv
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/secretsfromdatabase
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/sedtransformer
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml

View File

@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/someservicegenerator
go 1.16
require (
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/starlarkmixer
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml

View File

@@ -4,7 +4,7 @@ go 1.16
require (
github.com/pkg/errors v0.9.1
sigs.k8s.io/kustomize/api v0.8.5
sigs.k8s.io/kustomize/api v0.0.0
sigs.k8s.io/yaml v1.2.0
)

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/someteam.example.com/v1/validator
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml

View File

@@ -2,7 +2,7 @@ module sigs.k8s.io/kustomize/plugin/untested/v1/gogetter
go 1.16
require sigs.k8s.io/kustomize/api v0.8.5
require sigs.k8s.io/kustomize/api v0.0.0
replace sigs.k8s.io/kustomize/kyaml => ../../../../kyaml