From 9ff67ff54c67717b32b6cefc852ab42ed9f667d6 Mon Sep 17 00:00:00 2001 From: Daniel Tomcej Date: Wed, 12 Jun 2019 12:14:01 -0600 Subject: [PATCH 1/4] move CRD creation to mesh handler --- .../{meshcontroller.go => controller.go} | 16 +- meshcontroller/handler.go | 146 ++++++++++++++ meshcontroller/meshcontrollerhandler.go | 67 ------- templates/traefik-routing.tpl | 31 --- utils/utils.go | 185 +----------------- 5 files changed, 155 insertions(+), 290 deletions(-) rename meshcontroller/{meshcontroller.go => controller.go} (61%) create mode 100644 meshcontroller/handler.go delete mode 100644 meshcontroller/meshcontrollerhandler.go delete mode 100644 templates/traefik-routing.tpl diff --git a/meshcontroller/meshcontroller.go b/meshcontroller/controller.go similarity index 61% rename from meshcontroller/meshcontroller.go rename to meshcontroller/controller.go index 6aff5c9a6..2178154ed 100644 --- a/meshcontroller/meshcontroller.go +++ b/meshcontroller/controller.go @@ -3,7 +3,6 @@ package meshcontroller import ( "github.com/containous/i3o/controller" "github.com/containous/i3o/utils" - traefik_v1alpha1 "github.com/containous/traefik/pkg/provider/kubernetes/crd/traefik/v1alpha1" log "github.com/sirupsen/logrus" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -11,11 +10,8 @@ import ( ) type MeshController struct { - serviceController *controller.Controller - endpointController *controller.Controller - namespaceController *controller.Controller - crdController *controller.Controller - handler *Handler + serviceController *controller.Controller + handler *Handler } // New is used to build the informers and other required components of the mesh controller, @@ -28,12 +24,9 @@ func NewMeshController() *MeshController { func (m *MeshController) Init(clients *utils.ClientWrapper) { ignoredNamespaces := []string{metav1.NamespaceSystem, utils.MeshNamespace} - m.handler = NewHandler(ignoredNamespaces) + m.handler = NewHandler(clients, ignoredNamespaces) // Create the new subcontrollers m.serviceController = controller.NewController(clients, apiv1.Service{}, ignoredNamespaces, m.handler) - m.endpointController = controller.NewController(clients, apiv1.Endpoints{}, ignoredNamespaces, m.handler) - m.namespaceController = controller.NewController(clients, apiv1.Namespace{}, ignoredNamespaces, m.handler) - m.crdController = controller.NewController(clients, traefik_v1alpha1.IngressRoute{}, ignoredNamespaces, m.handler) } // Run is the main entrypoint for the controller @@ -45,9 +38,6 @@ func (m *MeshController) Run(stopCh <-chan struct{}) error { // run the informer to start listing and watching resources go m.serviceController.Run(stopCh) - go m.endpointController.Run(stopCh) - go m.namespaceController.Run(stopCh) - go m.crdController.Run(stopCh) <-stopCh log.Info("Shutting down workers") diff --git a/meshcontroller/handler.go b/meshcontroller/handler.go new file mode 100644 index 000000000..fbd529215 --- /dev/null +++ b/meshcontroller/handler.go @@ -0,0 +1,146 @@ +package meshcontroller + +import ( + "github.com/containous/i3o/utils" + crdclientset "github.com/containous/traefik/pkg/provider/kubernetes/crd/generated/clientset/versioned" + traefik_v1alpha1 "github.com/containous/traefik/pkg/provider/kubernetes/crd/traefik/v1alpha1" + log "github.com/sirupsen/logrus" + apiv1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" +) + +// MeshControllerHandler is an implementation of Handler +type Handler struct { + Clients *utils.ClientWrapper + IgnoredNamespaces []string +} + +func NewHandler(clients *utils.ClientWrapper, namespaces []string) *Handler { + h := &Handler{ + Clients: clients, + IgnoredNamespaces: namespaces, + } + + if err := h.Init(); err != nil { + log.Errorln("Could not initialize MeshControllerHandler") + } + + return h +} + +// Init handles any handler initialization +func (h *Handler) Init() error { + log.Debugln("MeshControllerHandler.Init") + return nil +} + +// ObjectCreated is called when an object is created +func (h *Handler) ObjectCreated(obj interface{}) { + // assert the type to an object to pull out relevant data + switch obj := obj.(type) { + case *corev1.Service: + if utils.Contains(h.IgnoredNamespaces, obj.Namespace) { + return + } + log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Service") + if err := VerifyMeshServiceExists(h.Clients.KubeClient, obj.Name, obj.Namespace); err != nil { + log.Errorf("Could not verify mesh service exists: %v", err) + return + } + + if err := VerifyMeshIngressRouteExists(h.Clients.CrdClient, obj); err != nil { + log.Errorf("Could not verify mesh ingressroute exists: %v", err) + } + } + +} + +// ObjectDeleted is called when an object is deleted +func (h *Handler) ObjectDeleted(obj interface{}) { + // assert the type to an object to pull out relevant data + switch obj := obj.(type) { + case *corev1.Service: + if utils.Contains(h.IgnoredNamespaces, obj.Namespace) { + return + } + log.Debugln("MeshControllerHandler.ObjectDeleted") + if err := VerifyMeshServiceDeleted(h.Clients.KubeClient, obj.Name, obj.Namespace); err != nil { + log.Errorf("Could not verify mesh service deleted: %v", err) + return + } + + if err := VerifyMeshIngressRouteDeleted(h.Clients.CrdClient, obj); err != nil { + log.Errorf("Could not verify mesh ingressroute deleted: %v", err) + } + } +} + +// ObjectUpdated is called when an object is updated +func (h *Handler) ObjectUpdated(objOld, objNew interface{}) { + log.Debugln("MeshControllerHandler.ObjectUpdated") +} + +func VerifyMeshServiceExists(client kubernetes.Interface, name, namespace string) error { + meshServiceName := utils.ServiceToMeshName(name, namespace) + meshServiceInstance, err := client.CoreV1().Services(utils.MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) + if meshServiceInstance == nil || err != nil { + svc := &apiv1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: meshServiceName, + Namespace: utils.MeshNamespace, + }, + Spec: apiv1.ServiceSpec{ + Ports: []apiv1.ServicePort{ + { + Name: "web", + Port: 80, + TargetPort: intstr.FromInt(8000), + }, + }, + Selector: map[string]string{ + "app": "traefik-mesh-node", + }, + }, + } + + if _, err := client.CoreV1().Services(utils.MeshNamespace).Create(svc); err != nil { + return err + } + } + + return nil +} + +func VerifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1.Service) error { + meshIngressRouteName := utils.ServiceToMeshName(service.Name, service.Namespace) + meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(metav1.NamespaceAll).Get(meshIngressRouteName, metav1.GetOptions{}) + if meshIngressRouteInstance == nil || err != nil { + ir := &traefik_v1alpha1.IngressRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: meshIngressRouteName, + Namespace: service.Namespace, + }, + Spec: traefik_v1alpha1.IngressRouteSpec{ + Routes: []traefik_v1alpha1.Route{ + { + Services: []traefik_v1alpha1.Service{ + { + Name: service.Name, + Port: service.Spec.Ports[0].Port, + }, + }, + }, + }, + }, + } + if _, err := client.TraefikV1alpha1().IngressRoutes(metav1.NamespaceAll).Create(ir); err != nil { + return err + } + + } + + return nil +} diff --git a/meshcontroller/meshcontrollerhandler.go b/meshcontroller/meshcontrollerhandler.go deleted file mode 100644 index cb801f565..000000000 --- a/meshcontroller/meshcontrollerhandler.go +++ /dev/null @@ -1,67 +0,0 @@ -package meshcontroller - -import ( - "github.com/containous/i3o/utils" - log "github.com/sirupsen/logrus" - corev1 "k8s.io/api/core/v1" -) - -// MeshControllerHandler is an implementation of Handler -type Handler struct { - IgnoredNamespaces []string -} - -func NewHandler(namespaces []string) *Handler { - return &Handler{ - IgnoredNamespaces: namespaces, - } -} - -// Init handles any handler initialization -func (m *Handler) Init() error { - log.Debugln("MeshControllerHandler.Init") - return nil -} - -// ObjectCreated is called when an object is created -func (m *Handler) ObjectCreated(obj interface{}) { - // assert the type to a Pod object to pull out relevant data - switch obj := obj.(type) { - case *corev1.Service: - if utils.Contains(m.IgnoredNamespaces, obj.Namespace) { - return - } - log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Service") - log.Debugf(" ResourceVersion: %s", obj.ObjectMeta.ResourceVersion) - log.Debugf(" Service Name: %s", obj.Name) - log.Debugf(" Namespace: %s", obj.Namespace) - - case *corev1.Endpoints: - if utils.Contains(m.IgnoredNamespaces, obj.Namespace) { - return - } - log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Endpoints") - log.Debugf(" ResourceVersion: %s", obj.ObjectMeta.ResourceVersion) - log.Debugf(" Endpoints Name: %s", obj.Name) - log.Debugf(" Namespace: %s", obj.Namespace) - - case *corev1.Namespace: - if utils.Contains(m.IgnoredNamespaces, obj.Name) { - return - } - log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Namespace") - log.Debugf(" ResourceVersion: %s", obj.ObjectMeta.ResourceVersion) - log.Debugf(" Namespace Name: %s", obj.Name) - - } -} - -// ObjectDeleted is called when an object is deleted -func (m *Handler) ObjectDeleted(obj interface{}) { - log.Debugln("MeshControllerHandler.ObjectDeleted") -} - -// ObjectUpdated is called when an object is updated -func (m *Handler) ObjectUpdated(objOld, objNew interface{}) { - log.Debugln("MeshControllerHandler.ObjectUpdated") -} diff --git a/templates/traefik-routing.tpl b/templates/traefik-routing.tpl deleted file mode 100644 index ca96d83e4..000000000 --- a/templates/traefik-routing.tpl +++ /dev/null @@ -1,31 +0,0 @@ -[global] -checkNewVersion = false -sendAnonymousUsage = false - -[log] -level = "DEBUG" - -[entryPoints] - [entryPoints.web] - address = ":8000" - -[providers] - [providers.file] - -[http.routers] -{{- range $key, $service := .Services }} - [http.routers.{{ $service.ServiceName}}_{{ $service.ServiceNamespace }}] - entrypoints = ["web"] - rule = "Host(`{{ $service.ServiceName }}.{{ $service.ServiceNamespace }}.traefik.mesh`)" - service = "{{ $service.ServiceName}}_{{ $service.ServiceNamespace }}" -{{- end }} - -[http.services] -{{- range $key, $service := .Services }} - [http.services.{{ $service.ServiceName}}_{{ $service.ServiceNamespace }}.loadbalancer] - {{- range $subkey, $server := $service.Servers }} - [[http.services.{{ $service.ServiceName}}_{{ $service.ServiceNamespace }}.loadbalancer.servers]] - url = "http://{{ $server.Address }}:{{ $server.Port }}" - weight = 1 - {{- end -}} -{{- end -}} diff --git a/utils/utils.go b/utils/utils.go index 2ff544ceb..17e0d581e 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,10 +1,8 @@ package utils import ( - "bytes" "errors" "fmt" - "html/template" "strings" "time" @@ -13,36 +11,13 @@ import ( apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" ) const ( - MeshNamespace string = "traefik-mesh" - MeshPodPrefix string = "traefik" - MeshConfigmapName string = "traefik-mesh-config" - MeshConfigmapKey string = "traefik.toml" + MeshNamespace string = "traefik-mesh" ) -// TraefikMeshConfig holds traefik mesh services. -type TraefikMeshConfig struct { - Services []TraefikMeshService -} - -// TraefikMeshService holds service information. -type TraefikMeshService struct { - ServicePort int32 - ServiceName string - ServiceNamespace string - Servers []TraefikMeshBackendServer -} - -// TraefikMeshBackendServer holds backend server. -type TraefikMeshBackendServer struct { - Address string - Port int32 -} - // InitCluster is used to initialize a kubernetes cluster with a variety of configuration options. func InitCluster(client kubernetes.Interface) error { log.Infoln("Preparing Cluster...") @@ -218,159 +193,6 @@ func restartCorePods(client kubernetes.Interface, coreDeployment *appsv1.Deploym return nil } -// CreateMeshConfig parses the kubernetes service list, and creates a structure for building configurations from. -func CreateMeshConfig(client kubernetes.Interface) (meshConfig *TraefikMeshConfig, err error) { - log.Infoln("Creating mesh structures for config...") - defer log.Infoln("Config Structure Creation Complete...") - - log.Debugln("Listing services in all namespaces:") - serviceListAll, err := client.CoreV1().Services(apiv1.NamespaceAll).List(metav1.ListOptions{}) - if err != nil { - return nil, err - } - - var meshServices []TraefikMeshService - - for _, s := range serviceListAll.Items { - if s.Namespace == MeshNamespace { - continue - } - - log.Debugf(" * %s/%s \n", s.Namespace, s.Name) - - if err = verifyMeshServiceExists(client, s.Namespace, s.Name); err != nil { - panic(err) - } - - var endpoints *apiv1.EndpointsList - E: - for { - endpoints, err = client.CoreV1().Endpoints(s.Namespace).List(metav1.ListOptions{ - FieldSelector: fmt.Sprintf("metadata.name=%s", s.Name), - }) - switch { - case err != nil: - time.Sleep(time.Second * 5) - - case len(endpoints.Items[0].Subsets) == 0: - time.Sleep(time.Second * 5) - - default: - break E - } - } - - // Verify that the expected amount of control nodes are listed in the endpoint list. - - var svr []TraefikMeshBackendServer - - for _, e := range endpoints.Items[0].Subsets[0].Addresses { - ip := e.IP - port := endpoints.Items[0].Subsets[0].Ports[0].Port - - svr = append(svr, TraefikMeshBackendServer{ - Address: ip, - Port: port, - }) - log.Debugf(" - Adding server %s:%d to routing config\n", ip, port) - } - - meshService := TraefikMeshService{ - ServiceName: s.Name, - ServiceNamespace: s.Namespace, - ServicePort: s.Spec.Ports[0].Port, - Servers: svr, - } - - meshServices = append(meshServices, meshService) - } - - return &TraefikMeshConfig{ - Services: meshServices, - }, nil -} - -func verifyMeshServiceExists(client kubernetes.Interface, name, namespace string) error { - meshServiceName := fmt.Sprintf("%s-%s-%s", MeshPodPrefix, namespace, name) - meshServiceInstance, err := client.CoreV1().Services(MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) - if meshServiceInstance == nil || err != nil { - svc := &apiv1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: meshServiceName, - Namespace: MeshNamespace, - }, - Spec: apiv1.ServiceSpec{ - Ports: []apiv1.ServicePort{ - { - Name: "web", - Port: 80, - TargetPort: intstr.FromInt(8000), - }, - }, - Selector: map[string]string{ - "app": "traefik-mesh-node", - }, - }, - } - - if _, err := client.CoreV1().Services(MeshNamespace).Create(svc); err != nil { - return err - } - } - - return nil -} - -// CreateRoutingConfigMap takes a config of traefik mesh, and creates the associated configmap. -func CreateRoutingConfigMap(client kubernetes.Interface, config *TraefikMeshConfig) error { - log.Infoln("Creating routing configmap...") - defer log.Infoln("Configmap Creation Complete...") - - t, _ := template.ParseFiles("templates/traefik-routing.tpl") // Parse template file. - - var tpl bytes.Buffer - if err := t.Execute(&tpl, &config); err != nil { - return err - } - - output := tpl.String() - - meshConfigMapList, _ := client.CoreV1().ConfigMaps(MeshNamespace).List(metav1.ListOptions{ - FieldSelector: fmt.Sprintf("metadata.name=%s", MeshConfigmapName), - }) - if len(meshConfigMapList.Items) > 0 { - // Config exists, update - log.Debugln("Updating configmap...") - - m, _ := client.CoreV1().ConfigMaps(MeshNamespace).Get(MeshConfigmapName, metav1.GetOptions{}) - newConfigmap := m - newConfigmap.Data[MeshConfigmapKey] = output - - if _, err := client.CoreV1().ConfigMaps(MeshNamespace).Update(newConfigmap); err != nil { - return err - } - return nil - } - - log.Debugln("Creating new configmap...") - - newConfigMap := &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: MeshConfigmapName, - Namespace: MeshNamespace, - }, - Data: map[string]string{ - MeshConfigmapKey: output, - }, - } - - if _, err := client.CoreV1().ConfigMaps(MeshNamespace).Create(newConfigMap); err != nil { - return err - } - - return nil -} - // Contains tells whether a contains x. func Contains(a []string, x string) bool { for _, n := range a { @@ -380,3 +202,8 @@ func Contains(a []string, x string) bool { } return false } + +// ServiceToMeshName converts a service with a namespace to a traefik-mesh ingressroute name +func ServiceToMeshName(serviceName string, namespace string) string { + return fmt.Sprintf("traefik-%s-%s", namespace, serviceName) +} From b5d02f520cbd065f5761ef6b6f6e7b2aaf437097 Mon Sep 17 00:00:00 2001 From: Daniel Tomcej Date: Wed, 12 Jun 2019 13:46:25 -0600 Subject: [PATCH 2/4] fix root --- cmd/root.go | 9 ---- meshcontroller/handler.go | 89 ++++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 885084a90..462c68f1c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -64,15 +64,6 @@ func runCommand() func(cmd *cobra.Command, args []string) { log.Fatalf("Error verifying cluster: %v", err) } - var meshConfig *utils.TraefikMeshConfig - if meshConfig, err = utils.CreateMeshConfig(clients.KubeClient); err != nil { - log.Fatalf("Error creating mesh config: %v", err) - } - - if err = utils.CreateRoutingConfigMap(clients.KubeClient, meshConfig); err != nil { - log.Fatalf("Error creating routing config map: %v", err) - } - // Create a new controller. controller := meshcontroller.NewMeshController() diff --git a/meshcontroller/handler.go b/meshcontroller/handler.go index fbd529215..464fbdbc7 100644 --- a/meshcontroller/handler.go +++ b/meshcontroller/handler.go @@ -40,20 +40,18 @@ func (h *Handler) Init() error { // ObjectCreated is called when an object is created func (h *Handler) ObjectCreated(obj interface{}) { // assert the type to an object to pull out relevant data - switch obj := obj.(type) { - case *corev1.Service: - if utils.Contains(h.IgnoredNamespaces, obj.Namespace) { - return - } - log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Service") - if err := VerifyMeshServiceExists(h.Clients.KubeClient, obj.Name, obj.Namespace); err != nil { - log.Errorf("Could not verify mesh service exists: %v", err) - return - } + service := obj.(*corev1.Service) + if utils.Contains(h.IgnoredNamespaces, service.Namespace) { + return + } + log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Service") + if err := VerifyMeshServiceExists(h.Clients.KubeClient, service); err != nil { + log.Errorf("Could not verify mesh service exists: %v", err) + return + } - if err := VerifyMeshIngressRouteExists(h.Clients.CrdClient, obj); err != nil { - log.Errorf("Could not verify mesh ingressroute exists: %v", err) - } + if err := VerifyMeshIngressRouteExists(h.Clients.CrdClient, service); err != nil { + log.Errorf("Could not verify mesh ingressroute exists: %v", err) } } @@ -61,20 +59,19 @@ func (h *Handler) ObjectCreated(obj interface{}) { // ObjectDeleted is called when an object is deleted func (h *Handler) ObjectDeleted(obj interface{}) { // assert the type to an object to pull out relevant data - switch obj := obj.(type) { - case *corev1.Service: - if utils.Contains(h.IgnoredNamespaces, obj.Namespace) { - return - } - log.Debugln("MeshControllerHandler.ObjectDeleted") - if err := VerifyMeshServiceDeleted(h.Clients.KubeClient, obj.Name, obj.Namespace); err != nil { - log.Errorf("Could not verify mesh service deleted: %v", err) - return - } + service := obj.(*corev1.Service) - if err := VerifyMeshIngressRouteDeleted(h.Clients.CrdClient, obj); err != nil { - log.Errorf("Could not verify mesh ingressroute deleted: %v", err) - } + if utils.Contains(h.IgnoredNamespaces, service.Namespace) { + return + } + log.Debugln("MeshControllerHandler.ObjectDeleted") + if err := VerifyMeshServiceDeleted(h.Clients.KubeClient, service); err != nil { + log.Errorf("Could not verify mesh service deleted: %v", err) + return + } + + if err := VerifyMeshIngressRouteDeleted(h.Clients.CrdClient, service); err != nil { + log.Errorf("Could not verify mesh ingressroute deleted: %v", err) } } @@ -83,8 +80,8 @@ func (h *Handler) ObjectUpdated(objOld, objNew interface{}) { log.Debugln("MeshControllerHandler.ObjectUpdated") } -func VerifyMeshServiceExists(client kubernetes.Interface, name, namespace string) error { - meshServiceName := utils.ServiceToMeshName(name, namespace) +func VerifyMeshServiceExists(client kubernetes.Interface, service *apiv1.Service) error { + meshServiceName := utils.ServiceToMeshName(service.Name, service.Namespace) meshServiceInstance, err := client.CoreV1().Services(utils.MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) if meshServiceInstance == nil || err != nil { svc := &apiv1.Service{ @@ -114,9 +111,26 @@ func VerifyMeshServiceExists(client kubernetes.Interface, name, namespace string return nil } +func VerifyMeshServiceDeleted(client kubernetes.Interface, service *apiv1.Service) error { + meshServiceName := utils.ServiceToMeshName(service.Name, service.Namespace) + meshServiceInstance, err := client.CoreV1().Services(utils.MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) + if err != nil { + return err + } + + if meshServiceInstance != nil { + // Service exists, delete + if err := client.CoreV1().Services(utils.MeshNamespace).Delete(meshServiceName, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + return nil +} + func VerifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1.Service) error { meshIngressRouteName := utils.ServiceToMeshName(service.Name, service.Namespace) - meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(metav1.NamespaceAll).Get(meshIngressRouteName, metav1.GetOptions{}) + meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(service.Namespace).Get(meshIngressRouteName, metav1.GetOptions{}) if meshIngressRouteInstance == nil || err != nil { ir := &traefik_v1alpha1.IngressRoute{ ObjectMeta: metav1.ObjectMeta{ @@ -144,3 +158,20 @@ func VerifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1. return nil } + +func VerifyMeshIngressRouteDeleted(client crdclientset.Interface, service *apiv1.Service) error { + meshIngressRouteName := utils.ServiceToMeshName(service.Name, service.Namespace) + meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(service.Namespace).Get(meshIngressRouteName, metav1.GetOptions{}) + if err != nil { + return err + } + + if meshIngressRouteInstance != nil { + // CRD exists, delete + if err := client.TraefikV1alpha1().IngressRoutes(service.Namespace).Delete(meshIngressRouteName, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + return nil +} From 39052d1c3cdabdca40db4c30b991c6699326af84 Mon Sep 17 00:00:00 2001 From: Daniel Tomcej Date: Wed, 12 Jun 2019 14:54:19 -0600 Subject: [PATCH 3/4] improve debug logging --- meshcontroller/handler.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/meshcontroller/handler.go b/meshcontroller/handler.go index 464fbdbc7..2124fe70b 100644 --- a/meshcontroller/handler.go +++ b/meshcontroller/handler.go @@ -44,12 +44,16 @@ func (h *Handler) ObjectCreated(obj interface{}) { if utils.Contains(h.IgnoredNamespaces, service.Namespace) { return } - log.Debugln("MeshControllerHandler ObjectCreated with type: *corev1.Service") + + log.Debugf("MeshControllerHandler ObjectCreated with type: *corev1.Service: %s/%s", service.Namespace, service.Name) + + log.Debugf("Verifying associated mesh service for service: %s/%s", service.Namespace, service.Name) if err := VerifyMeshServiceExists(h.Clients.KubeClient, service); err != nil { log.Errorf("Could not verify mesh service exists: %v", err) return } + log.Debugf("Verifying associated mesh ingressroute for service: %s/%s", service.Namespace, service.Name) if err := VerifyMeshIngressRouteExists(h.Clients.CrdClient, service); err != nil { log.Errorf("Could not verify mesh ingressroute exists: %v", err) } From 96a6f55466d1dddd4dadef16a14dc5037d14bb6e Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 13 Jun 2019 09:23:38 +0200 Subject: [PATCH 4/4] small fixes --- meshcontroller/handler.go | 36 ++++++++++++++++++------------------ utils/utils.go | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/meshcontroller/handler.go b/meshcontroller/handler.go index 2124fe70b..f73f68ce6 100644 --- a/meshcontroller/handler.go +++ b/meshcontroller/handler.go @@ -3,7 +3,7 @@ package meshcontroller import ( "github.com/containous/i3o/utils" crdclientset "github.com/containous/traefik/pkg/provider/kubernetes/crd/generated/clientset/versioned" - traefik_v1alpha1 "github.com/containous/traefik/pkg/provider/kubernetes/crd/traefik/v1alpha1" + traefikv1alpha1 "github.com/containous/traefik/pkg/provider/kubernetes/crd/traefik/v1alpha1" log "github.com/sirupsen/logrus" apiv1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1" @@ -12,7 +12,7 @@ import ( "k8s.io/client-go/kubernetes" ) -// MeshControllerHandler is an implementation of Handler +// MeshControllerHandler is an implementation of Handler. type Handler struct { Clients *utils.ClientWrapper IgnoredNamespaces []string @@ -31,13 +31,13 @@ func NewHandler(clients *utils.ClientWrapper, namespaces []string) *Handler { return h } -// Init handles any handler initialization +// Init handles any handler initialization. func (h *Handler) Init() error { log.Debugln("MeshControllerHandler.Init") return nil } -// ObjectCreated is called when an object is created +// ObjectCreated is called when an object is created. func (h *Handler) ObjectCreated(obj interface{}) { // assert the type to an object to pull out relevant data service := obj.(*corev1.Service) @@ -48,19 +48,19 @@ func (h *Handler) ObjectCreated(obj interface{}) { log.Debugf("MeshControllerHandler ObjectCreated with type: *corev1.Service: %s/%s", service.Namespace, service.Name) log.Debugf("Verifying associated mesh service for service: %s/%s", service.Namespace, service.Name) - if err := VerifyMeshServiceExists(h.Clients.KubeClient, service); err != nil { + if err := verifyMeshServiceExists(h.Clients.KubeClient, service); err != nil { log.Errorf("Could not verify mesh service exists: %v", err) return } log.Debugf("Verifying associated mesh ingressroute for service: %s/%s", service.Namespace, service.Name) - if err := VerifyMeshIngressRouteExists(h.Clients.CrdClient, service); err != nil { + if err := verifyMeshIngressRouteExists(h.Clients.CrdClient, service); err != nil { log.Errorf("Could not verify mesh ingressroute exists: %v", err) } } -// ObjectDeleted is called when an object is deleted +// ObjectDeleted is called when an object is deleted. func (h *Handler) ObjectDeleted(obj interface{}) { // assert the type to an object to pull out relevant data service := obj.(*corev1.Service) @@ -69,22 +69,22 @@ func (h *Handler) ObjectDeleted(obj interface{}) { return } log.Debugln("MeshControllerHandler.ObjectDeleted") - if err := VerifyMeshServiceDeleted(h.Clients.KubeClient, service); err != nil { + if err := verifyMeshServiceDeleted(h.Clients.KubeClient, service); err != nil { log.Errorf("Could not verify mesh service deleted: %v", err) return } - if err := VerifyMeshIngressRouteDeleted(h.Clients.CrdClient, service); err != nil { + if err := verifyMeshIngressRouteDeleted(h.Clients.CrdClient, service); err != nil { log.Errorf("Could not verify mesh ingressroute deleted: %v", err) } } -// ObjectUpdated is called when an object is updated +// ObjectUpdated is called when an object is updated. func (h *Handler) ObjectUpdated(objOld, objNew interface{}) { log.Debugln("MeshControllerHandler.ObjectUpdated") } -func VerifyMeshServiceExists(client kubernetes.Interface, service *apiv1.Service) error { +func verifyMeshServiceExists(client kubernetes.Interface, service *apiv1.Service) error { meshServiceName := utils.ServiceToMeshName(service.Name, service.Namespace) meshServiceInstance, err := client.CoreV1().Services(utils.MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) if meshServiceInstance == nil || err != nil { @@ -115,7 +115,7 @@ func VerifyMeshServiceExists(client kubernetes.Interface, service *apiv1.Service return nil } -func VerifyMeshServiceDeleted(client kubernetes.Interface, service *apiv1.Service) error { +func verifyMeshServiceDeleted(client kubernetes.Interface, service *apiv1.Service) error { meshServiceName := utils.ServiceToMeshName(service.Name, service.Namespace) meshServiceInstance, err := client.CoreV1().Services(utils.MeshNamespace).Get(meshServiceName, metav1.GetOptions{}) if err != nil { @@ -132,19 +132,19 @@ func VerifyMeshServiceDeleted(client kubernetes.Interface, service *apiv1.Servic return nil } -func VerifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1.Service) error { +func verifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1.Service) error { meshIngressRouteName := utils.ServiceToMeshName(service.Name, service.Namespace) meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(service.Namespace).Get(meshIngressRouteName, metav1.GetOptions{}) if meshIngressRouteInstance == nil || err != nil { - ir := &traefik_v1alpha1.IngressRoute{ + ir := &traefikv1alpha1.IngressRoute{ ObjectMeta: metav1.ObjectMeta{ Name: meshIngressRouteName, Namespace: service.Namespace, }, - Spec: traefik_v1alpha1.IngressRouteSpec{ - Routes: []traefik_v1alpha1.Route{ + Spec: traefikv1alpha1.IngressRouteSpec{ + Routes: []traefikv1alpha1.Route{ { - Services: []traefik_v1alpha1.Service{ + Services: []traefikv1alpha1.Service{ { Name: service.Name, Port: service.Spec.Ports[0].Port, @@ -163,7 +163,7 @@ func VerifyMeshIngressRouteExists(client crdclientset.Interface, service *apiv1. return nil } -func VerifyMeshIngressRouteDeleted(client crdclientset.Interface, service *apiv1.Service) error { +func verifyMeshIngressRouteDeleted(client crdclientset.Interface, service *apiv1.Service) error { meshIngressRouteName := utils.ServiceToMeshName(service.Name, service.Namespace) meshIngressRouteInstance, err := client.TraefikV1alpha1().IngressRoutes(service.Namespace).Get(meshIngressRouteName, metav1.GetOptions{}) if err != nil { diff --git a/utils/utils.go b/utils/utils.go index 17e0d581e..104b50d62 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -203,7 +203,7 @@ func Contains(a []string, x string) bool { return false } -// ServiceToMeshName converts a service with a namespace to a traefik-mesh ingressroute name +// ServiceToMeshName converts a service with a namespace to a traefik-mesh ingressroute name. func ServiceToMeshName(serviceName string, namespace string) string { return fmt.Sprintf("traefik-%s-%s", namespace, serviceName) }