From f7ff8d7b359192cc2ebdfccbd8539d47279cb47b Mon Sep 17 00:00:00 2001 From: faizanahmad055 Date: Fri, 13 Jul 2018 16:16:57 +0500 Subject: [PATCH] Remove upgrader --- internal/pkg/controller/controller.go | 66 ++++----- internal/pkg/controller/controller_test.go | 7 +- internal/pkg/upgrader/upgrader.go | 159 --------------------- 3 files changed, 29 insertions(+), 203 deletions(-) delete mode 100644 internal/pkg/upgrader/upgrader.go diff --git a/internal/pkg/controller/controller.go b/internal/pkg/controller/controller.go index 1d9b32b4..84cac772 100644 --- a/internal/pkg/controller/controller.go +++ b/internal/pkg/controller/controller.go @@ -5,7 +5,6 @@ import ( "time" "github.com/sirupsen/logrus" - "github.com/stakater/Reloader/internal/pkg/upgrader" "github.com/stakater/Reloader/pkg/kube" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/runtime" @@ -15,11 +14,10 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" ) - -// Event indicate the informerEvent -type Event struct { - key string - eventType string +// ResourceUpdated contains new or updated objects +type ResourceUpdated struct { + newObj interface{} + oldObj interface{} } // Controller for checking events @@ -57,26 +55,17 @@ func NewController( // Add function to add a 'create' event to the queue in case of creating a pod func (c *Controller) Add(obj interface{}) { - key, err := cache.MetaNamespaceKeyFunc(obj) - var event Event - - if err == nil { - event.key = key - event.eventType = "create" - c.queue.Add(event) - } + c.queue.Add(ResourceUpdated{ + newObj: obj, + }) } // Update function to add an 'update' event to the queue in case of updating a pod func (c *Controller) Update(old interface{}, new interface{}) { - key, err := cache.MetaNamespaceKeyFunc(new) - var event Event - - if err == nil { - event.key = key - event.eventType = "update" - c.queue.Add(event) - } + c.queue.Add(ResourceUpdated{ + newObj: new, + oldObj: old, + }) } //Run function for controller which handles the queue @@ -111,43 +100,36 @@ func (c *Controller) runWorker() { func (c *Controller) processNextItem() bool { // Wait until there is a new item in the working queue - event, quit := c.queue.Get() + resourceUpdated, quit := c.queue.Get() if quit { return false } // Tell the queue that we are done with processing this key. This unblocks the key for other workers // This allows safe parallel processing because two events with the same key are never processed in // parallel. - defer c.queue.Done(event) + defer c.queue.Done(resourceUpdated) // Invoke the method containing the business logic - err := c.takeAction(event.(Event)) + err := c.takeAction(resourceUpdated.(ResourceUpdated)) // Handle the error if something went wrong during the execution of the business logic - c.handleErr(err, event) + c.handleErr(err, resourceUpdated) return true } // main business logic that acts bassed on the event or key -func (c *Controller) takeAction(event Event) error { +func (c *Controller) takeAction(resourceUpdated ResourceUpdated) error { - obj, _, err := c.indexer.GetByKey(event.key) - if err != nil { - logrus.Infof("Fetching object with key %s from store failed with %v", event.key, err) - } - if obj == nil { + newObj := resourceUpdated.newObj + oldObj := resourceUpdated.oldObj + if newObj == nil { logrus.Infof("Error in Action") } else { - logrus.Infof("Detected changes in object %s", obj) + logrus.Infof("Detected changes in object %s", newObj) // process events based on its type - logrus.Infof("Performing '%s' action for controller of type '%s'", event.eventType, c.resource) - u, _ := upgrader.NewUpgrader(c.client, c.resource) - if c.resource == "configMaps" { - switch event.eventType { - case "create": - u.ObjectCreated(obj) - case "update": - u.ObjectUpdated(obj) - } + if(oldObj == nil){ + logrus.Infof("Performing 'Added' action for controller of type '%s'", c.resource) + } else { + logrus.Infof("Performing 'Updated' action for controller of type '%s'", c.resource) } } return nil diff --git a/internal/pkg/controller/controller_test.go b/internal/pkg/controller/controller_test.go index ba676ddd..047eb395 100644 --- a/internal/pkg/controller/controller_test.go +++ b/internal/pkg/controller/controller_test.go @@ -54,7 +54,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDeployment(t *testing.T) { } logrus.Infof("Created Configmap %q.\n", configmap.GetObjectMeta().GetName()) time.Sleep(10 * time.Second) - createDeployement(configmapName, namespace) + deployment := createDeployement(configmapName, namespace) logrus.Infof("Updating Configmap %q.\n", configmap.GetObjectMeta().GetName()) configmap, err = configmapClient.Get(configmapName, metav1.GetOptions{}) @@ -72,6 +72,8 @@ func TestControllerForUpdatingConfigmapShouldUpdateDeployment(t *testing.T) { panic(updateErr) } time.Sleep(10 * time.Second) + logrus.Infof("Deleting Deployment %q.\n", deployment.GetObjectMeta().GetName()) + controller.client.Extensions().Deployments(namespace).Delete(configmapName, &metav1.DeleteOptions{}); logrus.Infof("Deleting Configmap %q.\n", configmap.GetObjectMeta().GetName()) error := controller.client.CoreV1().ConfigMaps(namespace).Delete(configmapName, &metav1.DeleteOptions{}) if error != nil { @@ -80,7 +82,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDeployment(t *testing.T) { time.Sleep(15 * time.Second) } -func createDeployement(deploymentName string, namespace string) { +func createDeployement(deploymentName string, namespace string) *v1beta1.Deployment { deploymentClient := client.Extensions().Deployments(namespace) deployment := initDeployment(namespace, deploymentName) deployment, error := deploymentClient.Create(deployment) @@ -89,6 +91,7 @@ func createDeployement(deploymentName string, namespace string) { } //time.Sleep(10 * time.Second) logrus.Infof("Created Deployment %q.\n", deployment.GetObjectMeta().GetName()) + return deployment } func TestControllerForUpdatingSecretShouldUpdateDeployment(t *testing.T) { diff --git a/internal/pkg/upgrader/upgrader.go b/internal/pkg/upgrader/upgrader.go deleted file mode 100644 index 37d00f8f..00000000 --- a/internal/pkg/upgrader/upgrader.go +++ /dev/null @@ -1,159 +0,0 @@ -package upgrader - -import ( - "bytes" - "sort" - "strings" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -const ( - updateOnChangeAnnotation = "reloader.stakater.com/update-on-change" -) - -// Upgrader will upgrade the relevent deployment, deamonset and deamonset. -type Upgrader struct { - client kubernetes.Interface - resourceType string -} - -// NewUpgrader Initializes the Upgrader -func NewUpgrader(client kubernetes.Interface, resourceType string) (*Upgrader, error) { - u := Upgrader{ - client: client, - resourceType: resourceType, - } - return &u, nil -} - -// ObjectCreated Detects if the configmap or secret has been created -func (u *Upgrader) ObjectCreated(obj interface{}) { - message := u.resourceType + ": `" + obj.(*v1.ConfigMap).Name + "`has been created in Namespace: `" + obj.(*v1.ConfigMap).Namespace + "`" - logrus.Infof(message) - err := rollingUpgradeDeployments(obj, u.client) - if err != nil { - logrus.Errorf("failed to update Deployment: %v", err) - } -} - -// ObjectUpdated Detects if the configmap or secret has been updated -func (u *Upgrader) ObjectUpdated(oldObj interface{}) { - message := u.resourceType + ": `" + oldObj.(*v1.ConfigMap).Name + "`has been updated in Namespace: `" + oldObj.(*v1.ConfigMap).Namespace + "`" - logrus.Infof(message) - err := rollingUpgradeDeployments(oldObj, u.client) - if err != nil { - logrus.Errorf("failed to update Deployment: %v", err) - } -} - -// Implementation has been borrowed from fabric8io/configmapcontroller -// Method has been modified a little to use updated liberaries. -func rollingUpgradeDeployments(oldObj interface{}, client kubernetes.Interface) error { - ns := oldObj.(*v1.ConfigMap).Namespace - configMapName := oldObj.(*v1.ConfigMap).Name - configMapVersion := convertConfigMapToToken(oldObj.(*v1.ConfigMap)) - - deployments, err := client.ExtensionsV1beta1().Deployments(ns).List(meta_v1.ListOptions{}) - if err != nil { - return errors.Wrap(err, "failed to list deployments") - } - for _, d := range deployments.Items { - containers := d.Spec.Template.Spec.Containers - // match deployments with the correct annotation - annotationValue := d.ObjectMeta.Annotations[updateOnChangeAnnotation] - if annotationValue != "" { - values := strings.Split(annotationValue, ",") - matches := false - for _, value := range values { - if value == configMapName { - matches = true - break - } - } - if matches { - updateContainers(containers, annotationValue, configMapVersion) - - // update the deployment - _, err := client.ExtensionsV1beta1().Deployments(ns).Update(&d) - if err != nil { - return errors.Wrap(err, "update deployment failed") - } - logrus.Infof("Updated Deployment %s", d.Name) - } - } - } - return nil -} - -func updateContainers(containers []v1.Container, annotationValue, configMapVersion string) bool { - // we can have multiple configmaps to update - answer := false - configmaps := strings.Split(annotationValue, ",") - for _, cmNameToUpdate := range configmaps { - configmapEnvar := "STAKATER_" + convertToEnvVarName(cmNameToUpdate) + "_CONFIGMAP" - - for i := range containers { - envs := containers[i].Env - matched := false - for j := range envs { - if envs[j].Name == configmapEnvar { - matched = true - if envs[j].Value != configMapVersion { - logrus.Infof("Updating %s to %s", configmapEnvar, configMapVersion) - envs[j].Value = configMapVersion - answer = true - } - } - } - // if no existing env var exists lets create one - if !matched { - e := v1.EnvVar{ - Name: configmapEnvar, - Value: configMapVersion, - } - containers[i].Env = append(containers[i].Env, e) - answer = true - } - } - } - return answer -} - -// convertToEnvVarName converts the given text into a usable env var -// removing any special chars with '_' -func convertToEnvVarName(text string) string { - var buffer bytes.Buffer - lower := strings.ToUpper(text) - lastCharValid := false - for i := 0; i < len(lower); i++ { - ch := lower[i] - if (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') { - buffer.WriteString(string(ch)) - lastCharValid = true - } else { - if lastCharValid { - buffer.WriteString("_") - } - lastCharValid = false - } - } - return buffer.String() -} - -// lets convert the configmap into a unique token based on the data values -func convertConfigMapToToken(cm *v1.ConfigMap) string { - values := []string{} - for k, v := range cm.Data { - values = append(values, k+"="+v) - } - sort.Strings(values) - text := strings.Join(values, ";") - // we could zip and base64 encode - // but for now we could leave this easy to read so that its easier to diagnose when & why things changed - return text -}