Support network in functions

Signed-off-by: Eddie Zaneski <eddiezane@gmail.com>
This commit is contained in:
Eddie Zaneski
2020-02-07 15:39:10 -07:00
parent 91da8525c1
commit 6cdcb1f436
6 changed files with 295 additions and 21 deletions

View File

@@ -408,6 +408,17 @@ const (
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) (*yaml.RNode, error) {
for _, s := range functionAnnotationKeys {
fn := meta.Annotations[s]
if fn != "" {
return yaml.Parse(fn)
}
}
return n.Pipe(yaml.Lookup("metadata", "configFn"))
}
// GetContainerName returns the container image for an API if one exists
func GetContainerName(n *yaml.RNode) (string, string) {
meta, _ := n.GetMeta()
@@ -415,14 +426,10 @@ func GetContainerName(n *yaml.RNode) (string, string) {
// path to the function, this will be mounted into the container
path := meta.Annotations[kioutil.PathAnnotation]
// check previous keys for backwards compatibility
for _, s := range functionAnnotationKeys {
functionAnnotation := meta.Annotations[s]
if functionAnnotation != "" {
annotationContent, _ := yaml.Parse(functionAnnotation)
image, _ := annotationContent.Pipe(yaml.Lookup("container", "image"))
return image.YNode().Value, path
}
fn, _ := GetFunction(n, meta)
if fn != nil {
image, _ := fn.Pipe(yaml.Lookup("container", "image"))
return yaml.GetValue(image), path
}
container := meta.Annotations["config.kubernetes.io/container"]
@@ -434,5 +441,19 @@ func GetContainerName(n *yaml.RNode) (string, string) {
if err != nil || yaml.IsMissingOrNull(image) {
return "", path
}
return image.YNode().Value, path
return yaml.GetValue(image), path
}
// GetContainerNetworkRequired returns whether or not networking is required for the container
func GetContainerNetworkRequired(n *yaml.RNode) (bool, error) {
meta, err := n.GetMeta()
if err != nil {
return false, err
}
f, err := GetFunction(n, meta)
if err != nil {
return false, err
}
networkRequired, _ := f.Pipe(yaml.Lookup("container", "network", "required"))
return yaml.GetValue(networkRequired) == "true", nil
}

View File

@@ -309,6 +309,79 @@ metadata:
`, b.String())
}
func Test_GetFunction(t *testing.T) {
var tests = []struct {
name string
resource string
expectedFn string
missingFn bool
}{
// fn annotation
{
name: "fn annotation",
resource: `
apiVersion: v1beta1
kind: Example
metadata:
annotations:
config.kubernetes.io/function: |-
container: foo:v1.0.0
`,
expectedFn: `container: foo:v1.0.0`,
},
// legacy fn style
{name: "legacy fn meta",
resource: `
apiVersion: v1beta1
kind: Example
metadata:
configFn:
container: foo:v1.0.0
`,
expectedFn: `container: foo:v1.0.0`,
},
// no fn
{name: "no fn",
resource: `
apiVersion: v1beta1
kind: Example
metadata:
annotations: {}
`,
missingFn: true,
},
// test network, etc...
}
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
resource := yaml.MustParse(tt.resource)
meta, err := resource.GetMeta()
if !assert.NoError(t, err) {
t.FailNow()
}
fn, err := GetFunction(resource, meta)
if !assert.NoError(t, err) {
t.FailNow()
}
if tt.missingFn {
if !assert.Nil(t, fn) {
t.FailNow()
}
} else {
if !assert.Equal(t, strings.TrimSpace(fn.MustString()), strings.TrimSpace(tt.expectedFn)) {
t.FailNow()
}
}
})
}
}
func Test_GetContainerName(t *testing.T) {
// make sure gcr.io works
n, err := yaml.Parse(`apiVersion: v1beta1
@@ -364,6 +437,76 @@ metadata:
assert.Equal(t, "", c)
}
func Test_GetContainerNetworkRequired(t *testing.T) {
tests := []struct {
input string
required bool
}{
{
input: `apiVersion: v1
kind: Foo
metadata:
name: foo
configFn:
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
network:
required: true
`,
required: true,
},
{
input: `apiVersion: v1
kind: Foo
metadata:
name: foo
configFn:
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
network:
required: false
`,
required: false,
},
{
input: `apiVersion: v1
kind: Foo
metadata:
name: foo
configFn:
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
`,
required: false,
},
{
input: `apiVersion: v1
kind: Foo
metadata:
name: foo
annotations:
config.kubernetes.io/function: |
container:
image: gcr.io/kustomize-functions/example-tshirt:v0.1.0
network:
required: true
`,
required: true,
},
}
for _, tc := range tests {
cfg, err := yaml.Parse(tc.input)
if !assert.NoError(t, err) {
return
}
required, err := GetContainerNetworkRequired(cfg)
assert.NoError(t, err)
assert.Equal(t, tc.required, required)
}
}
func TestFilter_Filter_defaultNaming(t *testing.T) {
cfg, err := yaml.Parse(`apiVersion: apps/v1
kind: Deployment