mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
161 lines
3.7 KiB
Go
161 lines
3.7 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Package main implements adding an Application CR to a group of resources and
|
|
// is run with `kustomize fn run -- DIR/`.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"sigs.k8s.io/application/api/v1beta1"
|
|
yaml2 "sigs.k8s.io/yaml"
|
|
|
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
)
|
|
|
|
func appCR() error {
|
|
rw := &kio.ByteReadWriter{
|
|
Reader: os.Stdin,
|
|
Writer: os.Stdout,
|
|
OmitReaderAnnotations: true,
|
|
KeepReaderAnnotations: true,
|
|
}
|
|
p := kio.Pipeline{
|
|
Inputs: []kio.Reader{rw}, // read the inputs into a slice
|
|
Filters: []kio.Filter{appCRFilter{rw: rw}},
|
|
Outputs: []kio.Writer{rw}, // copy the inputs to the output
|
|
}
|
|
if err := p.Execute(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
if err := appCR(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// appCRFilter implements kio.Filter
|
|
type appCRFilter struct {
|
|
rw *kio.ByteReadWriter
|
|
}
|
|
|
|
// define the input API schema as a struct
|
|
type API struct {
|
|
Spec struct {
|
|
ManagedBy string `yaml:"managedBy"`
|
|
|
|
Name string `yaml:"name"`
|
|
|
|
Namespace string `yaml:"namespace"`
|
|
|
|
Descriptor v1beta1.Descriptor `yaml:"descriptor,omitempty"`
|
|
} `yaml:"spec"`
|
|
}
|
|
|
|
// Filter checks each resource for validity, otherwise returning an error.
|
|
func (f appCRFilter) Filter(in []*yaml.RNode) ([]*yaml.RNode, error) {
|
|
api := f.parseAPI()
|
|
|
|
groupKinds, err := getGroupKinds(in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
app, err := addApplicationCR(api, groupKinds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = addApplicationLabel(api.Spec.Name, in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if app != nil {
|
|
return append(in, app), nil
|
|
}
|
|
return in, nil
|
|
}
|
|
|
|
// parseAPI parses the functionConfig into an API struct.
|
|
func (f *appCRFilter) 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)
|
|
}
|
|
|
|
return api
|
|
}
|
|
|
|
func getGroupKinds(in []*yaml.RNode) ([]metav1.GroupKind, error) {
|
|
var groupKinds []metav1.GroupKind
|
|
for _, r := range in {
|
|
meta, err := r.GetMeta()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
gvk := schema.FromAPIVersionAndKind(meta.APIVersion, meta.Kind)
|
|
|
|
found := false
|
|
for _, gk := range groupKinds {
|
|
if gk.Group == gvk.Group && gk.Kind == gvk.Kind {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
groupKinds = append(groupKinds, metav1.GroupKind{
|
|
Group: gvk.Group,
|
|
Kind: gvk.Kind,
|
|
})
|
|
}
|
|
}
|
|
return groupKinds, nil
|
|
}
|
|
|
|
func addApplicationCR(api API, groupKinds []metav1.GroupKind) (*yaml.RNode, error) {
|
|
app := v1beta1.Application{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "app.k8s.io/v1beta1",
|
|
Kind: "Application",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: api.Spec.Namespace,
|
|
Name: api.Spec.Name,
|
|
Labels: map[string]string{"app.kubernetes.io/name": api.Spec.Name},
|
|
Annotations: map[string]string{"app.kubernetes.io/managed-by": api.Spec.ManagedBy},
|
|
},
|
|
Spec: v1beta1.ApplicationSpec{
|
|
ComponentGroupKinds: groupKinds,
|
|
Descriptor: api.Spec.Descriptor,
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app.kubernetes.io/name": api.Spec.Name},
|
|
},
|
|
},
|
|
}
|
|
|
|
data, err := yaml2.Marshal(app)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return yaml.Parse(string(data))
|
|
}
|
|
|
|
func addApplicationLabel(name string, in []*yaml.RNode) error {
|
|
for _, r := range in {
|
|
if _, err := r.Pipe(yaml.SetLabel("app.kubernetes.io/name", name)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|