From c4050352a3b62315549ecff0aeb0e6cb9fa69a01 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Wed, 15 Jan 2020 20:03:40 +0200 Subject: [PATCH] Make Kubernetes resources exclusion configurable --- cmd/fluxd/main.go | 6 ++--- pkg/cluster/kubernetes/kubernetes.go | 22 +++++++++-------- pkg/cluster/kubernetes/kubernetes_test.go | 2 +- pkg/cluster/kubernetes/sync.go | 30 ++++++++++++++++++++--- pkg/cluster/kubernetes/sync_test.go | 7 +++--- 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/cmd/fluxd/main.go b/cmd/fluxd/main.go index 53e84633a..cb142609c 100644 --- a/cmd/fluxd/main.go +++ b/cmd/fluxd/main.go @@ -178,8 +178,8 @@ func main() { k8sNamespaceWhitelist = fs.StringSlice("k8s-namespace-whitelist", []string{}, "restrict the view of the cluster to the namespaces listed. All namespaces are included if this is not set") k8sAllowNamespace = fs.StringSlice("k8s-allow-namespace", []string{}, "restrict all operations to the provided namespaces") k8sDefaultNamespace = fs.String("k8s-default-namespace", "", "the namespace to use for resources where a namespace is not specified") - - k8sVerbosity = fs.Int("k8s-verbosity", 0, "klog verbosity level") + k8sExcludeResource = fs.StringSlice("k8s-exclude-resource", []string{"*metrics.k8s.io/*", "webhook.certmanager.k8s.io/*", "v1/Event"}, "do not attempt to obtain cluster resources whose group/version/kind matches these glob expressions") + k8sVerbosity = fs.Int("k8s-verbosity", 0, "klog verbosity level") // SSH key generation sshKeyBits = optionalVar(fs, &ssh.KeyBitsValue{}, "ssh-keygen-bits", "-b argument to ssh-keygen (default unspecified)") @@ -505,7 +505,7 @@ func main() { for _, n := range append(*k8sNamespaceWhitelist, *k8sAllowNamespace...) { allowedNamespaces[n] = struct{}{} } - k8sInst := kubernetes.NewCluster(client, kubectlApplier, sshKeyRing, logger, allowedNamespaces, *registryExcludeImage) + k8sInst := kubernetes.NewCluster(client, kubectlApplier, sshKeyRing, logger, allowedNamespaces, *registryExcludeImage, *k8sExcludeResource) k8sInst.GC = *syncGC k8sInst.DryGC = *dryGC diff --git a/pkg/cluster/kubernetes/kubernetes.go b/pkg/cluster/kubernetes/kubernetes.go index d111a74e1..d97cdf028 100644 --- a/pkg/cluster/kubernetes/kubernetes.go +++ b/pkg/cluster/kubernetes/kubernetes.go @@ -109,20 +109,22 @@ type Cluster struct { allowedNamespaces map[string]struct{} loggedAllowedNS map[string]bool // to keep track of whether we've logged a problem with seeing an allowed namespace - imageExcludeList []string - mu sync.Mutex + imageExcludeList []string + resourceExcludeList []string + mu sync.Mutex } // NewCluster returns a usable cluster. -func NewCluster(client ExtendedClient, applier Applier, sshKeyRing ssh.KeyRing, logger log.Logger, allowedNamespaces map[string]struct{}, imageExcludeList []string) *Cluster { +func NewCluster(client ExtendedClient, applier Applier, sshKeyRing ssh.KeyRing, logger log.Logger, allowedNamespaces map[string]struct{}, imageExcludeList []string, resourceExcludeList []string) *Cluster { c := &Cluster{ - client: client, - applier: applier, - logger: logger, - sshKeyRing: sshKeyRing, - allowedNamespaces: allowedNamespaces, - loggedAllowedNS: map[string]bool{}, - imageExcludeList: imageExcludeList, + client: client, + applier: applier, + logger: logger, + sshKeyRing: sshKeyRing, + allowedNamespaces: allowedNamespaces, + loggedAllowedNS: map[string]bool{}, + imageExcludeList: imageExcludeList, + resourceExcludeList: resourceExcludeList, } return c diff --git a/pkg/cluster/kubernetes/kubernetes_test.go b/pkg/cluster/kubernetes/kubernetes_test.go index eddba0918..7be112b2f 100644 --- a/pkg/cluster/kubernetes/kubernetes_test.go +++ b/pkg/cluster/kubernetes/kubernetes_test.go @@ -32,7 +32,7 @@ func testGetAllowedNamespaces(t *testing.T, namespace []string, expected []strin for _, n := range namespace { allowedNamespaces[n] = struct{}{} } - c := NewCluster(client, nil, nil, log.NewNopLogger(), allowedNamespaces, []string{}) + c := NewCluster(client, nil, nil, log.NewNopLogger(), allowedNamespaces, []string{}, []string{}) namespaces, err := c.getAllowedAndExistingNamespaces(context.Background()) if err != nil { diff --git a/pkg/cluster/kubernetes/sync.go b/pkg/cluster/kubernetes/sync.go index 1640bb420..5d7ea95e7 100644 --- a/pkg/cluster/kubernetes/sync.go +++ b/pkg/cluster/kubernetes/sync.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "encoding/hex" "fmt" + "github.com/ryanuber/go-glob" "io" "os/exec" "sort" @@ -201,7 +202,28 @@ func (r *kuberesource) GetGCMark() string { return r.obj.GetLabels()[gcMarkLabel] } -var excludedGroups = []string{"metrics.k8s.io", "webhook.certmanager.k8s.io"} +func (c *Cluster) filterResources(resources *meta_v1.APIResourceList) *meta_v1.APIResourceList { + list := []meta_v1.APIResource{} + for _, apiResource := range resources.APIResources { + fullName := fmt.Sprintf("%s/%s", resources.GroupVersion, apiResource.Kind) + excluded := false + for _, exp := range c.resourceExcludeList { + if glob.Glob(exp, fullName) { + excluded = true + break + } + } + if !excluded { + list = append(list, apiResource) + } + } + + return &meta_v1.APIResourceList{ + TypeMeta: resources.TypeMeta, + GroupVersion: resources.GroupVersion, + APIResources: list, + } +} func (c *Cluster) getAllowedResourcesBySelector(selector string) (map[string]*kuberesource, error) { listOptions := meta_v1.ListOptions{} @@ -219,8 +241,8 @@ func (c *Cluster) getAllowedResourcesBySelector(selector string) (map[string]*ku gv := sgs.Groups[i].PreferredVersion.GroupVersion excluded := false - for _, exg := range excludedGroups { - if strings.HasSuffix(sgs.Groups[i].Name, exg) { + for _, exp := range c.resourceExcludeList { + if glob.Glob(exp, fmt.Sprintf("%s/", gv)) { excluded = true break } @@ -229,7 +251,7 @@ func (c *Cluster) getAllowedResourcesBySelector(selector string) (map[string]*ku if !excluded { if r, err := c.client.discoveryClient.ServerResourcesForGroupVersion(gv); err == nil { if r != nil { - resources = append(resources, r) + resources = append(resources, c.filterResources(r)) } } else { // ignore errors for resources with empty group version instead of failing to sync diff --git a/pkg/cluster/kubernetes/sync_test.go b/pkg/cluster/kubernetes/sync_test.go index 51f241a2d..9f89fd9a6 100644 --- a/pkg/cluster/kubernetes/sync_test.go +++ b/pkg/cluster/kubernetes/sync_test.go @@ -241,9 +241,10 @@ func setup(t *testing.T) (*Cluster, *fakeApplier, func()) { clients, cancel := fakeClients() applier := &fakeApplier{dynamicClient: clients.dynamicClient, coreClient: clients.coreClient, defaultNS: defaultTestNamespace} kube := &Cluster{ - applier: applier, - client: clients, - logger: log.NewLogfmtLogger(os.Stdout), + applier: applier, + client: clients, + logger: log.NewLogfmtLogger(os.Stdout), + resourceExcludeList: []string{"*metrics.k8s.io/*", "webhook.certmanager.k8s.io/v1beta1/*"}, } return kube, applier, cancel }