diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 3079ec4..8ba0e15 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -236,4 +236,10 @@ rules: resources: - apiservices verbs: - - "*" \ No newline at end of file + - "*" +- apiGroups: + - operator.kyma-project.io + resources: + - dockerregistries + verbs: + - "*" diff --git a/controllers/cfapi_controller_rendered_resources.go b/controllers/cfapi_controller_rendered_resources.go index 323e951..58bc47a 100644 --- a/controllers/cfapi_controller_rendered_resources.go +++ b/controllers/cfapi_controller_rendered_resources.go @@ -315,14 +315,23 @@ func (r *CFAPIReconciler) processResources(ctx context.Context, cfAPI *v1alpha1. cfDomain := wildCardDomain[2:] appsDomain := "apps." + cfDomain korifiApiDomain := "cfapi." + cfDomain - twuniDomain := "cr." + cfDomain logger.Info("wildcard domain retrieved : " + wildCardDomain) logger.Info("cf domain calculated : " + cfDomain) logger.Info("apps domain calculated : " + appsDomain) logger.Info("korifi api domain calculated : " + korifiApiDomain) - containerRegistry, err := r.getAppContainerRegistry(ctx, cfAPI, twuniDomain) + // ensure docker registry + logger.Info("Start ensuring docker registry ...") + err = r.ensureDockerRegistry(ctx, cfAPI) + if err != nil { + logger.Error(err, "error ensuring docker registry") + return "", err + } + logger.Info("docker registry ensured") + + // get app container registry + containerRegistry, err := r.getAppContainerRegistry(ctx, cfAPI) if err != nil { logger.Error(err, "error getting app container registry") return "", err @@ -362,15 +371,6 @@ func (r *CFAPIReconciler) processResources(ctx context.Context, cfAPI *v1alpha1. } logger.Info("namespaces created") - // install twuni - logger.Info("Start installing twuni ...") - err = r.installTwuni(ctx, cfAPI, cfDomain, twuniDomain) - if err != nil { - logger.Error(err, "error installing twuni") - return "", err - } - logger.Info("twuni installed") - // generate ingress certificates logger.Info("Start generating ingress certificates ...") err = r.generateIngressCertificates(ctx, cfDomain, appsDomain, korifiApiDomain) @@ -428,15 +428,6 @@ func (r *CFAPIReconciler) processResources(ctx context.Context, cfAPI *v1alpha1. } logger.Info("dns entries created") - // create twuni dns entries - logger.Info("Start creating twuni dns entries ...") - err = r.createTwuniDNSEntry(ctx, cfAPI, twuniDomain) - if err != nil { - logger.Error(err, "error creating twuni dns entries") - return "", err - } - logger.Info("twuni dns entries created") - var subjects = toSubjectList(cfAPI.Spec.CFAdmins) err = r.assignCfAdministrators(ctx, subjects, cfAPI.Spec.RootNamespace) if err != nil { @@ -449,6 +440,34 @@ func (r *CFAPIReconciler) processResources(ctx context.Context, cfAPI *v1alpha1. return "https://" + korifiApiDomain, nil } +func (r *CFAPIReconciler) ensureDockerRegistry(ctx context.Context, cfAPI *v1alpha1.CFAPI) error { + logger := log.FromContext(ctx) + + if cfAPI.Spec.AppImagePullSecret != "" { + logger.Info("App Container Img Reg Secret is set, using it") + return nil + } + + if !r.crdExists(ctx, "DockerRegistry") { + logger.Info("DockerRegistry CRD does not exist") + return errors.New("DockerRegistry CRD does not exist. Create it by enablib docker registry Kyma module") + } + + err := r.installOneGlob(ctx, "./module-data/docker-registry/docker-registry.yaml") + if err != nil { + logger.Error(err, "error installing docker registry") + return err + } + + err = r.waitForSecret("cfapi-system", "dockerregistry-config-external") + if err != nil { + logger.Error(err, "error waiting for secret dockerregistry-config-external") + return err + } + + return nil +} + func (r *CFAPIReconciler) createOIDCConfig(ctx context.Context, cfAPI *v1alpha1.CFAPI) error { logger := log.FromContext(ctx) @@ -501,8 +520,7 @@ func (r *CFAPIReconciler) createOIDCConfig(ctx context.Context, cfAPI *v1alpha1. return nil } -func (r *CFAPIReconciler) getAppContainerRegistry(ctx context.Context, cfAPI *v1alpha1.CFAPI, - twuniDomain string) (ContainerRegistry, error) { +func (r *CFAPIReconciler) getAppContainerRegistry(ctx context.Context, cfAPI *v1alpha1.CFAPI) (ContainerRegistry, error) { logger := log.FromContext(ctx) if cfAPI.Spec.AppImagePullSecret != "" { @@ -526,11 +544,23 @@ func (r *CFAPIReconciler) getAppContainerRegistry(ctx context.Context, cfAPI *v1 }, nil } - logger.Info("App Container Img Reg Secret is not set, using twuni") + logger.Info("Constructing app container registry from dockerregistry-config-external secret ") + + secret := corev1.Secret{} + err := r.Client.Get(context.Background(), client.ObjectKey{ + Namespace: "cfapi-system", + Name: "dockerregistry-config-external", + }, &secret) + + if err != nil { + logger.Error(err, "error getting app container registry secret") + return ContainerRegistry{}, err + } + return ContainerRegistry{ - Server: twuniDomain, - User: DefaultTwuniUser, - Pass: DefaultTwuniPass, + Server: string(secret.Data["pushRegAddr"]), + User: string(secret.Data["username"]), + Pass: string(secret.Data["password"]), }, nil } diff --git a/controllers/install_twuni.go b/controllers/install_twuni.go deleted file mode 100644 index df9266c..0000000 --- a/controllers/install_twuni.go +++ /dev/null @@ -1,268 +0,0 @@ -package controllers - -import ( - "bytes" - "context" - "text/template" - - "github.tools.sap/unified-runtime/cfapi-kyma-module/api/v1alpha1" - "helm.sh/helm/v3/pkg/chart/loader" - corev1 "k8s.io/api/core/v1" - errors2 "k8s.io/apimachinery/pkg/api/errors" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -func (r *CFAPIReconciler) installTwuni(ctx context.Context, cfAPI *v1alpha1.CFAPI, cfDomain, twuniDomain string) error { - logger := log.FromContext(ctx) - - if cfAPI.Spec.AppImagePullSecret != "" { - logger.Info("App Container Img Reg Secret is set, skipping twuni installation") - return nil - } - - // create twuni certificate - logger.Info("Start installing twuni ...") - err := r.createTwuniCertificate(ctx, cfDomain, twuniDomain) - if err != nil { - logger.Error(err, "error creating twuni certificate") - return err - } - - // deploy twuni helm - err = r.deployTwuniHelm(ctx) - if err != nil { - logger.Error(err, "error deploying twuni helm") - return err - } - - // create reference grant - err = r.createTwuniReferenceGrant(ctx) - if err != nil { - logger.Error(err, "error creating twuni reference grant") - return err - } - - // create tlsroute - err = r.createTwuniTLSRoute(ctx, twuniDomain) - if err != nil { - logger.Error(err, "error creating twuni tls route") - return err - } - - logger.Info("Finished installing twuni ...") - - return nil -} - -func (r *CFAPIReconciler) createTwuniTLSRoute(ctx context.Context, twuniDomain string) error { - logger := log.FromContext(ctx) - - vals := struct { - TwuniDomain string - }{ - TwuniDomain: twuniDomain, - } - - t1 := template.New("twuniTLSRoute") - - t2, err := t1.ParseFiles("./module-data/twuni-tlsroute/tlsroute.tmpl") - - if err != nil { - logger.Error(err, "error during parsing of twuni tls route template") - return err - } - - buf := &bytes.Buffer{} - - err = t2.ExecuteTemplate(buf, "twuniTLSRoute", vals) - - if err != nil { - logger.Error(err, "error during execution of twuni tls route template") - return err - } - - s := buf.String() - - resourceObjs, err := parseManifestStringToObjects(s) - - if err != nil { - logger.Error(err, "error during parsing of twuni tls route") - return nil - } - - for _, obj := range resourceObjs.Items { - if err = r.ssa(ctx, obj); err != nil && !errors2.IsAlreadyExists(err) { - logger.Error(err, "error during installation of twuni tls route") - return err - } - } - - return nil -} - -func (r *CFAPIReconciler) createTwuniReferenceGrant(ctx context.Context) error { - logger := log.FromContext(ctx) - - err := r.installOneGlob(ctx, "./module-data/twuni-referencegrant/referencegrant.yaml") - if err != nil { - logger.Error(err, "error installing twuni reference grant resources") - return err - } - - return nil -} - -func (r *CFAPIReconciler) createTwuniDNSEntry(ctx context.Context, cfAPI *v1alpha1.CFAPI, twuniDomain string) error { - logger := log.FromContext(ctx) - - if cfAPI.Spec.AppImagePullSecret != "" { - logger.Info("App Container Img Reg Secret is set, skipping twuni installation") - return nil - } - - // get ingress hostname - ingress := corev1.Service{} - err := r.Client.Get(context.Background(), client.ObjectKey{ - Namespace: "korifi-gateway", - Name: "korifi-istio", - }, &ingress) - - if err != nil { - logger.Error(err, "error getting ingress hostname") - return err - } - - hostname := ingress.Status.LoadBalancer.Ingress[0].Hostname - - // create dns entries - vals := struct { - TwuniDomain string - IngressHost string - }{ - TwuniDomain: twuniDomain, - IngressHost: hostname, - } - - t1 := template.New("twuniDNSEntry") - - t2, err := t1.ParseFiles("./module-data/twuni-dns-entry/dnsentry.tmpl") - if err != nil { - logger.Error(err, "error during parsing of twuni dns entries template") - return err - } - - buf := &bytes.Buffer{} - - err = t2.ExecuteTemplate(buf, "twuniDNSEntry", vals) - if err != nil { - logger.Error(err, "error during execution of twuni dns entries template") - return err - } - - s := buf.String() - - resourceObjs, err := parseManifestStringToObjects(s) - - if err != nil { - logger.Error(err, "error during parsing of twuni dns entries") - return nil - } - - for _, obj := range resourceObjs.Items { - if err = r.ssa(ctx, obj); err != nil && !errors2.IsAlreadyExists(err) { - logger.Error(err, "error during installation of twuni dns entries") - return err - } - } - - return nil -} - -func (r *CFAPIReconciler) deployTwuniHelm(ctx context.Context) error { - logger := log.FromContext(ctx) - - filename, err := findOneGlob("./module-data/twuni-helm/*.tar.gz") - if err != nil { - return err - } - - chart, err := loader.Load(filename) - if err != nil { - logger.Error(err, "error during loading twuni helm chart") - return err - } - - inputValues := map[string]interface{}{ - "persistence": map[string]interface{}{ - "enabled": true, - "deleteEnabled": true, - }, - "service": map[string]interface{}{ - "port": 30050, - }, - "secrets": map[string]interface{}{ - "htpasswd": "user:$2y$05$MKUm/h9dwwWoCOht5enn3uyih.awSPDILY.kovYyT3J8KSw5lmwIe", - }, - "tlsSecretName": "docker-registry-ingress-cert", - } - - err = applyRelease(chart, "cfapi-system", "localregistry", inputValues, logger) - - return err -} - -func (r *CFAPIReconciler) createTwuniCertificate(ctx context.Context, cfDomain, twuniDomain string) error { - logger := log.FromContext(ctx) - - vals := struct { - CFDomain string - TwuniDomain string - }{ - CFDomain: cfDomain, - TwuniDomain: twuniDomain, - } - - t1 := template.New("twuniCert") - - t2, err := t1.ParseFiles("./module-data/twuni-certificate/certificate.tmpl") - - if err != nil { - logger.Error(err, "error during parsing of twuni certificate template") - return err - } - - buf := &bytes.Buffer{} - - err = t2.ExecuteTemplate(buf, "twuniCert", vals) - - if err != nil { - logger.Error(err, "error during execution of twuni certificate template") - return err - } - - s := buf.String() - - resourceObjs, err := parseManifestStringToObjects(s) - - if err != nil { - logger.Error(err, "error during parsing of ingress certificates") - return nil - } - - for _, obj := range resourceObjs.Items { - if err = r.ssa(ctx, obj); err != nil && !errors2.IsAlreadyExists(err) { - logger.Error(err, "error during installation of cert manager resources") - return err - } - } - - // wait for respective secrets to be created - err = r.waitForSecret("cfapi-system", "docker-registry-ingress-cert") - if err != nil { - logger.Error(err, "error waiting for secret docker-registry-ingress-cert") - return err - } - - return nil -} diff --git a/module-data/docker-registry/docker-registry.yaml b/module-data/docker-registry/docker-registry.yaml new file mode 100644 index 0000000..60da697 --- /dev/null +++ b/module-data/docker-registry/docker-registry.yaml @@ -0,0 +1,9 @@ +apiVersion: operator.kyma-project.io/v1alpha1 +kind: DockerRegistry +metadata: + name: cfapi-docker-registry + namespace: cfapi-system +spec: + externalAccess: + enabled: true + hostPrefix: cfapi-registry diff --git a/module-data/twuni-certificate/certificate.tmpl b/module-data/twuni-certificate/certificate.tmpl deleted file mode 100644 index 57bd16a..0000000 --- a/module-data/twuni-certificate/certificate.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -{{ define "twuniCert" }} -apiVersion: cert.gardener.cloud/v1alpha1 -kind: Certificate -metadata: - name: docker-registry-ingress-cert - namespace: cfapi-system -spec: - commonName: {{ .CFDomain }} - dnsNames: - - "{{ .TwuniDomain }}" - secretRef: - name: docker-registry-ingress-cert - namespace: cfapi-system -{{ end }} \ No newline at end of file diff --git a/module-data/twuni-dns-entry/dnsentry.tmpl b/module-data/twuni-dns-entry/dnsentry.tmpl deleted file mode 100644 index 35a3840..0000000 --- a/module-data/twuni-dns-entry/dnsentry.tmpl +++ /dev/null @@ -1,16 +0,0 @@ -{{ define "twuniDNSEntry" }} ---- -apiVersion: dns.gardener.cloud/v1alpha1 -kind: DNSEntry -metadata: - annotations: - # Let Gardener manage this DNS entry. - dns.gardener.cloud/class: garden - name: twuni-ingress - namespace: cfapi-system -spec: - dnsName: {{ .TwuniDomain }} - ttl: 600 - targets: - - {{ .IngressHost }} -{{ end }} \ No newline at end of file diff --git a/module-data/twuni-referencegrant/referencegrant.yaml b/module-data/twuni-referencegrant/referencegrant.yaml deleted file mode 100644 index 890382e..0000000 --- a/module-data/twuni-referencegrant/referencegrant.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: ReferenceGrant -metadata: - name: docker-registry-reference-grant - namespace: cfapi-system -spec: - from: - - group: gateway.networking.k8s.io - kind: TLSRoute - namespace: korifi - to: - - group: '' - kind: Service - name: localregistry-docker-registry diff --git a/module-data/twuni-tlsroute/tlsroute.tmpl b/module-data/twuni-tlsroute/tlsroute.tmpl deleted file mode 100644 index d562109..0000000 --- a/module-data/twuni-tlsroute/tlsroute.tmpl +++ /dev/null @@ -1,22 +0,0 @@ -{{ define "twuniTLSRoute" }} -apiVersion: gateway.networking.k8s.io/v1alpha2 -kind: TLSRoute -metadata: - name: docker-registry - namespace: korifi -spec: - hostnames: - - {{ .TwuniDomain }} - parentRefs: - - group: gateway.networking.k8s.io - kind: Gateway - name: korifi - namespace: korifi-gateway - rules: - - backendRefs: - - group: "" - kind: Service - name: localregistry-docker-registry - namespace: cfapi-system - port: 30050 -{{ end }} \ No newline at end of file