Merge remote-tracking branch 'upstream/master'

This commit is contained in:
guoxudong
2020-01-08 14:10:46 +08:00
148 changed files with 3902 additions and 3343 deletions

View File

@@ -36,6 +36,7 @@ install: true
script:
- make verify-kustomize
- ./travis/kyaml-pre-commit.sh
- ./travis/check-go-mod.sh
# TBD. Suppressing for now.
notifications:

View File

@@ -52,7 +52,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
if len(matches) != 1 {
return fmt.Errorf("namespace tranformation produces ID conflict: %#v", matches)
return fmt.Errorf("namespace tranformation produces ID conflict: %+v", matches)
}
}
return nil

View File

@@ -136,6 +136,7 @@ func main() {
github.QueryWith(
github.Filename("kustomization.yaml"),
github.Filename("kustomization.yml"),
github.Filename("kustomization"),
github.User(user)),
)
} else if repo != "" {
@@ -143,13 +144,15 @@ func main() {
github.QueryWith(
github.Filename("kustomization.yaml"),
github.Filename("kustomization.yml"),
github.Filename("kustomization"),
github.Repo(repo)),
)
} else {
return github.NewCrawler(githubToken, retryCount, clientCache,
github.QueryWith(
github.Filename("kustomization.yaml"),
github.Filename("kustomization.yml")),
github.Filename("kustomization.yml"),
github.Filename("kustomization")),
)
}
}

View File

