Add support for ignoring namespaces

This commit is contained in:
waseem
2019-10-14 14:14:40 +02:00
parent 6d8a81fa26
commit a10b2fa747
4 changed files with 188 additions and 58 deletions
+42 -15
View File
@@ -1,6 +1,8 @@
package cmd
import (
"errors"
"fmt"
"os"
"github.com/sirupsen/logrus"
@@ -25,14 +27,11 @@ func NewReloaderCommand() *cobra.Command {
cmd.PersistentFlags().StringVar(&options.SecretUpdateOnChangeAnnotation, "secret-annotation", "secret.reloader.stakater.com/reload", "annotation to detect changes in secrets")
cmd.PersistentFlags().StringVar(&options.ReloaderAutoAnnotation, "auto-annotation", "reloader.stakater.com/auto", "annotation to detect changes in secrets")
cmd.PersistentFlags().StringSlice("resources-to-ignore", []string{}, "list of resources to ignore (valid options 'configMaps' or 'secrets')")
cmd.PersistentFlags().StringSlice("namespaces-to-ignore", []string{}, "list of namespaces to ignore")
return cmd
}
func startReloader(cmd *cobra.Command, args []string) {
var ignoreList util.List
var err error
logrus.Info("Starting Reloader")
currentNamespace := os.Getenv("KUBERNETES_NAMESPACE")
if len(currentNamespace) == 0 {
@@ -46,27 +45,22 @@ func startReloader(cmd *cobra.Command, args []string) {
logrus.Fatal(err)
}
ignoreList, err = cmd.Flags().GetStringSlice("resources-to-ignore")
ignoredResourcesList, err := getIgnoredResourcesList(cmd)
if err != nil {
logrus.Fatal(err)
}
for _, v := range ignoreList {
if v != "configMaps" && v != "secrets" {
logrus.Fatalf("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not '%s'", v)
}
}
if len(ignoreList) > 1 {
logrus.Fatal("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not both")
ignoredNamespacesList, err := getIgnoredNamespacesList(cmd)
if err != nil {
logrus.Fatal(err)
}
for k := range kube.ResourceMap {
if ignoreList.Contains(k) {
if ignoredResourcesList.Contains(k) {
continue
}
c, err := controller.NewController(clientset, k, currentNamespace)
c, err := controller.NewController(clientset, k, currentNamespace, ignoredNamespacesList)
if err != nil {
logrus.Fatalf("%s", err)
}
@@ -81,3 +75,36 @@ func startReloader(cmd *cobra.Command, args []string) {
// Wait forever
select {}
}
func getIgnoredNamespacesList(cmd *cobra.Command) (util.List, error) {
return getStringSliceFromFlags(cmd, "namespaces-to-ignore")
}
func getStringSliceFromFlags(cmd *cobra.Command, flag string) ([]string, error) {
slice, err := cmd.Flags().GetStringSlice(flag)
if err != nil {
return nil, err
}
return slice, nil
}
func getIgnoredResourcesList(cmd *cobra.Command) (util.List, error) {
ignoredResourcesList, err := getStringSliceFromFlags(cmd, "resources-to-ignore")
if err != nil {
return nil, err
}
for _, v := range ignoredResourcesList {
if v != "configMaps" && v != "secrets" {
return nil, fmt.Errorf("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not '%s'", v)
}
}
if len(ignoredResourcesList) > 1 {
return nil, errors.New("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not both")
}
return ignoredResourcesList, nil
}
+28 -11
View File
@@ -6,6 +6,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/handler"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/runtime"
@@ -13,24 +14,28 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
v1 "k8s.io/api/core/v1"
)
// Controller for checking events
type Controller struct {
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
namespace string
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
namespace string
ignoredNamespaces util.List
}
// NewController for initializing a Controller
func NewController(
client kubernetes.Interface, resource string, namespace string) (*Controller, error) {
client kubernetes.Interface, resource string, namespace string, ignoredNamespaces []string) (*Controller, error) {
c := Controller{
client: client,
namespace: namespace,
client: client,
namespace: namespace,
ignoredNamespaces: ignoredNamespaces,
}
queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
@@ -49,9 +54,21 @@ func NewController(
// Add function to add a new object to the queue in case of creating a resource
func (c *Controller) Add(obj interface{}) {
c.queue.Add(handler.ResourceCreatedHandler{
Resource: obj,
})
if !c.resourceInIgnoredNamespace(obj) {
c.queue.Add(handler.ResourceCreatedHandler{
Resource: obj,
})
}
}
func (c *Controller) resourceInIgnoredNamespace(raw interface{}) bool {
switch object := raw.(type) {
case *v1.ConfigMap:
return c.ignoredNamespaces.Contains(object.ObjectMeta.Namespace)
case *v1.Secret:
return c.ignoredNamespaces.Contains(object.ObjectMeta.Namespace)
}
return false
}
// Update function to add an old object and a new object to the queue in case of updating a resource
+88 -1
View File
@@ -12,6 +12,9 @@ import (
"github.com/stakater/Reloader/internal/pkg/testutil"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
)
var (
@@ -30,7 +33,7 @@ func TestMain(m *testing.M) {
logrus.Infof("Creating controller")
for k := range kube.ResourceMap {
c, err := NewController(clients.KubernetesClient, k, namespace)
c, err := NewController(clients.KubernetesClient, k, namespace, []string{})
if err != nil {
logrus.Fatalf("%s", err)
}
@@ -1076,3 +1079,87 @@ func TestControllerUpdatingSecretShouldUpdateEnvInStatefulSet(t *testing.T) {
}
time.Sleep(3 * time.Second)
}
func TestController_resourceInIgnoredNamespace(t *testing.T) {
type fields struct {
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
namespace string
ignoredNamespaces util.List
}
type args struct {
raw interface{}
}
tests := []struct {
name string
fields fields
args args
want bool
}{
{
name: "TestConfigMapResourceInIgnoredNamespaceShouldReturnTrue",
fields: fields{
ignoredNamespaces: util.List{
"system",
},
},
args: args{
raw: testutil.GetConfigmap("system", "testcm", "test"),
},
want: true,
},
{
name: "TestSecretResourceInIgnoredNamespaceShouldReturnTrue",
fields: fields{
ignoredNamespaces: util.List{
"system",
},
},
args: args{
raw: testutil.GetSecret("system", "testsecret", "test"),
},
want: true,
},
{
name: "TestConfigMapResourceInIgnoredNamespaceShouldReturnFalse",
fields: fields{
ignoredNamespaces: util.List{
"system",
},
},
args: args{
raw: testutil.GetConfigmap("some-other-namespace", "testcm", "test"),
},
want: false,
},
{
name: "TestConfigMapResourceInIgnoredNamespaceShouldReturnFalse",
fields: fields{
ignoredNamespaces: util.List{
"system",
},
},
args: args{
raw: testutil.GetSecret("some-other-namespace", "testsecret", "test"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Controller{
client: tt.fields.client,
indexer: tt.fields.indexer,
queue: tt.fields.queue,
informer: tt.fields.informer,
namespace: tt.fields.namespace,
ignoredNamespaces: tt.fields.ignoredNamespaces,
}
if got := c.resourceInIgnoredNamespace(tt.args.raw); got != tt.want {
t.Errorf("Controller.resourceInIgnoredNamespace() = %v, want %v", got, tt.want)
}
})
}
}