From 5b7a61bdfde51d5aa06dcb4ab71002f8078139bf Mon Sep 17 00:00:00 2001 From: Sina Date: Sun, 10 Dec 2023 14:46:34 +0330 Subject: [PATCH 1/2] adding service creation for deployments --- api/v1alpha1/basicauthenticator_types.go | 4 ++ ...tor.snappcloud.io_basicauthenticators.yaml | 3 ++ config/rbac/role.yaml | 12 ++++++ .../basicauthenticator_controller.go | 3 ++ .../basic_authenticator/provision.go | 41 ++++++++++++++++++- .../{nginx.go => workload.go} | 37 ++++++++++++++++- tests/e2e/deployment/00-install.yaml | 2 +- tests/e2e/deployment/02-assert.yaml | 4 ++ 8 files changed, 102 insertions(+), 4 deletions(-) rename internal/controller/basic_authenticator/{nginx.go => workload.go} (87%) create mode 100644 tests/e2e/deployment/02-assert.yaml diff --git a/api/v1alpha1/basicauthenticator_types.go b/api/v1alpha1/basicauthenticator_types.go index b0b4555..1754eae 100644 --- a/api/v1alpha1/basicauthenticator_types.go +++ b/api/v1alpha1/basicauthenticator_types.go @@ -35,6 +35,10 @@ type BasicAuthenticatorSpec struct { // +kubebuilder:validation:Optional Selector metav1.LabelSelector `json:"selector,omitempty"` + // +kubebuilder:validation:Optional + // +kubebuilder:default=ClusterIP + ServiceType string `json:"serviceType"` + // +kubebuilder:validation:Required AppPort int `json:"appPort"` diff --git a/config/crd/bases/authenticator.snappcloud.io_basicauthenticators.yaml b/config/crd/bases/authenticator.snappcloud.io_basicauthenticators.yaml index 2acfaec..30d60ef 100644 --- a/config/crd/bases/authenticator.snappcloud.io_basicauthenticators.yaml +++ b/config/crd/bases/authenticator.snappcloud.io_basicauthenticators.yaml @@ -100,6 +100,9 @@ spec: type: object type: object x-kubernetes-map-type: atomic + serviceType: + default: ClusterIP + type: string type: description: Type is used to determine that nginx should be sidercar or deployment diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index c62a758..9bf77aa 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -67,3 +67,15 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch diff --git a/internal/controller/basic_authenticator/basicauthenticator_controller.go b/internal/controller/basic_authenticator/basicauthenticator_controller.go index 1a0b04c..65bc3e2 100644 --- a/internal/controller/basic_authenticator/basicauthenticator_controller.go +++ b/internal/controller/basic_authenticator/basicauthenticator_controller.go @@ -23,6 +23,7 @@ import ( "github.com/snapp-incubator/simple-authenticator/internal/config" appv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" @@ -41,6 +42,7 @@ type BasicAuthenticatorReconciler struct { configMapName string credentialName string basicAuthenticatorNamespace string + deploymentLabel *v1.LabelSelector logger logr.Logger } @@ -63,6 +65,7 @@ func (r *BasicAuthenticatorReconciler) Reconcile(ctx context.Context, req ctrl.R func (r *BasicAuthenticatorReconciler) initVars(request ctrl.Request) { r.basicAuthenticatorNamespace = request.Namespace //configmap name and credential name's value would be set in reconcile loop + } // SetupWithManager sets up the controller with the Manager. diff --git a/internal/controller/basic_authenticator/provision.go b/internal/controller/basic_authenticator/provision.go index 89349b0..0a536fb 100644 --- a/internal/controller/basic_authenticator/provision.go +++ b/internal/controller/basic_authenticator/provision.go @@ -22,6 +22,7 @@ func (r *BasicAuthenticatorReconciler) Provision(ctx context.Context, req ctrl.R r.ensureSecret, r.ensureConfigmap, r.ensureDeployment, + r.ensureService, } for _, provisioner := range subProvisioner { result, err := provisioner(ctx, req) @@ -177,7 +178,45 @@ func (r *BasicAuthenticatorReconciler) ensureDeployment(ctx context.Context, req return r.createDeploymentAuthenticator(ctx, req, basicAuthenticator, r.configMapName, r.credentialName) } } +func (r *BasicAuthenticatorReconciler) ensureService(ctx context.Context, req ctrl.Request) (*ctrl.Result, error) { + basicAuthenticator := &v1alpha1.BasicAuthenticator{} + + if r, err := r.getLatestBasicAuthenticator(ctx, req, basicAuthenticator); subreconciler.ShouldHaltOrRequeue(r, err) { + return r, err + } + if r.deploymentLabel == nil { + return subreconciler.ContinueReconciling() + } + newService := createNginxService(ctx, basicAuthenticator, r.deploymentLabel) + foundService := corev1.Service{} + err := r.Get(ctx, types.NamespacedName{Name: newService.Name, Namespace: newService.Namespace}, &foundService) + if errors.IsNotFound(err) { + if err := ctrl.SetControllerReference(basicAuthenticator, newService, r.Scheme); err != nil { + r.logger.Error(err, "failed to set service owner") + return subreconciler.RequeueWithError(err) + } + err := r.Create(ctx, newService) + if err != nil { + r.logger.Error(err, "failed to create new service") + return subreconciler.RequeueWithError(err) + } + } else if err != nil { + r.logger.Error(err, "failed to fetch service") + return subreconciler.RequeueWithError(err) + } else { + if !reflect.DeepEqual(newService.Spec, foundService.Spec) { + r.logger.Info("updating service") + foundService.Spec = newService.Spec + err := r.Update(ctx, &foundService) + if err != nil { + r.logger.Error(err, "failed to update service") + return subreconciler.RequeueWithError(err) + } + } + } + return subreconciler.ContinueReconciling() +} func (r *BasicAuthenticatorReconciler) createDeploymentAuthenticator(ctx context.Context, req ctrl.Request, basicAuthenticator *v1alpha1.BasicAuthenticator, authenticatorConfigName, secretName string) (*ctrl.Result, error) { newDeployment := createNginxDeployment(basicAuthenticator, authenticatorConfigName, secretName, r.CustomConfig) @@ -203,7 +242,7 @@ func (r *BasicAuthenticatorReconciler) createDeploymentAuthenticator(ctx context return subreconciler.RequeueWithError(err) } r.logger.Info("created deployment") - + r.deploymentLabel = newDeployment.Spec.Selector } else if err != nil { if err != nil { r.logger.Error(err, "failed to fetch deployment") diff --git a/internal/controller/basic_authenticator/nginx.go b/internal/controller/basic_authenticator/workload.go similarity index 87% rename from internal/controller/basic_authenticator/nginx.go rename to internal/controller/basic_authenticator/workload.go index 8436911..de7ed39 100644 --- a/internal/controller/basic_authenticator/nginx.go +++ b/internal/controller/basic_authenticator/workload.go @@ -13,6 +13,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" "strings" ) @@ -90,7 +91,6 @@ func createNginxDeployment(basicAuthenticator *v1alpha1.BasicAuthenticator, conf }, }, } - return deploy } @@ -153,7 +153,29 @@ func createCredentials(basicAuthenticator *v1alpha1.BasicAuthenticator) (*corev1 } return secret, nil } - +func createNginxService(ctx context.Context, basicAuthenticator *v1alpha1.BasicAuthenticator, selector *metav1.LabelSelector) *corev1.Service { + serviceName := fmt.Sprintf("%s-svc", basicAuthenticator.Name) + serviceType := getServiceType(basicAuthenticator.Spec.ServiceType) + targetPort := intstr.IntOrString{Type: intstr.Int, IntVal: int32(basicAuthenticator.Spec.AuthenticatorPort)} + svc := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + Namespace: basicAuthenticator.Namespace, + }, + Spec: corev1.ServiceSpec{ + Selector: selector.MatchLabels, + Type: serviceType, + Ports: []corev1.ServicePort{ + { + Port: int32(basicAuthenticator.Spec.AuthenticatorPort), + TargetPort: targetPort, + Name: "authenticator", + }, + }, + }, + } + return &svc +} func injector(ctx context.Context, basicAuthenticator *v1alpha1.BasicAuthenticator, configMapName string, credentialName string, customConfig *config.CustomConfig, k8Client client.Client) ([]*appsv1.Deployment, error) { nginxImageAddress := getNginxContainerImage(customConfig) nginxContainerName := getNginxContainerName(customConfig) @@ -236,3 +258,14 @@ func fillTemplate(template string, secretPath string, authenticator *v1alpha1.Ba result = strings.Replace(result, "APP_PORT", fmt.Sprintf("%d", authenticator.Spec.AppPort), 1) return result } + +func getServiceType(serviceType string) corev1.ServiceType { + switch serviceType { + case "NodePort": + return corev1.ServiceTypeNodePort + case "LoadBalancer": + return corev1.ServiceTypeLoadBalancer + default: + return corev1.ServiceTypeClusterIP + } +} diff --git a/tests/e2e/deployment/00-install.yaml b/tests/e2e/deployment/00-install.yaml index 77771bd..566a3b3 100644 --- a/tests/e2e/deployment/00-install.yaml +++ b/tests/e2e/deployment/00-install.yaml @@ -14,4 +14,4 @@ spec: appPort: 8081 appService: google.com adaptiveScale: false - authenticatorPort: 8080 + authenticatorPort: 8082 diff --git a/tests/e2e/deployment/02-assert.yaml b/tests/e2e/deployment/02-assert.yaml new file mode 100644 index 0000000..b67f4ad --- /dev/null +++ b/tests/e2e/deployment/02-assert.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Service +metadata: + name: basicauthenticator-sample-svc From 9dd1af9b6414691e91d9410e279967ae86413c25 Mon Sep 17 00:00:00 2001 From: Sina Date: Mon, 11 Dec 2023 12:36:30 +0330 Subject: [PATCH 2/2] removed extra error check and owned service --- .../basic_authenticator/basicauthenticator_controller.go | 2 +- internal/controller/basic_authenticator/provision.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/controller/basic_authenticator/basicauthenticator_controller.go b/internal/controller/basic_authenticator/basicauthenticator_controller.go index 65bc3e2..f2413f8 100644 --- a/internal/controller/basic_authenticator/basicauthenticator_controller.go +++ b/internal/controller/basic_authenticator/basicauthenticator_controller.go @@ -65,7 +65,6 @@ func (r *BasicAuthenticatorReconciler) Reconcile(ctx context.Context, req ctrl.R func (r *BasicAuthenticatorReconciler) initVars(request ctrl.Request) { r.basicAuthenticatorNamespace = request.Namespace //configmap name and credential name's value would be set in reconcile loop - } // SetupWithManager sets up the controller with the Manager. @@ -75,6 +74,7 @@ func (r *BasicAuthenticatorReconciler) SetupWithManager(mgr ctrl.Manager) error Owns(&appv1.Deployment{}). Owns(&corev1.ConfigMap{}). Owns(&corev1.Secret{}). + Owns(&corev1.Service{}). Watches( &source.Kind{Type: &appv1.Deployment{}}, handler.EnqueueRequestsFromMapFunc(r.findExternallyManagedDeployments), diff --git a/internal/controller/basic_authenticator/provision.go b/internal/controller/basic_authenticator/provision.go index 0a536fb..b1829b0 100644 --- a/internal/controller/basic_authenticator/provision.go +++ b/internal/controller/basic_authenticator/provision.go @@ -244,10 +244,8 @@ func (r *BasicAuthenticatorReconciler) createDeploymentAuthenticator(ctx context r.logger.Info("created deployment") r.deploymentLabel = newDeployment.Spec.Selector } else if err != nil { - if err != nil { - r.logger.Error(err, "failed to fetch deployment") - return subreconciler.RequeueWithError(err) - } + r.logger.Error(err, "failed to fetch deployment") + return subreconciler.RequeueWithError(err) } else { //update deployment targetReplica := newDeployment.Spec.Replicas