mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
cmd/config: Add examples and tutorials for config functions
- Add examples under `functions` - Add built-in tutorial for functions
This commit is contained in:
@@ -14,6 +14,7 @@ func GetRunFnRunner(name string) *RunFnRunner {
|
||||
r := &RunFnRunner{}
|
||||
c := &cobra.Command{
|
||||
Use: "run-fns DIR",
|
||||
Aliases: []string{"run"},
|
||||
Short: commands.RunFnsShort,
|
||||
Long: commands.RunFnsLong,
|
||||
Example: commands.RunFnsExamples,
|
||||
|
||||
@@ -278,3 +278,186 @@ var ConfigurationBasicsLong = `
|
||||
│ ├── name: web
|
||||
│ └── image: <YOUR-CONTAINER>
|
||||
...`
|
||||
|
||||
var FunctionBasicsShort = `### Synopsis`
|
||||
var FunctionBasicsLong = `
|
||||
` + "`" + `kustomize config` + "`" + ` enables encapsulating function for manipulating Resource
|
||||
configuration inside containers, which are run using ` + "`" + `run-fns` + "`" + `.
|
||||
|
||||
First fetch the kustomize repository, which contains a collection of example
|
||||
functions
|
||||
|
||||
git clone https://github.com/kubernetes-sigs/kustomize
|
||||
cd kustomize/functions/examples/
|
||||
|
||||
### Templating -- CockroachDB
|
||||
|
||||
This section demonstrates how to leverage templating based solutions from
|
||||
` + "`" + `kustomize config` + "`" + `. The templating function is implemented as a ` + "`" + `bash` + "`" + ` script
|
||||
using a ` + "`" + `heredoc` + "`" + `.
|
||||
|
||||
#### 1: Generate the Resources
|
||||
|
||||
` + "`" + `cd` + "`" + ` into the ` + "`" + `kustomize/functions/examples/template-heredoc-cockroachdb/` + "`" + `
|
||||
directory, and invoke ` + "`" + `run-fns` + "`" + ` on the ` + "`" + `local-resource/` + "`" + ` directory.
|
||||
|
||||
cd template-heredoc-cockroachdb/
|
||||
|
||||
# view the Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# view the generated Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
` + "`" + `run-fns` + "`" + ` generated the directory ` + "`" + ` local-resource/config` + "`" + ` containing the generated
|
||||
Resources.
|
||||
|
||||
#### 2. Modify the Generated Resources
|
||||
|
||||
- modify the generated Resources by adding an annotation, sidecar container, etc.
|
||||
- modify the ` + "`" + `local-resources/example-use.yaml` + "`" + ` by changing the replicas
|
||||
|
||||
re-run ` + "`" + `run-fns` + "`" + `. this will apply the updated replicas to the generated Resources,
|
||||
but keep the fields that you manually added to the generated Resource configuration.
|
||||
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
` + "`" + `run-fns` + "`" + ` facilitates a non-destructive *smart templating* approach that allows templating
|
||||
to be composed with manual modifications directly to the template output, as well as
|
||||
composition with other functions which may appy validation or injection of values.
|
||||
|
||||
#### 3. Function Implementation
|
||||
|
||||
the function implementation is located under the ` + "`" + `image/` + "`" + ` directory as a ` + "`" + `Dockerfile` + "`" + `
|
||||
and a ` + "`" + `bash` + "`" + ` script.
|
||||
|
||||
### Templating -- Nginx
|
||||
|
||||
The steps in this section are identical to the CockroachDB templating example,
|
||||
but the function implementation is very different, and implemented as a ` + "`" + `go` + "`" + `
|
||||
program rather than a ` + "`" + `bash` + "`" + ` script.
|
||||
|
||||
#### 1: Generate the Resources
|
||||
|
||||
` + "`" + `cd` + "`" + ` into the ` + "`" + `kustomize/functions/examples/template-go-nginx/` + "`" + `
|
||||
directory, and invoke ` + "`" + `run-fns` + "`" + ` on the ` + "`" + `local-resource/` + "`" + ` directory.
|
||||
|
||||
cd template-go-nginx/
|
||||
|
||||
# view the Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# view the generated Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
` + "`" + `run-fns` + "`" + ` generated the directory ` + "`" + ` local-resource/config` + "`" + ` containing the generated
|
||||
Resources. this time it put the configuration in a single file rather than multiple
|
||||
files. The mapping of Resources to files is controlled by the function itself through
|
||||
annotations on the generated Resources.
|
||||
|
||||
#### 2. Modify the Generated Resources
|
||||
|
||||
- modify the generated Resources by adding an annotation, sidecar container, etc.
|
||||
- modify the ` + "`" + `local-resources/example-use.yaml` + "`" + ` by changing the replicas
|
||||
|
||||
re-run ` + "`" + `run-fns` + "`" + `. this will apply the updated replicas to the generated Resources,
|
||||
but keep the fields that you manually added to the generated Resource configuration.
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
Just like in the preceding section, the function is implemented using a non-destructive
|
||||
approach which merges the generated Resources into previously generated instances.
|
||||
|
||||
#### 3. Function Implementation
|
||||
|
||||
the function implementation is located under the ` + "`" + `image/` + "`" + ` directory as a ` + "`" + `Dockerfile` + "`" + `
|
||||
and a ` + "`" + `go` + "`" + ` program.
|
||||
|
||||
### Validation -- resource reservations
|
||||
|
||||
This section uses ` + "`" + `run-fns` + "`" + ` to perform validation rather than generate Resources.
|
||||
|
||||
#### 1: Run the Validator
|
||||
|
||||
` + "`" + `cd` + "`" + ` into the ` + "`" + `kustomize/functions/examples/validator-resource-requests` + "`" + `
|
||||
directory, and invoke ` + "`" + `run-fns` + "`" + ` on the ` + "`" + `local-resource/` + "`" + ` directory.
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
cpu-requests missing for a container in Deployment nginx (example-use.yaml [1])
|
||||
Error: exit status 1
|
||||
Usage:
|
||||
...
|
||||
|
||||
#### 2: Fix the validation issue
|
||||
|
||||
The command will fail complaining that the nginx Deployment is missing ` + "`" + `cpu-requests` + "`" + `,
|
||||
and print the name of the file + Resource index. Edit the file and uncomment the resources,
|
||||
then re-run the functions.
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
The validation now passes.
|
||||
|
||||
### Injection -- resource reservations
|
||||
|
||||
This section uses ` + "`" + `run-fns` + "`" + ` to perform injection of field values based off annotations
|
||||
on the Resource.
|
||||
|
||||
#### 1: Run the Injector
|
||||
|
||||
` + "`" + `cd` + "`" + ` into the ` + "`" + `kustomize/functions/examples/inject-tshirt-sizes` + "`" + `
|
||||
directory, and invoke ` + "`" + `run-fns` + "`" + ` on the ` + "`" + `local-resource/` + "`" + ` directory.
|
||||
|
||||
# print the resources
|
||||
kustomize config tree local-resource --resources --name
|
||||
local-resource
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
└── name: nginx
|
||||
|
||||
# run the functions
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# print the new resources
|
||||
kustomize config tree local-resource --resources --name
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
├── name: nginx
|
||||
└── resources: {requests: {cpu: 4, memory: 1GiB}}
|
||||
|
||||
#### 2: Change the tshirt-size
|
||||
|
||||
Change the ` + "`" + `tshirt-size` + "`" + ` annotation from ` + "`" + `medium` + "`" + ` to ` + "`" + `small` + "`" + ` and re-run the functions.
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
kustomize config tree local-resource/
|
||||
local-resource
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
├── name: nginx
|
||||
└── resources: {requests: {cpu: 200m, memory: 50MiB}}
|
||||
|
||||
The function has applied the reservations for the new tshirt-size
|
||||
|
||||
### Function Composition
|
||||
|
||||
Functions may be composed together. Try putting the Injection (tshirt-size) and
|
||||
Validation functions together in the same .yaml file (separated by ` + "`" + `---` + "`" + `). Run
|
||||
` + "`" + `run-fns` + "`" + ` and observe that the first function in the file is applied to the Resources,
|
||||
and then the second function in the file is applied.`
|
||||
|
||||
@@ -77,7 +77,7 @@ func NewConfigCommand(name string) *cobra.Command {
|
||||
})
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "docs-fn",
|
||||
Short: "[Alpha] Documentation for writing containerized functions run by run-fns.",
|
||||
Short: "[Alpha] Documentation for writing containerized functions run by run.",
|
||||
Long: api.ConfigFnLong,
|
||||
})
|
||||
root.AddCommand(&cobra.Command{
|
||||
@@ -87,10 +87,16 @@ func NewConfigCommand(name string) *cobra.Command {
|
||||
})
|
||||
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "tutorials-basics",
|
||||
Use: "tutorials-command-basics",
|
||||
Short: "[Alpha] Tutorials for using basic config commands.",
|
||||
Long: tutorials.ConfigurationBasicsLong,
|
||||
})
|
||||
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "tutorials-function-basics",
|
||||
Short: "[Alpha] Tutorials for using functions.",
|
||||
Long: tutorials.FunctionBasicsLong,
|
||||
})
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
184
cmd/config/docs/tutorials/function-basics.md
Normal file
184
cmd/config/docs/tutorials/function-basics.md
Normal file
@@ -0,0 +1,184 @@
|
||||
## Function Basics
|
||||
|
||||
### Synopsis
|
||||
|
||||
`kustomize config` enables encapsulating function for manipulating Resource
|
||||
configuration inside containers, which are run using `run-fns`.
|
||||
|
||||
First fetch the kustomize repository, which contains a collection of example
|
||||
functions
|
||||
|
||||
git clone https://github.com/kubernetes-sigs/kustomize
|
||||
cd kustomize/functions/examples/
|
||||
|
||||
### Templating -- CockroachDB
|
||||
|
||||
This section demonstrates how to leverage templating based solutions from
|
||||
`kustomize config`. The templating function is implemented as a `bash` script
|
||||
using a `heredoc`.
|
||||
|
||||
#### 1: Generate the Resources
|
||||
|
||||
`cd` into the `kustomize/functions/examples/template-heredoc-cockroachdb/`
|
||||
directory, and invoke `run-fns` on the `local-resource/` directory.
|
||||
|
||||
cd template-heredoc-cockroachdb/
|
||||
|
||||
# view the Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# view the generated Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
`run-fns` generated the directory ` local-resource/config` containing the generated
|
||||
Resources.
|
||||
|
||||
#### 2. Modify the Generated Resources
|
||||
|
||||
- modify the generated Resources by adding an annotation, sidecar container, etc.
|
||||
- modify the `local-resources/example-use.yaml` by changing the replicas
|
||||
|
||||
re-run `run-fns`. this will apply the updated replicas to the generated Resources,
|
||||
but keep the fields that you manually added to the generated Resource configuration.
|
||||
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
`run-fns` facilitates a non-destructive *smart templating* approach that allows templating
|
||||
to be composed with manual modifications directly to the template output, as well as
|
||||
composition with other functions which may appy validation or injection of values.
|
||||
|
||||
#### 3. Function Implementation
|
||||
|
||||
the function implementation is located under the `image/` directory as a `Dockerfile`
|
||||
and a `bash` script.
|
||||
|
||||
### Templating -- Nginx
|
||||
|
||||
The steps in this section are identical to the CockroachDB templating example,
|
||||
but the function implementation is very different, and implemented as a `go`
|
||||
program rather than a `bash` script.
|
||||
|
||||
#### 1: Generate the Resources
|
||||
|
||||
`cd` into the `kustomize/functions/examples/template-go-nginx/`
|
||||
directory, and invoke `run-fns` on the `local-resource/` directory.
|
||||
|
||||
cd template-go-nginx/
|
||||
|
||||
# view the Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# view the generated Resources
|
||||
kustomize config tree local-resource/ --name --image --replicas
|
||||
|
||||
`run-fns` generated the directory ` local-resource/config` containing the generated
|
||||
Resources. this time it put the configuration in a single file rather than multiple
|
||||
files. The mapping of Resources to files is controlled by the function itself through
|
||||
annotations on the generated Resources.
|
||||
|
||||
#### 2. Modify the Generated Resources
|
||||
|
||||
- modify the generated Resources by adding an annotation, sidecar container, etc.
|
||||
- modify the `local-resources/example-use.yaml` by changing the replicas
|
||||
|
||||
re-run `run-fns`. this will apply the updated replicas to the generated Resources,
|
||||
but keep the fields that you manually added to the generated Resource configuration.
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
Just like in the preceding section, the function is implemented using a non-destructive
|
||||
approach which merges the generated Resources into previously generated instances.
|
||||
|
||||
#### 3. Function Implementation
|
||||
|
||||
the function implementation is located under the `image/` directory as a `Dockerfile`
|
||||
and a `go` program.
|
||||
|
||||
### Validation -- resource reservations
|
||||
|
||||
This section uses `run-fns` to perform validation rather than generate Resources.
|
||||
|
||||
#### 1: Run the Validator
|
||||
|
||||
`cd` into the `kustomize/functions/examples/validator-resource-requests`
|
||||
directory, and invoke `run-fns` on the `local-resource/` directory.
|
||||
|
||||
# run the function
|
||||
kustomize config run-fns local-resource/
|
||||
cpu-requests missing for a container in Deployment nginx (example-use.yaml [1])
|
||||
Error: exit status 1
|
||||
Usage:
|
||||
...
|
||||
|
||||
#### 2: Fix the validation issue
|
||||
|
||||
The command will fail complaining that the nginx Deployment is missing `cpu-requests`,
|
||||
and print the name of the file + Resource index. Edit the file and uncomment the resources,
|
||||
then re-run the functions.
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
The validation now passes.
|
||||
|
||||
### Injection -- resource reservations
|
||||
|
||||
This section uses `run-fns` to perform injection of field values based off annotations
|
||||
on the Resource.
|
||||
|
||||
#### 1: Run the Injector
|
||||
|
||||
`cd` into the `kustomize/functions/examples/inject-tshirt-sizes`
|
||||
directory, and invoke `run-fns` on the `local-resource/` directory.
|
||||
|
||||
# print the resources
|
||||
kustomize config tree local-resource --resources --name
|
||||
local-resource
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
└── name: nginx
|
||||
|
||||
# run the functions
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
# print the new resources
|
||||
kustomize config tree local-resource --resources --name
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
├── name: nginx
|
||||
└── resources: {requests: {cpu: 4, memory: 1GiB}}
|
||||
|
||||
#### 2: Change the tshirt-size
|
||||
|
||||
Change the `tshirt-size` annotation from `medium` to `small` and re-run the functions.
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
kustomize config tree local-resource/
|
||||
local-resource
|
||||
├── [example-use.yaml] Validator
|
||||
└── [example-use.yaml] Deployment nginx
|
||||
└── spec.template.spec.containers
|
||||
└── 0
|
||||
├── name: nginx
|
||||
└── resources: {requests: {cpu: 200m, memory: 50MiB}}
|
||||
|
||||
The function has applied the reservations for the new tshirt-size
|
||||
|
||||
### Function Composition
|
||||
|
||||
Functions may be composed together. Try putting the Injection (tshirt-size) and
|
||||
Validation functions together in the same .yaml file (separated by `---`). Run
|
||||
`run-fns` and observe that the first function in the file is applied to the Resources,
|
||||
and then the second function in the file is applied.
|
||||
@@ -0,0 +1,2 @@
|
||||
Copyright {{.Year}} {{.Holder}}
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
42
functions/examples/injection-tshirt-sizes/Makefile
Normal file
42
functions/examples/injection-tshirt-sizes/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
all: generate license build fix vet fmt test lint tidy
|
||||
|
||||
fix:
|
||||
(cd image && go fix ./...)
|
||||
|
||||
fmt:
|
||||
(cd image && go fmt ./...)
|
||||
|
||||
generate:
|
||||
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
|
||||
(cd image && GOBIN=$(GOBIN) 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:
|
||||
(cd image && go mod tidy)
|
||||
|
||||
lint:
|
||||
(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
(cd image && $(GOBIN)/golangci-lint run ./...)
|
||||
|
||||
test:
|
||||
(cd image && go test -cover ./...)
|
||||
|
||||
vet:
|
||||
(cd image && go vet ./...)
|
||||
|
||||
image:
|
||||
docker build image -t gcr.io/kustomize-functions/example-tshirt:v0.1.0
|
||||
docker push gcr.io/kustomize-functions/example-tshirt:v0.1.0
|
||||
35
functions/examples/injection-tshirt-sizes/README.md
Normal file
35
functions/examples/injection-tshirt-sizes/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Injection
|
||||
|
||||
This is an example of implementing an injection function.
|
||||
|
||||
This example is written in `go` and uses the `kyaml` libraries for parsing the
|
||||
input and writing the output. Writing in `go` is not a requirement.
|
||||
|
||||
## Function implementation
|
||||
|
||||
The function is implemented as an [image](image), and built using `make image`.
|
||||
|
||||
The template is implemented as a go program, which reads a collection of input
|
||||
Resource configuration, and looks for invalid configuration.
|
||||
|
||||
## Function invocation
|
||||
|
||||
The function is invoked by authoring a [local Resource](local-resource)
|
||||
with `metadata.configFn` and running:
|
||||
|
||||
kustomize config run-fns local-resources/
|
||||
|
||||
This exists non-zero if there is an error.
|
||||
|
||||
## Running the Example
|
||||
|
||||
Run the validator with:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
This will add resource reservations to the Deployment. Change the `tshirt-size`
|
||||
annotation from `medium` to `small` and rerun:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
Observe that the reservations have changed.
|
||||
15
functions/examples/injection-tshirt-sizes/image/Dockerfile
Normal file
15
functions/examples/injection-tshirt-sizes/image/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.13-stretch
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /go/src/
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
COPY main.go .
|
||||
RUN go build -v -o /usr/local/bin/config-function ./
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=0 /usr/local/bin/config-function /usr/local/bin/config-function
|
||||
CMD ["config-function"]
|
||||
5
functions/examples/injection-tshirt-sizes/image/go.mod
Normal file
5
functions/examples/injection-tshirt-sizes/image/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module sigs.k8s.io/kustomize/functions/examples/injection-tshirt-sizes
|
||||
|
||||
go 1.13
|
||||
|
||||
require sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4
|
||||
27
functions/examples/injection-tshirt-sizes/image/go.sum
Normal file
27
functions/examples/injection-tshirt-sizes/image/go.sum
Normal file
@@ -0,0 +1,27 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4 h1:QfQuib3Xi0uyHUi/R5MgWmDScb5iy/+LjoaGIdpmMpE=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4/go.mod h1:rywm/rcR5LmCBghz9956tE45OdUPChFoXVVs+WmhMTI=
|
||||
116
functions/examples/injection-tshirt-sizes/image/main.go
Normal file
116
functions/examples/injection-tshirt-sizes/image/main.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main implements an injection function for resource reservations and
|
||||
// is run with `kustomize config run-fns -- DIR/`.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rw := &kio.ByteReadWriter{Reader: os.Stdin, Writer: os.Stdout, KeepReaderAnnotations: true}
|
||||
p := kio.Pipeline{
|
||||
Inputs: []kio.Reader{rw}, // read the inputs into a slice
|
||||
Filters: []kio.Filter{filter{}}, // run the inject into the inputs
|
||||
Outputs: []kio.Writer{rw}} // copy the inputs to the output
|
||||
if err := p.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// filter implements kio.Filter
|
||||
type filter struct{}
|
||||
|
||||
// Filter injects cpu and memory resource reservations into containers for
|
||||
// Resources containing the `tshirt-size` annotation.
|
||||
func (filter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
// inject the resource reservations into each Resource
|
||||
for _, r := range in {
|
||||
if err := inject(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return in, nil
|
||||
}
|
||||
|
||||
// cpuSizes is the mapping from tshirt-size to cpu reservation quantity
|
||||
var cpuSizes = map[string]string{
|
||||
"small": "200m",
|
||||
"medium": "4",
|
||||
"large": "16",
|
||||
}
|
||||
|
||||
// memorySizes is the mapping from tshirt-size to memory reservation quantity
|
||||
var memorySizes = map[string]string{
|
||||
"small": "50MiB",
|
||||
"medium": "1GiB",
|
||||
"large": "32GiB",
|
||||
}
|
||||
|
||||
// inject sets the cpu and memory reservations on all containers for Resources annotated
|
||||
// with `tshirt-size: small|medium|large`
|
||||
func inject(r *yaml.RNode) error {
|
||||
// lookup the containers field
|
||||
containers, err := r.Pipe(yaml.Lookup("spec", "template", "spec", "containers"))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
if containers == nil {
|
||||
// doesn't have containers, skip the Resource
|
||||
return nil
|
||||
}
|
||||
|
||||
// check for the tshirt-size annotations
|
||||
meta, err := r.GetMeta()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var memorySize, cpuSize string
|
||||
if size, found := meta.Annotations["tshirt-size"]; !found {
|
||||
// not a tshirt-sized Resource, ignore it
|
||||
return nil
|
||||
} else {
|
||||
// lookup the memory and cpu quantities based on the tshirt size
|
||||
memorySize = memorySizes[size]
|
||||
cpuSize = cpuSizes[size]
|
||||
if memorySize == "" || cpuSize == "" {
|
||||
return fmt.Errorf("unsupported tshirt-size: " + size)
|
||||
}
|
||||
}
|
||||
|
||||
// visit each container and apply the cpu and memory reservations
|
||||
return containers.VisitElements(func(node *yaml.RNode) error {
|
||||
// set cpu
|
||||
err := node.PipeE(
|
||||
// lookup resources.requests.cpu, creating the field as a
|
||||
// ScalarNode if it doesn't exist
|
||||
yaml.LookupCreate(yaml.ScalarNode, "resources", "requests", "cpu"),
|
||||
// set the field value to the cpuSize
|
||||
yaml.Set(yaml.NewScalarRNode(cpuSize)))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
|
||||
// set memory
|
||||
err = node.PipeE(
|
||||
// lookup resources.requests.memory, creating the field as a
|
||||
// ScalarNode if it doesn't exist
|
||||
yaml.LookupCreate(yaml.ScalarNode, "resources", "requests", "memory"),
|
||||
// set the field value to the memorySize
|
||||
yaml.Set(yaml.NewScalarRNode(memorySize)))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: Validator
|
||||
metadata:
|
||||
configFn:
|
||||
container:
|
||||
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
labels:
|
||||
app: nginx
|
||||
annotations:
|
||||
tshirt-size: small # this injects the resource reservations
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
2
functions/examples/template-go-nginx/LICENSE_TEMPLATE
Normal file
2
functions/examples/template-go-nginx/LICENSE_TEMPLATE
Normal file
@@ -0,0 +1,2 @@
|
||||
Copyright {{.Year}} {{.Holder}}
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
42
functions/examples/template-go-nginx/Makefile
Normal file
42
functions/examples/template-go-nginx/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
all: generate license build fix vet fmt test lint tidy
|
||||
|
||||
fix:
|
||||
(cd image && go fix ./...)
|
||||
|
||||
fmt:
|
||||
(cd image && go fmt ./...)
|
||||
|
||||
generate:
|
||||
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
|
||||
(cd image && GOBIN=$(GOBIN) 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:
|
||||
(cd image && go mod tidy)
|
||||
|
||||
lint:
|
||||
(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
(cd image && $(GOBIN)/golangci-lint run ./...)
|
||||
|
||||
test:
|
||||
(cd image && go test -cover ./...)
|
||||
|
||||
vet:
|
||||
(cd image && go vet ./...)
|
||||
|
||||
image:
|
||||
docker build image -t gcr.io/kustomize-functions/example-nginx:v0.1.0
|
||||
docker push gcr.io/kustomize-functions/example-nginx:v0.1.0
|
||||
55
functions/examples/template-go-nginx/README.md
Normal file
55
functions/examples/template-go-nginx/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Template GoTemplate
|
||||
|
||||
This is an example of implementing a template function using a `go` template.
|
||||
|
||||
This example uses a more sophisticated approach for building abstractions.
|
||||
|
||||
## Function implementation
|
||||
|
||||
The function is implemented as an [image](image), and built using `make image`.
|
||||
|
||||
The template is implemented as a go program with a `go` template. It parses the
|
||||
functionConfig into a `go` struct and uses the `kyaml` module for parsing the
|
||||
function input, and writing the function output.
|
||||
|
||||
1. read the inputs (stdin)
|
||||
2. apply filters
|
||||
- (custom filter) generate the nginx Deployment and Service from go templates using the
|
||||
functionConfig as the template input.
|
||||
- merge the generated Deployment and Service with the input Deployment and Service if
|
||||
present
|
||||
- set filenames on the Resources (`NAME.yaml`)
|
||||
- format the Resources
|
||||
3. write the outputs (stdout)
|
||||
|
||||
## Function invocation
|
||||
|
||||
The function is invoked by authoring a [local Resource](local-resource)
|
||||
with `metadata.configFn` and running:
|
||||
|
||||
kustomize config run-fns local-resources/
|
||||
|
||||
This generates the `local-resources/config` directory containing the template output.
|
||||
|
||||
- the template output may be modified by adding fields -- such as initContainers,
|
||||
sidecarConatiners, cpu resource limits, etc -- and these fields will be retained
|
||||
when re-running `run-fns`
|
||||
- the function input `example-use.yaml` may be changed and rerunning `run-fns` will update
|
||||
only the parts changed in the template output.
|
||||
|
||||
## Running the Example
|
||||
|
||||
Run the config with:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
This will create the directory
|
||||
|
||||
local-resource/config
|
||||
|
||||
Add an annotation to the StatefulSet Resource and change the replica count of the
|
||||
`kind: Nginx` Resource in `example-use.yaml`. Rerun the template:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
The replica count should be updated, but your annotation should remain.
|
||||
15
functions/examples/template-go-nginx/image/Dockerfile
Normal file
15
functions/examples/template-go-nginx/image/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.13-stretch
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /go/src/
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
COPY main.go .
|
||||
RUN go build -v -o /usr/local/bin/config-function ./
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=0 /usr/local/bin/config-function /usr/local/bin/config-function
|
||||
CMD ["config-function"]
|
||||
5
functions/examples/template-go-nginx/image/go.mod
Normal file
5
functions/examples/template-go-nginx/image/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module sigs.k8s.io/kustomize/functions/examples/template-go-nginx
|
||||
|
||||
go 1.12
|
||||
|
||||
require sigs.k8s.io/kustomize/kyaml v0.0.0-20191126203124-d1b33e746881
|
||||
27
functions/examples/template-go-nginx/image/go.sum
Normal file
27
functions/examples/template-go-nginx/image/go.sum
Normal file
@@ -0,0 +1,27 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126203124-d1b33e746881 h1:dmMlmv+TXMSAtCf6Za1GKNAjCssKtgnVkAYRiKdnjIY=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126203124-d1b33e746881/go.mod h1:rywm/rcR5LmCBghz9956tE45OdUPChFoXVVs+WmhMTI=
|
||||
169
functions/examples/template-go-nginx/image/main.go
Normal file
169
functions/examples/template-go-nginx/image/main.go
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rw := &kio.ByteReadWriter{
|
||||
Reader: os.Stdin,
|
||||
Writer: os.Stdout,
|
||||
KeepReaderAnnotations: true,
|
||||
}
|
||||
|
||||
err := kio.Pipeline{
|
||||
Inputs: []kio.Reader{rw},
|
||||
Filters: []kio.Filter{
|
||||
&filter{rw: rw}, // generate the Resources from the template
|
||||
filters.MergeFilter{}, // merge the generated template
|
||||
// set Resource filenames
|
||||
&filters.FileSetter{FilenamePattern: filepath.Join("config", "%n.yaml")},
|
||||
filters.FormatFilter{}, // format the output
|
||||
},
|
||||
Outputs: []kio.Writer{rw},
|
||||
}.Execute()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// define the input API schema as a struct
|
||||
type API struct {
|
||||
Metadata struct {
|
||||
// Name is the Deployment Resource and Container name
|
||||
Name string `yaml:"name"`
|
||||
} `yaml:"metadata"`
|
||||
|
||||
Spec struct {
|
||||
// Replicas is the number of Deployment replicas
|
||||
// Defaults to the REPLICAS env var, or 1
|
||||
Replicas *int `yaml:"replicas"`
|
||||
} `yaml:"spec"`
|
||||
}
|
||||
|
||||
// filter implements kio.Filter
|
||||
type filter struct {
|
||||
rw *kio.ByteReadWriter
|
||||
}
|
||||
|
||||
// Filter checks each input and ensures that all containers have cpu and memory
|
||||
// reservations set, otherwise it returns an error.
|
||||
func (f *filter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
api := f.parseAPI()
|
||||
|
||||
// execute the service template
|
||||
buff := &bytes.Buffer{}
|
||||
t := template.Must(template.New("nginx-service").Parse(serviceTemplate))
|
||||
if err := t.Execute(buff, api); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := yaml.Parse(buff.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// execute the deployment template
|
||||
buff = &bytes.Buffer{}
|
||||
t = template.Must(template.New("nginx-deployment").Parse(deploymentTemplate))
|
||||
if err := t.Execute(buff, api); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d, err := yaml.Parse(buff.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add the template generated Resources to the output -- these will get merged by the next
|
||||
// filter
|
||||
in = append(in, s, d)
|
||||
return in, nil
|
||||
}
|
||||
|
||||
// parseAPI parses the functionConfig into an API struct, and validates the input
|
||||
func (f *filter) parseAPI() API {
|
||||
// parse the input function config -- TODO: simplify this
|
||||
var api API
|
||||
if err := yaml.Unmarshal([]byte(f.rw.FunctionConfig.MustString()), &api); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Default functionConfig values from environment variables if they are not set
|
||||
// in the functionConfig
|
||||
r := os.Getenv("REPLICAS")
|
||||
if r != "" && api.Spec.Replicas == nil {
|
||||
replicas, err := strconv.Atoi(r)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
api.Spec.Replicas = &replicas
|
||||
}
|
||||
if api.Spec.Replicas == nil {
|
||||
r := 1
|
||||
api.Spec.Replicas = &r
|
||||
}
|
||||
if api.Metadata.Name == "" {
|
||||
fmt.Fprintf(os.Stderr, "must specify metadata.name\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return api
|
||||
}
|
||||
|
||||
var serviceTemplate = `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Metadata.Name }}
|
||||
labels:
|
||||
app: nginx
|
||||
instance: {{ .Metadata.Name }}
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
name: http
|
||||
selector:
|
||||
app: nginx
|
||||
instance: {{ .Metadata.Name }}
|
||||
`
|
||||
|
||||
var deploymentTemplate = `apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Metadata.Name }}
|
||||
labels:
|
||||
app: nginx
|
||||
instance: {{ .Metadata.Name }}
|
||||
spec:
|
||||
replicas: {{ .Spec.Replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
instance: {{ .Metadata.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
instance: {{ .Metadata.Name }}
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
ports:
|
||||
- containerPort: 80
|
||||
`
|
||||
@@ -0,0 +1,12 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1 # call `kustomize config run-fns` on a directory containing this file
|
||||
kind: Nginx
|
||||
metadata:
|
||||
name: demo
|
||||
configFn:
|
||||
container:
|
||||
image: gcr.io/kustomize-functions/example-nginx:v0.1.0
|
||||
spec:
|
||||
replicas: 4
|
||||
@@ -0,0 +1,2 @@
|
||||
Copyright {{.Year}} {{.Holder}}
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
12
functions/examples/template-heredoc-cockroachdb/Makefile
Normal file
12
functions/examples/template-heredoc-cockroachdb/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.PHONY: license image
|
||||
|
||||
license:
|
||||
(which $(GOPATH)/bin/addlicense || go get github.com/google/addlicense)
|
||||
$(GOPATH)/bin/addlicense -y 2019 -c "The Kubernetes Authors." -f LICENSE_TEMPLATE .
|
||||
|
||||
image:
|
||||
docker build image -t gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
|
||||
docker push gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
|
||||
50
functions/examples/template-heredoc-cockroachdb/README.md
Normal file
50
functions/examples/template-heredoc-cockroachdb/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Template HereDoc
|
||||
|
||||
This is an example of implementing a template function using a heredoc.
|
||||
|
||||
This example uses the simplest approach for building abstractions.
|
||||
|
||||
## Function implementation
|
||||
|
||||
The function is implemented as an [image](image), and built using `make image`.
|
||||
|
||||
The template is implemented as a heredoc, which substitutes environment variables
|
||||
into a static string.
|
||||
|
||||
This simple implementation uses `kustomize config run-fns wrap --` to perform the
|
||||
heavy lifting of implementing the function interface.
|
||||
|
||||
- parse functionConfig from stdin into environment variables
|
||||
- merge script output with items from stdin
|
||||
|
||||
## Function invocation
|
||||
|
||||
The function is invoked by authoring a [local Resource](local-resource)
|
||||
with `metadata.configFn` and running:
|
||||
|
||||
kustomize config run-fns local-resources/
|
||||
|
||||
This generates the `local-resources/config` directory containing the template output.
|
||||
|
||||
- the template output may be modified by adding fields -- such as initContainers,
|
||||
sidecarConatiners, cpu resource limits, etc -- and these fields will be retained
|
||||
when re-running `run-fns`
|
||||
- the function input `example-use.yaml` may be changed and rerunning `run-fns` will update
|
||||
only the parts changed in the template output.
|
||||
|
||||
## Running the Example
|
||||
|
||||
Run the config with:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
This will create the directory
|
||||
|
||||
local-resource/config
|
||||
|
||||
Add an annotation to the StatefulSet Resource and change the replica count of the
|
||||
`kind: CockroachDB` Resource in `example-use.yaml`. Rerun the template:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
The replica count should be updated, but your annotation should remain.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.13-stretch
|
||||
ENV CGO_ENABLED=0
|
||||
RUN go get -v sigs.k8s.io/kustomize/kustomize
|
||||
|
||||
FROM alpine:latest
|
||||
RUN apk add --no-cache bash
|
||||
COPY --from=0 /go/bin/kustomize /usr/local/bin
|
||||
COPY cockroachdb-template.sh /usr/local/bin/config-function
|
||||
CMD ["config-function"]
|
||||
204
functions/examples/template-heredoc-cockroachdb/image/cockroachdb-template.sh
Executable file
204
functions/examples/template-heredoc-cockroachdb/image/cockroachdb-template.sh
Executable file
@@ -0,0 +1,204 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
# use `kustomize config run-fns wrap` to parse the container stdin into
|
||||
# environment variables, and to merge the template output into the
|
||||
# input Resources.
|
||||
if [ -z ${WRAPPED} ]; then
|
||||
export WRAPPED=true
|
||||
kustomize config run-fns wrap -- $0
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# this is the template for a cockroachdb instance
|
||||
# environment variables are parsed from the input functionConfig by
|
||||
# `kustomize config run-fns wrap`
|
||||
cat <<End-of-message
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# This service is meant to be used by clients of the database. It exposes a ClusterIP that will
|
||||
# automatically load balance connections to the different database pods.
|
||||
name: ${NAME}-public
|
||||
labels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
spec:
|
||||
ports:
|
||||
# The main port, served by gRPC, serves Postgres-flavor SQL, internode
|
||||
# traffic and the cli.
|
||||
- port: 26257
|
||||
targetPort: 26257
|
||||
name: grpc
|
||||
# The secondary port serves the UI as well as health and debug endpoints.
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
name: http
|
||||
selector:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# This service only exists to create DNS entries for each pod in the stateful
|
||||
# set such that they can resolve each other's IP addresses. It does not
|
||||
# create a load-balanced ClusterIP and should not be used directly by clients
|
||||
# in most circumstances.
|
||||
name: ${NAME}
|
||||
labels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
annotations:
|
||||
# This is needed to make the peer-finder work properly and to help avoid
|
||||
# edge cases where instance 0 comes up after losing its data and needs to
|
||||
# decide whether it should create a new cluster or try to join an existing
|
||||
# one. If it creates a new cluster when it should have joined an existing
|
||||
# one, we'd end up with two separate clusters listening at the same service
|
||||
# endpoint, which would be very bad.
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
# Enable automatic monitoring of all instances when Prometheus is running in the cluster.
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/path: "_status/vars"
|
||||
prometheus.io/port: "8080"
|
||||
spec:
|
||||
ports:
|
||||
- port: 26257
|
||||
targetPort: 26257
|
||||
name: grpc
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
name: http
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: ${NAME}-budget
|
||||
labels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
minAvailable: 67%
|
||||
---
|
||||
apiVersion: apps/v1 # for k8s versions before 1.9.0 use apps/v1beta2 and before 1.8.0 use extensions/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: ${NAME}
|
||||
labels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
spec:
|
||||
serviceName: ${NAME}
|
||||
replicas: ${REPLICAS}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cockroachdb
|
||||
name: ${NAME}
|
||||
spec:
|
||||
# Init containers are run only once in the lifetime of a pod, before
|
||||
# it's started up for the first time. It has to exit successfully
|
||||
# before the pod's main containers are allowed to start.
|
||||
# This particular init container does a DNS lookup for other pods in
|
||||
# the set to help determine whether or not a cluster already exists.
|
||||
# If any other pods exist, it creates a file in the cockroach-data
|
||||
# directory to pass that information along to the primary container that
|
||||
# has to decide what command-line flags to use when starting CockroachDB.
|
||||
# This only matters when a pod's persistent volume is empty - if it has
|
||||
# data from a previous execution, that data will always be used.
|
||||
#
|
||||
# If your Kubernetes cluster uses a custom DNS domain, you will have
|
||||
# to add an additional arg to this pod: "-domain=<your-custom-domain>"
|
||||
initContainers:
|
||||
- name: bootstrap
|
||||
image: cockroachdb/cockroach-k8s-init:0.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- "-on-start=/on-start.sh"
|
||||
- "-service=cockroachdb"
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
volumeMounts:
|
||||
- name: datadir
|
||||
mountPath: "/cockroach/cockroach-data"
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- cockroachdb
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers:
|
||||
- name: ${NAME}
|
||||
image: cockroachdb/cockroach:v1.1.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 26257
|
||||
name: grpc
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
volumeMounts:
|
||||
- name: datadir
|
||||
mountPath: /cockroach/cockroach-data
|
||||
command:
|
||||
- "/bin/bash"
|
||||
- "-ecx"
|
||||
- |
|
||||
# The use of qualified \`hostname -f\` is crucial:
|
||||
# Other nodes aren't able to look up the unqualified hostname.
|
||||
CRARGS=("start" "--logtostderr" "--insecure" "--host" "\$(hostname -f)" "--http-host" "0.0.0.0")
|
||||
# We only want to initialize a new cluster (by omitting the join flag)
|
||||
# if we're sure that we're the first node (i.e. index 0) and that
|
||||
# there aren't any other nodes running as part of the cluster that
|
||||
# this is supposed to be a part of (which indicates that a cluster
|
||||
# already exists and we should make sure not to create a new one).
|
||||
# It's fine to run without --join on a restart if there aren't any
|
||||
# other nodes.
|
||||
if [ ! "\$(hostname)" == "cockroachdb-0" ] || \
|
||||
[ -e "/cockroach/cockroach-data/cluster_exists_marker" ]
|
||||
then
|
||||
# We don't join cockroachdb in order to avoid a node attempting
|
||||
# to join itself, which currently doesn't work
|
||||
# (https://github.com/cockroachdb/cockroach/issues/9625).
|
||||
CRARGS+=("--join" "cockroachdb-public")
|
||||
fi
|
||||
exec /cockroach/cockroach \${CRARGS[*]}
|
||||
# No pre-stop hook is required, a SIGTERM plus some time is all that's
|
||||
# needed for graceful shutdown of a node.
|
||||
terminationGracePeriodSeconds: 60
|
||||
volumes:
|
||||
- name: datadir
|
||||
persistentVolumeClaim:
|
||||
claimName: datadir
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: datadir
|
||||
spec:
|
||||
accessModes:
|
||||
- "ReadWriteOnce"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
End-of-message
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# call `kustomize config run-fns` on a directory containing this file
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: CockroachDB
|
||||
metadata:
|
||||
name: demo
|
||||
configFn:
|
||||
container:
|
||||
image: gcr.io/kustomize-functions/example-cockroachdb:v0.1.0
|
||||
spec:
|
||||
replicas: 3
|
||||
@@ -0,0 +1,2 @@
|
||||
Copyright {{.Year}} {{.Holder}}
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
42
functions/examples/validator-resource-requests/Makefile
Normal file
42
functions/examples/validator-resource-requests/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
all: generate license build fix vet fmt test lint tidy
|
||||
|
||||
fix:
|
||||
(cd image && go fix ./...)
|
||||
|
||||
fmt:
|
||||
(cd image && go fmt ./...)
|
||||
|
||||
generate:
|
||||
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
|
||||
(cd image && GOBIN=$(GOBIN) 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:
|
||||
(cd image && go mod tidy)
|
||||
|
||||
lint:
|
||||
(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
(cd image && $(GOBIN)/golangci-lint run ./...)
|
||||
|
||||
test:
|
||||
(cd image && go test -cover ./...)
|
||||
|
||||
vet:
|
||||
(cd image && go vet ./...)
|
||||
|
||||
image:
|
||||
docker build image -t gcr.io/kustomize-functions/example-validator:v0.1.0
|
||||
docker push gcr.io/kustomize-functions/example-validator:v0.1.0
|
||||
38
functions/examples/validator-resource-requests/README.md
Normal file
38
functions/examples/validator-resource-requests/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Validation
|
||||
|
||||
This is an example of implementing a validation function.
|
||||
|
||||
This example is written in `go` and uses the `kyaml` libraries for parsing the
|
||||
input and writing the output. Writing in `go` is not a requirement.
|
||||
|
||||
## Function implementation
|
||||
|
||||
The function is implemented as an [image](image), and built using `make image`.
|
||||
|
||||
The template is implemented as a go program, which reads a collection of input
|
||||
Resource configuration, and looks for invalid configuration.
|
||||
|
||||
## Function invocation
|
||||
|
||||
The function is invoked by authoring a [local Resource](local-resource)
|
||||
with `metadata.configFn` and running:
|
||||
|
||||
kustomize config run-fns local-resources/
|
||||
|
||||
This exists non-zero if there is an error.
|
||||
|
||||
## Running the Example
|
||||
|
||||
Run the validator with:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
This will return an error:
|
||||
|
||||
cpu-requests missing for container nginx
|
||||
|
||||
Now uncomment the resource reservations and run again:
|
||||
|
||||
kustomize config run-fns local-resource/
|
||||
|
||||
This will return success
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.13-stretch
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /go/src/
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
COPY main.go .
|
||||
RUN go build -v -o /usr/local/bin/config-function ./
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=0 /usr/local/bin/config-function /usr/local/bin/config-function
|
||||
CMD ["config-function"]
|
||||
@@ -0,0 +1,5 @@
|
||||
module sigs.k8s.io/kustomize/functions/examples/validator-resource-requests
|
||||
|
||||
go 1.13
|
||||
|
||||
require sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4
|
||||
27
functions/examples/validator-resource-requests/image/go.sum
Normal file
27
functions/examples/validator-resource-requests/image/go.sum
Normal file
@@ -0,0 +1,27 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4 h1:QfQuib3Xi0uyHUi/R5MgWmDScb5iy/+LjoaGIdpmMpE=
|
||||
sigs.k8s.io/kustomize/kyaml v0.0.0-20191126155111-73fb32c85ad4/go.mod h1:rywm/rcR5LmCBghz9956tE45OdUPChFoXVVs+WmhMTI=
|
||||
94
functions/examples/validator-resource-requests/image/main.go
Normal file
94
functions/examples/validator-resource-requests/image/main.go
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main implements a validator function run by `kustomize config run-fns`
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rw := &kio.ByteReadWriter{Reader: os.Stdin, Writer: os.Stdout, KeepReaderAnnotations: true}
|
||||
p := kio.Pipeline{
|
||||
Inputs: []kio.Reader{rw}, // read the inputs into a slice
|
||||
Filters: []kio.Filter{filter{}}, // run the filter against the inputs
|
||||
Outputs: []kio.Writer{rw}} // copy the inputs to the output
|
||||
if err := p.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// filter implements kio.Filter
|
||||
type filter struct{}
|
||||
|
||||
// Filter checks each input and ensures that all containers have cpu and memory
|
||||
// reservations set, otherwise it returns an error.
|
||||
func (filter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
// validate each Resource
|
||||
for _, r := range in {
|
||||
if err := validate(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return in, nil
|
||||
}
|
||||
|
||||
func validate(r *yaml.RNode) error {
|
||||
meta, err := r.GetMeta()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// lookup the containers field in the Resource
|
||||
containers, err := r.Pipe(yaml.Lookup("spec", "template", "spec", "containers"))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
if containers == nil {
|
||||
// doesn't have containers, ignore it
|
||||
return nil
|
||||
}
|
||||
|
||||
// visit each container in the list and validate
|
||||
return containers.VisitElements(func(node *yaml.RNode) error {
|
||||
|
||||
// check cpu is non-nil
|
||||
f, err := node.Pipe(yaml.Lookup("resources", "requests", "cpu"))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
if f == nil {
|
||||
return fmt.Errorf(
|
||||
"cpu-requests missing for a container in %s %s (%s [%s])",
|
||||
meta.Kind, meta.Name,
|
||||
meta.Annotations[kioutil.PathAnnotation],
|
||||
meta.Annotations[kioutil.IndexAnnotation])
|
||||
}
|
||||
|
||||
// check memory is non-nil
|
||||
f, err = node.Pipe(yaml.Lookup("resources", "requests", "memory"))
|
||||
if err != nil {
|
||||
s, _ := r.String()
|
||||
return fmt.Errorf("%v: %s", err, s)
|
||||
}
|
||||
if f == nil {
|
||||
return fmt.Errorf(
|
||||
"memory-requests missing for a container in %s in %s (%s [%s])",
|
||||
meta.Kind, meta.Name,
|
||||
meta.Annotations[kioutil.PathAnnotation],
|
||||
meta.Annotations[kioutil.IndexAnnotation])
|
||||
}
|
||||
|
||||
// container is valid
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright 2019 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
apiVersion: examples.config.kubernetes.io/v1beta1
|
||||
kind: Validator
|
||||
metadata:
|
||||
configFn:
|
||||
container:
|
||||
image: gcr.io/kustomize-functions/example-validator:v0.1.0
|
||||
---
|
||||
apiVersion: apps/v1 # this should fail validation
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
# uncomment these to pass validation
|
||||
# resources:
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 300MiB
|
||||
Reference in New Issue
Block a user