Skip to content

Commit

Permalink
feat: add preliminary support for Config Connector service KRM
Browse files Browse the repository at this point in the history
  • Loading branch information
briandealwis committed Sep 28, 2021
1 parent 151b8d3 commit 77e8402
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 1 deletion.
25 changes: 24 additions & 1 deletion pkg/skaffold/kubernetes/manifest/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package manifest

import (
"fmt"
"regexp"

apimachinery "k8s.io/apimachinery/pkg/runtime/schema"

Expand All @@ -42,6 +43,20 @@ var transformableAllowlist = map[apimachinery.GroupKind]bool{
{Group: "argoproj.io", Kind: "Rollout"}: true,
}

type wildcardGroupKind struct {
Group *regexp.Regexp
Kind *regexp.Regexp
}

func (w *wildcardGroupKind) Matches(group, kind string) bool {
return (w.Group == nil || w.Group.Match([]byte(group))) && (w.Kind == nil || w.Kind.Match([]byte(kind)))
}

var wildcardedAllowlist = []wildcardGroupKind{
// add preliminary support for config connector services; group name is currently in flux
{Group: regexp.MustCompile(`([[:alpha:]]+\.)+cnrm\.cloud\.google\.com`), Kind: regexp.MustCompile("Service")},
}

// FieldVisitor represents the aggregation/transformation that should be performed on each traversed field.
type FieldVisitor interface {
// Visit is called for each transformable key contained in the object and may apply transformations/aggregations on it.
Expand Down Expand Up @@ -107,7 +122,15 @@ func shouldTransformManifest(manifest map[string]interface{}) bool {
Kind: gvk.Kind,
}

return transformableAllowlist[groupKind]
if result, found := transformableAllowlist[groupKind]; found {
return result
}
for _, w := range wildcardedAllowlist {
if w.Matches(gvk.Group, gvk.Kind) {
return true
}
}
return false
}

// recursiveVisitorDecorator adds recursion to a FieldVisitor.
Expand Down
110 changes: 110 additions & 0 deletions pkg/skaffold/kubernetes/manifest/visitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package manifest

import (
"fmt"
"regexp"
"testing"

"github.com/GoogleContainerTools/skaffold/testutil"
Expand Down Expand Up @@ -264,3 +265,112 @@ spec:
})
}
}

func TestWildcardedGroupKind(t *testing.T) {
tests := []struct {
description string
pattern wildcardGroupKind
group string
kind string
expected bool
}{
{
description: "exact match",
pattern: wildcardGroupKind{Group: regexp.MustCompile("group"), Kind: regexp.MustCompile("kind")},
group: "group",
kind: "kind",
expected: true,
},
{
description: "use real regexp",
pattern: wildcardGroupKind{Group: regexp.MustCompile(".*"), Kind: regexp.MustCompile(".*")},
group: "group",
kind: "kind",
expected: true,
},
{
description: "null group and kind should match all",
pattern: wildcardGroupKind{},
group: "group",
kind: "kind",
expected: true,
},
{
description: "null group should match all",
pattern: wildcardGroupKind{Kind: regexp.MustCompile("kind")},
group: "group",
kind: "kind",
expected: true,
},
{
description: "null kind should match all",
pattern: wildcardGroupKind{Group: regexp.MustCompile("group")},
group: "group",
kind: "kind",
expected: true,
},
{
description: "no match",
pattern: wildcardGroupKind{Group: regexp.MustCompile("xxx"), Kind: regexp.MustCompile("xxx")},
group: "group",
kind: "kind",
expected: false,
},
{
description: "no kind match",
pattern: wildcardGroupKind{Group: regexp.MustCompile("group"), Kind: regexp.MustCompile("xxx")},
group: "group",
kind: "kind",
expected: false,
},
{
description: "no group match",
pattern: wildcardGroupKind{Group: regexp.MustCompile("xxx"), Kind: regexp.MustCompile("kind")},
group: "group",
kind: "kind",
expected: false,
},
}
for _, test := range tests {
result := test.pattern.Matches(test.group, test.kind)
t.Run(test.description, func(t *testing.T) {
if result != test.expected {
t.Errorf("got %v, expected %v", result, test.expected)
}
})
}
}

func TestShouldTransformManifest(t *testing.T) {
tests := []struct {
manifest map[string]interface{}
expected bool
}{
{manifest: map[string]interface{}{}, expected: false},
{manifest: map[string]interface{}{"xxx": "v1", "yyy": "Pod"}, expected: false}, // non-KRM
{manifest: map[string]interface{}{"apiVersion": "v1", "kind": "Pod"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "apps/v1", "kind": "DaemonSet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "apps/v1", "kind": "Deployment"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "apps/v1", "kind": "StatefulSet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "apps/v1", "kind": "ReplicaSet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "extensions/v1beta1", "kind": "Deployment"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "extensions/v1beta1", "kind": "DaemonSet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "extensions/v1beta1", "kind": "ReplicaSet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "batch/v1", "kind": "CronJob"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "batch/v1", "kind": "Job"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "serving.knative.dev/v1", "kind": "Service"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "agones.dev/v1", "kind": "Fleet"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "agones.dev/v1", "kind": "GameServer"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "argoproj.io/v1", "kind": "Rollout"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "foo.cnrm.cloud.google.com/v1", "kind": "Service"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "foo.bar.cnrm.cloud.google.com/v1", "kind": "Service"}, expected: true},
{manifest: map[string]interface{}{"apiVersion": "foo/v1", "kind": "Blah"}, expected: false},
{manifest: map[string]interface{}{"apiVersion": "foo.bar.cnrm.cloud.google.com/v1", "kind": "Other"}, expected: false},
}
for _, test := range tests {
testutil.Run(t, fmt.Sprintf("%v", test.manifest), func(t *testutil.T) {
result := shouldTransformManifest(test.manifest)
t.CheckDeepEqual(test.expected, result)
})
}
}

0 comments on commit 77e8402

Please sign in to comment.