mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Support for source and sink with functions
This commit is contained in:
@@ -80,6 +80,8 @@ func NewConfigCommand(name string) *cobra.Command {
|
|||||||
root.AddCommand(commands.SetCommand(name))
|
root.AddCommand(commands.SetCommand(name))
|
||||||
root.AddCommand(commands.ListSettersCommand(name))
|
root.AddCommand(commands.ListSettersCommand(name))
|
||||||
root.AddCommand(commands.CreateSetterCommand(name))
|
root.AddCommand(commands.CreateSetterCommand(name))
|
||||||
|
root.AddCommand(commands.SinkCommand(name))
|
||||||
|
root.AddCommand(commands.SourceCommand(name))
|
||||||
|
|
||||||
root.AddCommand(&cobra.Command{
|
root.AddCommand(&cobra.Command{
|
||||||
Use: "docs-merge",
|
Use: "docs-merge",
|
||||||
|
|||||||
18
cmd/config/docs/commands/sink.md
Normal file
18
cmd/config/docs/commands/sink.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
## sink
|
||||||
|
|
||||||
|
[Alpha] Implement a Sink by writing input to a local directory.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
[Alpha] Implement a Sink by writing input to a local directory.
|
||||||
|
|
||||||
|
kustomize config sink DIR
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
|
||||||
|
`sink` writes its input to a directory
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
kustomize config source DIR/ | your-function | kustomize config sink DIR/
|
||||||
21
cmd/config/docs/commands/source.md
Normal file
21
cmd/config/docs/commands/source.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
## source
|
||||||
|
|
||||||
|
[Alpha] Implement a Source by reading a local directory.
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
[Alpha] Implement a Source by reading a local directory.
|
||||||
|
|
||||||
|
kustomize config source DIR
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
|
||||||
|
`source` emits configuration to act as input to a function
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
# emity configuration directory as input source to a function
|
||||||
|
kustomize config source DIR/
|
||||||
|
|
||||||
|
kustomize config source DIR/ | your-function | kustomize config sink DIR/
|
||||||
48
cmd/config/internal/commands/sink.go
Normal file
48
cmd/config/internal/commands/sink.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSinkRunner returns a command for Sink.
|
||||||
|
func GetSinkRunner(name string) *SinkRunner {
|
||||||
|
r := &SinkRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "sink DIR",
|
||||||
|
Short: commands.SinkShort,
|
||||||
|
Long: commands.SinkLong,
|
||||||
|
Example: commands.SinkExamples,
|
||||||
|
RunE: r.runE,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
}
|
||||||
|
fixDocs(name, c)
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func SinkCommand(name string) *cobra.Command {
|
||||||
|
return GetSinkRunner(name).Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// SinkRunner contains the run function
|
||||||
|
type SinkRunner struct {
|
||||||
|
Command *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SinkRunner) runE(c *cobra.Command, args []string) error {
|
||||||
|
err := kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{&kio.ByteReader{Reader: c.InOrStdin()}},
|
||||||
|
Outputs: []kio.Writer{
|
||||||
|
&kio.LocalPackageWriter{
|
||||||
|
PackagePath: args[0],
|
||||||
|
ClearAnnotations: []string{"config.kubernetes.io/path"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}.Execute()
|
||||||
|
return handleError(c, err)
|
||||||
|
}
|
||||||
140
cmd/config/internal/commands/sink_test.go
Normal file
140
cmd/config/internal/commands/sink_test.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSinkCommand(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-source-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(d)
|
||||||
|
|
||||||
|
// fmt the files
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
r := commands.GetSinkRunner("")
|
||||||
|
r.Command.SetIn(bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1
|
||||||
|
kind: ResourceList
|
||||||
|
items:
|
||||||
|
- kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/index: '0'
|
||||||
|
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/path: 'f1.yaml'
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
- apiVersion: v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/function: |
|
||||||
|
container:
|
||||||
|
image: gcr.io/example/reconciler:v1
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
config.kubernetes.io/index: '0'
|
||||||
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/index: '1'
|
||||||
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`))
|
||||||
|
r.Command.SetArgs([]string{d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err := ioutil.ReadFile(filepath.Join(d, "f1.yaml"))
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
expected := `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
|
||||||
|
`
|
||||||
|
if !assert.Equal(t, expected, string(actual)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err = ioutil.ReadFile(filepath.Join(d, "f2.yaml"))
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
expected = `apiVersion: v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/function: |
|
||||||
|
container:
|
||||||
|
image: gcr.io/example/reconciler:v1
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`
|
||||||
|
if !assert.Equal(t, expected, string(actual)) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
77
cmd/config/internal/commands/source.go
Normal file
77
cmd/config/internal/commands/source.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSourceRunner returns a command for Source.
|
||||||
|
func GetSourceRunner(name string) *SourceRunner {
|
||||||
|
r := &SourceRunner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "source DIR",
|
||||||
|
Short: commands.SourceShort,
|
||||||
|
Long: commands.SourceLong,
|
||||||
|
Example: commands.SourceExamples,
|
||||||
|
RunE: r.runE,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
}
|
||||||
|
fixDocs(name, c)
|
||||||
|
c.Flags().StringVar(&r.WrapKind, "wrap-kind", kio.ResourceListKind,
|
||||||
|
"output using this format.")
|
||||||
|
c.Flags().StringVar(&r.WrapApiVersion, "wrap-version", kio.ResourceListAPIVersion,
|
||||||
|
"output using this format.")
|
||||||
|
c.Flags().StringVar(&r.FunctionConfig, "function-config", "",
|
||||||
|
"path to function config.")
|
||||||
|
r.Command = c
|
||||||
|
_ = c.MarkFlagFilename("function-config", "yaml", "json", "yml")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func SourceCommand(name string) *cobra.Command {
|
||||||
|
return GetSourceRunner(name).Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// SourceRunner contains the run function
|
||||||
|
type SourceRunner struct {
|
||||||
|
WrapKind string
|
||||||
|
WrapApiVersion string
|
||||||
|
FunctionConfig string
|
||||||
|
Command *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SourceRunner) 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}.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 outputs []kio.Writer
|
||||||
|
outputs = append(outputs, kio.ByteWriter{
|
||||||
|
Writer: c.OutOrStdout(),
|
||||||
|
KeepReaderAnnotations: true,
|
||||||
|
WrappingKind: r.WrapKind,
|
||||||
|
WrappingAPIVersion: r.WrapApiVersion,
|
||||||
|
FunctionConfig: functionConfig,
|
||||||
|
})
|
||||||
|
|
||||||
|
err := kio.Pipeline{
|
||||||
|
Inputs: []kio.Reader{kio.LocalPackageReader{PackagePath: args[0]}},
|
||||||
|
Outputs: outputs}.Execute()
|
||||||
|
return handleError(c, err)
|
||||||
|
}
|
||||||
136
cmd/config/internal/commands/source_test.go
Normal file
136
cmd/config/internal/commands/source_test.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSourceCommand(t *testing.T) {
|
||||||
|
d, err := ioutil.TempDir("", "kustomize-source-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: v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/function: |
|
||||||
|
container:
|
||||||
|
image: gcr.io/example/reconciler:v1
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
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 := commands.GetSourceRunner("")
|
||||||
|
r.Command.SetArgs([]string{d})
|
||||||
|
r.Command.SetOut(b)
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
|
||||||
|
kind: ResourceList
|
||||||
|
items:
|
||||||
|
- kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx2
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
app: nginx2
|
||||||
|
config.kubernetes.io/index: '0'
|
||||||
|
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/path: 'f1.yaml'
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
- apiVersion: v1
|
||||||
|
kind: Abstraction
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/function: |
|
||||||
|
container:
|
||||||
|
image: gcr.io/example/reconciler:v1
|
||||||
|
config.kubernetes.io/local-config: "true"
|
||||||
|
config.kubernetes.io/index: '0'
|
||||||
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
- apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
name: bar
|
||||||
|
annotations:
|
||||||
|
app: nginx
|
||||||
|
config.kubernetes.io/index: '1'
|
||||||
|
config.kubernetes.io/path: 'f2.yaml'
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
`, b.String()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -332,6 +332,37 @@ var SetExamples = `
|
|||||||
name: test-app2 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
|
name: test-app2 # {"description":"test environment","type":"string","x-kustomize":{"setBy":"dev","partialFieldSetters":[{"name":"name-prefix","value":"test"}]}}
|
||||||
...`
|
...`
|
||||||
|
|
||||||
|
var SinkShort = `[Alpha] Implement a Sink by writing input to a local directory.`
|
||||||
|
var SinkLong = `
|
||||||
|
[Alpha] Implement a Sink by writing input to a local directory.
|
||||||
|
|
||||||
|
kustomize config sink DIR
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
|
||||||
|
` + "`" + `sink` + "`" + ` writes its input to a directory
|
||||||
|
`
|
||||||
|
var SinkExamples = `
|
||||||
|
kustomize config source DIR/ | your-function | kustomize config sink DIR/`
|
||||||
|
|
||||||
|
var SourceShort = `[Alpha] Implement a Source by reading a local directory.`
|
||||||
|
var SourceLong = `
|
||||||
|
[Alpha] Implement a Source by reading a local directory.
|
||||||
|
|
||||||
|
kustomize config source DIR
|
||||||
|
|
||||||
|
DIR:
|
||||||
|
Path to local directory.
|
||||||
|
|
||||||
|
` + "`" + `source` + "`" + ` emits configuration to act as input to a function
|
||||||
|
`
|
||||||
|
var SourceExamples = `
|
||||||
|
# emity configuration directory as input source to a function
|
||||||
|
kustomize config source DIR/
|
||||||
|
|
||||||
|
kustomize config source DIR/ | your-function | kustomize config sink DIR/`
|
||||||
|
|
||||||
var TreeShort = `[Alpha] Display Resource structure from a directory or stdin.`
|
var TreeShort = `[Alpha] Display Resource structure from a directory or stdin.`
|
||||||
var TreeLong = `
|
var TreeLong = `
|
||||||
[Alpha] Display Resource structure from a directory or stdin.
|
[Alpha] Display Resource structure from a directory or stdin.
|
||||||
|
|||||||
Reference in New Issue
Block a user