@@ -0,0 +1,8 @@
This binary takes as its input a json file including GKE logs (which can be
[exported](https://cloud.google.com/logging/docs/export/configure_export_v2) into
[Cloud Storage](https://cloud.google.com/storage/docs/)),
and extracts the `textPayload` field of each log entry.
Here is an log entry example:
{"insertId":"1sxuh4jg5lw6w10","labels":{"compute.googleapis.com/resource_name":"gke-crawler2-default-pool-5e55ea05-gzgv","container.googleapis.com/namespace_name":"default","container.googleapis.com/pod_name":"kustomize-stats-5bczg","container.googleapis.com/stream":"stdout"},"logName":"projects/haiyanmeng-gke-dev/logs/kustomize-stats","receiveTimestamp":"2020-01-06T23:33:07.012831742Z","resource":{"labels":{"cluster_name":"crawler2","container_name":"kustomize-stats","instance_id":"8183086081854184383","namespace_id":"default","pod_id":"kustomize-stats-5bczg","project_id":"haiyanmeng-gke-dev","zone":"us-central1-a"},"type":"container"},"severity":"INFO","textPayload":"The kustomize index already exists\n","timestamp":"2020-01-06T23:32:46.628930547Z"}

View File

@@ -0,0 +1,48 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"log"
"os"
)
func main() {
if len(os.Args) != 2 {
log.Fatalf("The usage of the command is: \n\t%s <log-file.json>", os.Args[0])
}
file, err := os.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
closeFile := func(file *os.File) {
if err := file.Close(); err != nil {
log.Fatal(err)
}
}
defer closeFile(file)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
var entry interface{}
if err := json.Unmarshal([]byte(line), &entry); err != nil {
log.Printf("failed to unmarshal a log entry: %s\n", line)
}
m := entry.(map[string]interface{})
if payload, ok := m["textPayload"]; ok {
fmt.Printf("%s", payload)
} else {
log.Printf("the log entry does not have the `textPayload` field: %s\n", line)
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}

View File

@@ -97,6 +97,17 @@ func (gc githubCrawler) Crawl(
// it will try to add each string in konfig.RecognizedKustomizationFileNames() to
// d.FilePath, and try to fetch the document again.
func (gc githubCrawler) FetchDocument(_ context.Context, d *doc.Document) error {
// set the default branch if it is empty
if d.DefaultBranch == "" {
url := gc.client.ReposRequest(d.RepositoryFullName())
defaultBranch, err := gc.client.GetDefaultBranch(url)
if err != nil {
logger.Printf(
"(error: %v) setting default_branch to master\n", err)
defaultBranch = "master"
}
d.DefaultBranch = defaultBranch
}
repoURL := d.RepositoryURL + "/" + d.FilePath + "?ref=" + d.DefaultBranch
repoSpec, err := git.NewRepoSpecFromUrl(repoURL)
if err != nil {

View File

@@ -116,9 +116,11 @@ type RequestConfig struct {
// the URL method to get the string value of the URL. See request.CopyWith, to
// understand why the request object is useful.
func (rc RequestConfig) CodeSearchRequestWith(query Query) request {
req := rc.makeRequest("search/code", query)
req.vals.Set("sort", "indexed")
req.vals.Set("order", "desc")
vals := url.Values{
"sort": []string{"indexed"},
"order": []string{"desc"},
}
req := rc.makeRequest("search/code", query, vals)
return req
}
@@ -126,27 +128,25 @@ func (rc RequestConfig) CodeSearchRequestWith(query Query) request {
// query for the Github API to find the dowload information of this filepath.
func (rc RequestConfig) ContentsRequest(fullRepoName, path string) string {
uri := fmt.Sprintf("repos/%s/contents/%s", fullRepoName, path)
return rc.makeRequest(uri, Query{}).URL()
return rc.makeRequest(uri, Query{}, url.Values{}).URL()
}
func (rc RequestConfig) ReposRequest(fullRepoName string) string {
uri := fmt.Sprintf("repos/%s", fullRepoName)
return rc.makeRequest(uri, Query{}).URL()
}
func escapeSpace(s string) string {
return strings.Replace(s, " ", "%20", -1)
return rc.makeRequest(uri, Query{}, url.Values{}).URL()
}
// CommitsRequest given the repo name, and a filepath returns a formatted query
// for the Github API to find the commits that affect this file.
func (rc RequestConfig) CommitsRequest(fullRepoName, path string) string {
uri := fmt.Sprintf("repos/%s/commits", fullRepoName)
return rc.makeRequest(uri, Query{Path(escapeSpace(path))}).URL()
vals := url.Values{
"path": []string{path},
}
return rc.makeRequest(uri, Query{}, vals).URL()
}
func (rc RequestConfig) makeRequest(path string, query Query) request {
vals := url.Values{}
func (rc RequestConfig) makeRequest(path string, query Query, vals url.Values) request {
vals.Set(perPageArg, fmt.Sprint(rc.perPage))
return request{

View File

@@ -101,7 +101,7 @@ func TestGithubSearchQuery(t *testing.T) {
"examples/helloWorld/kustomization.yaml?per_page=100",
expectedCommitsQuery: "https://api.github.com/repos/kubernetes-sigs/kustomize/commits?" +
"q=path:examples/helloWorld/kustomization.yaml&per_page=100",
"path=examples%2FhelloWorld%2Fkustomization.yaml&per_page=100",
},
{
rc: RequestConfig{
@@ -121,7 +121,7 @@ func TestGithubSearchQuery(t *testing.T) {
"examples%201/helloWorld/kustomization.yaml?per_page=100",
expectedCommitsQuery: "https://api.github.com/repos/kubernetes-sigs/kustomize/commits?" +
"q=path:examples%201/helloWorld/kustomization.yaml&per_page=100",
"path=examples+1%2FhelloWorld%2Fkustomization.yaml&per_page=100",
},
}

View File

@@ -78,6 +78,9 @@ func (doc *KustomizationDocument) GetResources() ([]*Document, error) {
res := make([]*Document, 0, len(k.Resources))
for _, r := range k.Resources {
if strings.TrimSpace(r) == "" {
continue
}
next, err := doc.Document.FromRelativePath(r)
if err != nil {
fmt.Printf("GetResources error: %v\n", err)

View File

@@ -8,6 +8,6 @@ require (
github.com/gorilla/mux v1.7.3
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
github.com/rs/cors v1.7.0
sigs.k8s.io/kustomize/api v0.3.0
sigs.k8s.io/kustomize/api v0.3.1
sigs.k8s.io/yaml v1.1.0
)

View File

@@ -133,13 +133,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -198,7 +193,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -240,7 +234,6 @@ github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lz
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -387,7 +380,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -415,8 +407,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.3.0 h1:riR/YsL75nGb+aIPFdIRiqu21+OZbAXQybDS7+FUYRg=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:DWNMJBV1xvLruMpihGgnIPznMwHpwUSrxz6v3gnw5kw=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -309,9 +309,9 @@ func (idx *index) Exists(id string) (bool, error) {
op.WithPretty(),
)
if !res.IsError() {
if res != nil && !res.IsError() {
return true, nil
} else if res.StatusCode == 404 {
} else if res != nil && res.StatusCode == 404 {
return false, nil
} else {
return false, idx.responseErrorOrNil(

View File

@@ -153,9 +153,9 @@ FRUIT=banana
LEGUME=chickpea
`)
th.WriteF("/app/overlay/configmap/dummy.txt",
`Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
`Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
`)
th.WriteF("/app/overlay/deployment/deployment.yaml", `
apiVersion: apps/v1
@@ -292,8 +292,10 @@ metadata:
---
apiVersion: v1
data:
nonsense: "Lorem ipsum dolor sit amet, consectetur\nadipiscing elit, sed do eiusmod
tempor\nincididunt ut labore et dolore magna aliqua. \n"
nonsense: |
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
kind: ConfigMap
metadata:
annotations:
@@ -302,6 +304,6 @@ metadata:
app: mungebot
org: kubernetes
repo: test-infra
name: test-infra-app-config-f462h769f9
name: test-infra-app-config-4mt28b5bg2
`)
}

View File

@@ -9,6 +9,7 @@ import (
"fmt"
"os"
"path"
"regexp"
"strings"
"unicode"
"unicode/utf8"
@@ -85,11 +86,17 @@ func (kvl *loader) keyValuesFromFileSources(sources []string) ([]types.Pair, err
if err != nil {
return nil, err
}
kvs = append(kvs, types.Pair{Key: k, Value: string(content)})
kvs = append(kvs, types.Pair{Key: k, Value: trimTrailingSpacesInLines(string(content))})
}
return kvs, nil
}
// trimTrailingSpacesInLines takes string with multiple lines and trims the trailing white spaces and tabs from each line.
func trimTrailingSpacesInLines(str string) string {
re := regexp.MustCompile(`\s*\n`)
return re.ReplaceAllString(str, "\n")
}
func (kvl *loader) keyValuesFromEnvFiles(paths []string) ([]types.Pair, error) {
var kvs []types.Pair
for _, p := range paths {

View File

@@ -95,3 +95,12 @@ func TestKeyValuesFromFileSources(t *testing.T) {
}
}
}
func TestTrimTrailingSpacesInLines(t *testing.T) {
input := "\"fooKey\": \"fooValue\" \t\n\t\"barKey\": \"barValue\""
expected := "\"fooKey\": \"fooValue\"\n\t\"barKey\": \"barValue\""
res := trimTrailingSpacesInLines(input)
if !reflect.DeepEqual(res, expected) {
t.Errorf("Trim trailing spaces in lines should succeed, got: %s exptected: %s", res, expected)
}
}

View File

@@ -74,10 +74,12 @@ func NewConfigCommand(name string) *cobra.Command {
root.AddCommand(commands.CatCommand(name))
root.AddCommand(commands.FmtCommand(name))
root.AddCommand(commands.MergeCommand(name))
root.AddCommand(commands.Merge3Command(name))
root.AddCommand(commands.CountCommand(name))
root.AddCommand(commands.RunFnCommand(name))
root.AddCommand(commands.SubCommand(name))
root.AddCommand(commands.SubSetCommand(name))
root.AddCommand(commands.SetCommand(name))
root.AddCommand(commands.ListSettersCommand(name))
root.AddCommand(commands.CreateSetterCommand(name))
root.AddCommand(&cobra.Command{
Use: "docs-merge",
@@ -91,8 +93,13 @@ func NewConfigCommand(name string) *cobra.Command {
})
root.AddCommand(&cobra.Command{
Use: "docs-fn",
Short: "[Alpha] Documentation for writing containerized functions run by run.",
Long: api.ConfigFnLong,
Short: "[Alpha] Documentation for developing and invoking Configuration Functions.",
Long: api.FunctionsImplLong,
})
root.AddCommand(&cobra.Command{
Use: "docs-fn-spec",
Short: "[Alpha] Documentation for Configuration Functions Specification.",
Long: api.FunctionsSpecLong,
})
root.AddCommand(&cobra.Command{
Use: "docs-io-annotations",

View File

@@ -1,281 +0,0 @@
# Configuration Functions API Semantics
Configuration Functions are functions packaged as executables in containers which enable
**shift-left practices**. They configure applications and infrastructure through
Kubernetes style Resource Configuration, but run locally pre-commit.
Configuration functions enable shift-left practices (client-side) through:
- Pre-commit / delivery validation and linting of configuration
- e.g. Fail if any containers don't have PodSecurityPolicy or CPU / Memory limits
- Implementation of abstractions as client actuated APIs (e.g. templating)
- e.g. Create a client-side *"CRD"* for generating configuration checked into git
- Aspect Orient configuration / Injection of cross-cutting configuration
- e.g. T-Shirt size containers by annotating Resources with `small`, `medium`, `large`
and inject the cpu and memory resources into containers accordingly.
- e.g. Inject `init` and `side-car` containers into Resources based off of Resource
Type, annotations, etc.
Performing these on the client rather than the server enables:
- Configuration to be reviewed prior to being sent to the API server
- Configuration to be validated as part of the CD pipeline
- Configuration for Resources to validated holistically rather than individually
per-Resource -- e.g. ensure the `Service.selector` and `Deployment.spec.template` labels
match.
- MutatingWebHooks are scoped to a single Resource instance at a time.
- Low-level tweaks to the output of high-level abstractions -- e.g. add an `init container`
to a client *"CRD"* Resource after it was generated.
- Composition and layering of multiple functions together
- Compose generation, injection, validation together
Configuration Functions are implemented as executable programs published in containers which:
- Accept as input (stdin):
- A list of Resource Configuration
- A Function Configuration (to configure the function itself)
- Emit as output (stdout + exit):
- A list of Resource Configuration
- An exit code for success / failure
### Function Specification
- Functions **SHOULD** be published as container images containing a `CMD` invoking an executable.
- Functions **MUST** accept input on STDIN a `ResourceList` containing the Resources and
`functionConfig`.
- Functions **MUST** emit output on STDOUT a `ResourceList` containing the modified
Resources.
- Functions **MUST** exit non-0 on failure, and exit 0 on success.
- Functions **MAY** emit output on STDERR with error messaging.
- Functions performing validation **SHOULD** exit failure and emit error messaging
on a validation failure.
- Functions generating Resources **SHOULD** retain non-conflicting changes on the
generated Resources -- e.g. 1. the function generates a Deployment, but doesn't
specify `cpu`, 2. the user sets the `cpu` on the generated Resource, 3. the
function should keep the `cpu` when regenerating the Resource a second time.
- Functions **SHOULD** be usable outside `kustomize config run` -- e.g. though pipeline
mechanisms such as Tekton.
#### Input Format
Functions must accept on STDIN:
`ResourceList`:
- contains `items` field, same as `List.items`
- contains `functionConfig` field -- a single item with the configuration for the function itself
Example `ResourceList` Input:
apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
functionConfig:
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
spec:
replicas: 5
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
spec:
replicas: 3
...
- apiVersion: v1
kind: Service
metadata:
name: my-instance
spec:
...
#### Output Format
Functions must emit on STDOUT:
`ResourceList`:
- contains `items` field, same as `List.items`
Example `ResourceList` Output:
apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
spec:
replicas: 5
...
- apiVersion: v1
kind: Service
metadata:
name: my-instance
spec:
...
#### Container Environment
When run by `kustomize config run`, functions are run in containers with the
following environment:
- Network: `none`
- User: `nobody`
- Security Options: `no-new-privileges`
- Volumes: the volume containing the `functionConfig` yaml is mounted under `/local` as `ro`
### Example Function Implementation
Following is an example for implementing an nginx abstraction using a config
function.
#### `nginx-template.sh`
`nginx-template.sh` is a simple bash script which uses a *heredoc* as a templating solution
for generating Resources from the functionConfig input fields.
The script wraps itself using `config run wrap -- $0` which will:
1. Parse the `ResourceList.functionConfig` (provided to the container stdin) into env vars
2. Merge the stdout into the original list of Resources
3. Defaults filenames for newly generated Resources (if they are not set as annotations)
to `config/NAME_KIND.yaml`
4. Format the output
#!/bin/bash
# script must run wrapped by `kustomize config run wrap`
# for parsing input the functionConfig into env vars
if [ -z ${WRAPPED} ]; then
export WRAPPED=true
config run wrap -- $0
exit $?
fi
cat <<End-of-message
apiVersion: v1
kind: Service
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: ${NAME}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
replicas: ${REPLICAS}
selector:
matchLabels:
app: nginx
instance: ${NAME}
template:
metadata:
labels:
app: nginx
instance: ${NAME}
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
End-of-message
#### `Dockerfile`
`Dockerfile` installs `kustomize config` and copies the script into the container image.
FROM golang:1.13-stretch
RUN go get sigs.k8s.io/kustomize/cmd/config
RUN mv /go/bin/config /usr/bin/config
COPY nginx-template.sh /usr/bin/nginx-template.sh
CMD ["nginx-template.sh]
### Example Function Usage
Following is an example of running the `kustomize config run` using the preceding API.
#### `nginx.yaml` (Input)
`dir/nginx.yaml` contains a reference to the Function. The contents of `nginx.yaml`
are passed to the Function through the `ResourceList.functionConfig` field.
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
configFn:
container:
image: gcr.io/example-functions/nginx-template:v1.0.0
spec:
replicas: 5
- `configFn.container.image`: the image to use for this API
- `annotations[config.kubernetes.io/local-config]`: mark this as not a Resource that should
be applied
#### `kustomize config run dir/` (Output)
`dir/my-instance_deployment.yaml` contains the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
replicas: 5
selector:
matchLabels:
app: nginx
instance: my-instance
template:
metadata:
labels:
app: nginx
instance: my-instance
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
`dir/my-instance_service.yaml` contains the Service:
apiVersion: v1
kind: Service
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: my-instance

View File

@@ -0,0 +1,181 @@
# Running Configuration Functions using kustomize CLI
Configuration functions can be implemented using any toolchain and invoked using any
container workflow orchestrator including Tekton, Cloud Build, or run directly using `docker run`.
Run `config help docs-fn-spec` to see the Configuration Functions Specification.
`kustomize config run` is an example orchestrator for invoking Configuration Functions. This
document describes how to implement and invoke an example function.
## Example Function Implementation
Following is an example for implementing an nginx abstraction using a configuration
function.
### `nginx-template.sh`
`nginx-template.sh` is a simple bash script which uses a _heredoc_ as a templating solution
for generating Resources from the functionConfig input fields.
The script wraps itself using `config run wrap -- $0` which will:
1. Parse the `ResourceList.functionConfig` (provided to the container stdin) into env vars
2. Merge the stdout into the original list of Resources
3. Defaults filenames for newly generated Resources (if they are not set as annotations)
to `config/NAME_KIND.yaml`
4. Format the output
```bash
#!/bin/bash
# script must run wrapped by "kustomize config run wrap"
# for parsing input the functionConfig into env vars
if [ -z ${WRAPPED} ]; then
export WRAPPED=true
config run wrap -- $0
exit $?
fi
cat <<End-of-message
apiVersion: v1
kind: Service
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: ${NAME}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
replicas: ${REPLICAS}
selector:
matchLabels:
app: nginx
instance: ${NAME}
template:
metadata:
labels:
app: nginx
instance: ${NAME}
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
End-of-message
```
### Dockerfile
`Dockerfile` installs `kustomize config` and copies the script into the container image.
```
FROM golang:1.13-stretch
RUN go get sigs.k8s.io/kustomize/cmd/config
RUN mv /go/bin/config /usr/bin/config
COPY nginx-template.sh /usr/bin/nginx-template.sh
CMD ["nginx-template.sh]
```
## Example Function Usage
Following is an example of running the `kustomize config run` using the preceding API.
When run by `kustomize config run`, functions are run in containers with the
following environment:
- Network: `none`
- User: `nobody`
- Security Options: `no-new-privileges`
- Volumes: the volume containing the `functionConfig` yaml is mounted under `/local` as `ro`
### Input
`dir/nginx.yaml` contains a reference to the Function. The contents of `nginx.yaml`
are passed to the Function through the `ResourceList.functionConfig` field.
```yaml
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
config.k8s.io/function: |
container:
image: gcr.io/example-functions/nginx-template:v1.0.0
spec:
replicas: 5
```
- `annotations[config.k8s.io/function].container.image`: the image to use for this API
- `annotations[config.kubernetes.io/local-config]`: mark this as not a Resource that should
be applied
### Output
The function is invoked using by runing `kustomize config run dir/`.
`dir/my-instance_deployment.yaml` contains the Deployment:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
replicas: 5
selector:
matchLabels:
app: nginx
instance: my-instance
template:
metadata:
labels:
app: nginx
instance: my-instance
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
```
`dir/my-instance_service.yaml` contains the Service:
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: my-instance
```

View File

@@ -0,0 +1,186 @@
# Configuration Functions Specification
This document specifies a standard for client-side functions that operate on
Kubernetes declarative configurations. This standard enables creating
small, interoperable, and language-independent executable programs packaged as
containers that can be chained together as part of a configuration management pipeline.
The end result of such a pipeline are fully rendered configurations that can then be
applied to a control plane (e.g. Using kubectl apply for Kubernetes control plane).
As such, although this document references Kubernetes Resource Model and API conventions,
it is completely decoupled from Kuberentes API machinery and does not depend on any
in-cluster components.
This document references terms described in [Kubernetes API Conventions][1].
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][2].
## Use Cases
_Configuration functions_ enable shift-left practices (client-side) through:
- Pre-commit / delivery validation and linting of configuration
- e.g. Fail if any containers don't have PodSecurityPolicy or CPU / Memory limits
- Implementation of abstractions as client actuated APIs (e.g. templating)
- e.g. Create a client-side _"CRD"_ for generating configuration checked into git
- Aspect Orient configuration / Injection of cross-cutting configuration
- e.g. T-Shirt size containers by annotating Resources with `small`, `medium`, `large`
and inject the cpu and memory resources into containers accordingly.
- e.g. Inject `init` and `side-car` containers into Resources based off of Resource
Type, annotations, etc.
Performing these on the client rather than the server enables:
- Configuration to be reviewed prior to being sent to the API server
- Configuration to be validated as part of the CI?CD pipeline
- Configuration for Resources to validated holistically rather than individually
per-Resource
- e.g. ensure the `Service.selector` and `Deployment.spec.template` labels
match.
- e.g. MutatingWebHooks are scoped to a single Resource instance at a time.
- Low-level tweaks to the output of high-level abstractions
- e.g. add an `init container` to a client _"CRD"_ Resource after it was generated.
- Composition and layering of multiple functions together
- Compose generation, injection, validation together
## Spec
### Input Type
A function MUST accept as input a single [Kubernetes List type][3].
The `items` field in the input will contain a sequence of [Object types][3].
A function MAY not support [Simple types][3] and List types.
An example using `v1/ConfigMapList` as input:
```yaml
apiVersion: v1
kind: ConfigMapList
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: config1
data:
p1: v1
p2: v2
- apiVersion: v1
kind: ConfigMap
metadata:
name: config2
```
An example using `v1/List` as input:
```yaml
apiVersion: v1
kind: List
items:
spec:
- apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
address: "100 Main St."
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- resources:
- namespaces
apiGroups:
- ""
verbs:
- get
- watch
- list
```
In addition, a function MUST accept as input a List of kind `ResourceList` where the
`functionConfig` field, if present, will contain the invocation-specific configuration passed to the function
by the orchestrator.
Functions MAY consider this field optional so that they can be triggered in an ad-hoc fashion.
An example using `config.kubernetes.io/v1beta1/ResourceList` as input:
```yaml
apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
metadata:
annotations:
config.k8s.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
spec:
address: "100 Main St."
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- resources:
- namespaces
apiGroups:
- ""
verbs:
- get
- watch
- list
```
Here `FulfillmentCenter` kind with name `staging` is passed as the invocation-specific configuration
to the function.
### Output Type
A functions output MUST be the same as the input specification above
-- i.e. `ResourceList` or `List`.
This is necessary to enable chaining two or more functions together in a pipeline.
The serialization format of the output SHOULD match that of its input on each invocation
-- e.g. if the input was a `ResourceList`, the output should also be a `ResourceList`.
### Serialization Format
A function MUST support YAML as a serialization format for the input and output.
A function MUST use utf8 encoding (as YAML is a superset of JSON, JSON will also be supported
by any conforming function).
### Operations
A function MAY Create, Update, or Delete any number of items in the `items` field and output the
resultant list.
A function MAY modify annotations with prefix `config.kubernetes.io`, but must be careful about
doing so since theyre used for orchestration purposes and will likely impact subsequent functions
in the pipeline.
A function SHOULD preserve comments when input serialization format is YAML.
This allows for human authoring of configuration to coexist with changes made by functions.
### Containerization
A function MUST be implemented as a container.
A function container MUST be capable of running as a non-root user if it does not require
access to host filesystem or makes network calls.
### stdin/stdout/stderr and Exit Codes
A function MUST accept input from stdin and emit output to stdout.
Any error messages MUST be emitted to stderr.
An exit code of zero indicates function execution was successful.
A non-zero exit code indicates a failure.
[1]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[2]: https://tools.ietf.org/html/rfc2119
[3]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds

View File

@@ -0,0 +1,93 @@
## create-setter
[Alpha] Create a custom setter for a Resource field
### Synopsis
Create a custom setter for a Resource field by inlining OpenAPI as comments.
DIR
A directory containing Resource configuration.
NAME
The name of the setter to create.
VALUE
The current value of the field, or a substring within the field.
### Creating a Custom Setter
**Given the YAML:**
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080
...
**Create a new setter:**
# create a setter for ports
$ kustomize config set create DIR/ http-port 8080 --type "integer" --field "port"
Resources fields with a field name matching `--field` and field value matching `VALUE` will
have a line comment added marking this field as settable.
**Newly modified YAML:**
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080 # {"type":"integer","x-kustomize":{"partialFieldSetters":[{"name":"http-port","value":"8080"}]}}
...
Setters may also be defined directly by editing the yaml and adding the comment.
Users may not set the field value using the `set` command:
# change the http-port value to 8081
$ kustomize config set DIR/ http-port 8081
### Using default values
The default values for a setter may be:
- valid field values (e.g. `8080` or `008080` for a port)
- invalid values that adhere to the schema (e.g. `0000` for a port)
- values that do not adhere to the schema (e.g. `[PORT]` for port)
A setter may be for a substring of a full field:
$ kustomize config set create DIR/ image-tag v1.0.01 --type "string" --field "image"
image: gcr.io/example/app:v1.0.1 # # {"type":"string","x-kustomize":{"partialFieldSetters":[{"name":"image-tag","value":"v1.0.1"}]}}
A single field value may have multiple setters applied to it for different parts of the field.
### Examples
# create a setter for port fields matching "8080"
kustomize config create-setter DIR/ port 8080 --type "integer" --field port \
--description "default port used by the app"
# create a setter for a substring of a field rather than the full field -- e.g. only the
# image tag, not the full image
kustomize config create-setter DIR/ image-tag v1.0.1 --type "string" \
--field image --description "current stable release"

View File

@@ -0,0 +1,23 @@
## set
[Alpha] List setters for Resources.
### Synopsis
List setters for Resources.
DIR
A directory containing Resource configuration.
NAME
Optional. The name of the setter to display.
### Examples
Show setters:
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2

View File

@@ -0,0 +1,23 @@
## merge3
[Alpha] Merge diff of Resource configuration files into a destination (3-way)
### Synopsis
[Alpha] Merge diff of Resource configuration files into a destination (3-way)
Merge3 performs a 3-way merge by applying the diff between 2 sets of Resources to a 3rd set.
Merge3 may be for rebasing changes to a forked set of configuration -- e.g. compute the difference between the original
set of Resources that was forked and an updated set of those Resources, then apply that difference to the fork.
If a field value differs between the ORIGINAL_DIR and UPDATED_DIR, the value from the UPDATED_DIR is taken and applied
to the Resource in the DEST_DIR.
For information on merge rules, run:
kustomize config docs-merge3
### Examples
kustomize config merge3 --ancestor a/ --from b/ --to c/

View File

@@ -22,8 +22,8 @@ order they appear in the file).
#### Config Functions:
Config functions are specified as Kubernetes types containing a metadata.configFn.container.image
field. This field tells run how to invoke the container.
Config functions are specified as Kubernetes types containing a metadata.annotations.[config.k8s.io/function]
field specifying an image for the container to run. This image tells run how to invoke the container.
Example config function:
@@ -31,17 +31,17 @@ order they appear in the file).
apiVersion: fn.example.com/v1beta1
kind: ExampleFunctionKind
metadata:
configFn:
container:
# function is invoked as a container running this image
image: gcr.io/example/examplefunction:v1.0.1
annotations:
config.k8s.io/function: |
container:
# function is invoked as a container running this image
image: gcr.io/example/examplefunction:v1.0.1
config.kubernetes.io/local-config: "true" # tools should ignore this
spec:
configField: configValue
In the preceding example, 'kustomize config run example/' would identify the function by
the metadata.configFn field. It would then write all Resources in the directory to
the metadata.annotations.[config.k8s.io/function] field. It would then write all Resources in the directory to
a container stdin (running the gcr.io/example/examplefunction:v1.0.1 image). It
would then write the container stdout back to example/, replacing the directory
file contents.

View File

@@ -0,0 +1,87 @@
## set
[Alpha] Set values on Resources fields values.
### Synopsis
Set values on Resources fields. May set either the complete or partial field value.
`set` identifies setters using field metadata published as OpenAPI extensions.
`set` parses both the Kubernetes OpenAPI, as well OpenAPI published inline in
the configuration as comments.
`set` maybe be used to:
- edit configuration programmatically from the cli
- create reusable bundles of configuration with custom setters
DIR
A directory containing Resource configuration.
NAME
Optional. The name of the setter to perform or display.
VALUE
Optional. The value to set on the field.
To print the possible setters for the Resources in a directory, run `set` on
a directory -- e.g. `kustomize config set DIR/`.
#### Tips
- A description of the value may be specified with `--description`.
- The last setter for the field's value may be defined with `--set-by`.
- Create custom setters on Resources, Kustomization.yaml's, patches, etc
The description and setBy fields are left unmodified unless specified with flags.
To create a custom setter for a field see: `kustomize help config create-setter`
### Examples
Resource YAML: Name Prefix Setter
# DIR/resources.yaml
...
metadata:
name: PREFIX-app1 # {"type":"string","x-kustomize":{"partialFieldSetters":[{"name":"name-prefix","value":"PREFIX"}]}}
...
---
...
metadata:
name: PREFIX-app2 # {"type":"string","x-kustomize":{"partialFieldSetters":[{"name":"name-prefix","value":"PREFIX"}]}}
...
List setters: Show the possible setters
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2
Perform set: set a new value, owner and description
$ kustomize config set DIR/ name-prefix "test" --description "test environment" --set-by "dev"
set 2 values
List setters: Show the new values
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix 'test environment' test string 2 dev
New Resource YAML:
# DIR/resources.yaml
...
metadata:
name: test-app1 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
...
---
...
metadata:
name: test-app2 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
...

View File

@@ -1,98 +0,0 @@
## set
[Alpha] Set values on Resources fields by substituting values.
### Synopsis
Set values on Resources fields by substituting predefined markers for new values.
`set` looks for markers specified on Resource fields and substitute a new user defined
value for the existing value.
`set` maybe be used to:
- edit configuration programmatically from the cli or scripts
- create reusable bundles of configuration
DIR
A directory containing Resource configuration.
NAME
Optional. The name of the substitution to perform or display.
VALUE
Optional. The new value to substitute into the field.
To print the possible substitutions for the Resources in a directory, run `set` on
a directory -- e.g. `kustomize config set DIR/`.
#### Tips
- A description of the value may be specified with `--description`.
- An owner for the field's value may be defined with `--owned-by`.
- Prevent overriding previous substitutions with `--override=false`.
- Revert previous substitutions with `--revert`.
- Create substitutions on Kustomization.yaml's, patches, etc
When overriding or reverting previous substitutions, the description and owner are left
unmodified unless specified with flags.
To create a substitution for a field see: `kustomize help config set create`
### Examples
Resource YAML: Name substitution
# dir/resources.yaml
...
metadata:
name: PREFIX-app1 # {"substitutions":[{"name":"prefix","marker":"PREFIX-"}]}
...
---
...
metadata:
name: PREFIX-app2 # {"substitutions":[{"name":"prefix","marker":"PREFIX-"}]}
...
Show substitutions: Show the possible substitutions
$ config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix '' PREFIX- string 2 false
Perform substitution: set a new value, owner and description
$ config set dir prefix "test-" --description "test environment" --owned-by "dev"
performed 2 substitutions
Show substitutions: Show the new values
$ config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix 'test environment' test- string 2 true dev
New Resource YAML:
# dir/resources.yaml
...
metadata:
name: test-app1 # {"substitutions":[{"name":"prefix","marker":"PREFIX-","value":"test-"}],"setBy":"dev","description":"test environment"}
...
---
...
metadata:
name: test-app2 # {"substitutions":[{"name":"prefix","marker":"PREFIX-","value":"test-"}],"setBy":"dev","description":"test environment"}
...
Revert substitution:
config set dir prefix --revert
performed 2 substitutions
config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix 'test environment' PREFIX- string 2 false dev

View File

@@ -1,167 +0,0 @@
## sub-set-marker
[Alpha] Create a new substitution for a Resource field
### Synopsis
Create a new substitution for a Resource field -- recognized by `kustomize config set`.
DIR
A directory containing Resource configuration.
NAME
The name of the substitution to create.
VALUE
The current value of the field, or a substring of the field.
#### Tips: Picking Good Marker
Substitutions may be defined by directly editing yaml **or** by running `kustomize config set create`
to create a new substitution.
Given the YAML:
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080
...
Create a new set marker:
# create a substitution for ports
$ kustomize config set create dir/ http-port 8080 --type "int" --field "port"
Modified YAML:
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080 # {"substitutions":[{"name":"port","marker":"[MARKER]"}],"type":"int"}
...
Change the value using the `set` command:
# change the http-port value to 8081
$ kustomize config set dir/ http-port 8081
Resources fields with a field name matching `--field` and field value matching `VALUE` will
have a line comment added marking this field as settable.
Substitution markers may be:
- valid field values (e.g. `8080` for a port)
- Note: `008080` would be preferred because it is more recognizable as a marker
- invalid values that adhere to the schema (e.g. `0000` for a port)
- values that do not adhere to the schema (e.g. `[PORT]` for port)
Markers **SHOULD be clearly identifiable as a marker and either**:
- **adhere to the field schema** -- e.g. use a valid value
port: 008080 # {"substitutions":[{"name":"port","marker":"008080"}],"type":"int"}
- **be pre-filled in with a value** -- e.g. set the value when setting the marker
port: 8080 # {"substitutions":[{"name":"port","marker":"[MARKER]","value":"8080""}],"type":"int"}
**Note:** The important thing is that in both cases the Resource configuration may be directly
applied to a cluster and validated by tools without the tool knowing about the substitution
marker.
The difference between the preceding examples is that:
- the former will be shown as `SUBSTITUTED=false` (`config sub dir/` exits non-0)
- the latter with show up as `SUBSTITUTED=true` (`config sub dir/` exits 0)
When choosing the which to use, consider that checks for unsubstituted values MAY be
configured as pre-commit checks -- if you want to these checks to fail if the value
hasn't been substituted, then don't specify a `value`.
Markers which are invalid field values MAY be chosen in cases where it is preferred to have
the create or update request fail rather than succeed if the substitution has not yet been
performed.
A substitution may be a substring of the full field:
$ kustomize config set create dir/ app-image-tag v1.0.01 --type "string" --field "image"
image: gcr.io/example/app:v1.0.1 # {"substitutions":[{"name":"app-image-tag","marker":"[MARKER]","value":"v1.0.1"}]}
A single field value may have multiple substitutions applied to it:
name: PREFIX-app-SUFFIX # {"substitutions":[{"name":"prefix","marker":"PREFIX-"},{"name":"suffix","marker":"-SUFFIX"}]}
#### Substitution Format
Substitutions are defined as json encoded FieldMeta comments on fields.
FieldMeta Schema read by `sub`:
{
"title": "FieldMeta",
"type": "object",
"properties": {
"substitutions": {
"type": "array",
"description": "Possible substitutions that may be performed against this field.",
"items": {
"type": "object",
"properties": {
"name": "Name of the substitution.",
"marker": "Marker for the value to be substituted.",
"value": "Current substituted value"
}
}
},
"type": {
"type": "string",
"description": "The value type. Defaults to string."
"enum": ["string", "int", "float", "bool"]
},
"description": {
"type": "string",
"description": "A description of the field's current value. Optional."
},
"setBy": {
"type": "string",
"description": "The current owner of the field. Optional."
},
}
}
### Examples
# set a substitution for port fields matching "8080"
kustomize config sub create dir/ port 8080 --type "int" --field port \
--description "default port used by the app"
# set a substitution for port fields matching "8080", using "0000" as a marker.
kustomize config sub dir/ port 8080 --marker "0000" --type "int" \
--field port --description "default port used by the app"
# substitute a substring of a field rather than the full field -- e.g. only the
# image tag, not the full image
kustomize config sub dir/ app-image-tag v1.0.1 --type "string" --substring \
--field port --description "current stable release"

View File

@@ -1,8 +1,11 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.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-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@@ -16,16 +19,25 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
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.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
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/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
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/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -43,7 +55,6 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
@@ -51,21 +62,20 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/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 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/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 h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -81,9 +91,7 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -94,11 +102,9 @@ github.com/posener/script v1.0.4 h1:nSuXW5ZdmFnQIueLB2s0qvs4oNsUloM1Zydzh75v42w=
github.com/posener/script v1.0.4/go.mod h1:Rg3ijooqulo05aGLyGsHoLmIOUzHUVK19WVgrYBPU/E=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -119,6 +125,9 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -128,12 +137,12 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
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=

View File

@@ -0,0 +1,75 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/setters"
)
// NewCreateSetterRunner returns a command runner.
func NewCreateSetterRunner(parent string) *CreateSetterRunner {
r := &CreateSetterRunner{}
set := &cobra.Command{
Use: "create-setter DIR NAME VALUE",
Args: cobra.ExactArgs(3),
Short: commands.CreateSetterShort,
Long: commands.CreateSetterLong,
Example: commands.CreateSetterExamples,
PreRunE: r.preRunE,
RunE: r.runE,
}
set.Flags().StringVar(&r.Set.SetPartialField.SetBy, "set-by", "",
"set the setBy annotation.")
set.Flags().StringVar(&r.Set.SetPartialField.Description, "description", "",
"set the description of the field value.")
set.Flags().StringVar(&r.Set.SetPartialField.Field, "field", "",
"name of the field to set -- e.g. --field port")
set.Flags().StringVar(&r.Set.ResourceMeta.Name, "name", "",
"name of the Resource on which to create the setter.")
set.Flags().StringVar(&r.Set.ResourceMeta.Kind, "kind", "",
"kind of the Resource on which to create the setter.")
set.Flags().StringVar(&r.Set.SetPartialField.Type, "type", "",
"valid OpenAPI field type -- e.g. integer,boolean,string.")
set.Flags().BoolVar(&r.Set.SetPartialField.Partial, "partial", false,
"create a partial setter for only part of the field value.")
fixDocs(parent, set)
set.MarkFlagRequired("type")
set.MarkFlagRequired("field")
r.Command = set
return r
}
func CreateSetterCommand(parent string) *cobra.Command {
return NewCreateSetterRunner(parent).Command
}
type CreateSetterRunner struct {
Command *cobra.Command
Set setters.CreateSetter
}
func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error {
return handleError(c, r.set(c, args))
}
func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
r.Set.SetPartialField.Setter.Name = args[1]
r.Set.SetPartialField.Setter.Value = args[2]
return nil
}
func (r *CreateSetterRunner) set(c *cobra.Command, args []string) error {
rw := &kio.LocalPackageReadWriter{PackagePath: args[0]}
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Set},
Outputs: []kio.Writer{rw}}.Execute()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,47 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/setters"
)
// NewListSettersRunner returns a command runner.
func NewListSettersRunner(parent string) *ListSettersRunner {
r := &ListSettersRunner{}
c := &cobra.Command{
Use: "list-setters DIR [NAME]",
Args: cobra.RangeArgs(1, 2),
Short: commands.ListSettersShort,
Long: commands.ListSettersLong,
Example: commands.ListSettersExamples,
PreRunE: r.preRunE,
RunE: r.runE,
}
fixDocs(parent, c)
r.Command = c
return r
}
func ListSettersCommand(parent string) *cobra.Command {
return NewListSettersRunner(parent).Command
}
type ListSettersRunner struct {
Command *cobra.Command
Lookup setters.LookupSetters
}
func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
if len(args) > 1 {
r.Lookup.Name = args[1]
}
return nil
}
func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
return handleError(c, lookup(r.Lookup, c, args))
}

View File

@@ -0,0 +1,130 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands
import (
"fmt"
"os"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/setters"
)
// NewSetRunner returns a command runner.
func NewSetRunner(parent string) *SetRunner {
r := &SetRunner{}
c := &cobra.Command{
Use: "set DIR [NAME] [VALUE]",
Args: cobra.RangeArgs(1, 3),
Short: commands.SetShort,
Long: commands.SetLong,
Example: commands.SetExamples,
PreRunE: r.preRunE,
RunE: r.runE,
}
fixDocs(parent, c)
r.Command = c
c.Flags().StringVar(&r.Perform.SetBy, "set-by", "",
"annotate the field with who set it")
c.Flags().StringVar(&r.Perform.Description, "description", "",
"annotate the field with a description of its value")
return r
}
func SetCommand(parent string) *cobra.Command {
return NewSetRunner(parent).Command
}
type SetRunner struct {
Command *cobra.Command
Lookup setters.LookupSetters
Perform setters.PerformSetters
}
func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
if len(args) > 1 {
r.Perform.Name = args[1]
r.Lookup.Name = args[1]
}
if len(args) > 2 {
r.Perform.Value = args[2]
}
return nil
}
func (r *SetRunner) runE(c *cobra.Command, args []string) error {
if len(args) == 3 {
return handleError(c, r.perform(c, args))
}
return handleError(c, lookup(r.Lookup, c, args))
}
func lookup(l setters.LookupSetters, c *cobra.Command, args []string) error {
// lookup the setters
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: args[0]}},
Filters: []kio.Filter{&l},
}.Execute()
if err != nil {
return err
}
table := tablewriter.NewWriter(c.OutOrStdout())
table.SetRowLine(false)
table.SetBorder(false)
table.SetHeaderLine(false)
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader([]string{
"NAME", "DESCRIPTION", "VALUE", "TYPE", "COUNT", "SETBY",
})
for i := range l.SetterCounts {
s := l.SetterCounts[i]
v := s.Value
if s.Value == "" {
v = s.Value
}
table.Append([]string{
s.Name,
"'" + s.Description + "'",
v,
fmt.Sprintf("%v", s.Type),
fmt.Sprintf("%d", s.Count),
s.SetBy,
})
}
table.Render()
if len(l.SetterCounts) == 0 {
// exit non-0 if no matching setters are found
os.Exit(1)
}
return nil
}
// perform the setters
func (r *SetRunner) perform(c *cobra.Command, args []string) error {
rw := &kio.LocalPackageReadWriter{
PackagePath: args[0],
}
// perform the setters in the package
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Perform},
Outputs: []kio.Writer{rw},
}.Execute()
if err != nil {
return err
}
fmt.Fprintf(c.OutOrStdout(), "set %d fields\n", r.Perform.Count)
return nil
}

View File

@@ -1,162 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"fmt"
"os"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/set"
)
// NewSubRunner returns a command runner.
func NewSubRunner(parent string) *SubRunner {
r := &SubRunner{}
c := &cobra.Command{
Use: "set DIR [NAME] [VALUE]",
Args: cobra.RangeArgs(1, 3),
Short: commands.SubShort,
Long: commands.SubLong,
Example: commands.SubExamples,
Aliases: []string{"sub"},
PreRunE: r.preRunE,
RunE: r.runE,
}
c.Flags().BoolVar(&r.Perform.Override, "override", true,
"override previously substituted values.")
c.Flags().BoolVar(&r.Perform.Revert, "revert", false,
"override previously substituted values.")
fixDocs(parent, c)
r.Command = c
c.AddCommand(SubSetCommand(parent))
return r
}
func SubCommand(parent string) *cobra.Command {
return NewSubRunner(parent).Command
}
type SubRunner struct {
Command *cobra.Command
Lookup set.LookupSubstitutions
Perform set.PerformSubstitutions
}
func (r *SubRunner) preRunE(c *cobra.Command, args []string) error {
if len(args) > 1 {
r.Perform.Name = args[1]
r.Lookup.Name = args[1]
}
if len(args) > 2 {
r.Perform.NewValue = args[2]
}
if len(args) < 2 && r.Perform.Revert {
return errors.Errorf("must specify NAME with --revert")
}
var mutex int
if r.Perform.Revert {
mutex++
}
if r.Perform.Override {
mutex++
}
if mutex > 1 {
return errors.Errorf("--revert, --override are mutually exclusive")
}
return nil
}
func (r *SubRunner) runE(c *cobra.Command, args []string) error {
if len(args) == 3 {
return handleError(c, r.perform(c, args))
}
if len(args) == 2 && r.Perform.Revert {
return handleError(c, r.perform(c, args))
}
return handleError(c, r.lookup(c, args))
}
func (r *SubRunner) lookup(c *cobra.Command, args []string) error {
// lookup the substitutions
err := kio.Pipeline{
Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: args[0]}},
Filters: []kio.Filter{&r.Lookup},
}.Execute()
if err != nil {
return err
}
remaining := false
table := tablewriter.NewWriter(c.OutOrStdout())
table.SetRowLine(false)
table.SetBorder(false)
table.SetHeaderLine(false)
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader([]string{
"NAME", "DESCRIPTION", "VALUE", "TYPE", "COUNT", "SUBSTITUTED", "OWNER",
})
for i := range r.Lookup.SubstitutionCounts {
s := r.Lookup.SubstitutionCounts[i]
remaining = remaining || s.Count > s.CountComplete
v := s.CurrentValue
if s.CurrentValue == "" {
v = s.Marker
}
table.Append([]string{
s.Name,
"'" + s.Description + "'",
v,
fmt.Sprintf("%v", s.Type),
fmt.Sprintf("%d", s.Count),
fmt.Sprintf("%v", s.Count == s.CountComplete),
s.OwnedBy,
})
}
table.Render()
if remaining {
os.Exit(1)
}
return nil
}
// perform the substitutions
func (r *SubRunner) perform(c *cobra.Command, args []string) error {
rw := &kio.LocalPackageReadWriter{
PackagePath: args[0],
}
// perform the substitutions in the package
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Perform},
Outputs: []kio.Writer{rw},
}.Execute()
if err != nil {
return err
}
fmt.Fprintf(c.OutOrStdout(), "performed %d substitutions\n", r.Perform.Count)
return nil
}

View File

@@ -1,93 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/set"
)
// NewSubSetRunner returns a command runner.
func NewSubSetRunner(parent string) *SubSetRunner {
r := &SubSetRunner{}
set := &cobra.Command{
Use: "create PKG_DIR NAME [VALUE]",
Args: cobra.ExactArgs(3),
Short: commands.SubsetShort,
Long: commands.SubsetLong,
Example: commands.SubsetExamples,
PreRunE: r.preRunE,
RunE: r.runE,
}
set.Flags().StringVar(&r.Set.Marker.OwnedBy, "owned-by", "",
"set this owner on for the current value.")
set.Flags().StringVar(&r.Set.Marker.Description, "description", "",
"set this description for the current value description.")
set.Flags().StringVar(&r.Set.Marker.Substitution.Marker, "marker", "[MARKER]",
"use this marker.")
set.Flags().StringVar(&r.Set.Marker.Field, "field", "",
"name of the field to set -- e.g. --field port")
set.Flags().StringVar(&r.Set.ResourceMeta.Name, "name", "",
"name of the Resource on which to set the substitution.")
set.Flags().StringVar(&r.Set.ResourceMeta.Kind, "kind", "",
"kind of the Resource on which to set substitution.")
set.Flags().StringVar(&r.Set.Marker.Type, "type", "",
"field type -- e.g. int,float,bool,string.")
set.Flags().BoolVar(&r.Set.Marker.PartialMatch, "substring", false,
"if true, the value may be a substring of the current value.")
fixDocs(parent, set)
set.MarkFlagRequired("type")
set.MarkFlagRequired("field")
r.Command = set
return r
}
func SubSetCommand(parent string) *cobra.Command {
return NewSubSetRunner(parent).Command
}
type SubSetRunner struct {
Command *cobra.Command
Set set.SetSubstitutionMarker
}
func (r *SubSetRunner) runE(c *cobra.Command, args []string) error {
return handleError(c, r.set(c, args))
}
func (r *SubSetRunner) preRunE(c *cobra.Command, args []string) error {
r.Set.Marker.Substitution.Name = args[1]
r.Set.Marker.Substitution.Value = args[2]
return nil
}
// perform the substitutions
func (r *SubSetRunner) set(c *cobra.Command, args []string) error {
rw := &kio.LocalPackageReadWriter{
PackagePath: args[0],
}
// add the substitution marker to the Resource
err := kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{&r.Set},
Outputs: []kio.Writer{rw},
}.Execute()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,55 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands
import (
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/kio/filters"
)
func GetMerge3Runner(name string) *Merge3Runner {
r := &Merge3Runner{}
c := &cobra.Command{
Use: "merge3 --ancestor [ORIGINAL_DIR] --from [UPDATED_DIR] --to [DESTINATION_DIR]",
Short: commands.Merge3Short,
Long: commands.Merge3Long,
Example: commands.Merge3Examples,
RunE: r.runE,
}
fixDocs(name, c)
c.Flags().StringVar(&r.ancestor, "ancestor", "",
"Path to original package")
c.Flags().StringVar(&r.fromDir, "from", "",
"Path to updated package")
c.Flags().StringVar(&r.toDir, "to", "",
"Path to destination package")
r.Command = c
return r
}
func Merge3Command(name string) *cobra.Command {
return GetMerge3Runner(name).Command
}
// Merge3Runner contains the run function
type Merge3Runner struct {
Command *cobra.Command
ancestor string
fromDir string
toDir string
}
func (r *Merge3Runner) runE(c *cobra.Command, args []string) error {
err := filters.Merge3{
OriginalPath: r.ancestor,
UpdatedPath: r.fromDir,
DestPath: r.toDir,
}.Merge()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,236 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
"sigs.k8s.io/kustomize/kyaml/copyutil"
)
// TestMerge3Command verifies the merge3 correctly applies the diff between 2 sets of resources into another
func TestMerge3Command(t *testing.T) {
datadir, err := ioutil.TempDir("", "test-data")
defer os.RemoveAll(datadir)
if !assert.NoError(t, err) {
return
}
err = ioutil.WriteFile(filepath.Join(datadir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: java
spec:
replicas: 1
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
spec:
restartPolicy: Always
containers:
- name: app
image: gcr.io/project/app:version
command:
- java
- -jar
- /app.jar
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
env:
- name: JAVA_OPTS
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
-Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 5
`), 0600)
if !assert.NoError(t, err) {
return
}
expected_dir, err := ioutil.TempDir("", "test-data-expected")
defer os.RemoveAll(expected_dir)
if !assert.NoError(t, err) {
return
}
err = ioutil.WriteFile(filepath.Join(expected_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: java
new-local: label
new-remote: label
spec:
replicas: 3
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
spec:
restartPolicy: Always
containers:
- name: app
image: gcr.io/project/app:version
command:
- java
- -jar
- /app.jar
- otherstuff
args:
- foo
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
env:
- name: JAVA_OPTS
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
-Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 20
`), 0600)
if !assert.NoError(t, err) {
return
}
updated_dir, err := ioutil.TempDir("", "test-data-updated")
defer os.RemoveAll(updated_dir)
if !assert.NoError(t, err) {
return
}
err = ioutil.WriteFile(filepath.Join(updated_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: java
new-remote: label
spec:
replicas: 3
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
spec:
restartPolicy: Always
containers:
- name: app
image: gcr.io/project/app:version
command:
- java
- -jar
- /app.jar
- otherstuff
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
env:
- name: JAVA_OPTS
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
-Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 5
`), 0600)
if !assert.NoError(t, err) {
return
}
dest_dir, err := ioutil.TempDir("", "test-data-dest")
defer os.RemoveAll(dest_dir)
if !assert.NoError(t, err) {
return
}
err = ioutil.WriteFile(filepath.Join(dest_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: java
new-local: label
spec:
replicas: 2
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
spec:
restartPolicy: Always
containers:
- name: app
image: gcr.io/project/app:version
command:
- java
- -jar
- /app.jar
args:
- foo
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
env:
- name: JAVA_OPTS
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
-Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 20
`), 0600)
if !assert.NoError(t, err) {
return
}
// Perform merge3 with newly created sets
r := commands.GetMerge3Runner("")
r.Command.SetArgs([]string{
"--ancestor",
datadir,
"--from",
updated_dir,
"--to",
dest_dir,
})
if !assert.NoError(t, r.Command.Execute()) {
return
}
diffs, err := copyutil.Diff(dest_dir, expected_dir)
if !assert.NoError(t, err) {
t.FailNow()
}
// Verify there are no diffs
if !assert.Empty(t, diffs.List()) {
t.FailNow()
}
}

