Files
kustomize/functions/examples/template-go-nginx/image/main.go
Phillip Wittrock dc66de6bf3 cmd/config: Add examples and tutorials for config functions
- Add examples under `functions`
- Add built-in tutorial for functions
2019-11-26 20:08:23 -08:00

170 lines
3.8 KiB
Go

// 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
`