Refactor container functions

This commit is contained in:
Phillip Wittrock
2020-03-24 11:18:46 -07:00
parent 6c2adc48dd
commit 85e9779bd6
3 changed files with 98 additions and 78 deletions

View File

@@ -389,85 +389,13 @@ type IsReconcilerFilter struct {
func (c *IsReconcilerFilter) Filter(inputs []*yaml.RNode) ([]*yaml.RNode, error) {
var out []*yaml.RNode
for i := range inputs {
isContainerResource := GetFunctionSpec(inputs[i]) != nil
if isContainerResource && !c.ExcludeReconcilers {
isFnResource := GetFunctionSpec(inputs[i]) != nil
if isFnResource && !c.ExcludeReconcilers {
out = append(out, inputs[i])
}
if !isContainerResource && c.IncludeNonReconcilers {
if !isFnResource && c.IncludeNonReconcilers {
out = append(out, inputs[i])
}
}
return out, nil
}
const (
FunctionAnnotationKey = "config.kubernetes.io/function"
oldFunctionAnnotationKey = "config.k8s.io/function"
)
var functionAnnotationKeys = []string{FunctionAnnotationKey, oldFunctionAnnotationKey}
// getFunction parses the config function from the object if it is found
func getFunction(n *yaml.RNode, meta yaml.ResourceMeta) *FunctionSpec {
var fs FunctionSpec
for _, s := range functionAnnotationKeys {
fn := meta.Annotations[s]
if fn != "" {
_ = yaml.Unmarshal([]byte(fn), &fs)
return &fs
}
}
n, err := n.Pipe(yaml.Lookup("metadata", "configFn"))
if err != nil || yaml.IsEmpty(n) {
return nil
}
s, err := n.String()
if err != nil {
return nil
}
_ = yaml.Unmarshal([]byte(s), &fs)
return &fs
}
type ContainerSpec struct {
Image string `json:"image,omitempty" yaml:"image,omitempty"`
Network ContainerNetwork `json:"network,omitempty" yaml:"network,omitempty"`
}
type FunctionSpec struct {
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Network string `json:"network,omitempty" yaml:"network,omitempty"`
Container ContainerSpec `json:"container,omitempty" yaml:"container,omitempty"`
}
type ContainerNetwork struct {
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
}
// GetFunctionSpec returns the FunctionSpec for a resource. Returns
// nil if the resource does not have a FunctionSpec.
//
// The FunctionSpec is read from the resource metadata.annotation
// "config.kubernetes.io/function"
func GetFunctionSpec(n *yaml.RNode) *FunctionSpec {
meta, err := n.GetMeta()
if err != nil {
return nil
}
// path to the function, this will be mounted into the container
path := meta.Annotations[kioutil.PathAnnotation]
if fn := getFunction(n, meta); fn != nil {
fn.Network = ""
fn.Path = path
return fn
}
// legacy function specification for backwards compatibility
container := meta.Annotations["config.kubernetes.io/container"]
if container != "" {
return &FunctionSpec{
Path: path, Container: ContainerSpec{Image: container}}
}
return nil
}

View File

@@ -511,9 +511,7 @@ metadata:
if !assert.NoError(t, err) {
return
}
meta, _ := cfg.GetMeta()
fn := getFunction(cfg, meta)
fn := GetFunctionSpec(cfg)
assert.Equal(t, tc.required, fn.Container.Network.Required)
}
}

View File

@@ -0,0 +1,94 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package filters
import (
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
const (
FunctionAnnotationKey = "config.kubernetes.io/function"
oldFunctionAnnotationKey = "config.k8s.io/function"
)
var functionAnnotationKeys = []string{FunctionAnnotationKey, oldFunctionAnnotationKey}
// FunctionSpec defines a spec for running a function
type FunctionSpec struct {
// Path defines the path for scoped functions
Path string `json:"path,omitempty" yaml:"path,omitempty"`
// Network is the name of the network to use from a container
Network string `json:"network,omitempty" yaml:"network,omitempty"`
// Container is the spec for running a function as a container
Container ContainerSpec `json:"container,omitempty" yaml:"container,omitempty"`
}
// ContainerSpec defines a spec for running a function as a container
type ContainerSpec struct {
// Image is the container image to run
Image string `json:"image,omitempty" yaml:"image,omitempty"`
// Network defines network specific configuration
Network ContainerNetwork `json:"network,omitempty" yaml:"network,omitempty"`
}
// ContainerNetwork
type ContainerNetwork struct {
// Required specifies that function requires a network
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
}
// GetFunctionSpec returns the FunctionSpec for a resource. Returns
// nil if the resource does not have a FunctionSpec.
//
// The FunctionSpec is read from the resource metadata.annotation
// "config.kubernetes.io/function"
func GetFunctionSpec(n *yaml.RNode) *FunctionSpec {
meta, err := n.GetMeta()
if err != nil {
return nil
}
// path to the function, this will be mounted into the container
path := meta.Annotations[kioutil.PathAnnotation]
if fn := getFunctionSpecFromAnnotation(n, meta); fn != nil {
fn.Network = ""
fn.Path = path
return fn
}
// legacy function specification for backwards compatibility
container := meta.Annotations["config.kubernetes.io/container"]
if container != "" {
return &FunctionSpec{
Path: path, Container: ContainerSpec{Image: container}}
}
return nil
}
// getFunctionSpecFromAnnotation parses the config function from an annotation
// if it is found
func getFunctionSpecFromAnnotation(n *yaml.RNode, meta yaml.ResourceMeta) *FunctionSpec {
var fs FunctionSpec
for _, s := range functionAnnotationKeys {
fn := meta.Annotations[s]
if fn != "" {
_ = yaml.Unmarshal([]byte(fn), &fs)
return &fs
}
}
n, err := n.Pipe(yaml.Lookup("metadata", "configFn"))
if err != nil || yaml.IsEmpty(n) {
return nil
}
s, err := n.String()
if err != nil {
return nil
}
_ = yaml.Unmarshal([]byte(s), &fs)
return &fs
}