// 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 fn run -- DIR/`. package main import ( "fmt" "os" "sigs.k8s.io/kustomize/kyaml/fn/framework" "sigs.k8s.io/kustomize/kyaml/fn/framework/command" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" ) var ( // cpuSizes is the mapping from tshirt-size to cpu reservation quantity cpuSizes = map[string]string{ "small": "200m", "medium": "4", "large": "16", } // memorySizes is the mapping from tshirt-size to memory reservation quantity memorySizes = map[string]string{ "small": "50M", "medium": "1G", "large": "32G", } ) func main() { fn := func(items []*yaml.RNode) ([]*yaml.RNode, error) { for _, item := range items { if err := size(item); err != nil { return nil, err } } return items, nil } p := framework.SimpleProcessor{Config: nil, Filter: kio.FilterFunc(fn)} cmd := command.Build(p, command.StandaloneDisabled, false) command.AddGenerateDockerfile(cmd) if err := cmd.Execute(); err != nil { os.Exit(1) } } // size sets the cpu and memory reservations on all containers for Resources annotated // with `tshirt-size: small|medium|large` func size(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: %s", 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 }) }