View File

@@ -4,288 +4,6 @@
// Code generated by "mdtogo"; DO NOT EDIT.
package api
var ConfigFnLong = `# Configuration Functions API Semantics
Configuration Functions are functions packaged as executables in containers which enable
**shift-left practices**. They configure applications and infrastructure through
Kubernetes style Resource Configuration, but run locally pre-commit.
Configuration functions enable shift-left practices (client-side) through:
- Pre-commit / delivery validation and linting of configuration
- e.g. Fail if any containers don't have PodSecurityPolicy or CPU / Memory limits
- Implementation of abstractions as client actuated APIs (e.g. templating)
- e.g. Create a client-side *"CRD"* for generating configuration checked into git
- Aspect Orient configuration / Injection of cross-cutting configuration
- e.g. T-Shirt size containers by annotating Resources with ` + "`" + `small` + "`" + `, ` + "`" + `medium` + "`" + `, ` + "`" + `large` + "`" + `
and inject the cpu and memory resources into containers accordingly.
- e.g. Inject ` + "`" + `init` + "`" + ` and ` + "`" + `side-car` + "`" + ` containers into Resources based off of Resource
Type, annotations, etc.
Performing these on the client rather than the server enables:
- Configuration to be reviewed prior to being sent to the API server
- Configuration to be validated as part of the CD pipeline
- Configuration for Resources to validated holistically rather than individually
per-Resource -- e.g. ensure the ` + "`" + `Service.selector` + "`" + ` and ` + "`" + `Deployment.spec.template` + "`" + ` labels
match.
- MutatingWebHooks are scoped to a single Resource instance at a time.
- Low-level tweaks to the output of high-level abstractions -- e.g. add an ` + "`" + `init container` + "`" + `
to a client *"CRD"* Resource after it was generated.
- Composition and layering of multiple functions together
- Compose generation, injection, validation together
Configuration Functions are implemented as executable programs published in containers which:
- Accept as input (stdin):
- A list of Resource Configuration
- A Function Configuration (to configure the function itself)
- Emit as output (stdout + exit):
- A list of Resource Configuration
- An exit code for success / failure
### Function Specification
- Functions **SHOULD** be published as container images containing a ` + "`" + `CMD` + "`" + ` invoking an executable.
- Functions **MUST** accept input on STDIN a ` + "`" + `ResourceList` + "`" + ` containing the Resources and
` + "`" + `functionConfig` + "`" + `.
- Functions **MUST** emit output on STDOUT a ` + "`" + `ResourceList` + "`" + ` containing the modified
Resources.
- Functions **MUST** exit non-0 on failure, and exit 0 on success.
- Functions **MAY** emit output on STDERR with error messaging.
- Functions performing validation **SHOULD** exit failure and emit error messaging
on a validation failure.
- Functions generating Resources **SHOULD** retain non-conflicting changes on the
generated Resources -- e.g. 1. the function generates a Deployment, but doesn't
specify ` + "`" + `cpu` + "`" + `, 2. the user sets the ` + "`" + `cpu` + "`" + ` on the generated Resource, 3. the
function should keep the ` + "`" + `cpu` + "`" + ` when regenerating the Resource a second time.
- Functions **SHOULD** be usable outside ` + "`" + `kustomize config run` + "`" + ` -- e.g. though pipeline
mechanisms such as Tekton.
#### Input Format
Functions must accept on STDIN:
` + "`" + `ResourceList` + "`" + `:
- contains ` + "`" + `items` + "`" + ` field, same as ` + "`" + `List.items` + "`" + `
- contains ` + "`" + `functionConfig` + "`" + ` field -- a single item with the configuration for the function itself
Example ` + "`" + `ResourceList` + "`" + ` Input:
apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
functionConfig:
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
spec:
replicas: 5
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
spec:
replicas: 3
...
- apiVersion: v1
kind: Service
metadata:
name: my-instance
spec:
...
#### Output Format
Functions must emit on STDOUT:
` + "`" + `ResourceList` + "`" + `:
- contains ` + "`" + `items` + "`" + ` field, same as ` + "`" + `List.items` + "`" + `
Example ` + "`" + `ResourceList` + "`" + ` Output:
apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
spec:
replicas: 5
...
- apiVersion: v1
kind: Service
metadata:
name: my-instance
spec:
...
#### Container Environment
When run by ` + "`" + `kustomize config run` + "`" + `, functions are run in containers with the
following environment:
- Network: ` + "`" + `none` + "`" + `
- User: ` + "`" + `nobody` + "`" + `
- Security Options: ` + "`" + `no-new-privileges` + "`" + `
- Volumes: the volume containing the ` + "`" + `functionConfig` + "`" + ` yaml is mounted under ` + "`" + `/local` + "`" + ` as ` + "`" + `ro` + "`" + `
### Example Function Implementation
Following is an example for implementing an nginx abstraction using a config
function.
#### ` + "`" + `nginx-template.sh` + "`" + `
` + "`" + `nginx-template.sh` + "`" + ` is a simple bash script which uses a *heredoc* as a templating solution
for generating Resources from the functionConfig input fields.
The script wraps itself using ` + "`" + `config run wrap -- $0` + "`" + ` which will:
1. Parse the ` + "`" + `ResourceList.functionConfig` + "`" + ` (provided to the container stdin) into env vars
2. Merge the stdout into the original list of Resources
3. Defaults filenames for newly generated Resources (if they are not set as annotations)
to ` + "`" + `config/NAME_KIND.yaml` + "`" + `
4. Format the output
#!/bin/bash
# script must run wrapped by ` + "`" + `kustomize config run wrap` + "`" + `
# for parsing input the functionConfig into env vars
if [ -z ${WRAPPED} ]; then
export WRAPPED=true
config run wrap -- $0
exit $?
fi
cat <<End-of-message
apiVersion: v1
kind: Service
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: ${NAME}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
replicas: ${REPLICAS}
selector:
matchLabels:
app: nginx
instance: ${NAME}
template:
metadata:
labels:
app: nginx
instance: ${NAME}
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
End-of-message
#### ` + "`" + `Dockerfile` + "`" + `
` + "`" + `Dockerfile` + "`" + ` installs ` + "`" + `kustomize config` + "`" + ` and copies the script into the container image.
FROM golang:1.13-stretch
RUN go get sigs.k8s.io/kustomize/cmd/config
RUN mv /go/bin/config /usr/bin/config
COPY nginx-template.sh /usr/bin/nginx-template.sh
CMD ["nginx-template.sh]
### Example Function Usage
Following is an example of running the ` + "`" + `kustomize config run` + "`" + ` using the preceding API.
#### ` + "`" + `nginx.yaml` + "`" + ` (Input)
` + "`" + `dir/nginx.yaml` + "`" + ` contains a reference to the Function. The contents of ` + "`" + `nginx.yaml` + "`" + `
are passed to the Function through the ` + "`" + `ResourceList.functionConfig` + "`" + ` field.
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
configFn:
container:
image: gcr.io/example-functions/nginx-template:v1.0.0
spec:
replicas: 5
- ` + "`" + `configFn.container.image` + "`" + `: the image to use for this API
- ` + "`" + `annotations[config.kubernetes.io/local-config]` + "`" + `: mark this as not a Resource that should
be applied
#### ` + "`" + `kustomize config run dir/` + "`" + ` (Output)
` + "`" + `dir/my-instance_deployment.yaml` + "`" + ` contains the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
replicas: 5
selector:
matchLabels:
app: nginx
instance: my-instance
template:
metadata:
labels:
app: nginx
instance: my-instance
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
` + "`" + `dir/my-instance_service.yaml` + "`" + ` contains the Service:
apiVersion: v1
kind: Service
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: my-instance`
var ConfigIoLong = `# Configuration IO API Semantics
Resource Configuration may be read / written from / to sources such as directories,
@@ -346,6 +64,355 @@ Example:
annotations:
config.kubernetes.io/local-config: "true"`
var FunctionsImplShort = `Following is an example for implementing an nginx abstraction using a configuration`
var FunctionsImplLong = `# Running Configuration Functions using kustomize CLI
Configuration functions can be implemented using any toolchain and invoked using any
container workflow orchestrator including Tekton, Cloud Build, or run directly using ` + "`" + `docker run` + "`" + `.
Run ` + "`" + `config help docs-fn-spec` + "`" + ` to see the Configuration Functions Specification.
` + "`" + `kustomize config run` + "`" + ` is an example orchestrator for invoking Configuration Functions. This
document describes how to implement and invoke an example function.
function.
### ` + "`" + `nginx-template.sh` + "`" + `
` + "`" + `nginx-template.sh` + "`" + ` is a simple bash script which uses a _heredoc_ as a templating solution
for generating Resources from the functionConfig input fields.
The script wraps itself using ` + "`" + `config run wrap -- $0` + "`" + ` which will:
1. Parse the ` + "`" + `ResourceList.functionConfig` + "`" + ` (provided to the container stdin) into env vars
2. Merge the stdout into the original list of Resources
3. Defaults filenames for newly generated Resources (if they are not set as annotations)
to ` + "`" + `config/NAME_KIND.yaml` + "`" + `
4. Format the output
#!/bin/bash
# script must run wrapped by "kustomize config run wrap"
# for parsing input the functionConfig into env vars
if [ -z ${WRAPPED} ]; then
export WRAPPED=true
config run wrap -- $0
exit $?
fi
cat <<End-of-message
apiVersion: v1
kind: Service
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: ${NAME}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${NAME}
labels:
app: nginx
instance: ${NAME}
spec:
replicas: ${REPLICAS}
selector:
matchLabels:
app: nginx
instance: ${NAME}
template:
metadata:
labels:
app: nginx
instance: ${NAME}
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
End-of-message
### Dockerfile
` + "`" + `Dockerfile` + "`" + ` installs ` + "`" + `kustomize config` + "`" + ` and copies the script into the container image.
FROM golang:1.13-stretch
RUN go get sigs.k8s.io/kustomize/cmd/config
RUN mv /go/bin/config /usr/bin/config
COPY nginx-template.sh /usr/bin/nginx-template.sh
CMD ["nginx-template.sh]
## Example Function Usage
Following is an example of running the ` + "`" + `kustomize config run` + "`" + ` using the preceding API.
When run by ` + "`" + `kustomize config run` + "`" + `, functions are run in containers with the
following environment:
- Network: ` + "`" + `none` + "`" + `
- User: ` + "`" + `nobody` + "`" + `
- Security Options: ` + "`" + `no-new-privileges` + "`" + `
- Volumes: the volume containing the ` + "`" + `functionConfig` + "`" + ` yaml is mounted under ` + "`" + `/local` + "`" + ` as ` + "`" + `ro` + "`" + `
### Input
` + "`" + `dir/nginx.yaml` + "`" + ` contains a reference to the Function. The contents of ` + "`" + `nginx.yaml` + "`" + `
are passed to the Function through the ` + "`" + `ResourceList.functionConfig` + "`" + ` field.
apiVersion: example.com/v1beta1
kind: Nginx
metadata:
name: my-instance
annotations:
config.kubernetes.io/local-config: "true"
config.k8s.io/function: |
container:
image: gcr.io/example-functions/nginx-template:v1.0.0
spec:
replicas: 5
- ` + "`" + `annotations[config.k8s.io/function].container.image` + "`" + `: the image to use for this API
- ` + "`" + `annotations[config.kubernetes.io/local-config]` + "`" + `: mark this as not a Resource that should
be applied
### Output
The function is invoked using by runing ` + "`" + `kustomize config run dir/` + "`" + `.
` + "`" + `dir/my-instance_deployment.yaml` + "`" + ` contains the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
replicas: 5
selector:
matchLabels:
app: nginx
instance: my-instance
template:
metadata:
labels:
app: nginx
instance: my-instance
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
` + "`" + `dir/my-instance_service.yaml` + "`" + ` contains the Service:
apiVersion: v1
kind: Service
metadata:
name: my-instance
labels:
app: nginx
instance: my-instance
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx
instance: my-instance`
var FunctionsSpecShort = `_Configuration functions_ enable shift-left practices (client-side) through:`
var FunctionsSpecLong = `# Configuration Functions Specification
This document specifies a standard for client-side functions that operate on
Kubernetes declarative configurations. This standard enables creating
small, interoperable, and language-independent executable programs packaged as
containers that can be chained together as part of a configuration management pipeline.
The end result of such a pipeline are fully rendered configurations that can then be
applied to a control plane (e.g. Using kubectl apply for Kubernetes control plane).
As such, although this document references Kubernetes Resource Model and API conventions,
it is completely decoupled from Kuberentes API machinery and does not depend on any
in-cluster components.
This document references terms described in [Kubernetes API Conventions][1].
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][2].
- Pre-commit / delivery validation and linting of configuration
- e.g. Fail if any containers don't have PodSecurityPolicy or CPU / Memory limits
- Implementation of abstractions as client actuated APIs (e.g. templating)
- e.g. Create a client-side _"CRD"_ for generating configuration checked into git
- Aspect Orient configuration / Injection of cross-cutting configuration
- e.g. T-Shirt size containers by annotating Resources with ` + "`" + `small` + "`" + `, ` + "`" + `medium` + "`" + `, ` + "`" + `large` + "`" + `
and inject the cpu and memory resources into containers accordingly.
- e.g. Inject ` + "`" + `init` + "`" + ` and ` + "`" + `side-car` + "`" + ` containers into Resources based off of Resource
Type, annotations, etc.
Performing these on the client rather than the server enables:
- Configuration to be reviewed prior to being sent to the API server
- Configuration to be validated as part of the CI?CD pipeline
- Configuration for Resources to validated holistically rather than individually
per-Resource
- e.g. ensure the ` + "`" + `Service.selector` + "`" + ` and ` + "`" + `Deployment.spec.template` + "`" + ` labels
match.
- e.g. MutatingWebHooks are scoped to a single Resource instance at a time.
- Low-level tweaks to the output of high-level abstractions
- e.g. add an ` + "`" + `init container` + "`" + ` to a client _"CRD"_ Resource after it was generated.
- Composition and layering of multiple functions together
- Compose generation, injection, validation together
## Spec
### Input Type
A function MUST accept as input a single [Kubernetes List type][3].
The ` + "`" + `items` + "`" + ` field in the input will contain a sequence of [Object types][3].
A function MAY not support [Simple types][3] and List types.
An example using ` + "`" + `v1/ConfigMapList` + "`" + ` as input:
apiVersion: v1
kind: ConfigMapList
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: config1
data:
p1: v1
p2: v2
- apiVersion: v1
kind: ConfigMap
metadata:
name: config2
An example using ` + "`" + `v1/List` + "`" + ` as input:
apiVersion: v1
kind: List
items:
spec:
- apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
address: "100 Main St."
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- resources:
- namespaces
apiGroups:
- ""
verbs:
- get
- watch
- list
In addition, a function MUST accept as input a List of kind ` + "`" + `ResourceList` + "`" + ` where the
` + "`" + `functionConfig` + "`" + ` field, if present, will contain the invocation-specific configuration passed to the function
by the orchestrator.
Functions MAY consider this field optional so that they can be triggered in an ad-hoc fashion.
An example using ` + "`" + `config.kubernetes.io/v1beta1/ResourceList` + "`" + ` as input:
apiVersion: config.kubernetes.io/v1beta1
kind: ResourceList
functionConfig:
apiVersion: foo-corp.com/v1
kind: FulfillmentCenter
metadata:
name: staging
metadata:
annotations:
config.k8s.io/function: |
container:
image: gcr.io/example/foo:v1.0.0
spec:
address: "100 Main St."
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- resources:
- namespaces
apiGroups:
- ""
verbs:
- get
- watch
- list
Here ` + "`" + `FulfillmentCenter` + "`" + ` kind with name ` + "`" + `staging` + "`" + ` is passed as the invocation-specific configuration
to the function.
### Output Type
A functions output MUST be the same as the input specification above
-- i.e. ` + "`" + `ResourceList` + "`" + ` or ` + "`" + `List` + "`" + `.
This is necessary to enable chaining two or more functions together in a pipeline.
The serialization format of the output SHOULD match that of its input on each invocation
-- e.g. if the input was a ` + "`" + `ResourceList` + "`" + `, the output should also be a ` + "`" + `ResourceList` + "`" + `.
### Serialization Format
A function MUST support YAML as a serialization format for the input and output.
A function MUST use utf8 encoding (as YAML is a superset of JSON, JSON will also be supported
by any conforming function).
### Operations
A function MAY Create, Update, or Delete any number of items in the ` + "`" + `items` + "`" + ` field and output the
resultant list.
A function MAY modify annotations with prefix ` + "`" + `config.kubernetes.io` + "`" + `, but must be careful about
doing so since theyre used for orchestration purposes and will likely impact subsequent functions
in the pipeline.
A function SHOULD preserve comments when input serialization format is YAML.
This allows for human authoring of configuration to coexist with changes made by functions.
### Containerization
A function MUST be implemented as a container.
A function container MUST be capable of running as a non-root user if it does not require
access to host filesystem or makes network calls.
### stdin/stdout/stderr and Exit Codes
A function MUST accept input from stdin and emit output to stdout.
Any error messages MUST be emitted to stderr.
An exit code of zero indicates function execution was successful.
A non-zero exit code indicates a failure.
[1]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[2]: https://tools.ietf.org/html/rfc2119
[3]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds`
var Merge2Long = `# Merge (2-way)
2-way merges fields from a source to a destination, overriding the destination fields

View File

@@ -49,6 +49,32 @@ var CountExamples = `
# print Resource counts from a directory
kustomize config count my-dir/`
var CreateSetterShort = `[Alpha] Create a custom setter for a Resource field`
var CreateSetterLong = `
Create a custom setter for a Resource field by inlining OpenAPI as comments.
DIR
A directory containing Resource configuration.
NAME
The name of the setter to create.
VALUE
The current value of the field, or a substring within the field.
`
var CreateSetterExamples = `
# create a setter for port fields matching "8080"
kustomize config create-setter DIR/ port 8080 --type "integer" --field port \
--description "default port used by the app"
# create a setter for a substring of a field rather than the full field -- e.g. only the
# image tag, not the full image
kustomize config create-setter DIR/ image-tag v1.0.1 --type "string" \
--field image --description "current stable release"`
var FmtShort = `[Alpha] Format yaml configuration files.`
var FmtLong = `
[Alpha] Format yaml configuration files.
@@ -116,6 +142,25 @@ var GrepExamples = `
# look for Resources matching a specific container image
kustomize config grep "spec.template.spec.containers[name=nginx].image=nginx:1\.7\.9" my-dir/ | kustomize config tree`
var ListSettersShort = `[Alpha] List setters for Resources.`
var ListSettersLong = `
List setters for Resources.
DIR
A directory containing Resource configuration.
NAME
Optional. The name of the setter to display.
`
var ListSettersExamples = `
Show setters:
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2`
var MergeShort = `[Alpha] Merge Resource configuration files`
var MergeLong = `
[Alpha] Merge Resource configuration files
@@ -136,6 +181,25 @@ For information on merge rules, run:
var MergeExamples = `
cat resources_and_patches.yaml | kustomize config merge > merged_resources.yaml`
var Merge3Short = `[Alpha] Merge diff of Resource configuration files into a destination (3-way)`
var Merge3Long = `
[Alpha] Merge diff of Resource configuration files into a destination (3-way)
Merge3 performs a 3-way merge by applying the diff between 2 sets of Resources to a 3rd set.
Merge3 may be for rebasing changes to a forked set of configuration -- e.g. compute the difference between the original
set of Resources that was forked and an updated set of those Resources, then apply that difference to the fork.
If a field value differs between the ORIGINAL_DIR and UPDATED_DIR, the value from the UPDATED_DIR is taken and applied
to the Resource in the DEST_DIR.
For information on merge rules, run:
kustomize config docs-merge3
`
var Merge3Examples = `
kustomize config merge3 --ancestor a/ --from b/ --to c/`
var RunFnsShort = `[Alpha] Reoncile config functions to Resources.`
var RunFnsLong = `
[Alpha] Reconcile config functions to Resources.
@@ -156,8 +220,8 @@ order they appear in the file).
#### Config Functions:
Config functions are specified as Kubernetes types containing a metadata.configFn.container.image
field. This field tells run how to invoke the container.
Config functions are specified as Kubernetes types containing a metadata.annotations.[config.k8s.io/function]
field specifying an image for the container to run. This image tells run how to invoke the container.
Example config function:
@@ -165,17 +229,17 @@ order they appear in the file).
apiVersion: fn.example.com/v1beta1
kind: ExampleFunctionKind
metadata:
configFn:
container:
# function is invoked as a container running this image
image: gcr.io/example/examplefunction:v1.0.1
annotations:
config.k8s.io/function: |
container:
# function is invoked as a container running this image
image: gcr.io/example/examplefunction:v1.0.1
config.kubernetes.io/local-config: "true" # tools should ignore this
spec:
configField: configValue
In the preceding example, 'kustomize config run example/' would identify the function by
the metadata.configFn field. It would then write all Resources in the directory to
the metadata.annotations.[config.k8s.io/function] field. It would then write all Resources in the directory to
a container stdin (running the gcr.io/example/examplefunction:v1.0.1 image). It
would then write the container stdout back to example/, replacing the directory
file contents.
@@ -185,17 +249,18 @@ order they appear in the file).
var RunFnsExamples = `
kustomize config run example/`
var SubShort = `[Alpha] Set values on Resources fields by substituting values.`
var SubLong = `
Set values on Resources fields by substituting predefined markers for new values.
var SetShort = `[Alpha] Set values on Resources fields values.`
var SetLong = `
Set values on Resources fields. May set either the complete or partial field value.
` + "`" + `set` + "`" + ` looks for markers specified on Resource fields and substitute a new user defined
value for the existing value.
` + "`" + `set` + "`" + ` identifies setters using field metadata published as OpenAPI extensions.
` + "`" + `set` + "`" + ` parses both the Kubernetes OpenAPI, as well OpenAPI published inline in
the configuration as comments.
` + "`" + `set` + "`" + ` maybe be used to:
- edit configuration programmatically from the cli or scripts
- create reusable bundles of configuration
- edit configuration programmatically from the cli
- create reusable bundles of configuration with custom setters
DIR
@@ -203,244 +268,69 @@ value for the existing value.
NAME
Optional. The name of the substitution to perform or display.
Optional. The name of the setter to perform or display.
VALUE
Optional. The new value to substitute into the field.
Optional. The value to set on the field.
To print the possible substitutions for the Resources in a directory, run ` + "`" + `set` + "`" + ` on
To print the possible setters for the Resources in a directory, run ` + "`" + `set` + "`" + ` on
a directory -- e.g. ` + "`" + `kustomize config set DIR/` + "`" + `.
#### Tips
- A description of the value may be specified with ` + "`" + `--description` + "`" + `.
- An owner for the field's value may be defined with ` + "`" + `--owned-by` + "`" + `.
- Prevent overriding previous substitutions with ` + "`" + `--override=false` + "`" + `.
- Revert previous substitutions with ` + "`" + `--revert` + "`" + `.
- Create substitutions on Kustomization.yaml's, patches, etc
- The last setter for the field's value may be defined with ` + "`" + `--set-by` + "`" + `.
- Create custom setters on Resources, Kustomization.yaml's, patches, etc
When overriding or reverting previous substitutions, the description and owner are left
unmodified unless specified with flags.
The description and setBy fields are left unmodified unless specified with flags.
To create a substitution for a field see: ` + "`" + `kustomize help config set create` + "`" + `
To create a custom setter for a field see: ` + "`" + `kustomize help config create-setter` + "`" + `
`
var SubExamples = `
Resource YAML: Name substitution
var SetExamples = `
Resource YAML: Name Prefix Setter
# dir/resources.yaml
# DIR/resources.yaml
...
metadata:
name: PREFIX-app1 # {"substitutions":[{"name":"prefix","marker":"PREFIX-"}]}
name: PREFIX-app1 # {"type":"string","x-kustomize":{"partialFieldSetters":[{"name":"name-prefix","value":"PREFIX"}]}}
...
---
...
metadata:
name: PREFIX-app2 # {"substitutions":[{"name":"prefix","marker":"PREFIX-"}]}
name: PREFIX-app2 # {"type":"string","x-kustomize":{"partialFieldSetters":[{"name":"name-prefix","value":"PREFIX"}]}}
...
Show substitutions: Show the possible substitutions
List setters: Show the possible setters
$ config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix '' PREFIX- string 2 false
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix '' PREFIX string 2
Perform substitution: set a new value, owner and description
Perform set: set a new value, owner and description
$ config set dir prefix "test-" --description "test environment" --owned-by "dev"
performed 2 substitutions
$ kustomize config set DIR/ name-prefix "test" --description "test environment" --set-by "dev"
set 2 values
Show substitutions: Show the new values
List setters: Show the new values
$ config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix 'test environment' test- string 2 true dev
$ config set DIR/
NAME DESCRIPTION VALUE TYPE COUNT SETBY
name-prefix 'test environment' test string 2 dev
New Resource YAML:
# dir/resources.yaml
# DIR/resources.yaml
...
metadata:
name: test-app1 # {"substitutions":[{"name":"prefix","marker":"PREFIX-","value":"test-"}],"setBy":"dev","description":"test environment"}
name: test-app1 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
...
---
...
metadata:
name: test-app2 # {"substitutions":[{"name":"prefix","marker":"PREFIX-","value":"test-"}],"setBy":"dev","description":"test environment"}
...
Revert substitution:
config set dir prefix --revert
performed 2 substitutions
config set dir
NAME DESCRIPTION VALUE TYPE COUNT SUBSTITUTED OWNER
prefix 'test environment' PREFIX- string 2 false dev `
var SubsetShort = `[Alpha] Create a new substitution for a Resource field`
var SubsetLong = `
Create a new substitution for a Resource field -- recognized by ` + "`" + `kustomize config set` + "`" + `.
DIR
A directory containing Resource configuration.
NAME
The name of the substitution to create.
VALUE
The current value of the field, or a substring of the field.
#### Tips: Picking Good Marker
Substitutions may be defined by directly editing yaml **or** by running ` + "`" + `kustomize config set create` + "`" + `
to create a new substitution.
Given the YAML:
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080
...
Create a new set marker:
# create a substitution for ports
$ kustomize config set create dir/ http-port 8080 --type "int" --field "port"
Modified YAML:
# resource.yaml
apiVersion: v1
kind: Service
metadata:
...
spec:
...
ports:
...
- name: http
port: 8080 # {"substitutions":[{"name":"port","marker":"[MARKER]"}],"type":"int"}
...
Change the value using the ` + "`" + `set` + "`" + ` command:
# change the http-port value to 8081
$ kustomize config set dir/ http-port 8081
Resources fields with a field name matching ` + "`" + `--field` + "`" + ` and field value matching ` + "`" + `VALUE` + "`" + ` will
have a line comment added marking this field as settable.
Substitution markers may be:
- valid field values (e.g. ` + "`" + `8080` + "`" + ` for a port)
- Note: ` + "`" + `008080` + "`" + ` would be preferred because it is more recognizable as a marker
- invalid values that adhere to the schema (e.g. ` + "`" + `0000` + "`" + ` for a port)
- values that do not adhere to the schema (e.g. ` + "`" + `[PORT]` + "`" + ` for port)
Markers **SHOULD be clearly identifiable as a marker and either**:
- **adhere to the field schema** -- e.g. use a valid value
port: 008080 # {"substitutions":[{"name":"port","marker":"008080"}],"type":"int"}
- **be pre-filled in with a value** -- e.g. set the value when setting the marker
port: 8080 # {"substitutions":[{"name":"port","marker":"[MARKER]","value":"8080""}],"type":"int"}
**Note:** The important thing is that in both cases the Resource configuration may be directly
applied to a cluster and validated by tools without the tool knowing about the substitution
marker.
The difference between the preceding examples is that:
- the former will be shown as ` + "`" + `SUBSTITUTED=false` + "`" + ` (` + "`" + `config sub dir/` + "`" + ` exits non-0)
- the latter with show up as ` + "`" + `SUBSTITUTED=true` + "`" + ` (` + "`" + `config sub dir/` + "`" + ` exits 0)
When choosing the which to use, consider that checks for unsubstituted values MAY be
configured as pre-commit checks -- if you want to these checks to fail if the value
hasn't been substituted, then don't specify a ` + "`" + `value` + "`" + `.
Markers which are invalid field values MAY be chosen in cases where it is preferred to have
the create or update request fail rather than succeed if the substitution has not yet been
performed.
A substitution may be a substring of the full field:
$ kustomize config set create dir/ app-image-tag v1.0.01 --type "string" --field "image"
image: gcr.io/example/app:v1.0.1 # {"substitutions":[{"name":"app-image-tag","marker":"[MARKER]","value":"v1.0.1"}]}
A single field value may have multiple substitutions applied to it:
name: PREFIX-app-SUFFIX # {"substitutions":[{"name":"prefix","marker":"PREFIX-"},{"name":"suffix","marker":"-SUFFIX"}]}
#### Substitution Format
Substitutions are defined as json encoded FieldMeta comments on fields.
FieldMeta Schema read by ` + "`" + `sub` + "`" + `:
{
"title": "FieldMeta",
"type": "object",
"properties": {
"substitutions": {
"type": "array",
"description": "Possible substitutions that may be performed against this field.",
"items": {
"type": "object",
"properties": {
"name": "Name of the substitution.",
"marker": "Marker for the value to be substituted.",
"value": "Current substituted value"
}
}
},
"type": {
"type": "string",
"description": "The value type. Defaults to string."
"enum": ["string", "int", "float", "bool"]
},
"description": {
"type": "string",
"description": "A description of the field's current value. Optional."
},
"setBy": {
"type": "string",
"description": "The current owner of the field. Optional."
},
}
}
`
var SubsetExamples = `
# set a substitution for port fields matching "8080"
kustomize config sub create dir/ port 8080 --type "int" --field port \
--description "default port used by the app"
# set a substitution for port fields matching "8080", using "0000" as a marker.
kustomize config sub dir/ port 8080 --marker "0000" --type "int" \
--field port --description "default port used by the app"
# substitute a substring of a field rather than the full field -- e.g. only the
# image tag, not the full image
kustomize config sub dir/ app-image-tag v1.0.1 --type "string" --substring \
--field port --description "current stable release"`
name: test-app2 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
...`
var TreeShort = `[Alpha] Display Resource structure from a directory or stdin.`
var TreeLong = `

