Files
kustomize/functions/examples/injection-tshirt-sizes/image/main.go
2020-02-03 15:39:05 -08:00

117 lines
3.2 KiB
Go

// 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 -- 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": "50M",
"medium": "1G",
"large": "32G",
}
// 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
})
}