mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
kyaml: Add kyaml filters as cli commands
This commit is contained in:
54
cmd/kyaml/.golangci.yml
Normal file
54
cmd/kyaml/.golangci.yml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
run:
|
||||||
|
deadline: 5m
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- depguard
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
# - errcheck
|
||||||
|
# - funlen
|
||||||
|
# - gochecknoinits
|
||||||
|
# - goconst
|
||||||
|
# - gocritic
|
||||||
|
- gocyclo
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
# - golint
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- interfacer
|
||||||
|
# - lll
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
# - scopelint
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
# - stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
# - unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
# - whitespace
|
||||||
|
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
dupl:
|
||||||
|
threshold: 400
|
||||||
|
lll:
|
||||||
|
line-length: 170
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 30
|
||||||
|
golint:
|
||||||
|
min-confidence: 0.85
|
||||||
2
cmd/kyaml/LICENSE_TEMPLATE
Normal file
2
cmd/kyaml/LICENSE_TEMPLATE
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Copyright {{.Year}} {{.Holder}}
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
38
cmd/kyaml/Makefile
Normal file
38
cmd/kyaml/Makefile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
.PHONY: generate license fix vet fmt test build tidy
|
||||||
|
|
||||||
|
GOPATH := $(shell go env GOPATH)
|
||||||
|
|
||||||
|
build:
|
||||||
|
go build -v -o $(GOPATH)/bin/kyaml .
|
||||||
|
|
||||||
|
all: generate license fix vet fmt test lint tidy
|
||||||
|
|
||||||
|
fix:
|
||||||
|
go fix ./...
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
generate:
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
license:
|
||||||
|
(which $(GOPATH)/bin/addlicense || go get github.com/google/addlicense)
|
||||||
|
$(GOPATH)/bin/addlicense -y 2019 -c "The Kubernetes Authors." -f LICENSE_TEMPLATE .
|
||||||
|
|
||||||
|
tidy:
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
lint:
|
||||||
|
(which $(GOPATH)/bin/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||||
|
$(GOPATH)/bin/golangci-lint run ./...
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test -cover ./...
|
||||||
|
|
||||||
|
vet:
|
||||||
|
go vet ./...
|
||||||
|
|
||||||
4
cmd/kyaml/README.md
Normal file
4
cmd/kyaml/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# cmd/kyaml
|
||||||
|
|
||||||
|
This package exists to expose kyaml filters directly as cli commands for the purposes
|
||||||
|
of development of the kyaml package and as a reference implementation for using the libraries.
|
||||||
130
cmd/kyaml/cmd/cat.go
Normal file
130
cmd/kyaml/cmd/cat.go
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCatRunner returns a command CatRunner.
|
||||||
|
func GetCatRunner() *CatRunner {
|
||||||
|
r := &CatRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "cat DIR...",
|
||||||
|
Short: "Print Resource Config from a local directory",
|
||||||
|
Long: `Print Resource Config from a local directory.
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
`,
|
||||||
|
Example: `# print Resource config from a directory
|
||||||
|
kyaml cat my-dir/
|
||||||
|
|
||||||
|
# wrap Resource config from a directory in an ResourceList
|
||||||
|
kyaml cat my-dir/ --wrap-kind ResourceList --wrap-version kyaml.kustomize.dev/v1alpha1 --function-config fn.yaml
|
||||||
|
|
||||||
|
# unwrap Resource config from a directory in an ResourceList
|
||||||
|
... | kyaml cat
|
||||||
|
`,
|
||||||
|
RunE: r.runE,
|
||||||
|
}
|
||||||
|
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
|
||||||
|
"also print resources from subpackages.")
|
||||||
|
c.Flags().BoolVar(&r.Format, "format", true,
|
||||||
|
"format resource config yaml before printing.")
|
||||||
|
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", false,
|
||||||
|
"annotate resources with their file origins.")
|
||||||
|
c.Flags().StringVar(&r.WrapKind, "wrap-kind", "",
|
||||||
|
"if set, wrap the output in this list type kind.")
|
||||||
|
c.Flags().StringVar(&r.WrapApiVersion, "wrap-version", "",
|
||||||
|
"if set, wrap the output in this list type apiVersion.")
|
||||||
|
c.Flags().StringVar(&r.FunctionConfig, "function-config", "",
|
||||||
|
"path to function config to put in ResourceList -- only if wrapped in a ResourceList.")
|
||||||
|
c.Flags().StringSliceVar(&r.Styles, "style", []string{},
|
||||||
|
"yaml styles to apply. may be 'TaggedStyle', 'DoubleQuotedStyle', 'LiteralStyle', "+
|
||||||
|
"'FoldedStyle', 'FlowStyle'.")
|
||||||
|
c.Flags().BoolVar(&r.StripComments, "strip-comments", false,
|
||||||
|
"remove comments from yaml.")
|
||||||
|
c.Flags().BoolVar(&r.IncludeReconcilers, "include-reconcilers", false,
|
||||||
|
"if true, include reconciler Resources in the output.")
|
||||||
|
c.Flags().BoolVar(&r.ExcludeNonReconcilers, "exclude-non-reconcilers", false,
|
||||||
|
"if true, exclude non-reconciler Resources in the output.")
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func CatCommand() *cobra.Command {
|
||||||
|
return GetCatRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// CatRunner contains the run function
|
||||||
|
type CatRunner struct {
|
||||||
|
IncludeSubpackages bool
|
||||||
|
Format bool
|
||||||
|
KeepAnnotations bool
|
||||||
|
WrapKind string
|
||||||
|
WrapApiVersion string
|
||||||
|
FunctionConfig string
|
||||||
|
Styles []string
|
||||||
|
StripComments bool
|
||||||
|
IncludeReconcilers bool
|
||||||
|
ExcludeNonReconcilers bool
|
||||||
|
Command *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CatRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
// if there is a function-config specified, emit it
|
||||||
|
var functionConfig *yaml.RNode
|
||||||
|
if r.FunctionConfig != "" {
|
||||||
|
configs, err := kio.LocalPackageReader{PackagePath: r.FunctionConfig,
|
||||||
|
OmitReaderAnnotations: !r.KeepAnnotations}.Read()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(configs) != 1 {
|
||||||
|
return fmt.Errorf("expected exactly 1 functionConfig, found %d", len(configs))
|
||||||
|
}
|
||||||
|
functionConfig = configs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var inputs []kio.Reader
|
||||||
|
for _, a := range args {
|
||||||
|
inputs = append(inputs, kio.LocalPackageReader{
|
||||||
|
PackagePath: a,
|
||||||
|
IncludeSubpackages: r.IncludeSubpackages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(inputs) == 0 {
|
||||||
|
inputs = append(inputs, &kio.ByteReader{Reader: c.InOrStdin()})
|
||||||
|
}
|
||||||
|
var fltr []kio.Filter
|
||||||
|
// don't include reconcilers
|
||||||
|
fltr = append(fltr, &filters.IsReconcilerFilter{
|
||||||
|
ExcludeReconcilers: !r.IncludeReconcilers,
|
||||||
|
IncludeNonReconcilers: !r.ExcludeNonReconcilers,
|
||||||
|
})
|
||||||
|
if r.Format {
|
||||||
|
fltr = append(fltr, filters.FormatFilter{})
|
||||||
|
}
|
||||||
|
if r.StripComments {
|
||||||
|
fltr = append(fltr, filters.StripCommentsFilter{})
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputs []kio.Writer
|
||||||
|
outputs = append(outputs, kio.ByteWriter{
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
KeepReaderAnnotations: r.KeepAnnotations,
|
||||||
|
WrappingKind: r.WrapKind,
|
||||||
|
WrappingApiVersion: r.WrapApiVersion,
|
||||||
|
FunctionConfig: functionConfig,
|
||||||
|
Style: yaml.GetStyle(r.Styles...),
|
||||||
|
})
|
||||||
|
|
||||||
|
return kio.Pipeline{Inputs: inputs, Filters: fltr, Outputs: outputs}.Execute()
|
||||||
|
}
|
||||||
304
cmd/kyaml/cmd/cat_test.go
Normal file
304
cmd/kyaml/cmd/cat_test.go
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(pwittrock): write tests for reading / writing ResourceLists
|
||||||
|
|
||||||
|
func TestCmd_files(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-cat-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/image:version
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetCatRunner()
|
||||||
|
r.Command.SetArgs([]string{d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: bar
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f2.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmd_filesWithReconcilers(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-cat-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/image:version
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetCatRunner()
|
||||||
|
r.Command.SetArgs([]string{d, "--include-reconcilers"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
---
|
||||||
|
apiVersion: gcr.io/example/image:version
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f2.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f2.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmd_filesWithoutNonReconcilers(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-cat-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/image:version
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetCatRunner()
|
||||||
|
r.Command.SetArgs([]string{d, "--include-reconcilers", "--exclude-non-reconcilers"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `apiVersion: gcr.io/example/image:version
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f2.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
92
cmd/kyaml/cmd/count.go
Normal file
92
cmd/kyaml/cmd/count.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetCountRunner() *CountRunner {
|
||||||
|
r := &CountRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "count DIR...",
|
||||||
|
Short: "Count Resources Config from a local directory",
|
||||||
|
Long: `Count Resources Config from a local directory.
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
`,
|
||||||
|
Example: `# print Resource counts from a directory
|
||||||
|
kyaml count my-dir/
|
||||||
|
`,
|
||||||
|
RunE: r.runE,
|
||||||
|
}
|
||||||
|
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
|
||||||
|
"also print resources from subpackages.")
|
||||||
|
c.Flags().BoolVar(&r.Kind, "kind", true,
|
||||||
|
"count resources by kind.")
|
||||||
|
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountCommand() *cobra.Command {
|
||||||
|
return GetCountRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountRunner contains the run function
|
||||||
|
type CountRunner struct {
|
||||||
|
IncludeSubpackages bool
|
||||||
|
Kind bool
|
||||||
|
Command *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CountRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
var inputs []kio.Reader
|
||||||
|
for _, a := range args {
|
||||||
|
inputs = append(inputs, kio.LocalPackageReader{
|
||||||
|
PackagePath: a,
|
||||||
|
IncludeSubpackages: r.IncludeSubpackages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(inputs) == 0 {
|
||||||
|
inputs = append(inputs, &kio.ByteReader{Reader: c.InOrStdin()})
|
||||||
|
}
|
||||||
|
|
||||||
|
var out []kio.Writer
|
||||||
|
if r.Kind {
|
||||||
|
out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error {
|
||||||
|
count := map[string]int{}
|
||||||
|
k := sets.String{}
|
||||||
|
for _, n := range nodes {
|
||||||
|
m, _ := n.GetMeta()
|
||||||
|
count[m.Kind]++
|
||||||
|
k.Insert(m.Kind)
|
||||||
|
}
|
||||||
|
order := k.List()
|
||||||
|
sort.Strings(order)
|
||||||
|
for _, k := range order {
|
||||||
|
fmt.Fprintf(c.OutOrStdout(), "%s: %d\n", k, count[k])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error {
|
||||||
|
fmt.Fprintf(c.OutOrStdout(), "%d\n", len(nodes))
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return kio.Pipeline{
|
||||||
|
Inputs: inputs,
|
||||||
|
Outputs: out,
|
||||||
|
}.Execute()
|
||||||
|
}
|
||||||
73
cmd/kyaml/cmd/count_test.go
Normal file
73
cmd/kyaml/cmd/count_test.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCountCommand_files(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-count-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetCountRunner()
|
||||||
|
r.Command.SetArgs([]string{d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, "Deployment: 2\nService: 1\n", b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
127
cmd/kyaml/cmd/fmt.go
Normal file
127
cmd/kyaml/cmd/fmt.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FmtCmd returns a command FmtRunner.
|
||||||
|
func GetFmtRunner() *FmtRunner {
|
||||||
|
r := &FmtRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "fmt",
|
||||||
|
Short: "Format yaml configuration files",
|
||||||
|
Long: `Format yaml configuration files
|
||||||
|
|
||||||
|
Fmt will format input by ordering fields and unordered list items in Kubernetes
|
||||||
|
objects. Inputs may be directories, files or stdin, and their contents must
|
||||||
|
include both apiVersion and kind fields.
|
||||||
|
|
||||||
|
- Stdin inputs are formatted and written to stdout
|
||||||
|
- File inputs (args) are formatted and written back to the file
|
||||||
|
- Directory inputs (args) are walked, each encountered .yaml and .yml file
|
||||||
|
acts as an input
|
||||||
|
|
||||||
|
For inputs which contain multiple yaml documents separated by \n---\n,
|
||||||
|
each document will be formatted and written back to the file in the original
|
||||||
|
order.
|
||||||
|
|
||||||
|
Field ordering roughly follows the ordering defined in the source Kubernetes
|
||||||
|
resource definitions (i.e. go structures), falling back on lexicographical
|
||||||
|
sorting for unrecognized fields.
|
||||||
|
|
||||||
|
Unordered list item ordering is defined for specific Resource types and
|
||||||
|
field paths.
|
||||||
|
|
||||||
|
- .spec.template.spec.containers (by element name)
|
||||||
|
- .webhooks.rules.operations (by element value)
|
||||||
|
`,
|
||||||
|
Example: `
|
||||||
|
# format file1.yaml and file2.yml
|
||||||
|
kyaml fmt file1.yaml file2.yml
|
||||||
|
|
||||||
|
# format all *.yaml and *.yml recursively traversing directories
|
||||||
|
kyaml fmt my-dir/
|
||||||
|
|
||||||
|
# format kubectl output
|
||||||
|
kubectl get -o yaml deployments | kyaml fmt
|
||||||
|
|
||||||
|
# format kustomize output
|
||||||
|
kustomize build | kyaml fmt
|
||||||
|
`,
|
||||||
|
RunE: r.runE,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
|
}
|
||||||
|
c.Flags().StringVar(&r.FilenamePattern, "pattern", filters.DefaultFilenamePattern,
|
||||||
|
`pattern to use for generating filenames for resources -- may contain the following
|
||||||
|
formatting substitution verbs {'%n': 'metadata.name', '%s': 'metadata.namespace', '%k': 'kind'}`)
|
||||||
|
c.Flags().BoolVar(&r.SetFilenames, "set-filenames", false,
|
||||||
|
`if true, set default filenames on Resources without them`)
|
||||||
|
c.Flags().BoolVar(&r.KeepAnnotations, "keep-annotations", false,
|
||||||
|
`if true, keep index and filename annotations set on Resources.`)
|
||||||
|
c.Flags().BoolVar(&r.Override, "override", false,
|
||||||
|
`if true, override existing filepath annotations.`)
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func FmtCommand() *cobra.Command {
|
||||||
|
return GetFmtRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// FmtRunner contains the run function
|
||||||
|
type FmtRunner struct {
|
||||||
|
Command *cobra.Command
|
||||||
|
FilenamePattern string
|
||||||
|
SetFilenames bool
|
||||||
|
KeepAnnotations bool
|
||||||
|
Override bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *FmtRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
|
if r.SetFilenames {
|
||||||
|
r.KeepAnnotations = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *FmtRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
f := []kio.Filter{filters.FormatFilter{}}
|
||||||
|
|
||||||
|
// format with file names
|
||||||
|
if r.SetFilenames {
|
||||||
|
f = append(f, &filters.FileSetter{
|
||||||
|
FilenamePattern: r.FilenamePattern,
|
||||||
|
Override: r.Override,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// format stdin if there are no args
|
||||||
|
if len(args) == 0 {
|
||||||
|
rw := &kio.ByteReadWriter{
|
||||||
|
Reader: c.InOrStdin(),
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
KeepReaderAnnotations: r.KeepAnnotations,
|
||||||
|
}
|
||||||
|
return kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{rw}, Filters: f, Outputs: []kio.Writer{rw}}.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range args {
|
||||||
|
path := args[i]
|
||||||
|
rw := &kio.LocalPackageReadWriter{
|
||||||
|
NoDeleteFiles: true,
|
||||||
|
PackagePath: path,
|
||||||
|
KeepReaderAnnotations: r.KeepAnnotations}
|
||||||
|
err := kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{rw}, Filters: f, Outputs: []kio.Writer{rw}}.Execute()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
162
cmd/kyaml/cmd/fmt_test.go
Normal file
162
cmd/kyaml/cmd/fmt_test.go
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters/testyaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestCmd_files verifies the fmt command formats the files
|
||||||
|
func TestFmtCommand_files(t *testing.T) {
|
||||||
|
f1, err := ioutil.TempFile("", "cmdfmt*.yaml")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(f1.Name())
|
||||||
|
err = ioutil.WriteFile(f1.Name(), testyaml.UnformattedYaml1, 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f2, err := ioutil.TempFile("", "cmdfmt*.yaml")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(f2.Name())
|
||||||
|
err = ioutil.WriteFile(f2.Name(), testyaml.UnformattedYaml2, 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
r := cmd.GetFmtRunner()
|
||||||
|
r.Command.SetArgs([]string{f1.Name(), f2.Name()})
|
||||||
|
err = r.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the contents
|
||||||
|
b, err := ioutil.ReadFile(f1.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, string(testyaml.FormattedYaml1), string(b)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = ioutil.ReadFile(f2.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, string(testyaml.FormattedYaml2), string(b)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFmtCommand_stdin(t *testing.T) {
|
||||||
|
out := &bytes.Buffer{}
|
||||||
|
r := cmd.GetFmtRunner()
|
||||||
|
r.Command.SetOut(out)
|
||||||
|
r.Command.SetIn(bytes.NewReader(testyaml.UnformattedYaml1))
|
||||||
|
|
||||||
|
// fmt the input
|
||||||
|
err := r.Command.Execute()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// verify the output
|
||||||
|
assert.Equal(t, string(testyaml.FormattedYaml1), out.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCmd_filesAndstdin verifies that if both files and stdin input are provided, only
|
||||||
|
// the files are formatted and the input is ignored
|
||||||
|
func TestFmtCmd_filesAndStdin(t *testing.T) {
|
||||||
|
f1, err := ioutil.TempFile("", "cmdfmt*.yaml")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(f1.Name(), testyaml.UnformattedYaml1, 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f2, err := ioutil.TempFile("", "cmdfmt*.yaml")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(f2.Name(), testyaml.UnformattedYaml2, 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out := &bytes.Buffer{}
|
||||||
|
in := &bytes.Buffer{}
|
||||||
|
r := cmd.GetFmtRunner()
|
||||||
|
r.Command.SetOut(out)
|
||||||
|
r.Command.SetIn(in)
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
r = cmd.GetFmtRunner()
|
||||||
|
r.Command.SetArgs([]string{f1.Name(), f2.Name()})
|
||||||
|
err = r.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the output
|
||||||
|
b, err := ioutil.ReadFile(f1.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, string(testyaml.FormattedYaml1), string(b)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = ioutil.ReadFile(f2.Name())
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, string(testyaml.FormattedYaml2), string(b)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = r.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, "", out.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCmd_files verifies the fmt command formats the files
|
||||||
|
func TestCmd_failFiles(t *testing.T) {
|
||||||
|
// fmt the files
|
||||||
|
r := cmd.GetFmtRunner()
|
||||||
|
r.Command.SetArgs([]string{"notrealfile"})
|
||||||
|
err := r.Command.Execute()
|
||||||
|
assert.EqualError(t, err, "lstat notrealfile: no such file or directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCmd_files verifies the fmt command formats the files
|
||||||
|
func TestCmd_failFileContents(t *testing.T) {
|
||||||
|
out := &bytes.Buffer{}
|
||||||
|
r := cmd.GetFmtRunner()
|
||||||
|
r.Command.SetOut(out)
|
||||||
|
r.Command.SetIn(strings.NewReader(`{`))
|
||||||
|
|
||||||
|
// fmt the input
|
||||||
|
err := r.Command.Execute()
|
||||||
|
|
||||||
|
// expect an error
|
||||||
|
assert.EqualError(t, err, "yaml: line 1: did not find expected node content")
|
||||||
|
}
|
||||||
144
cmd/kyaml/cmd/grep.go
Normal file
144
cmd/kyaml/cmd/grep.go
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cmd returns a command GrepRunner.
|
||||||
|
func GetGrepRunner() *GrepRunner {
|
||||||
|
r := &GrepRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "grep QUERY [DIR]...",
|
||||||
|
Short: "Search for matching Resources in a directory or from stdin",
|
||||||
|
Long: `Search for matching Resources in a directory or from stdin.
|
||||||
|
QUERY:
|
||||||
|
Query to match expressed as 'path.to.field=value'.
|
||||||
|
Maps and fields are matched as '.field-name' or '.map-key'
|
||||||
|
List elements are matched as '[list-elem-field=field-value]'
|
||||||
|
The value to match is expressed as '=value'
|
||||||
|
'.' as part of a key or value can be escaped as '\.'
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
`,
|
||||||
|
Example: `# find Deployment Resources
|
||||||
|
kyaml grep "kind=Deployment" my-dir/
|
||||||
|
|
||||||
|
# find Resources named nginx
|
||||||
|
kyaml grep "metadata.name=nginx" my-dir/
|
||||||
|
|
||||||
|
# use tree to display matching Resources
|
||||||
|
kyaml grep "metadata.name=nginx" my-dir/ | kyaml tree
|
||||||
|
|
||||||
|
# look for Resources matching a specific container image
|
||||||
|
kyaml grep "spec.template.spec.containers[name=nginx].image=nginx:1\.7\.9" my-dir/ | kyaml tree
|
||||||
|
`,
|
||||||
|
PreRunE: r.preRunE,
|
||||||
|
RunE: r.runE,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
}
|
||||||
|
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
|
||||||
|
"also print resources from subpackages.")
|
||||||
|
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", true,
|
||||||
|
"annotate resources with their file origins.")
|
||||||
|
c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "v", false,
|
||||||
|
" Selected Resources are those not matching any of the specified patterns..")
|
||||||
|
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func GrepCommand() *cobra.Command {
|
||||||
|
return GetGrepRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// GrepRunner contains the run function
|
||||||
|
type GrepRunner struct {
|
||||||
|
IncludeSubpackages bool
|
||||||
|
KeepAnnotations bool
|
||||||
|
Command *cobra.Command
|
||||||
|
filters.GrepFilter
|
||||||
|
Format bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error {
|
||||||
|
r.GrepFilter.Compare = func(a, b string) (int, error) {
|
||||||
|
qa, err := resource.ParseQuantity(a)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("%s: %v", a, err)
|
||||||
|
}
|
||||||
|
qb, err := resource.ParseQuantity(b)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return qa.Cmp(qb), err
|
||||||
|
}
|
||||||
|
parts, err := parseFieldPath(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var last []string
|
||||||
|
if strings.Contains(parts[len(parts)-1], ">=") {
|
||||||
|
last = strings.Split(parts[len(parts)-1], ">=")
|
||||||
|
r.MatchType = filters.GreaterThanEq
|
||||||
|
} else if strings.Contains(parts[len(parts)-1], "<=") {
|
||||||
|
last = strings.Split(parts[len(parts)-1], "<=")
|
||||||
|
r.MatchType = filters.LessThanEq
|
||||||
|
} else if strings.Contains(parts[len(parts)-1], ">") {
|
||||||
|
last = strings.Split(parts[len(parts)-1], ">")
|
||||||
|
r.MatchType = filters.GreaterThan
|
||||||
|
} else if strings.Contains(parts[len(parts)-1], "<") {
|
||||||
|
last = strings.Split(parts[len(parts)-1], "<")
|
||||||
|
r.MatchType = filters.LessThan
|
||||||
|
} else {
|
||||||
|
last = strings.Split(parts[len(parts)-1], "=")
|
||||||
|
r.MatchType = filters.Regexp
|
||||||
|
}
|
||||||
|
if len(last) > 2 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"ambiguous match -- multiple of ['<', '>', '<=', '>=', '=' in final path element: %s",
|
||||||
|
parts[len(parts)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(last) > 1 {
|
||||||
|
r.Value = last[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Path = append(parts[:len(parts)-1], last[0])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GrepRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
var filters = []kio.Filter{r.GrepFilter}
|
||||||
|
|
||||||
|
var inputs []kio.Reader
|
||||||
|
for _, a := range args[1:] {
|
||||||
|
inputs = append(inputs, kio.LocalPackageReader{
|
||||||
|
PackagePath: a,
|
||||||
|
IncludeSubpackages: r.IncludeSubpackages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(inputs) == 0 {
|
||||||
|
inputs = append(inputs, &kio.ByteReader{Reader: c.InOrStdin()})
|
||||||
|
}
|
||||||
|
|
||||||
|
return kio.Pipeline{
|
||||||
|
Inputs: inputs,
|
||||||
|
Filters: filters,
|
||||||
|
Outputs: []kio.Writer{kio.ByteWriter{
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
KeepReaderAnnotations: r.KeepAnnotations,
|
||||||
|
}},
|
||||||
|
}.Execute()
|
||||||
|
}
|
||||||
272
cmd/kyaml/cmd/grep_test.go
Normal file
272
cmd/kyaml/cmd/grep_test.go
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestGrepCommand_files verifies grep reads the files and filters them
|
||||||
|
func TestGrepCommand_files(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-kyaml-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetGrepRunner()
|
||||||
|
r.Command.SetArgs([]string{"metadata.name=foo", d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/index: 0
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/index: 1
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCmd_stdin verifies the grep command reads stdin if no files are provided
|
||||||
|
func TestGrepCmd_stdin(t *testing.T) {
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetGrepRunner()
|
||||||
|
r.Command.SetArgs([]string{"metadata.name=foo"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`))
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/index: 0
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/index: 1
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestGrepCmd_errInputs verifies the grep command errors on invalid matches
|
||||||
|
func TestGrepCmd_errInputs(t *testing.T) {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetGrepRunner()
|
||||||
|
r.Command.SetArgs([]string{"metadata.name=foo=bar"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
`))
|
||||||
|
err := r.Command.Execute()
|
||||||
|
if !assert.Error(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Contains(t, err.Error(), "ambiguous match")
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b = &bytes.Buffer{}
|
||||||
|
r = cmd.GetGrepRunner()
|
||||||
|
r.Command.SetArgs([]string{"spec.template.spec.containers[a[b=c].image=foo"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
`))
|
||||||
|
err = r.Command.Execute()
|
||||||
|
if !assert.Error(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Contains(t, err.Error(), "unrecognized path element:")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestGrepCommand_escapeDots verifies the grep command correctly escapes '\.' in inputs
|
||||||
|
func TestGrepCommand_escapeDots(t *testing.T) {
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetGrepRunner()
|
||||||
|
r.Command.SetArgs([]string{"spec.template.spec.containers[name=nginx].image=nginx:1\\.7\\.9",
|
||||||
|
"--annotate=false"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx1.8
|
||||||
|
name: nginx1.8
|
||||||
|
annotations:
|
||||||
|
app: nginx1.8
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.8.1
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx1.7
|
||||||
|
name: nginx1.7
|
||||||
|
annotations:
|
||||||
|
app: nginx1.7
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9
|
||||||
|
`))
|
||||||
|
err := r.Command.Execute()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, `kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx1.7
|
||||||
|
name: nginx1.7
|
||||||
|
annotations:
|
||||||
|
app: nginx1.7
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.7.9
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
80
cmd/kyaml/cmd/merge.go
Normal file
80
cmd/kyaml/cmd/merge.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMergeRunner() *MergeRunner {
|
||||||
|
r := &MergeRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "merge [SOURCE_DIR...] [DESTINATION_DIR]",
|
||||||
|
Short: "Merge Resource configuration files",
|
||||||
|
Long: `Merge Resource configuration files
|
||||||
|
|
||||||
|
Merge reads Kubernetes Resource yaml configuration files from stdin or sources packages and write
|
||||||
|
the result to stdout or a destination package.
|
||||||
|
|
||||||
|
Resources are merged using the Resource [apiVersion, kind, name, namespace] as the key. If any of
|
||||||
|
these are missing, merge will default the missing values to empty.
|
||||||
|
|
||||||
|
Resources specified later are high-precedence (the source) and Resources specified
|
||||||
|
earlier are lower-precedence (the destination).
|
||||||
|
|
||||||
|
For information on merge rules, run:
|
||||||
|
|
||||||
|
kyaml help merge
|
||||||
|
`,
|
||||||
|
Example: `cat resources_and_patches.yaml | kyaml merge > merged_resources.yaml`,
|
||||||
|
RunE: r.runE,
|
||||||
|
}
|
||||||
|
r.Command = c
|
||||||
|
r.Command.Flags().BoolVar(&r.InvertOrder, "invert-order", false,
|
||||||
|
"if true, merge Resources in the reverse order")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func MergeCommand() *cobra.Command {
|
||||||
|
return GetMergeRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeRunner contains the run function
|
||||||
|
type MergeRunner struct {
|
||||||
|
Command *cobra.Command
|
||||||
|
InvertOrder bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MergeRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
var inputs []kio.Reader
|
||||||
|
// add the packages in reverse order -- the arg list should be highest precedence first
|
||||||
|
// e.g. merge from -> to, but the MergeFilter is highest precedence last
|
||||||
|
for i := len(args) - 1; i >= 0; i-- {
|
||||||
|
inputs = append(inputs, kio.LocalPackageReader{PackagePath: args[i]})
|
||||||
|
}
|
||||||
|
// if there is no "from" package, read from stdin
|
||||||
|
rw := &kio.ByteReadWriter{
|
||||||
|
Reader: c.InOrStdin(),
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
KeepReaderAnnotations: true,
|
||||||
|
}
|
||||||
|
if len(inputs) < 2 {
|
||||||
|
inputs = append(inputs, rw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write to the "to" package if specified
|
||||||
|
var outputs []kio.Writer
|
||||||
|
if len(args) != 0 {
|
||||||
|
outputs = append(outputs, kio.LocalPackageWriter{PackagePath: args[len(args)-1]})
|
||||||
|
}
|
||||||
|
// if there is no "to" package, write to stdout
|
||||||
|
if len(outputs) == 0 {
|
||||||
|
outputs = append(outputs, rw)
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := []kio.Filter{filters.MergeFilter{}, filters.FormatFilter{}}
|
||||||
|
return kio.Pipeline{Inputs: inputs, Filters: filters, Outputs: outputs}.Execute()
|
||||||
|
}
|
||||||
229
cmd/kyaml/cmd/tree.go
Normal file
229
cmd/kyaml/cmd/tree.go
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTreeRunner() *TreeRunner {
|
||||||
|
r := &TreeRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "tree DIR",
|
||||||
|
Short: "Display Resource structure from a directory or stdin",
|
||||||
|
Long: `Display Resource structure from a directory or stdin.
|
||||||
|
|
||||||
|
kyaml tree may be used to print Resources in a directory or cluster, preserving structure
|
||||||
|
|
||||||
|
Args:
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory directory.
|
||||||
|
|
||||||
|
Resource fields may be printed as part of the Resources by specifying the fields as flags.
|
||||||
|
|
||||||
|
kyaml tree has build-in support for printing common fields, such as replicas, container images,
|
||||||
|
container names, etc.
|
||||||
|
|
||||||
|
kyaml tree supports printing arbitrary fields using the '--field' flag.
|
||||||
|
|
||||||
|
By default, kyaml tree uses the directory structure for the tree structure, however when printing
|
||||||
|
from the cluster, the Resource graph structure may be used instead.
|
||||||
|
`,
|
||||||
|
Example: `# print Resources using directory structure
|
||||||
|
kyaml tree my-dir/
|
||||||
|
|
||||||
|
# print replicas, container name, and container image and fields for Resources
|
||||||
|
kyaml tree my-dir --replicas --image --name
|
||||||
|
|
||||||
|
# print all common Resource fields
|
||||||
|
kyaml tree my-dir/ --all
|
||||||
|
|
||||||
|
# print the "foo"" annotation
|
||||||
|
kyaml tree my-dir/ --field "metadata.annotations.foo"
|
||||||
|
|
||||||
|
# print the "foo"" annotation
|
||||||
|
kubectl get all -o yaml | kyaml tree my-dir/ --structure=graph \
|
||||||
|
--field="status.conditions[type=Completed].status"
|
||||||
|
|
||||||
|
# print live Resources from a cluster using graph for structure
|
||||||
|
kubectl get all -o yaml | kyaml tree --replicas --name --image --structure=graph
|
||||||
|
|
||||||
|
|
||||||
|
# print live Resources using graph for structure
|
||||||
|
kubectl get all,applications,releasetracks -o yaml | kyaml tree --structure=graph \
|
||||||
|
--name --image --replicas \
|
||||||
|
--field="status.conditions[type=Completed].status" \
|
||||||
|
--field="status.conditions[type=Complete].status" \
|
||||||
|
--field="status.conditions[type=Ready].status" \
|
||||||
|
--field="status.conditions[type=ContainersReady].status"
|
||||||
|
`,
|
||||||
|
RunE: r.runE,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
}
|
||||||
|
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
|
||||||
|
"also print resources from subpackages.")
|
||||||
|
|
||||||
|
// TODO(pwittrock): Figure out if these are the right things to expose, and consider making it
|
||||||
|
// a list of options instead of individual flags
|
||||||
|
c.Flags().BoolVar(&r.name, "name", false, "print name field")
|
||||||
|
c.Flags().BoolVar(&r.resources, "resources", false, "print resources field")
|
||||||
|
c.Flags().BoolVar(&r.ports, "ports", false, "print ports field")
|
||||||
|
c.Flags().BoolVar(&r.images, "image", false, "print image field")
|
||||||
|
c.Flags().BoolVar(&r.replicas, "replicas", false, "print replicas field")
|
||||||
|
c.Flags().BoolVar(&r.args, "args", false, "print args field")
|
||||||
|
c.Flags().BoolVar(&r.cmd, "command", false, "print command field")
|
||||||
|
c.Flags().BoolVar(&r.env, "env", false, "print env field")
|
||||||
|
c.Flags().BoolVar(&r.all, "all", false, "print all field infos")
|
||||||
|
c.Flags().StringSliceVar(&r.fields, "field", []string{}, "print field")
|
||||||
|
c.Flags().BoolVar(&r.includeReconcilers, "include-reconcilers", false,
|
||||||
|
"if true, include reconciler Resources in the output.")
|
||||||
|
c.Flags().BoolVar(&r.excludeNonReconcilers, "exclude-non-reconcilers", false,
|
||||||
|
"if true, exclude non-reconciler Resources in the output.")
|
||||||
|
c.Flags().StringVar(&r.structure, "graph-structure", "directory",
|
||||||
|
"Graph structure to use for printing the tree. may be 'directory' or 'owners'.")
|
||||||
|
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func TreeCommand() *cobra.Command {
|
||||||
|
return GetTreeRunner().Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeRunner contains the run function
|
||||||
|
type TreeRunner struct {
|
||||||
|
IncludeSubpackages bool
|
||||||
|
Command *cobra.Command
|
||||||
|
name bool
|
||||||
|
resources bool
|
||||||
|
ports bool
|
||||||
|
images bool
|
||||||
|
replicas bool
|
||||||
|
all bool
|
||||||
|
env bool
|
||||||
|
args bool
|
||||||
|
cmd bool
|
||||||
|
fields []string
|
||||||
|
includeReconcilers bool
|
||||||
|
excludeNonReconcilers bool
|
||||||
|
structure string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TreeRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
var input kio.Reader
|
||||||
|
var root = "."
|
||||||
|
if len(args) == 1 {
|
||||||
|
root = filepath.Clean(args[0])
|
||||||
|
input = kio.LocalPackageReader{PackagePath: args[0]}
|
||||||
|
} else {
|
||||||
|
input = &kio.ByteReader{Reader: c.InOrStdin()}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fields []kio.TreeWriterField
|
||||||
|
for _, field := range r.fields {
|
||||||
|
path, err := parseFieldPath(field)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fields = append(fields, newField(path...))
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.name || (r.all && !c.Flag("name").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "name"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "name"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if r.images || (r.all && !c.Flag("image").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "image"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "image"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.cmd || (r.all && !c.Flag("command").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "command"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "command"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if r.args || (r.all && !c.Flag("args").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "args"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "args"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if r.env || (r.all && !c.Flag("env").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "env"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "env"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.replicas || (r.all && !c.Flag("replicas").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "replicas"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if r.resources || (r.all && !c.Flag("resources").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "resources"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "resources"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if r.ports || (r.all && !c.Flag("ports").Changed) {
|
||||||
|
fields = append(fields,
|
||||||
|
newField("spec", "containers", "[name=.*]", "ports"),
|
||||||
|
newField("spec", "template", "spec", "containers", "[name=.*]", "ports"),
|
||||||
|
newField("spec", "ports"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show reconcilers in tree
|
||||||
|
fltrs := []kio.Filter{&filters.IsReconcilerFilter{
|
||||||
|
ExcludeReconcilers: !r.includeReconcilers,
|
||||||
|
IncludeNonReconcilers: !r.excludeNonReconcilers,
|
||||||
|
}}
|
||||||
|
|
||||||
|
return kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{input},
|
||||||
|
Filters: fltrs,
|
||||||
|
Outputs: []kio.Writer{kio.TreeWriter{
|
||||||
|
Root: root,
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
Fields: fields,
|
||||||
|
Structure: kio.TreeStructure(r.structure)}},
|
||||||
|
}.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newField(val ...string) kio.TreeWriterField {
|
||||||
|
if strings.HasPrefix(strings.Join(val, "."), "spec.template.spec.containers") {
|
||||||
|
return kio.TreeWriterField{
|
||||||
|
Name: "spec.template.spec.containers",
|
||||||
|
PathMatcher: yaml.PathMatcher{Path: val, StripComments: true},
|
||||||
|
SubName: val[len(val)-1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(strings.Join(val, "."), "spec.containers") {
|
||||||
|
return kio.TreeWriterField{
|
||||||
|
Name: "spec.containers",
|
||||||
|
PathMatcher: yaml.PathMatcher{Path: val, StripComments: true},
|
||||||
|
SubName: val[len(val)-1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kio.TreeWriterField{
|
||||||
|
Name: strings.Join(val, "."),
|
||||||
|
PathMatcher: yaml.PathMatcher{Path: val, StripComments: true},
|
||||||
|
}
|
||||||
|
}
|
||||||
345
cmd/kyaml/cmd/tree_test.go
Normal file
345
cmd/kyaml/cmd/tree_test.go
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package cmd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestCmd_files verifies fmt reads the files and filters them
|
||||||
|
func TestTreeCommand_files(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-tree-test")
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/reconciler:v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetTreeRunner()
|
||||||
|
r.Command.SetArgs([]string{d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, fmt.Sprintf(`%s
|
||||||
|
├── [f1.yaml] Deployment foo
|
||||||
|
├── [f1.yaml] Service foo
|
||||||
|
└── [f2.yaml] Deployment bar
|
||||||
|
`, d), b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTreeCommand_stdin(t *testing.T) {
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetTreeRunner()
|
||||||
|
r.Command.SetArgs([]string{})
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`apiVersion: extensions/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo3
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo3
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo3
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo2
|
||||||
|
namespace: default2
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx3
|
||||||
|
name: foo
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
app: nginx3
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: bar-package
|
||||||
|
config.kubernetes.io/path: f2.yaml
|
||||||
|
name: bar
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
namespace: default
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/package: .
|
||||||
|
config.kubernetes.io/path: f1.yaml
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`))
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, fmt.Sprintf(`.
|
||||||
|
├── [f1.yaml] Deployment default/foo
|
||||||
|
├── [f1.yaml] Service default/foo
|
||||||
|
├── [f1.yaml] Deployment default/foo3
|
||||||
|
├── [f1.yaml] Deployment default/foo3
|
||||||
|
├── [f1.yaml] Deployment default/foo3
|
||||||
|
├── [f1.yaml] Deployment default2/foo2
|
||||||
|
└── bar-package
|
||||||
|
└── [f2.yaml] Deployment bar
|
||||||
|
`), b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTreeCommand_includeReconcilers(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-tree-test")
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/reconciler:v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetTreeRunner()
|
||||||
|
r.Command.SetArgs([]string{d, "--include-reconcilers"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, fmt.Sprintf(`%s
|
||||||
|
├── [f1.yaml] Deployment foo
|
||||||
|
├── [f1.yaml] Service foo
|
||||||
|
├── [f2.yaml] Deployment bar
|
||||||
|
└── [f2.yaml] Abstraction foo
|
||||||
|
`, d), b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTreeCommand_excludeNonReconcilers(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustmoize-tree-test")
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f1.yaml"), []byte(`
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(d, "f2.yaml"), []byte(`
|
||||||
|
apiVersion: gcr.io/example/reconciler:v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := cmd.GetTreeRunner()
|
||||||
|
r.Command.SetArgs([]string{d, "--include-reconcilers", "--exclude-non-reconcilers"})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, fmt.Sprintf(`%s
|
||||||
|
└── [f2.yaml] Abstraction foo
|
||||||
|
`, d), b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
36
cmd/kyaml/cmd/util.go
Normal file
36
cmd/kyaml/cmd/util.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parseFieldPath parse a flag value into a field path
|
||||||
|
func parseFieldPath(path string) ([]string, error) {
|
||||||
|
// fixup '\.' so we don't split on it
|
||||||
|
match := strings.ReplaceAll(path, "\\.", "$$$$")
|
||||||
|
parts := strings.Split(match, ".")
|
||||||
|
for i := range parts {
|
||||||
|
parts[i] = strings.ReplaceAll(parts[i], "$$$$", ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// split the list index from the list field
|
||||||
|
var newParts []string
|
||||||
|
for i := range parts {
|
||||||
|
if !strings.Contains(parts[i], "[") {
|
||||||
|
newParts = append(newParts, parts[i])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p := strings.Split(parts[i], "[")
|
||||||
|
if len(p) != 2 {
|
||||||
|
return nil, fmt.Errorf("unrecognized path element: %s. "+
|
||||||
|
"Should be of the form 'list[field=value]'", parts[i])
|
||||||
|
}
|
||||||
|
p[1] = "[" + p[1]
|
||||||
|
newParts = append(newParts, p[0], p[1])
|
||||||
|
}
|
||||||
|
return newParts, nil
|
||||||
|
}
|
||||||
12
cmd/kyaml/go.mod
Normal file
12
cmd/kyaml/go.mod
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module sigs.k8s.io/kustomize/cmd/kyaml
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/spf13/cobra v0.0.5
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
k8s.io/apimachinery v0.0.0-20191107105744-2c7f8d2b0fd8
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
replace sigs.k8s.io/kustomize/kyaml v0.0.0 => ../../kyaml
|
||||||
132
cmd/kyaml/go.sum
Normal file
132
cmd/kyaml/go.sum
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
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/urlesc v0.0.0-20160726150825-5bd2802263f2/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=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
|
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/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/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||||
|
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||||
|
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||||
|
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=
|
||||||
|
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/go-cmp v0.3.0/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=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
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=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.7/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/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/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/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=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
|
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
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/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
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=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
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/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/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 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||||
|
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
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-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=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-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/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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
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.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
k8s.io/apimachinery v0.0.0-20191107105744-2c7f8d2b0fd8 h1:IMbv9UOD3FKoJGrF2u3EtJIeQC99bnXxS7JKciNFUi8=
|
||||||
|
k8s.io/apimachinery v0.0.0-20191107105744-2c7f8d2b0fd8/go.mod h1:DJOb3m0kw91A0YaUsaoYChi4d7xVF84HLiuRCxGsV04=
|
||||||
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||||
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
42
cmd/kyaml/inpututil/inpututil.go
Normal file
42
cmd/kyaml/inpututil/inpututil.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package inpututil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MapInputsEFn func(*yaml.RNode, yaml.ResourceMeta) error
|
||||||
|
|
||||||
|
func MapInputsE(inputs []*yaml.RNode, fn MapInputsEFn) error {
|
||||||
|
for i := range inputs {
|
||||||
|
meta, err := inputs[i].GetMeta()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fn(inputs[i], meta); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapInputsFn func(*yaml.RNode, yaml.ResourceMeta) ([]*yaml.RNode, error)
|
||||||
|
|
||||||
|
// runs the function against each input Resource, providing the parsed metadata
|
||||||
|
func MapInputs(inputs []*yaml.RNode, fn MapInputsFn) ([]*yaml.RNode, error) {
|
||||||
|
var outputs []*yaml.RNode
|
||||||
|
for i := range inputs {
|
||||||
|
meta, err := inputs[i].GetMeta()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
o, err := fn(inputs[i], meta)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputs = append(outputs, o...)
|
||||||
|
}
|
||||||
|
return outputs, nil
|
||||||
|
}
|
||||||
37
cmd/kyaml/main.go
Normal file
37
cmd/kyaml/main.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/kyaml/cmd"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml/merge2"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml/merge3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var root = &cobra.Command{
|
||||||
|
Use: "kyaml",
|
||||||
|
Short: "kyaml reference comand",
|
||||||
|
Long: `Description:
|
||||||
|
Reference implementation for using the kyaml libraries.
|
||||||
|
`,
|
||||||
|
Example: ``,
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
root.AddCommand(cmd.GrepCommand())
|
||||||
|
root.AddCommand(cmd.TreeCommand())
|
||||||
|
root.AddCommand(cmd.CatCommand())
|
||||||
|
root.AddCommand(cmd.FmtCommand())
|
||||||
|
root.AddCommand(cmd.MergeCommand())
|
||||||
|
root.AddCommand(cmd.CountCommand())
|
||||||
|
root.AddCommand(&cobra.Command{Use: "merge", Long: merge2.Help})
|
||||||
|
root.AddCommand(&cobra.Command{Use: "merge3", Long: merge3.Help})
|
||||||
|
|
||||||
|
if err := root.Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ GOPATH := $(shell go env GOPATH)
|
|||||||
build:
|
build:
|
||||||
go build -v -o $(GOPATH)/bin/kyaml .
|
go build -v -o $(GOPATH)/bin/kyaml .
|
||||||
|
|
||||||
all: generate license fix vet fmt test lint lint tidy
|
all: generate license fix vet fmt test lint tidy
|
||||||
|
|
||||||
fix:
|
fix:
|
||||||
go fix ./...
|
go fix ./...
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ go 1.12
|
|||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/go-errors/errors v1.0.1
|
github.com/go-errors/errors v1.0.1
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
|
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
|
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ 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/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 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
|
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
@@ -12,7 +17,11 @@ github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mB
|
|||||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/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.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8=
|
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -65,6 +65,25 @@ func Map(nodes []*yaml.RNode, fn func(*yaml.RNode) (*yaml.RNode, error)) ([]*yam
|
|||||||
return returnNodes, nil
|
return returnNodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MapMeta(nodes []*yaml.RNode, fn func(*yaml.RNode, yaml.ResourceMeta) (*yaml.RNode, error)) (
|
||||||
|
[]*yaml.RNode, error) {
|
||||||
|
var returnNodes []*yaml.RNode
|
||||||
|
for i := range nodes {
|
||||||
|
meta, err := nodes[i].GetMeta()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n, err := fn(nodes[i], meta)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n != nil {
|
||||||
|
returnNodes = append(returnNodes, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnNodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SortNodes sorts nodes in place:
|
// SortNodes sorts nodes in place:
|
||||||
// - by PathAnnotation annotation
|
// - by PathAnnotation annotation
|
||||||
// - by IndexAnnotation annotation
|
// - by IndexAnnotation annotation
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type TreeStructure string
|
|||||||
const (
|
const (
|
||||||
// TreeStructurePackage configures TreeWriter to generate the tree structure off of the
|
// TreeStructurePackage configures TreeWriter to generate the tree structure off of the
|
||||||
// Resources packages.
|
// Resources packages.
|
||||||
TreeStructurePackage TreeStructure = "package"
|
TreeStructurePackage TreeStructure = "directory"
|
||||||
|
|
||||||
// TreeStructureOwners configures TreeWriter to generate the tree structure off of the
|
// TreeStructureOwners configures TreeWriter to generate the tree structure off of the
|
||||||
// Resource owners.
|
// Resource owners.
|
||||||
|
|||||||
@@ -2,4 +2,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
cd kyaml
|
cd kyaml
|
||||||
|
make all
|
||||||
|
|
||||||
|
cd ../cmd/kyaml
|
||||||
make all
|
make all
|
||||||
Reference in New Issue
Block a user