View File

@@ -85,6 +85,8 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc=
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/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=

View File

@@ -15,7 +15,7 @@ linters:
- dogsled
- dupl
- errcheck
- funlen
# - funlen
# - gochecknoinits
- goconst
- gocritic

View File

@@ -17,8 +17,8 @@ fmt:
go fmt ./...
generate:
#(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/resource)
#GOBIN=$(GOBIN) go generate ./...
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
GOBIN=$(GOBIN) go generate ./...
license:
(which $(GOBIN)/addlicense || go get github.com/google/addlicense)

View File

@@ -3,9 +3,12 @@ module sigs.k8s.io/kustomize/cmd/resource
go 1.12
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/pkg/errors v0.8.1
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f
k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90
sigs.k8s.io/controller-runtime v0.4.0

View File

@@ -18,6 +18,8 @@ github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
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=
@@ -74,6 +76,7 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+
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/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
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=
@@ -88,6 +91,7 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA
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.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=
@@ -95,6 +99,7 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
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/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/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@@ -167,6 +172,7 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
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/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
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=
@@ -280,6 +286,7 @@ golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -344,8 +351,10 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
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=

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package main
import (

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
@@ -6,23 +9,29 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/resource/status/generateddocs/commands"
"sigs.k8s.io/kustomize/kstatus/wait"
"sigs.k8s.io/kustomize/kyaml/kio"
)
// GetEventsRunner returns a command EventsRunner.
func GetEventsRunner() *EventsRunner {
r := &EventsRunner{}
r := &EventsRunner{
createClientFunc: createClient,
}
c := &cobra.Command{
Use: "events",
Short: "Events",
RunE: r.runE,
Use: "events DIR...",
Short: commands.EventsShort,
Long: commands.EventsLong,
Example: commands.EventsExamples,
RunE: r.runE,
}
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
"also print resources from subpackages.")
c.Flags().DurationVar(&r.Interval, "interval", 2*time.Second,
"check every n seconds. Default is every 2 seconds.")
"check every n seconds.")
c.Flags().DurationVar(&r.Timeout, "timeout", 60*time.Second,
"give up after n seconds. Default is 60 seconds.")
"give up after n seconds.")
r.Command = c
return r
@@ -32,22 +41,30 @@ func EventsCommand() *cobra.Command {
return GetEventsRunner().Command
}
// EventsRunner captures the parameters for the command
// and contains the run function.
type EventsRunner struct {
IncludeSubpackages bool
Interval time.Duration
Timeout time.Duration
Command *cobra.Command
createClientFunc createClientFunc
}
func (r *EventsRunner) runE(c *cobra.Command, args []string) error {
ctx := context.Background()
client, err := getClient()
// Create a client and use it to set up a new resolver.
client, err := r.createClientFunc()
if err != nil {
return errors.Wrap(err, "error creating client")
}
resolver := wait.NewResolver(client, r.Interval)
// Set up a CaptureIdentifierFilter and run all inputs through the
// filter with the pipeline to capture the inventory of resources
// which we are interested in.
captureFilter := &CaptureIdentifiersFilter{}
filters := []kio.Filter{captureFilter}
@@ -70,12 +87,17 @@ func (r *EventsRunner) runE(c *cobra.Command, args []string) error {
return errors.Wrap(err, "error reading manifests")
}
// Create a new printer that knows how to print updates about
// resourdes and their aggregate status in the events format.
printer := newEventPrinter(c.OutOrStdout(), c.OutOrStderr())
ctx, cancel := context.WithTimeout(ctx, r.Timeout)
defer cancel()
resChannel := resolver.WaitForStatus(ctx, captureFilter.Identifiers)
// Print events until the channel is closed. This will happen
// either because all resources has reached the Current status
// or it has timed out.
for msg := range resChannel {
printer.printEvent(msg)
}

View File

@@ -0,0 +1,298 @@
package cmd
import (
"bytes"
"fmt"
"reflect"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kstatus/status"
"sigs.k8s.io/kustomize/kstatus/wait"
)
func TestEventsNoResources(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
fakeClient := &FakeClient{}
r := GetEventsRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err := r.Command.Execute()
if !assert.NoError(t, err) {
return
}
eventOutput := parseEventOutput(t, outBuffer.String())
if want, got := 1, len(eventOutput.events); want != got {
t.Errorf("expected %d events, but got %d", want, got)
}
event := eventOutput.events[0]
if want, got := status.CurrentStatus, event.aggStatus; want != got {
t.Errorf("expected agg status %s, but got %s", want, got)
}
}
func TestEventsMultipleUpdates(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
_, err := fmt.Fprint(inBuffer, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: bar
namespace: default
`)
if !assert.NoError(t, err) {
return
}
fakeClient := &FakeClient{
resourceCallbackMap: map[string]ResourceGetCallback{
"Deployment": createDeploymentStatusFunc(),
},
}
r := GetEventsRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
eventOutput := parseEventOutput(t, outBuffer.String())
aggStatuses := eventOutput.allAggStatuses()
expectedAggStatuses := []status.Status{
status.InProgressStatus,
status.InProgressStatus,
status.InProgressStatus,
status.InProgressStatus,
status.CurrentStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(aggStatuses, expectedAggStatuses) {
t.Errorf("expected agg statuses to be %s, but got %s", joinStatuses(expectedAggStatuses),
joinStatuses(aggStatuses))
}
resources := eventOutput.allResources()
if want, got := 1, len(resources); want != got {
t.Errorf("expected %d resource, but got %d", want, got)
}
resource := resources[0]
resourceStatuses := eventOutput.statusesForResource(resource)
expectedResourceStatuses := []status.Status{
status.InProgressStatus,
status.InProgressStatus,
status.InProgressStatus,
status.InProgressStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(resourceStatuses, expectedResourceStatuses) {
t.Errorf("expected statuses to be %s, but got %s", joinStatuses(expectedResourceStatuses),
joinStatuses(resourceStatuses))
}
}
func TestEventsMultipleResources(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
_, err := fmt.Fprint(inBuffer, `
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: default
- apiVersion: v1
kind: Service
metadata:
name: bar
namespace: default
`)
if !assert.NoError(t, err) {
return
}
fakeClient := &FakeClient{
resourceCallbackMap: map[string]ResourceGetCallback{
"Pod": createPodStatusFunc(),
"Service": createServiceStatusFunc(),
},
}
r := GetEventsRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
eventOutput := parseEventOutput(t, outBuffer.String())
aggStatuses := eventOutput.allAggStatuses()
expectedAggStatuses := []status.Status{
status.UnknownStatus,
status.CurrentStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(aggStatuses, expectedAggStatuses) {
t.Errorf("expected agg statuses to be %s, but got %s", joinStatuses(expectedAggStatuses),
joinStatuses(aggStatuses))
}
resources := eventOutput.allResources()
if want, got := 2, len(resources); got != want {
t.Errorf("expected %d resource, but got %d", want, got)
}
for _, resource := range resources {
resourceStatuses := eventOutput.statusesForResource(resource)
if want, got := status.CurrentStatus, resourceStatuses[len(resourceStatuses)-1]; want != got {
t.Errorf("expected resource %q to have final status %s, but got %s", resource.name, want, got)
}
}
}
type EventOutput struct {
events []EventOutputLine
unknownLines []string
}
func (e *EventOutput) allAggStatuses() []status.Status {
var aggStatuses []status.Status
for _, event := range e.events {
aggStatuses = append(aggStatuses, event.aggStatus)
}
return aggStatuses
}
func (e *EventOutput) allResources() []ResourceIdentifier {
var resources []ResourceIdentifier
seenResources := make(map[ResourceIdentifier]bool)
for _, event := range e.events {
if !event.isResourceUpdateEvent() {
continue
}
r := event.identifier
if _, found := seenResources[r]; !found {
resources = append(resources, r)
seenResources[r] = true
}
}
return resources
}
func (e *EventOutput) statusesForResource(resource ResourceIdentifier) []status.Status {
var statuses []status.Status
for _, event := range e.events {
if !event.isResourceUpdateEvent() {
continue
}
if event.identifier.Equals(resource) {
statuses = append(statuses, event.status)
}
}
return statuses
}
type EventOutputLine struct {
eventType string
aggStatus status.Status
identifier ResourceIdentifier
status status.Status
message string
}
func (e *EventOutputLine) isResourceUpdateEvent() bool {
return e.eventType == string(wait.ResourceUpdate)
}
var (
eventRegex = regexp.MustCompile(`^\s*` +
`(?P<eventType>\S+)\s+` +
`(?P<aggStatus>\S+)\s+` +
`((?P<resourceType>\S+)\s+` +
`(?P<namespace>\S+)\s+` +
`(?P<name>\S+)\s+` +
`(?P<status>\S+)\s+` +
`(?P<message>.*\S)){0,1}` +
`\s*$`)
eventHeaderRegex = regexp.MustCompile(`^\s*` +
`EVENT TYPE\s+` +
`AGG STATUS\s+` +
`TYPE\s+` +
`NAMESPACE\s+` +
`NAME\s+` +
`STATUS\s+` +
`MESSAGE` +
`\s*$`)
)
func parseEventOutput(_ *testing.T, output string) EventOutput {
var eventOutput EventOutput
lines := strings.Split(output, "\n")
for _, line := range lines {
if len(line) == 0 {
continue // Ignore empty lines
}
match := eventHeaderRegex.FindStringSubmatch(line)
if match != nil {
continue // Ignore headers
}
match = eventRegex.FindStringSubmatch(line)
if match == nil {
eventOutput.unknownLines = append(eventOutput.unknownLines, line)
continue
}
eventOutputLine := EventOutputLine{
eventType: match[1],
aggStatus: status.FromStringOrDie(match[2]),
}
if eventOutputLine.eventType == string(wait.ResourceUpdate) {
resourceType := match[4]
parts := strings.Split(resourceType, "/")
var identifier ResourceIdentifier
if len(parts) == 2 {
identifier.apiVersion = parts[0]
identifier.kind = parts[1]
} else {
identifier.apiVersion = strings.Join(parts[:2], "/")
identifier.kind = parts[2]
}
identifier.namespace = match[5]
identifier.name = match[6]
eventOutputLine.identifier = identifier
eventOutputLine.status = status.FromStringOrDie(match[7])
eventOutputLine.message = match[8]
}
eventOutput.events = append(eventOutput.events, eventOutputLine)
}
return eventOutput
}

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
@@ -6,17 +9,23 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/resource/status/generateddocs/commands"
"sigs.k8s.io/kustomize/kstatus/status"
"sigs.k8s.io/kustomize/kstatus/wait"
"sigs.k8s.io/kustomize/kyaml/kio"
)
// GetFetchRunner returns a command FetchRunner.
func GetFetchRunner() *FetchRunner {
r := &FetchRunner{}
r := &FetchRunner{
createClientFunc: createClient,
}
c := &cobra.Command{
Use: "fetch",
Short: "Fetch",
RunE: r.runE,
Use: "fetch DIR...",
Short: commands.FetchShort,
Long: commands.FetchLong,
Example: commands.FetchExamples,
RunE: r.runE,
}
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
"also print resources from subpackages.")
@@ -29,20 +38,29 @@ func FetchCommand() *cobra.Command {
return GetFetchRunner().Command
}
// FetchRunner captures the parameters for the command and contains
// the run function.
type FetchRunner struct {
IncludeSubpackages bool
Command *cobra.Command
createClientFunc createClientFunc
}
func (r *FetchRunner) runE(c *cobra.Command, args []string) error {
ctx := context.Background()
client, err := getClient()
// Create a new client and use it to set up a resolver.
k8sClient, err := r.createClientFunc()
if err != nil {
return errors.Wrap(err, "error creating client")
return errors.Wrap(err, "error creating k8sClient")
}
resolver := wait.NewResolver(client, time.Minute)
resolver := wait.NewResolver(k8sClient, time.Minute)
// Set up a CaptureIdentifierFilter and run all inputs through the
// filter with the pipeline to capture the inventory of resources
// which we are interested in.
captureFilter := &CaptureIdentifiersFilter{}
filters := []kio.Filter{captureFilter}
@@ -65,16 +83,27 @@ func (r *FetchRunner) runE(c *cobra.Command, args []string) error {
return errors.Wrap(err, "error reading manifests")
}
// Pass in the inventory of resources to the FetchAndResolve function
// on the resolver. It will return the status (or an error) for each
// resource in the inventory.
results := resolver.FetchAndResolve(ctx, captureFilter.Identifiers)
// Create new printer that knows how to print resource statuses
// in a table format and ask it to print the results.
newTablePrinter(FetchStatusInfo{results}, c.OutOrStdout(), c.OutOrStderr(), false).Print()
return nil
}
// FetchStatusInfo wraps the results from the FetchAndResolve function
// to the format expected in the TablePrinter.
type FetchStatusInfo struct {
Results []wait.ResourceResult
}
// CurrentStatus returns the latest information known about the
// status of each of the resources. For FetchStatusInfo, the result
// is never updated, so it just returns the information provided
// by the slice of wait.ResourceResult at creation.
func (f FetchStatusInfo) CurrentStatus() StatusData {
var resourceData []ResourceStatusData
for _, res := range f.Results {

View File

@@ -0,0 +1,230 @@
package cmd
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/acarl005/stripansi"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/kustomize/kstatus/status"
)
func TestEmptyManifest(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
fakeClient := fake.NewFakeClientWithScheme(scheme)
r := GetFetchRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err := r.Command.Execute()
if !assert.NoError(t, err) {
return
}
output := outBuffer.String()
lines := strings.Split(output, "\n")
if want, got := 2, len(lines); want != got {
t.Errorf("Expected %d lines, but got %d", want, got)
}
}
func TestFetchStatusFromManifestStdIn(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
_, err := fmt.Fprint(inBuffer, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: bar
namespace: default
`)
if !assert.NoError(t, err) {
return
}
deployment := createDeployment("bar", "default", 42, appsv1.DeploymentStatus{
ObservedGeneration: 1,
})
fakeClient := fake.NewFakeClientWithScheme(scheme, deployment)
r := GetFetchRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
cleanOutput := stripansi.Strip(outBuffer.String())
tableOutput := parseTableOutput(t, cleanOutput)
expectedResource := ResourceIdentifier{
apiVersion: "apps/v1",
kind: "Deployment",
namespace: "default",
name: "bar",
}
expectedStatus := status.InProgressStatus
expectedMessage := "Deployment generation is 2, but latest observed generation is 1"
verifyOutputContains(t, tableOutput, expectedResource, expectedStatus, expectedMessage)
}
//nolint:funlen
func TestFetchStatusFromManifestsFiles(t *testing.T) {
d, err := ioutil.TempDir("", "status-fetch-test")
if !assert.NoError(t, err) {
return
}
defer os.RemoveAll(d)
err = ioutil.WriteFile(filepath.Join(d, "dep.yaml"), []byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo
namespace: default
`), 0600)
if !assert.NoError(t, err) {
return
}
err = ioutil.WriteFile(filepath.Join(d, "svc.yaml"), []byte(`
apiVersion: v1
kind: Service
metadata:
name: foo
namespace: default
`), 0600)
if !assert.NoError(t, err) {
return
}
replicas := int32(42)
deployment := createDeployment("foo", "default", replicas, appsv1.DeploymentStatus{
ObservedGeneration: 2,
Replicas: replicas,
ReadyReplicas: replicas,
AvailableReplicas: replicas,
UpdatedReplicas: replicas,
Conditions: []appsv1.DeploymentCondition{
{
Type: appsv1.DeploymentAvailable,
Status: v1.ConditionTrue,
},
},
})
service := createService("foo", "default")
fakeClient := fake.NewFakeClientWithScheme(scheme, deployment, service)
outBuffer := &bytes.Buffer{}
r := GetFetchRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{d})
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
cleanOutput := stripansi.Strip(outBuffer.String())
tableOutput := parseTableOutput(t, cleanOutput)
expectedDeploymentResource := ResourceIdentifier{
apiVersion: "apps/v1",
kind: "Deployment",
namespace: "default",
name: "foo",
}
expectedDeploymentStatus := status.CurrentStatus
expectedDeploymentMessage := "Deployment is available. Replicas: 42"
verifyOutputContains(t, tableOutput, expectedDeploymentResource, expectedDeploymentStatus, expectedDeploymentMessage)
expectedServiceResource := ResourceIdentifier{
apiVersion: "v1",
kind: "Service",
namespace: "default",
name: "foo",
}
expectedServiceStatus := status.CurrentStatus
expectedServiceMessage := "Service is ready"
verifyOutputContains(t, tableOutput, expectedServiceResource, expectedServiceStatus, expectedServiceMessage)
}
func createDeployment(name, namespace string, replicas int32, status appsv1.DeploymentStatus) *appsv1.Deployment {
return &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Generation: 2,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
},
Status: status,
}
}
func createService(name, namespace string) *v1.Service {
return &v1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}
}
func verifyOutputContains(t *testing.T, tableOutput TableOutput, resource ResourceIdentifier, status status.Status, message string) {
if len(tableOutput.Frames) == 0 {
t.Fatalf("expected match for resource %s, but output had no frames", resource.name)
}
firstFrame := tableOutput.Frames[0]
var foundResource ResourceOutput
match := false
for _, resourceOutput := range firstFrame.Resources {
if resourceOutput.identifier.Equals(resource) {
foundResource = resourceOutput
match = true
break
}
}
if !match {
t.Errorf("expected match for resource %s, but didn't find it", resource.name)
}
if want, got := status, foundResource.status; want != got {
t.Errorf("expected status %s for resource %s, but got %s", want, resource.name, got)
}
if want, got := message, foundResource.message; !strings.HasPrefix(want, got) {
t.Errorf("expected message %s for resource %s, but got %s", want, resource.name, got)
}
}

View File

@@ -0,0 +1,245 @@
package cmd
import (
"context"
"fmt"
"regexp"
"strings"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/kustomize/kstatus/status"
)
type TableOutput struct {
Frames []TableOutputFrame
UnknownRows []string
}
func (t *TableOutput) allAggStatuses() []status.Status {
var statuses []status.Status
for _, frame := range t.Frames {
if frame.AggregateStatus != "" {
statuses = append(statuses, frame.AggregateStatus)
}
}
return statuses
}
func (t *TableOutput) dedupedAggStatuses() []status.Status {
var dedupedStatuses []status.Status
statuses := t.allAggStatuses()
var previousStatus status.Status
for _, s := range statuses {
if s != previousStatus {
dedupedStatuses = append(dedupedStatuses, s)
previousStatus = s
}
}
return dedupedStatuses
}
func (t *TableOutput) resources() []ResourceIdentifier {
seenResources := make(map[ResourceIdentifier]bool)
var resources []ResourceIdentifier
for _, frame := range t.Frames {
for _, resource := range frame.Resources {
r := resource.identifier
_, found := seenResources[r]
if !found {
seenResources[r] = true
resources = append(resources, r)
}
}
}
return resources
}
func (t *TableOutput) dedupedStatusesForResource(resource ResourceIdentifier) []status.Status {
var dedupedStatuses []status.Status
var previousStatus status.Status
for _, frame := range t.Frames {
for _, r := range frame.Resources {
if r.identifier.Equals(resource) {
if r.status != previousStatus {
previousStatus = r.status
dedupedStatuses = append(dedupedStatuses, r.status)
}
}
}
}
return dedupedStatuses
}
type TableOutputFrame struct {
AggregateStatus status.Status
Resources []ResourceOutput
}
type ResourceIdentifier struct {
apiVersion string
kind string
name string
namespace string
}
func (r ResourceIdentifier) Equals(identifier ResourceIdentifier) bool {
return r.apiVersion == identifier.apiVersion &&
r.kind == identifier.kind &&
r.namespace == identifier.namespace &&
r.name == identifier.name
}
type ResourceOutput struct {
identifier ResourceIdentifier
status status.Status
message string
}
var (
headerRegex = regexp.MustCompile(`^\s*TYPE\s+NAMESPACE\s+NAME\s+STATUS\s+MESSAGE\s*$`)
resourceRegex = regexp.MustCompile(`^(?P<resourceType>\S+)\s+(?P<namespace>\S+)\s+(?P<name>\S+)\s+(?P<status>\S+)\s+(?P<message>.*\S)\s*$`)
aggStatusRegex = regexp.MustCompile(`^\s*AggregateStatus: (?P<aggregateStatus>\S+)\s*$`)
)
func parseTableOutput(_ *testing.T, output string) TableOutput {
tableOutput := TableOutput{}
lines := strings.Split(output, "\n")
hasAggStatus := false
var currentFrame TableOutputFrame
for i, line := range lines {
if len(line) == 0 {
continue // We don't care about empty lines.
}
// Check for lines with aggregate status. They are not always present, but if they are,
// they always start a new frame of output.
match := aggStatusRegex.FindStringSubmatch(line)
if match != nil {
hasAggStatus = true
if i != 0 {
tableOutput.Frames = append(tableOutput.Frames, currentFrame)
}
currentFrame = TableOutputFrame{
AggregateStatus: status.FromStringOrDie(match[1]),
}
continue
}
match = headerRegex.FindStringSubmatch(line)
if match != nil {
if !hasAggStatus {
if i != 0 {
tableOutput.Frames = append(tableOutput.Frames, currentFrame)
}
currentFrame = TableOutputFrame{}
}
continue
}
match = resourceRegex.FindStringSubmatch(line)
if match != nil {
var identifier ResourceIdentifier
resourceType := match[1]
parts := strings.Split(resourceType, "/")
if len(parts) == 2 {
identifier.apiVersion = parts[0]
identifier.kind = parts[1]
} else {
identifier.apiVersion = strings.Join(parts[:2], "/")
identifier.kind = parts[2]
}
identifier.namespace = match[2]
identifier.name = match[3]
res := ResourceOutput{
identifier: identifier,
}
res.status = status.FromStringOrDie(match[4])
res.message = match[5]
currentFrame.Resources = append(currentFrame.Resources, res)
continue
}
tableOutput.UnknownRows = append(tableOutput.UnknownRows, line)
}
tableOutput.Frames = append(tableOutput.Frames, currentFrame)
return tableOutput
}
func createDeploymentStatusFunc() func(*unstructured.Unstructured) error {
metadataMap := map[string]interface{}{
"generation": int64(2),
}
specMap := map[string]interface{}{
"replicas": int64(2),
}
statusMap := map[string]interface{}{
"observedGeneration": int64(2),
"replicas": int64(4),
"updatedReplicas": int64(4),
"readyReplicas": int64(4),
}
var conditions = make([]interface{}, 0)
conditions = append(conditions, map[string]interface{}{
"type": "Available",
"status": "True",
})
callbackCount := int64(0)
return func(deployment *unstructured.Unstructured) error {
_ = unstructured.SetNestedMap(deployment.Object, metadataMap, "metadata")
_ = unstructured.SetNestedMap(deployment.Object, specMap, "spec")
statusMap["availableReplicas"] = callbackCount
_ = unstructured.SetNestedMap(deployment.Object, statusMap, "status")
_ = unstructured.SetNestedSlice(deployment.Object, conditions, "status", "conditions")
callbackCount++
return nil
}
}
func createServiceStatusFunc() func(*unstructured.Unstructured) error {
return func(*unstructured.Unstructured) error {
return nil
}
}
func createPodStatusFunc() func(*unstructured.Unstructured) error {
statusMap := map[string]interface{}{
"phase": "Succeeded",
}
return func(pod *unstructured.Unstructured) error {
_ = unstructured.SetNestedMap(pod.Object, statusMap, "status")
return nil
}
}
type ResourceGetCallback func(resource *unstructured.Unstructured) error
type FakeClient struct {
resourceCallbackMap map[string]ResourceGetCallback
}
func (f *FakeClient) Get(_ context.Context, _ client.ObjectKey, obj runtime.Object) error {
kind := obj.GetObjectKind().GroupVersionKind().Kind
callbackFunc, found := f.resourceCallbackMap[kind]
if !found {
return fmt.Errorf("no callback func found for kind %s", kind)
}
u := obj.(*unstructured.Unstructured)
return callbackFunc(u)
}
func (f *FakeClient) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
return nil
}
func joinStatuses(statuses []status.Status) string {
var stringStatuses []string
for _, s := range statuses {
stringStatuses = append(stringStatuses, s.String())
}
return strings.Join(stringStatuses, ",")
}

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
@@ -176,10 +179,13 @@ func (s *TablePrinter) printTable(data StatusData, deleteUp bool) {
}
func (s *TablePrinter) printTableRow(rowData []RowData) {
for _, row := range rowData {
for i, row := range rowData {
setColor(s.out, row.color)
format := fmt.Sprintf("%%-%ds ", row.width)
format := fmt.Sprintf("%%-%ds", row.width)
printOrDie(s.out, format, trimString(row.content, row.width))
if i != len(rowData)-1 {
printOrDie(s.out, " ")
}
setColor(s.out, WHITE)
}
printOrDie(s.out, "\n")

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
@@ -19,7 +22,11 @@ func init() {
_ = clientgoscheme.AddToScheme(scheme)
}
func getClient() (client.Client, error) {
type createClientFunc func() (client.Reader, error)
// createClient returns a client for talking to a Kubernetes cluster. The client
// is from controller-runtime.
func createClient() (client.Reader, error) {
config := ctrl.GetConfigOrDie()
mapper, err := apiutil.NewDiscoveryRESTMapper(config)
if err != nil {
@@ -28,6 +35,14 @@ func getClient() (client.Client, error) {
return client.New(config, client.Options{Scheme: scheme, Mapper: mapper})
}
func newClientFunc(c client.Reader) func() (client.Reader, error) {
return func() (client.Reader, error) {
return c, nil
}
}
// CaptureIdentifiersFilter implements the Filter interface in the kio package. It
// captures the identifiers for all resources passed through the pipeline.
type CaptureIdentifiersFilter struct {
Identifiers []wait.ResourceIdentifier
}

View File

@@ -1,3 +1,6 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
@@ -7,18 +10,23 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/resource/status/generateddocs/commands"
"sigs.k8s.io/kustomize/kstatus/status"
"sigs.k8s.io/kustomize/kstatus/wait"
"sigs.k8s.io/kustomize/kyaml/kio"
)
// GetWaitRunner return a command WaitRunner.
func GetWaitRunner() *WaitRunner {
r := &WaitRunner{}
r := &WaitRunner{
createClientFunc: createClient,
}
c := &cobra.Command{
Use: "wait",
Short: "Wait",
RunE: r.runE,
Use: "wait DIR...",
Short: commands.WaitShort,
Long: commands.WaitLong,
Example: commands.WaitExamples,
RunE: r.runE,
}
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
"also print resources from subpackages.")
@@ -35,16 +43,23 @@ func WaitCommand() *cobra.Command {
return GetWaitRunner().Command
}
// WaitRunner captures the parameters for the command and contains
// the run function.
type WaitRunner struct {
IncludeSubpackages bool
Interval time.Duration
Timeout time.Duration
Command *cobra.Command
createClientFunc createClientFunc
}
// runE implements the logic of the command and will call the Wait command in the wait
// package, use a ResourceStatusCollector to capture the events from the channel, and the
// TablePrinter to display the information.
func (r *WaitRunner) runE(c *cobra.Command, args []string) error {
ctx := context.Background()
client, err := getClient()
client, err := r.createClientFunc()
if err != nil {
return errors.Wrap(err, "error creating client")
}
@@ -98,6 +113,9 @@ func (r *WaitRunner) runE(c *cobra.Command, args []string) error {
return nil
}
// ResourceStatusCollector captures the latest state seen for all resources
// based on the events from the Wait channel. This is used by the TablePrinter
// to display status for all resources.
type ResourceStatusCollector struct {
mux sync.RWMutex
@@ -105,6 +123,8 @@ type ResourceStatusCollector struct {
ResourceStatuses []*ResourceStatus
}
// updateResourceStatus takes the given event and update the status info
// in the ResourceStatusCollector.
func (r *ResourceStatusCollector) updateResourceStatus(msg wait.Event) {
r.mux.Lock()
defer r.mux.Unlock()
@@ -121,18 +141,23 @@ func (r *ResourceStatusCollector) updateResourceStatus(msg wait.Event) {
}
}
// updateAggregateStatus sets the aggregate status of the ResourceStatusCollector to the
// given value.
func (r *ResourceStatusCollector) updateAggregateStatus(aggregateStatus status.Status) {
r.mux.Lock()
defer r.mux.Unlock()
r.AggregateStatus = aggregateStatus
}
// ResourceStatus contains the status information for a single resource.
type ResourceStatus struct {
Identifier wait.ResourceIdentifier
Status status.Status
Message string
}
// newResourceStatusCollector creates a new ResourceStatusCollector with the given
// resources and sets the status for all of them to Unknown.
func newResourceStatusCollector(identifiers []wait.ResourceIdentifier) *ResourceStatusCollector {
var statuses []*ResourceStatus
@@ -150,10 +175,16 @@ func newResourceStatusCollector(identifiers []wait.ResourceIdentifier) *Resource
}
}
// CollectorStatusInfo is a wrapper around the ResourceStatusCollector
// to make it adhere to the interface of the TableWriter.
type CollectorStatusInfo struct {
Collector *ResourceStatusCollector
}
// CurrentStatus implements the interface for the TableWriter and
// returns a copy of the current status of the resources in the
// ResourceStatusCollector. This is done to make sure the TableWriter
// does not have to deal with synchronization when accessing the data.
func (f CollectorStatusInfo) CurrentStatus() StatusData {
f.Collector.mux.RLock()
defer f.Collector.mux.RUnlock()

View File

@@ -0,0 +1,176 @@
package cmd
import (
"bytes"
"fmt"
"reflect"
"testing"
"github.com/acarl005/stripansi"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kstatus/status"
)
func TestWaitNoResources(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
fakeClient := &FakeClient{}
r := GetWaitRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err := r.Command.Execute()
if !assert.NoError(t, err) {
return
}
cleanOutput := stripansi.Strip(outBuffer.String())
tableOutput := parseTableOutput(t, cleanOutput)
if want, got := 2, len(tableOutput.Frames); want != got {
t.Errorf("expected %d frames, but found %d", want, got)
}
aggStatuses := tableOutput.allAggStatuses()
expectedAggStatuses := []status.Status{
status.CurrentStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(aggStatuses, expectedAggStatuses) {
t.Errorf("expected agg statuses to be %s, but got %s", joinStatuses(expectedAggStatuses),
joinStatuses(aggStatuses))
}
resources := tableOutput.resources()
if want, got := 0, len(resources); want != got {
t.Errorf("expected %d resources, but found %d", want, got)
}
}
func TestWaitMultipleUpdates(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
_, err := fmt.Fprint(inBuffer, `
apiVersion: apps/v1
kind: Deployment
metadata:
name: bar
namespace: default
`)
if !assert.NoError(t, err) {
return
}
fakeClient := &FakeClient{
resourceCallbackMap: map[string]ResourceGetCallback{
"Deployment": createDeploymentStatusFunc(),
},
}
r := GetWaitRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
cleanOutput := stripansi.Strip(outBuffer.String())
tableOutput := parseTableOutput(t, cleanOutput)
aggStatuses := tableOutput.dedupedAggStatuses()
expectedStatuses := []status.Status{
status.UnknownStatus,
status.InProgressStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(aggStatuses, expectedStatuses) {
t.Errorf("expected deduped agg statuses to be %s, but got %s", joinStatuses(expectedStatuses),
joinStatuses(aggStatuses))
}
resources := tableOutput.resources()
if want, got := 1, len(resources); got != want {
t.Errorf("expected %d resource, but got %d", want, got)
}
resource := resources[0]
resourceStatuses := tableOutput.dedupedStatusesForResource(resource)
expectedResourceStatuses := []status.Status{
status.InProgressStatus,
status.CurrentStatus,
}
if !reflect.DeepEqual(expectedResourceStatuses, resourceStatuses) {
t.Errorf("expected resource %q to have statuses %s, but got %s", resource.name,
joinStatuses(expectedResourceStatuses), joinStatuses(resourceStatuses))
}
}
func TestWaitMultipleResources(t *testing.T) {
inBuffer := &bytes.Buffer{}
outBuffer := &bytes.Buffer{}
_, err := fmt.Fprint(inBuffer, `
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: default
- apiVersion: v1
kind: Service
metadata:
name: bar
namespace: default
`)
if !assert.NoError(t, err) {
return
}
fakeClient := &FakeClient{
resourceCallbackMap: map[string]ResourceGetCallback{
"Pod": createPodStatusFunc(),
"Service": createServiceStatusFunc(),
},
}
r := GetWaitRunner()
r.createClientFunc = newClientFunc(fakeClient)
r.Command.SetArgs([]string{})
r.Command.SetIn(inBuffer)
r.Command.SetOut(outBuffer)
err = r.Command.Execute()
if !assert.NoError(t, err) {
return
}
cleanOutput := stripansi.Strip(outBuffer.String())
tableOutput := parseTableOutput(t, cleanOutput)
aggStatuses := tableOutput.dedupedAggStatuses()
if want, got := status.CurrentStatus, aggStatuses[len(aggStatuses)-1]; want != got {
t.Errorf("expected final agg statuses to be %s, but got %s", want, got)
}
resources := tableOutput.resources()
if want, got := 2, len(resources); got != want {
t.Errorf("expected %d resource, but got %d", want, got)
}
for _, resource := range resources {
resourceStatuses := tableOutput.dedupedStatusesForResource(resource)
if want, got := status.CurrentStatus, resourceStatuses[len(resourceStatuses)-1]; want != got {
t.Errorf("expected resource %q to have final status %s, but got %s", resource.name, want, got)
}
}
}

View File

@@ -0,0 +1,22 @@
## events
[Alpha] Poll the cluster until all provided resources have become Current and list the status change events.
### Synopsis
[Alpha] Poll the cluster for the state of all the provided resources until either they have all become
Current or the timeout is reached. The output will be status change events.
The list of resources which should be polled are provided as manifests either on the filesystem or
on StdIn.
DIR:
Path to local directory. If not provided, input is expected on StdIn.
### Examples
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status events my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status events --timeout=5m

View File

@@ -0,0 +1,21 @@
## fetch
[Alpha] Fetch the state of the provided resources from the cluster and display status in a table.
### Synopsis
[Alpha] Fetches the state of all provided resources from the cluster and displays the status in
a table.
The list of resources are provided as manifests either on the filesystem or on StdIn.
DIR:
Path to local directory.
### Examples
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status fetch my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status fetch

View File

@@ -0,0 +1,22 @@
## wait
[Alpha] Poll the cluster until all provided resources have become Current and display progress in a table.
### Synopsis
[Alpha] Poll the cluster for the state of all the provided resources until either they have all become
Current or the timeout is reached. The output will be presented as a table.
The list of resources which should be polled are provided as manifests either on the filesystem or
on StdIn.
DIR:
Path to local directory. If not provided, input is expected on StdIn.
### Examples
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status wait my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status wait --timeout=5m

View File

@@ -0,0 +1,55 @@
// Code generated by "mdtogo"; DO NOT EDIT.
package commands
var EventsShort = `[Alpha] Poll the cluster until all provided resources have become Current and list the status change events.`
var EventsLong = `
[Alpha] Poll the cluster for the state of all the provided resources until either they have all become
Current or the timeout is reached. The output will be status change events.
The list of resources which should be polled are provided as manifests either on the filesystem or
on StdIn.
DIR:
Path to local directory. If not provided, input is expected on StdIn.
`
var EventsExamples = `
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status events my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status events --timeout=5m`
var FetchShort = `[Alpha] Fetch the state of the provided resources from the cluster and display status in a table.`
var FetchLong = `
[Alpha] Fetches the state of all provided resources from the cluster and displays the status in
a table.
The list of resources are provided as manifests either on the filesystem or on StdIn.
DIR:
Path to local directory.
`
var FetchExamples = `
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status fetch my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status fetch`
var WaitShort = `[Alpha] Poll the cluster until all provided resources have become Current and display progress in a table. `
var WaitLong = `
[Alpha] Poll the cluster for the state of all the provided resources until either they have all become
Current or the timeout is reached. The output will be presented as a table.
The list of resources which should be polled are provided as manifests either on the filesystem or
on StdIn.
DIR:
Path to local directory. If not provided, input is expected on StdIn.
`
var WaitExamples = `
# Read resources from the filesystem and wait up to 1 minute for all of them to become Current
resource status wait my-dir/
# Fetch all resources in the cluster and wait up to 5 minutes for all of them to become Current
kubectl get all --all-namespaces -oyaml | resource status wait --timeout=5m`

View File

@@ -1,3 +1,8 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
//go:generate $GOBIN/mdtogo docs/commands generateddocs/commands --license=none
package status
import (
@@ -8,7 +13,7 @@ import (
func StatusCommand() *cobra.Command {
var status = &cobra.Command{
Use: "status",
Short: "status reference command",
Short: "[Alpha] Commands for working with resource status.",
}
status.AddCommand(cmd.FetchCommand())

View File

@@ -196,14 +196,13 @@ By definition, an _exec_ plugin must be executable:
chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
```
## Download kustomize 3.0.0
## Install kustomize
Per the [instructions](../../INSTALL.md):
```
mkdir -p $DEMO/bin
gh=https://github.com/kubernetes-sigs/kustomize/releases/download
url=$gh/v3.0.0/kustomize_3.0.0_linux_amd64
curl -o $DEMO/bin/kustomize -L $url
chmod u+x $DEMO/bin/kustomize
curl -s "https://raw.githubusercontent.com/\
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
mv kustomize $DEMO/bin
```
## Review the layout

View File

@@ -15,7 +15,7 @@ Resource configuration, and looks for invalid configuration.
## Function invocation
The function is invoked by authoring a [local Resource](local-resource)
with `metadata.configFn` and running:
with `metadata.annotations.[config.k8s.io/function]` and running:
kustomize config run local-resource/

View File

@@ -4,9 +4,10 @@
apiVersion: examples.config.kubernetes.io/v1beta1
kind: Validator
metadata:
configFn:
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
---
apiVersion: apps/v1
kind: Deployment

View File

@@ -25,7 +25,7 @@ function input, and writing the function output.
## Function invocation
The function is invoked by authoring a [local Resource](local-resource)
with `metadata.configFn` and running:
with `metadata.annotations.[config.k8s.io/function]` and running:
kustomize config run local-resource/

View File

@@ -5,8 +5,9 @@ apiVersion: examples.config.kubernetes.io/v1beta1 # call `kustomize config run`
kind: Nginx
metadata:
name: demo
configFn:
container:
image: gcr.io/kustomize-functions/example-nginx:v0.1.0
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kustomize-functions/example-nginx:v0.1.0
spec:
replicas: 4

View File

@@ -20,7 +20,7 @@ heavy lifting of implementing the function interface.
## Function invocation
The function is invoked by authoring a [local Resource](local-resource)
with `metadata.configFn` and running:
with `metadata.annotations.[config.k8s.io/function]` and running:
kustomize config run local-resource/

View File

@@ -6,8 +6,9 @@ apiVersion: examples.config.kubernetes.io/v1beta1
kind: CockroachDB
metadata:
name: demo
configFn:
container:
image: gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
spec:
replicas: 3

View File

@@ -18,7 +18,7 @@ the `API` struct definition in [main.go](image/main.go) for documentation.
## Function invocation
The function is invoked by authoring a [local Resource](local-resource)
with `metadata.configFn` and running:
with `metadata.annotations.[config.k8s.io/function]` and running:
kustomize config run local-resource/

View File

@@ -4,9 +4,10 @@
apiVersion: examples.config.kubernetes.io/v1beta1
kind: Kubeval
metadata:
configFn:
container:
image: gcr.io/kustomize-functions/example-validator-kubeval:v0.1.0
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kustomize-functions/example-validator-kubeval:v0.1.0
spec:
strict: true
ignoreMissingSchemas: true

View File

@@ -15,7 +15,7 @@ Resource configuration, and looks for invalid configuration.
## Function invocation
The function is invoked by authoring a [local Resource](local-resource)
with `metadata.configFn` and running:
with `metadata.annotations.[config.k8s.io/function]` and running:
kustomize config run local-resource/

View File

@@ -4,9 +4,10 @@
apiVersion: examples.config.kubernetes.io/v1beta1
kind: Validator
metadata:
configFn:
container:
image: gcr.io/kustomize-functions/example-validator:v0.1.0
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kustomize-functions/example-validator:v0.1.0
---
apiVersion: apps/v1 # this should fail validation
kind: Deployment

67
hack/pinUnpin.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
#
# In general, pin modules to a specific version of the
# kustomize API before a release of that module, and
# unpin the module after the module release so that
# development proceeds against the API's HEAD.
#
# E.g. for the kustomize CLI module, do this before
# releasing the CLI:
#
# ./hack/pinUnpin.sh pin kustomize v0.3.1
#
# where v0.3.1 is the most recently released version of
# the API, and do the following afterwards:
#
# ./hack/pinUnpin.sh unPin kustomize
set -o nounset
set -o pipefail
if [ "$#" -lt 2 ]; then
echo "usage:"
echo " ./hack/pinUnpin.sh pin kustomize v0.3.1"
echo " or "
echo " ./hack/pinUnpin.sh unPin kustomize"
exit 1
fi
operation=$1
if [[ ("$operation" != "pin") && ("$operation" != "unPin") ]]; then
echo "unknown operation $operation"
exit 1
fi
module=$2
if [ ! -d "$module" ]; then
echo "directory $module doesn't exist"
exit 1
fi
version="unnecessary"
if [ "$operation" == "pin" ]; then
if [ "$#" -le 2 ]; then
echo "Specify version to pin, e.g. '$0 $module pin v0.2.0'"
exit 1
fi
version=$3
fi
function unPin {
oldV=$(grep -m 1 sigs.k8s.io/kustomize/api go.mod | awk '{print $NF}')
go mod edit -replace=sigs.k8s.io/kustomize/api@${oldV}=../api
go mod tidy
}
function pin {
oldV=$(grep -m 1 sigs.k8s.io/kustomize/api go.mod | awk '{print $NF}')
go mod edit -dropreplace=sigs.k8s.io/kustomize/api@${oldV}
go mod edit -require=sigs.k8s.io/kustomize/api@$version
go mod tidy
}
pushd $module >& /dev/null
$operation
popd >& /dev/null

View File

@@ -4,6 +4,7 @@
package status
import (
"fmt"
"time"
"github.com/pkg/errors"
@@ -26,6 +27,11 @@ const (
UnknownStatus Status = "Unknown"
)
var (
Statuses = []Status{InProgressStatus, FailedStatus, CurrentStatus, TerminatingStatus, UnknownStatus}
ConditionTypes = []ConditionType{ConditionFailed, ConditionInProgress}
)
// ConditionType defines the set of condition types allowed inside a Condition struct.
type ConditionType string
@@ -42,6 +48,18 @@ func (s Status) String() string {
return string(s)
}
// StatusFromString turns a string into a Status. Will panic if the provided string is
// not a valid status.
func FromStringOrDie(text string) Status {
s := Status(text)
for _, r := range Statuses {
if s == r {
return s
}
}
panic(fmt.Errorf("string has invalid status: %s", s))
}
// Result contains the results of a call to compute the status of
// a resource.
type Result struct {

View File

@@ -17,3 +17,5 @@ exclude (
github.com/russross/blackfriday v2.0.0+incompatible
sigs.k8s.io/kustomize/api v0.2.0
)
replace sigs.k8s.io/kustomize/api v0.3.1 => ../api

View File

@@ -207,15 +207,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0 h1:UykbtMB/w5No2LmE16gINgLj+r/vbziTgaoERQv6U+0=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a h1:YH0IojQwndMQdeRWdw1aPT8bkbiWaYR3WD+Zf5e09DU=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741 h1:OuuPl66BpF1q3OEkaPpp+VfzxrBBY62ATGdWqql/XX8=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
@@ -302,8 +293,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.1 h1:LzwNWb8ge3+4iBZmxIE6VfUR5KIxhF7DKdf85t8Yvos=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -361,8 +350,6 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
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/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -540,8 +527,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0 h1:+FlnIV8DSQnT7NZ43hcVKcdJdzZoeCmJj4Ql8gq5keA=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -594,16 +579,12 @@ mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8Eo
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/kustomize/api v0.3.0 h1:e7Erw2n8lT8+IWUukktozF0bgWwH2fFC+qsXP0gabg0=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:4jaPCtRzxfQLFdYq4gYo40dBGW1hyPp/f4AuiZB5dAQ=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/kustomize/cmd/config v0.0.2 h1:FphfIoGJ0jGGJJXq9WoG5sqqEIuTeDGx58E5NWHV8Hc=
sigs.k8s.io/kustomize/cmd/config v0.0.2/go.mod h1:c6IBoPpAAm5a2aD+0iH8IfeyCF5GPsY5Ws57Dwpcvg0=
sigs.k8s.io/kustomize/cmd/kubectl v0.0.2 h1:MxUAU5ie0tqx2MuDrUlcAL+Mgt8LVFcXc2scinSD8/w=
sigs.k8s.io/kustomize/cmd/kubectl v0.0.2/go.mod h1:SbNCE1g937W1yvaQrZbvPNT3aDRdicdeW2qXLTa+YiM=
sigs.k8s.io/kustomize/kyaml v0.0.2 h1:Rl/wMrnpZzZjsVeFIIOAb92Kz/UfLrTUEXjiHW6oS0o=
sigs.k8s.io/kustomize/kyaml v0.0.2/go.mod h1:rywm/rcR5LmCBghz9956tE45OdUPChFoXVVs+WmhMTI=
sigs.k8s.io/kustomize/pluginator/v2 v2.0.0/go.mod h1:zrXhTv8BAKt0egmZX/8AtMOSFUSWM9YuoHvvqz8/eHE=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -4,6 +4,7 @@
package copyutil_test
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -104,7 +105,9 @@ func TestDiff_srcDestContentsDiffer(t *testing.T) {
diff, err := Diff(s, d)
assert.NoError(t, err)
assert.ElementsMatch(t, diff.List(), []string{"a1/f.yaml"})
assert.ElementsMatch(t, diff.List(), []string{
fmt.Sprintf("a1%sf.yaml", string(filepath.Separator)),
})
}
// TestDiff_srcDestContentsDifferInDirs verifies if identical files
@@ -130,7 +133,11 @@ func TestDiff_srcDestContentsDifferInDirs(t *testing.T) {
diff, err := Diff(s, d)
assert.NoError(t, err)
assert.ElementsMatch(t, diff.List(), []string{
"a1", "a1/f.yaml", "b1/f.yaml", "b1"})
"a1",
fmt.Sprintf("a1%sf.yaml", string(filepath.Separator)),
fmt.Sprintf("b1%sf.yaml", string(filepath.Separator)),
"b1",
})
}
// TestDiff_skipGitSrc verifies that .git directories in the source

View File

@@ -4,37 +4,36 @@
package fieldmeta
import (
"bytes"
"encoding/json"
"strconv"
"strings"
"github.com/go-openapi/spec"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// FieldMeta contains metadata that may be attached to fields as comments
type FieldMeta struct {
// Substitutions are substitutions that may be performed against this field
Substitutions []Substitution `yaml:"substitutions,omitempty" json:"substitutions,omitempty"`
// OwnedBy records the owner of this field
OwnedBy string `yaml:"setBy,omitempty" json:"setBy,omitempty"`
// DefaultedBy records that this field was default, but may be changed by other owners
DefaultedBy string `yaml:"defaultedBy,omitempty" json:"defaultedBy,omitempty"`
// Description is a description of the current field value, e.g. why it was set
Description string `yaml:"description,omitempty" json:"description,omitempty"`
// Type is the type of the field value
Type FieldValueType `yaml:"type,omitempty" json:"type,omitempty"`
Schema spec.Schema
Extensions XKustomize
}
// Substitution defines a substitution that may be performed against the field
type Substitution struct {
// Name is the name of the substitution and read by tools
Name string `yaml:"name,omitempty" json:"name,omitempty"`
// Marker is the marker used for replacement
Marker string `yaml:"marker,omitempty" json:"marker,omitempty"`
// Value is the current value that has been substituted for the Marker
Value string `yaml:"value,omitempty" json:"value,omitempty"`
type XKustomize struct {
SetBy string `yaml:"setBy,omitempty" json:"setBy,omitempty"`
PartialFieldSetters []PartialFieldSetter `yaml:"partialSetters,omitempty" json:"partialSetters,omitempty"`
FieldSetter *PartialFieldSetter `yaml:"setter,omitempty" json:"setter,omitempty"`
}
// PartialFieldSetter defines how to set part of a field rather than the full field
// value. e.g. the tag part of an image field
type PartialFieldSetter struct {
// Name is the name of this setter.
Name string `yaml:"name" json:"name"`
// Value is the current value that has been set.
Value string `yaml:"value" json:"value"`
}
// Read reads the FieldMeta from a node
@@ -43,16 +42,30 @@ func (fm *FieldMeta) Read(n *yaml.RNode) error {
v := strings.TrimLeft(n.YNode().LineComment, "#")
// if it doesn't Unmarshal that is fine, it means there is no metadata
// other comments are valid, they just don't parse
d := yaml.NewDecoder(bytes.NewBuffer([]byte(v)))
d.KnownFields(false)
_ = d.Decode(fm)
// TODO: consider most sophisticated parsing techniques similar to what is used
// for go struct tags.
if err := fm.Schema.UnmarshalJSON([]byte(v)); err != nil {
// note: don't return an error if the comment isn't a fieldmeta struct
return nil
}
fe := fm.Schema.VendorExtensible.Extensions["x-kustomize"]
if fe == nil {
return nil
}
b, err := json.Marshal(fe)
if err != nil {
return err
}
return json.Unmarshal(b, &fm.Extensions)
}
return nil
}
// Write writes the FieldMeta to a node
func (fm *FieldMeta) Write(n *yaml.RNode) error {
b, err := json.Marshal(fm)
fm.Schema.VendorExtensible.AddExtension("x-kustomize", fm.Extensions)
b, err := json.Marshal(fm.Schema)
if err != nil {
return err
}
@@ -67,11 +80,9 @@ const (
// String defines a string flag
String FieldValueType = "string"
// Bool defines a bool flag
Bool = "bool"
// Float defines a float flag
Float = "float"
Bool = "boolean"
// Int defines an int flag
Int = "int"
Int = "integer"
)
func (it FieldValueType) String() string {
@@ -91,10 +102,6 @@ func (it FieldValueType) Validate(value string) error {
if _, err := strconv.ParseBool(value); err != nil {
return errors.WrapPrefixf(err, "value must be a bool")
}
case Float:
if _, err := strconv.ParseFloat(value, 64); err != nil {
return errors.WrapPrefixf(err, "value must be a float")
}
}
return nil
}
@@ -107,8 +114,6 @@ func (it FieldValueType) Tag() string {
return "!!bool"
case Int:
return "!!int"
case Float:
return "!!float"
}
return ""
}
@@ -127,11 +132,6 @@ func (it FieldValueType) TagForValue(value string) string {
return ""
}
return "!!int"
case Float:
if _, err := strconv.ParseFloat(string(it), 64); err != nil {
return ""
}
return "!!float"
}
return ""
}

View File

@@ -5,10 +5,8 @@ go 1.12
require (
github.com/davecgh/go-spew v1.1.1
github.com/go-errors/errors v1.0.1
github.com/kr/pretty v0.1.0 // indirect
github.com/go-openapi/spec v0.19.5
github.com/stretchr/testify v1.4.0
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.4 // indirect
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d
)

View File

@@ -1,25 +1,50 @@
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/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/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-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.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
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/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/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/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -130,7 +130,11 @@ func (c *ContainerFilter) getArgs() []string {
// export the local environment vars to the container
for _, pair := range os.Environ() {
args = append(args, "-e", strings.Split(pair, "=")[0])
tokens := strings.Split(pair, "=")
if tokens[0] == "" {
continue
}
args = append(args, "-e", tokens[0])
}
return append(args, c.Image)
}
@@ -197,6 +201,13 @@ func GetContainerName(n *yaml.RNode) (string, string) {
// path to the function, this will be mounted into the container
path := meta.Annotations[kioutil.PathAnnotation]
functionAnnotation := meta.Annotations["config.k8s.io/function"]
if functionAnnotation != "" {
annotationContent, _ := yaml.Parse(functionAnnotation)
image, _ := annotationContent.Pipe(yaml.Lookup("container", "image"))
return image.YNode().Value, path
}
container := meta.Annotations["config.kubernetes.io/container"]
if container != "" {
return container, path

View File

@@ -131,7 +131,11 @@ metadata:
}
for _, e := range os.Environ() {
// the process env
expected = append(expected, "-e", strings.Split(e, "=")[0])
tokens := strings.Split(e, "=")
if tokens[0] == "" {
continue
}
expected = append(expected, "-e", tokens[0])
}
expected = append(expected, "example.com:version")
assert.Equal(t, expected, cmd.Args)
@@ -316,7 +320,7 @@ metadata:
c, _ := GetContainerName(n)
assert.Equal(t, "gcr.io/foo/bar:something", c)
// container from annotation
// container from config.kubernetes.io/container annotation
n, err = yaml.Parse(`apiVersion: v1
kind: MyThing
metadata:
@@ -329,6 +333,21 @@ metadata:
c, _ = GetContainerName(n)
assert.Equal(t, "gcr.io/foo/bar:something", c)
// container from config.k8s.io/function annotation
n, err = yaml.Parse(`apiVersion: v1
kind: MyThing
metadata:
annotations:
config.k8s.io/function: |
container:
image: gcr.io/foo/bar:something
`)
if !assert.NoError(t, err) {
return
}
c, _ = GetContainerName(n)
assert.Equal(t, "gcr.io/foo/bar:something", c)
// doesn't have a container
n, err = yaml.Parse(`apiVersion: v1
kind: MyThing

View File

@@ -136,7 +136,7 @@ func SortNodes(nodes []*yaml.RNode) error {
return false
}
if iIndex != jIndex {
return iValue < jValue
return iIndex < jIndex
}
// elements are equal

View File

@@ -0,0 +1,77 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package kioutil_test
import (
"bytes"
"math/rand"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
)
func TestSortNodes_moreThan10(t *testing.T) {
input := `
a: b
---
c: d
---
e: f
---
g: h
---
i: j
---
k: l
---
m: n
---
o: p
---
q: r
---
s: t
---
u: v
---
w: x
---
y: z
`
actual := &bytes.Buffer{}
rw := kio.ByteReadWriter{Reader: bytes.NewBufferString(input), Writer: actual}
nodes, err := rw.Read()
if !assert.NoError(t, err) {
t.Fail()
}
// randomize the list
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(nodes), func(i, j int) { nodes[i], nodes[j] = nodes[j], nodes[i] })
// sort them back into their original order
if !assert.NoError(t, kioutil.SortNodes(nodes)) {
t.Fail()
}
// check the sorted values
expected := strings.Split(input, "---")
for i := range nodes {
a := strings.TrimSpace(nodes[i].MustString())
b := strings.TrimSpace(expected[i])
if !assert.Contains(t, a, b) {
t.Fail()
}
}
if !assert.NoError(t, rw.Write(nodes)) {
t.Fail()
}
assert.Equal(t, strings.TrimSpace(input), strings.TrimSpace(actual.String()))
}

View File

@@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -269,15 +270,15 @@ func TestLocalPackageReader_Read_nestedDirs(t *testing.T) {
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`c: d # second
metadata:
annotations:
config.kubernetes.io/index: '1'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`# second thing
e: f
@@ -288,8 +289,8 @@ g:
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/b_test.yaml'
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}b_test.yaml'
`,
}
for i := range nodes {
@@ -297,7 +298,8 @@ metadata:
if !assert.NoError(t, err) {
return
}
if !assert.Equal(t, expected[i], val) {
want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
if !assert.Equal(t, want, val) {
return
}
}
@@ -321,25 +323,29 @@ func TestLocalPackageReader_Read_matchRegex(t *testing.T) {
assert.FailNow(t, "wrong number items")
}
val, err := nodes[0].String()
assert.NoError(t, err)
assert.Equal(t, `a: b #first
expected := []string{
`a: b #first
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
val, err = nodes[1].String()
assert.NoError(t, err)
assert.Equal(t, `c: d # second
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`c: d # second
metadata:
annotations:
config.kubernetes.io/index: '1'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
}
for i, node := range nodes {
val, err := node.String()
assert.NoError(t, err)
want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
assert.Equal(t, want, val)
}
}
func TestLocalPackageReader_Read_skipSubpackage(t *testing.T) {
@@ -360,25 +366,29 @@ func TestLocalPackageReader_Read_skipSubpackage(t *testing.T) {
assert.FailNow(t, "wrong number items")
}
val, err := nodes[0].String()
assert.NoError(t, err)
assert.Equal(t, `a: b #first
expected := []string{
`a: b #first
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
val, err = nodes[1].String()
assert.NoError(t, err)
assert.Equal(t, `c: d # second
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`c: d # second
metadata:
annotations:
config.kubernetes.io/index: '1'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
}
for i, node := range nodes {
val, err := node.String()
assert.NoError(t, err)
want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
assert.Equal(t, want, val)
}
}
func TestLocalPackageReader_Read_includeSubpackage(t *testing.T) {
@@ -398,29 +408,23 @@ func TestLocalPackageReader_Read_includeSubpackage(t *testing.T) {
if !assert.Len(t, nodes, 3) {
assert.FailNow(t, "wrong number items")
}
val, err := nodes[0].String()
assert.NoError(t, err)
assert.Equal(t, `a: b #first
expected := []string{
`a: b #first
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
val, err = nodes[1].String()
assert.NoError(t, err)
assert.Equal(t, `c: d # second
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`c: d # second
metadata:
annotations:
config.kubernetes.io/index: '1'
config.kubernetes.io/package: 'a/b'
config.kubernetes.io/path: 'a/b/a_test.yaml'
`, val)
val, err = nodes[2].String()
assert.NoError(t, err)
assert.Equal(t, `# second thing
config.kubernetes.io/package: 'a${SEP}b'
config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
`,
`# second thing
e: f
g:
h:
@@ -429,9 +433,17 @@ g:
metadata:
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/package: 'a/c'
config.kubernetes.io/path: 'a/c/c_test.yaml'
`, val)
config.kubernetes.io/package: 'a${SEP}c'
config.kubernetes.io/path: 'a${SEP}c${SEP}c_test.yaml'
`,
}
for i, node := range nodes {
val, err := node.String()
assert.NoError(t, err)
want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
assert.Equal(t, want, val)
}
}
// func TestLocalPackageReaderWriter_DeleteFiles(t *testing.T) {

View File

@@ -1,105 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"strings"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &Marker{}
// substituteResource substitutes a Marker value on a field
type Marker struct {
// Path is the path of the field to add the substitution for
Field string
// Substitution is the substitution to add
Substitution fieldmeta.Substitution
// PartialMatch if true will match if the Substitution value is a substring of the current
// value.
PartialMatch bool
Description string
OwnedBy string
Type string
// currentFieldName is the name of the current field being processed
currentFieldName string
}
// Filter performs the substitutions for a single object
func (m *Marker) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
return m.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
// set the current field name
n := m.currentFieldName
defer func() { m.currentFieldName = n }()
m.currentFieldName = node.Key.YNode().Value
_, err := m.Filter(node.Value)
return err
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
_, err := m.Filter(node)
return err
})
case yaml.ScalarNode:
if m.currentFieldName != m.Field {
return object, nil
}
if err := m.createSub(object); err != nil {
return nil, err
}
return object, nil
default:
return object, nil
}
}
func (m *Marker) createSub(field *yaml.RNode) error {
// doesn't match the supplied value
if field.YNode().Value != m.Substitution.Value {
if !m.PartialMatch || !strings.Contains(field.YNode().Value, m.Substitution.Value) {
return nil
}
}
fm := fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return errors.Wrap(err)
}
fm.OwnedBy = m.OwnedBy
fm.Description = m.Description
fm.Type = fieldmeta.FieldValueType(m.Type)
if m.Substitution.Marker == "" {
m.Substitution.Marker = "[MARKER]"
}
found := false
for i := range fm.Substitutions {
s := fm.Substitutions[i]
if s.Name == m.Substitution.Name {
// update the substitution if we find it
found = true
fm.Substitutions[i] = m.Substitution
break
}
}
if !found {
// add the substitution if it wasn't found
fm.Substitutions = append(fm.Substitutions, m.Substitution)
}
if err := fm.Write(field); err != nil {
return errors.Wrap(err)
}
return nil
}

View File

@@ -1,53 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ kio.Filter = &PerformSubstitutions{}
// Sub performs substitutions
type PerformSubstitutions struct {
// Name is the name of the substitution to perform
Name string
// NewValue is the substitution value
NewValue string
// Override if set to true will re-substitute already fields with a new value
Override bool
// Revert if set to true will substitute fields back to the marker value
Revert bool
// Description, if set will annotate the field with a description.
Description string
// OwnedBy, if set will annotate the field with an owner.
OwnedBy string
// Count is the number of substitutions performed by Filter.
Count int
}
func (s *PerformSubstitutions) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
for i := range input {
p := &performSubstitutions{
Name: s.Name,
Override: s.Override,
Revert: s.Revert,
NewValue: s.NewValue,
OwnedBy: s.OwnedBy,
Description: s.Description,
}
if err := input[i].PipeE(p); err != nil {
return nil, err
}
s.Count += p.Count
}
return input, nil
}

View File

@@ -1,155 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package sub substitutes strings in fields
package set
import (
"strings"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &performSubstitutions{}
// substituteResource substitutes a Marker value on a field
type performSubstitutions struct {
// Name of the substitution to perform.
Name string
// Override if set to true will replace previously substituted values
Override bool
// Revert if set to true will undo previously substituted values
Revert bool
// NewValue is the new value to set. Mutually exclusive with Revert.
NewValue string
// Description, if set will annotate the field with a description.
Description string
// OwnedBy, if set will annotate the field with an owner.
OwnedBy string
// Count will be incremented for each substituted value.
Count int
}
// Filter performs the substitutions for a single object
func (fs *performSubstitutions) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
return fs.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
_, err := fs.Filter(node.Value)
return err
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
_, err := fs.Filter(node)
return err
})
case yaml.ScalarNode:
s, f, err := fs.findSub(object)
if err != nil {
return nil, err
}
if s == nil {
return object, nil
}
return object, fs.substitute(object, s, f)
default:
return object, nil
}
}
// findSub finds the substitution matching the name if one exists
func (fs *performSubstitutions) findSub(field *yaml.RNode) (
*fieldmeta.Substitution, *fieldmeta.FieldMeta, error) {
// check if there are any substitutions for this field
var fm = &fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return nil, nil, err
}
if fs.OwnedBy != "" {
fm.OwnedBy = fs.OwnedBy
}
if fs.Description != "" {
fm.Description = fs.Description
}
// check if there is a matching substitution
for i := range fm.Substitutions {
if fm.Substitutions[i].Name == fs.Name {
// validate the value if we are not reverting to the marker.
// markers are allowed to be invalid.
// only validate if there is a substitution matching the name
if !fs.Revert {
if err := fm.Type.Validate(fs.NewValue); err != nil {
return nil, nil, err
}
}
return &fm.Substitutions[i], fm, nil
}
}
return nil, nil, nil
}
// substitute performs the substitution for the given field, substitution, and metadata
func (fs *performSubstitutions) substitute(
field *yaml.RNode, s *fieldmeta.Substitution, f *fieldmeta.FieldMeta) error {
// undo or override previous substitutions by substituting the marker back
// NOTE: check if s.Value != "" so we never try to substitute the empty string back
if (fs.Revert || fs.Override) && s.Value != "" {
// revert to the marker value
if strings.Contains(field.YNode().Value, s.Value) {
// revert the substitution
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Value, s.Marker)
// only use the tag matching the type if the marker parses to that type
field.YNode().Tag = f.Type.TagForValue(s.Marker)
// record that the config has been modified
}
}
if fs.Revert {
fs.Count++
s.Value = "" // value has been cleared and replaced with marker
if err := f.Write(field); err != nil {
return err
}
return nil
}
if s.Value == fs.NewValue || !strings.Contains(field.YNode().Value, s.Marker) {
// no substitutions necessary -- already substituted or doesn't have the marker
return nil
}
// replace the marker with the new value
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Marker, fs.NewValue)
// be sure to set the tag so the yaml doesn't incorrectly quote ints, bools or floats
field.YNode().Tag = f.Type.Tag()
field.YNode().Style = 0
// record that the config has been modified
fs.Count++
// update the comment on the field
s.Value = fs.NewValue
if err := f.Write(field); err != nil {
return err
}
return nil
}

View File

@@ -1,69 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"sort"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ kio.Filter = &LookupSubstitutions{}
// Sub performs substitutions
type LookupSubstitutions struct {
// Name is the name of the substitution to match. If unspecified, all substitutions will
// be matched.
Name string
// SubstitutionCounts are the aggregate substitutions matched.
SubstitutionCounts []FieldSubstitutionCount
}
type FieldSubstitutionCount struct {
// Count is the number of substitutions possible to perform
Count int
// CountComplete is the number of substitutions that have already been performed
// independent of this object.
CountComplete int
// FieldSubstitution is the substitution found
FieldSubstitution
}
func (l *LookupSubstitutions) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
subs := map[string]*FieldSubstitutionCount{}
for i := range input {
// lookup substitutions for this object
ls := &lookupSubstitutions{Name: l.Name}
if err := input[i].PipeE(ls); err != nil {
return nil, err
}
// aggregate counts for each substitution
for j := range ls.Substitutions {
sub := ls.Substitutions[j]
curr, found := subs[sub.Name]
if !found {
curr = &FieldSubstitutionCount{FieldSubstitution: sub}
subs[sub.Name] = curr
}
curr.Count++
if sub.CurrentValue != "" {
curr.CountComplete++
}
}
}
// pull out and sort the results
for _, v := range subs {
l.SubstitutionCounts = append(l.SubstitutionCounts, *v)
}
sort.Slice(l.SubstitutionCounts, func(i, j int) bool {
return l.SubstitutionCounts[i].Name < l.SubstitutionCounts[j].Name
})
return input, nil
}

View File

@@ -1,65 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &lookupSubstitutions{}
// substituteResource substitutes a Marker value on a field
type lookupSubstitutions struct {
// Name of the substitution to lookup. If unspecified lookup all substitutions.
Name string
// FieldSubstitution is the list of substitutions that were found
Substitutions []FieldSubstitution
}
func (ls *lookupSubstitutions) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
return ls.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
_, err := ls.Filter(node.Value)
return err
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
_, err := ls.Filter(node)
return err
})
case yaml.ScalarNode:
return object, ls.lookup(object)
default:
return object, nil
}
}
// lookup finds any substitutions for this field
func (ls *lookupSubstitutions) lookup(field *yaml.RNode) error {
// check if there is a substitution for this field
var fm = &fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return err
}
for i := range fm.Substitutions {
s := fm.Substitutions[i]
if ls.Name == "" || ls.Name == s.Name {
ls.Substitutions = append(ls.Substitutions, FieldSubstitution{
Name: s.Name,
CurrentValue: s.Value,
Description: fm.Description,
Marker: s.Marker,
Type: fm.Type,
OwnedBy: fm.OwnedBy,
})
}
}
return nil
}

View File

@@ -1,29 +0,0 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
)
// FieldSubstitution is a possible field substitution read from a field
type FieldSubstitution struct {
// Name is the name of the substitution
Name string
// Description is a description of the fields current value
Description string
// Value is the current substituted value for the field.
CurrentValue string
// Type is the type of the substitution
Type fieldmeta.FieldValueType
// Marker is the marker used
Marker string
// OwnedBy, if set will annotate the field with an owner.
OwnedBy string
}

View File

@@ -1,25 +1,25 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
package setters
import (
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ kio.Filter = &SetSubstitutionMarker{}
var _ kio.Filter = &CreateSetter{}
// Sub performs substitutions
type SetSubstitutionMarker struct {
// Marker is the marker to set
Marker Marker
// CreateSetter creates a custom setter as an OpenAPI property through a comment
type CreateSetter struct {
// customFieldSetter is the marker to set
SetPartialField customFieldSetter
// ResourceMeta defines the Resource to set the marker on
ResourceMeta yaml.ResourceMeta
}
func (s *SetSubstitutionMarker) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
func (s *CreateSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
for i := range input {
m, err := input[i].GetMeta()
if err != nil {
@@ -31,7 +31,7 @@ func (s *SetSubstitutionMarker) Filter(input []*yaml.RNode) ([]*yaml.RNode, erro
if s.ResourceMeta.Kind != "" && m.Kind != s.ResourceMeta.Kind {
continue
}
if err := input[i].PipeE(&s.Marker); err != nil {
if err := input[i].PipeE(&s.SetPartialField); err != nil {
return nil, err
}
}

117
kyaml/setters/addyaml.go Normal file
View File

@@ -0,0 +1,117 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package setters
import (
"strings"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &customFieldSetter{}
// customFieldSetter creates a new custom field setter
type customFieldSetter struct {
// Path is the path of the field to add the setter for
Field string
// Setter is the setter to add
Setter fieldmeta.PartialFieldSetter
// Description is the description to add to the OpenAPI
Description string
// SetBy is the setBy to add to the OpenAPI extension
SetBy string
Type string
// Partial will create a partial setter if set to true
Partial bool
// currentFieldName is the name of the current field being processed
currentFieldName string
}
// Filter performs the setter for a single object
func (m *customFieldSetter) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
return m.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
// record the current field name, resetting it back to its original value
// when done
n := m.currentFieldName
defer func() { m.currentFieldName = n }()
m.currentFieldName = node.Key.YNode().Value
return node.Value.PipeE(m)
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
return node.PipeE(m)
})
case yaml.ScalarNode:
// only create the setter for fields with the given name
if m.currentFieldName != m.Field {
return object, nil
}
if err := m.create(object); err != nil {
return nil, err
}
return object, nil
default:
return object, nil
}
}
func (m *customFieldSetter) create(field *yaml.RNode) error {
fm := fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return errors.Wrap(err)
}
if m.Description != "" {
fm.Schema.Description = m.Description
}
fm.Extensions.SetBy = m.SetBy
fm.Schema.Type = []string{m.Type}
if !m.Partial {
// doesn't match the supplied value
if field.YNode().Value != m.Setter.Value {
return nil
}
// full setter
fm.Extensions.FieldSetter = &m.Setter
fm.Extensions.PartialFieldSetters = nil
} else {
// doesn't match the supplied value
if !strings.Contains(field.YNode().Value, m.Setter.Value) {
return nil
}
found := false
for i := range fm.Extensions.PartialFieldSetters {
s := fm.Extensions.PartialFieldSetters[i]
if s.Name == m.Setter.Name {
// update the setter if we find it
found = true
fm.Extensions.PartialFieldSetters[i] = m.Setter
break
}
}
if !found {
// add the setter if it wasn't found
fm.Extensions.PartialFieldSetters = append(fm.Extensions.PartialFieldSetters, m.Setter)
}
}
if err := fm.Write(field); err != nil {
return errors.Wrap(err)
}
return nil
}

45
kyaml/setters/dokio.go Normal file
View File

@@ -0,0 +1,45 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package setters
import (
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ kio.Filter = &PerformSetters{}
// PerformSetters sets field values
type PerformSetters struct {
// Name is the name of the setter to perform
Name string
// Value is the value to set
Value string
// Description, if set will annotate the field with a description.
Description string
// SetBy, if set will annotate the field with who set it.
SetBy string
// Count is set by Filter and is the number of fields modified.
Count int
}
func (s *PerformSetters) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
for i := range input {
p := &fieldSetter{
Name: s.Name,
Value: s.Value,
Description: s.Description,
SetBy: s.SetBy,
}
if err := input[i].PipeE(p); err != nil {
return nil, err
}
s.Count += p.Count
}
return input, nil
}

130
kyaml/setters/doyaml.go Normal file
View File

@@ -0,0 +1,130 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
// Package sub substitutes strings in fields
package setters
import (
"strings"
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &fieldSetter{}
// fieldSetter sets part or all of a field value.
type fieldSetter struct {
// Name is the name of the setter to perform.
Name string
// Value is the value to set.
Value string
// Description, if specified will set 'description' for the field. Optional.
Description string
// SetBy, if specified will set 'setBy' for the field. Optional.
SetBy string
// Count is incremented by Filter for each field that is set.
Count int
}
// Filter implements yaml.Filter
func (fs *fieldSetter) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
// Document is the root of the object and always contains 1 node
return fs.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
// Traverse each field value
return node.Value.PipeE(fs)
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
// Traverse each list element
return node.PipeE(fs)
})
case yaml.ScalarNode:
// Check if there is a setter matching the name
s, f, partial, err := fs.findSetter(object)
if err != nil {
return nil, err
}
if s == nil {
// no matching setter
return object, nil
}
// set the field value
return object, fs.set(object, s, f, partial)
default:
return object, nil
}
}
// findPartialSetter finds the setter matching the name if one exists
func (fs *fieldSetter) findSetter(field *yaml.RNode) (
*fieldmeta.PartialFieldSetter, *fieldmeta.FieldMeta, bool, error) {
// check if there are any substitutions for this field
var fm = &fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return nil, nil, false, err
}
if fs.SetBy != "" {
fm.Extensions.SetBy = fs.SetBy
}
if fs.Description != "" {
fm.Schema.Description = fs.Description
}
if fm.Extensions.FieldSetter != nil && fm.Extensions.FieldSetter.Name == fs.Name {
return fm.Extensions.FieldSetter, fm, false, nil
}
// check if there is a matching substitution
for i := range fm.Extensions.PartialFieldSetters {
if fm.Extensions.PartialFieldSetters[i].Name == fs.Name {
return &fm.Extensions.PartialFieldSetters[i], fm, true, nil
}
}
return nil, nil, false, nil
}
// set performs the substitution for the given field, substitution, and metadata
func (fs *fieldSetter) set(
field *yaml.RNode, s *fieldmeta.PartialFieldSetter,
f *fieldmeta.FieldMeta, partial bool) error {
if s.Value == fs.Value || !strings.Contains(field.YNode().Value, s.Value) {
// no substitutions necessary -- already substituted or doesn't have the set value
// which acts as a marker
return nil
}
// record that the config has been modified
fs.Count++
if !partial {
// full setter
field.YNode().Value = fs.Value
} else {
// replace the current value with the new value
field.YNode().Value = strings.ReplaceAll(field.YNode().Value, s.Value, fs.Value)
}
// be sure to set the tag to the matching type so the yaml doesn't incorrectly quote
//integers or booleans as strings
fType := fieldmeta.FieldValueType(f.Schema.Type[0])
if err := fType.Validate(field.YNode().Value); err != nil {
return err
}
field.YNode().Tag = fType.Tag()
// update the comment on the field
s.Value = fs.Value
if err := f.Write(field); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,65 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package setters
import (
"sort"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ kio.Filter = &LookupSetters{}
// LookupSetters identifies setters for a collection of Resources
type LookupSetters struct {
// Name is the name of the setter to match. Optional.
Name string
// SetterCounts is populated by Filter and contains the count of fields matching each setter.
SetterCounts []setterCount
}
// setterCount records the identified setters and number of fields matching those setters
type setterCount struct {
// Count is the number of substitutions possible to perform
Count int
// setter is the substitution found
setter
}
// Filter implements kio.Filter
func (l *LookupSetters) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
setters := map[string]*setterCount{}
for i := range input {
// lookup substitutions for this object
ls := &lookupSetters{Name: l.Name}
if err := input[i].PipeE(ls); err != nil {
return nil, err
}
// aggregate counts for each setter by name. takes the description and value from
// the first setter for each name encountered.
for j := range ls.Setters {
setter := ls.Setters[j]
curr, found := setters[setter.Name]
if !found {
curr = &setterCount{setter: setter}
setters[setter.Name] = curr
}
curr.Count++
}
}
// pull out and sort the results by setter name
for _, v := range setters {
l.SetterCounts = append(l.SetterCounts, *v)
}
sort.Slice(l.SetterCounts, func(i, j int) bool {
return l.SetterCounts[i].Name < l.SetterCounts[j].Name
})
return input, nil
}

View File

@@ -0,0 +1,86 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package setters
import (
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
var _ yaml.Filter = &lookupSetters{}
// lookupSetters looks up setters for a Resource
type lookupSetters struct {
// Name of the setter to lookup. Optional
Name string
// Setters is a list of setters that were found
Setters []setter
}
type setter struct {
fieldmeta.PartialFieldSetter
Description string
Type string
SetBy string
}
func (ls *lookupSetters) Filter(object *yaml.RNode) (*yaml.RNode, error) {
switch object.YNode().Kind {
case yaml.DocumentNode:
// skip the document node
return ls.Filter(yaml.NewRNode(object.YNode().Content[0]))
case yaml.MappingNode:
return object, object.VisitFields(func(node *yaml.MapNode) error {
return node.Value.PipeE(ls)
})
case yaml.SequenceNode:
return object, object.VisitElements(func(node *yaml.RNode) error {
return node.PipeE(ls)
})
case yaml.ScalarNode:
return object, ls.lookup(object)
default:
return object, nil
}
}
// lookup finds any setters for a field
func (ls *lookupSetters) lookup(field *yaml.RNode) error {
// check if there is a substitution for this field
var fm = &fieldmeta.FieldMeta{}
if err := fm.Read(field); err != nil {
return err
}
if fm.Extensions.FieldSetter != nil {
if ls.Name != "" && ls.Name != fm.Extensions.FieldSetter.Name {
// skip this setter, it doesn't match the specified setter
return nil
}
// full setter
ls.Setters = append(ls.Setters, setter{
PartialFieldSetter: *fm.Extensions.FieldSetter,
Description: fm.Schema.Description,
Type: fm.Schema.Type[0],
SetBy: fm.Extensions.SetBy,
})
return nil
}
// partial setters
for i := range fm.Extensions.PartialFieldSetters {
if ls.Name != "" && ls.Name != fm.Extensions.PartialFieldSetters[i].Name {
// skip this setter
continue
}
ls.Setters = append(ls.Setters, setter{
PartialFieldSetter: fm.Extensions.PartialFieldSetters[i],
Description: fm.Schema.Description,
Type: fm.Schema.Type[0],
SetBy: fm.Extensions.SetBy,
})
}
return nil
}

View File

@@ -3,6 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/annotationstransformer
go 1.13
require (
sigs.k8s.io/kustomize/api v0.3.0
gopkg.in/yaml.v2 v2.2.7 // indirect
sigs.k8s.io/kustomize/api v0.3.1
sigs.k8s.io/yaml v1.1.0
)

View File

@@ -2,14 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -46,14 +42,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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=
@@ -103,12 +94,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -122,12 +110,9 @@ github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvL
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
@@ -139,8 +124,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -153,25 +136,15 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -206,9 +179,7 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
@@ -223,8 +194,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.0/go.mod h1:N1/ppRG9CaPeUKAUHZ3dUlfOT81lTpKZLkyhCvTETwM=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -257,17 +226,13 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -292,13 +257,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
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/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -319,7 +282,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -342,7 +304,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -369,7 +330,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -379,7 +339,6 @@ 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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -398,8 +357,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -423,7 +380,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -431,6 +387,8 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
@@ -447,16 +405,12 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.2.0/go.mod h1:zVtMg179jW1gr74jo9fc2Ac9dLYLTZZThc3DDb9lDW4=
sigs.k8s.io/kustomize/api v0.3.0 h1:e7Erw2n8lT8+IWUukktozF0bgWwH2fFC+qsXP0gabg0=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:4jaPCtRzxfQLFdYq4gYo40dBGW1hyPp/f4AuiZB5dAQ=
sigs.k8s.io/kustomize/pluginator/v2 v2.0.0/go.mod h1:zrXhTv8BAKt0egmZX/8AtMOSFUSWM9YuoHvvqz8/eHE=
sigs.k8s.io/kustomize/pseudo/k8s v0.1.0/go.mod h1:bl/gVJgYYhJZCZdYU2BfnaKYAlqFkgbJEkpl302jEss=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -3,6 +3,7 @@ module sigs.k8s.io/kustomize/plugin/builtin/configmapgenerator
go 1.13
require (
sigs.k8s.io/kustomize/api v0.3.0
gopkg.in/yaml.v2 v2.2.7 // indirect
sigs.k8s.io/kustomize/api v0.3.1
sigs.k8s.io/yaml v1.1.0
)

View File

@@ -2,14 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -46,14 +42,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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=
@@ -103,12 +94,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -122,12 +110,9 @@ github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvL
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
@@ -139,8 +124,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -153,25 +136,15 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -206,9 +179,7 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
@@ -223,8 +194,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.0/go.mod h1:N1/ppRG9CaPeUKAUHZ3dUlfOT81lTpKZLkyhCvTETwM=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -257,17 +226,13 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -292,13 +257,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
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/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -319,7 +282,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -342,7 +304,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -369,7 +330,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -379,7 +339,6 @@ 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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -398,8 +357,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -423,7 +380,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -431,6 +387,8 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
@@ -447,16 +405,12 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.2.0/go.mod h1:zVtMg179jW1gr74jo9fc2Ac9dLYLTZZThc3DDb9lDW4=
sigs.k8s.io/kustomize/api v0.3.0 h1:e7Erw2n8lT8+IWUukktozF0bgWwH2fFC+qsXP0gabg0=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:4jaPCtRzxfQLFdYq4gYo40dBGW1hyPp/f4AuiZB5dAQ=
sigs.k8s.io/kustomize/pluginator/v2 v2.0.0/go.mod h1:zrXhTv8BAKt0egmZX/8AtMOSFUSWM9YuoHvvqz8/eHE=
sigs.k8s.io/kustomize/pseudo/k8s v0.1.0/go.mod h1:bl/gVJgYYhJZCZdYU2BfnaKYAlqFkgbJEkpl302jEss=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -2,4 +2,4 @@ module sigs.k8s.io/kustomize/plugin/builtin/hashtransformer
go 1.13
require sigs.k8s.io/kustomize/api v0.3.0
require sigs.k8s.io/kustomize/api v0.3.1

View File

@@ -2,14 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -46,14 +42,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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=
@@ -103,12 +94,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -122,12 +110,9 @@ github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvL
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
@@ -139,8 +124,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -153,25 +136,15 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -206,9 +179,7 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
@@ -223,8 +194,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.0/go.mod h1:N1/ppRG9CaPeUKAUHZ3dUlfOT81lTpKZLkyhCvTETwM=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -257,17 +226,13 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -292,13 +257,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
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/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -319,7 +282,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -342,7 +304,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -369,7 +330,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -379,7 +339,6 @@ 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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -398,8 +357,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -423,7 +380,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -447,16 +403,12 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.2.0/go.mod h1:zVtMg179jW1gr74jo9fc2Ac9dLYLTZZThc3DDb9lDW4=
sigs.k8s.io/kustomize/api v0.3.0 h1:e7Erw2n8lT8+IWUukktozF0bgWwH2fFC+qsXP0gabg0=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:4jaPCtRzxfQLFdYq4gYo40dBGW1hyPp/f4AuiZB5dAQ=
sigs.k8s.io/kustomize/pluginator/v2 v2.0.0/go.mod h1:zrXhTv8BAKt0egmZX/8AtMOSFUSWM9YuoHvvqz8/eHE=
sigs.k8s.io/kustomize/pseudo/k8s v0.1.0/go.mod h1:bl/gVJgYYhJZCZdYU2BfnaKYAlqFkgbJEkpl302jEss=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -3,6 +3,6 @@ module sigs.k8s.io/kustomize/plugin/builtin/imagetagtransformer
go 1.13
require (
sigs.k8s.io/kustomize/api v0.3.0
sigs.k8s.io/kustomize/api v0.3.1
sigs.k8s.io/yaml v1.1.0
)

View File

@@ -2,14 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -46,14 +42,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.6+incompatible h1:tfrHha8zJ01ywiOEC1miGY8st1/igzWB8OmvPgoYX7w=
github.com/emicklei/go-restful v2.9.6+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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=
@@ -103,12 +94,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -122,12 +110,9 @@ github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvL
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.19.1/go.mod h1:2CEc4Fxx3vxDv7g8DyXkHCBF73AOzAymcJAprs2vCps=
github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
@@ -139,8 +124,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -153,25 +136,15 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0 h1:CcQijm0XKekKjP/YCz28LXVSpgguuB+nCxaSjCe09y0=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -206,9 +179,7 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matoous/godox v0.0.0-20190910121045-032ad8106c86/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
@@ -223,8 +194,6 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monopole/mdrip v1.0.0/go.mod h1:N1/ppRG9CaPeUKAUHZ3dUlfOT81lTpKZLkyhCvTETwM=
github.com/monopole/mdrip v1.0.1/go.mod h1:/7E04hlzRG9Jrp6WILZfYYm/REoJWL2l+MlsCO1eH74=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -257,17 +226,13 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218/go.mod h1:q6oYAujd2qyeU4cJqIri4LBIgdHXGvxWHZ1E29HNFRE=
github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
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/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -292,13 +257,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
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/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.3/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -319,7 +282,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -342,7 +304,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -369,7 +330,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -379,7 +339,6 @@ 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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -398,8 +357,6 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190912215617-3720d1ec3678/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -423,7 +380,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -447,16 +403,12 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
sigs.k8s.io/kustomize/api v0.2.0/go.mod h1:zVtMg179jW1gr74jo9fc2Ac9dLYLTZZThc3DDb9lDW4=
sigs.k8s.io/kustomize/api v0.3.0 h1:e7Erw2n8lT8+IWUukktozF0bgWwH2fFC+qsXP0gabg0=
sigs.k8s.io/kustomize/api v0.3.0/go.mod h1:4jaPCtRzxfQLFdYq4gYo40dBGW1hyPp/f4AuiZB5dAQ=
sigs.k8s.io/kustomize/pluginator/v2 v2.0.0/go.mod h1:zrXhTv8BAKt0egmZX/8AtMOSFUSWM9YuoHvvqz8/eHE=
sigs.k8s.io/kustomize/pseudo/k8s v0.1.0/go.mod h1:bl/gVJgYYhJZCZdYU2BfnaKYAlqFkgbJEkpl302jEss=
sigs.k8s.io/kustomize/api v0.3.1 h1:oqMIXvS6tFEUVuKIRUKDa05eC4Hh+cb9JYg8Zhp2d24=
sigs.k8s.io/kustomize/api v0.3.1/go.mod h1:A+ATnlHqzictQfQC1q3KB/T6MSr0UWQsrrLxMWkge2E=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

Some files were not shown because too many files have changed in this diff Show More