From a37b5d93ab3d4cc3dbc5ac9dc965659d7e7d90d8 Mon Sep 17 00:00:00 2001 From: Manabu Mccloskey Date: Fri, 17 Nov 2023 17:20:51 -0800 Subject: [PATCH] rename repo url field make gitea server endpoints available create repos and argo apps for bootstrap apps Signed-off-by: Manabu Mccloskey --- api/v1alpha1/gitrepository_types.go | 7 +- api/v1alpha1/localbuild_types.go | 20 +++-- api/v1alpha1/zz_generated.deepcopy.go | 16 ++++ pkg/controllers/gitrepository/controller.go | 12 ++- pkg/controllers/localbuild/controller.go | 87 +++++++++++++++++-- pkg/controllers/localbuild/gitea.go | 15 ++-- .../idpbuilder.cnoe.io_gitrepositories.yaml | 9 +- .../idpbuilder.cnoe.io_localbuilds.yaml | 19 ++-- pkg/controllers/run.go | 2 +- 9 files changed, 147 insertions(+), 40 deletions(-) diff --git a/api/v1alpha1/gitrepository_types.go b/api/v1alpha1/gitrepository_types.go index 5ea94036..8e24bbb7 100644 --- a/api/v1alpha1/gitrepository_types.go +++ b/api/v1alpha1/gitrepository_types.go @@ -6,13 +6,14 @@ import ( type GitRepositorySpec struct { Source GitRepositorySource `json:"source,omitempty"` - // GitURL is the base URL of GitTea server + // GitURL is the base URL of Git server // +kubebuilder:validation:Required - GitURL string `json:"giteaURL"` + // +kubebuilder:validation:Pattern=`^https?:\/\/.+$` + GitURL string `json:"gitURL"` } type GitRepositorySource struct { - // +kubebuilder:validation:Enum:=argocd;gitea;nginx + // +kubebuilder:validation:Enum:=argocd;backstage;crossplane;gitea;nginx // +kubebuilder:validation:Optional EmbeddedAppName string `json:"embeddedAppName"` // Path is the absolute path to directory that contains Kustomize structure or raw manifests. diff --git a/api/v1alpha1/localbuild_types.go b/api/v1alpha1/localbuild_types.go index e4c7ea83..67e24bc1 100644 --- a/api/v1alpha1/localbuild_types.go +++ b/api/v1alpha1/localbuild_types.go @@ -41,13 +41,19 @@ type LocalbuildStatus struct { // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` - GitServerAvailable bool `json:"gitServerAvailable,omitempty"` - ArgoAvailable bool `json:"argoAvailable,omitempty"` - NginxAvailable bool `json:"nginxAvailable,omitempty"` - GiteaAvailable bool `json:"giteaAvailable,omitempty"` - ArgoAppsCreated bool `json:"argoAppsCreated,omitempty"` - GiteaSecretName string `json:"giteaSecret,omitempty"` - GiteaSecretNamespace string `json:"giteaSecretNamespace,omitempty"` + GitServerAvailable bool `json:"gitServerAvailable,omitempty"` + ArgoAvailable bool `json:"argoAvailable,omitempty"` + NginxAvailable bool `json:"nginxAvailable,omitempty"` + ArgoAppsCreated bool `json:"argoAppsCreated,omitempty"` + Gitea GiteaStatus `json:"giteaStatus,omitempty"` +} + +type GiteaStatus struct { + Available bool `json:"available,omitempty"` + ExternalURL string `json:"externalURL,omitempty"` + InternalURL string `json:"internalURL,omitempty"` + AdminUserSecretName string `json:"adminUserSecretNameecret,omitempty"` + AdminUserSecretNamespace string `json:"adminUserSecretNamespace,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8da9e244..536ef585 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -296,6 +296,21 @@ func (in *GitServerStatus) DeepCopy() *GitServerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GiteaStatus) DeepCopyInto(out *GiteaStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GiteaStatus. +func (in *GiteaStatus) DeepCopy() *GiteaStatus { + if in == nil { + return nil + } + out := new(GiteaStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Localbuild) DeepCopyInto(out *Localbuild) { *out = *in @@ -374,6 +389,7 @@ func (in *LocalbuildSpec) DeepCopy() *LocalbuildSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalbuildStatus) DeepCopyInto(out *LocalbuildStatus) { *out = *in + out.Gitea = in.Gitea } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalbuildStatus. diff --git a/pkg/controllers/gitrepository/controller.go b/pkg/controllers/gitrepository/controller.go index 88212173..dae6273f 100644 --- a/pkg/controllers/gitrepository/controller.go +++ b/pkg/controllers/gitrepository/controller.go @@ -22,9 +22,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/source" ) const ( @@ -65,8 +63,8 @@ func (r *RepositoryReconciler) getCredentials(ctx context.Context, repo *v1alpha var secret v1.Secret err = r.Client.Get(ctx, types.NamespacedName{ - Namespace: lb.Status.GiteaSecretNamespace, - Name: lb.Status.GiteaSecretName, + Namespace: lb.Status.Gitea.AdminUserSecretNamespace, + Name: lb.Status.Gitea.AdminUserSecretName, }, &secret) if err != nil { return "", "", err @@ -74,11 +72,11 @@ func (r *RepositoryReconciler) getCredentials(ctx context.Context, repo *v1alpha username, ok := secret.Data[giteaAdminUsernameKey] if !ok { - return "", "", fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminUsernameKey, lb.Status.GiteaSecretName, lb.Status.GiteaSecretNamespace) + return "", "", fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminUsernameKey, lb.Status.Gitea.AdminUserSecretName, lb.Status.Gitea.AdminUserSecretNamespace) } password, ok := secret.Data[giteaAdminPasswordKey] if !ok { - return "", "", fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminPasswordKey, lb.Status.GiteaSecretName, lb.Status.GiteaSecretNamespace) + return "", "", fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminPasswordKey, lb.Status.Gitea.AdminUserSecretName, lb.Status.Gitea.AdminUserSecretNamespace) } return string(username), string(password), nil } @@ -271,9 +269,9 @@ func reconcileRepo(giteaClient GiteaClient, repo *v1alpha1.GitRepository) (*gite } func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager, notifyChan chan event.GenericEvent) error { + // TODO: should use notifyChan to trigger reconcile when FS changes return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.GitRepository{}). - Watches(&source.Channel{Source: notifyChan}, &handler.EnqueueRequestForObject{}). Complete(r) } diff --git a/pkg/controllers/localbuild/controller.go b/pkg/controllers/localbuild/controller.go index 1cff0ae3..97e4e7d9 100644 --- a/pkg/controllers/localbuild/controller.go +++ b/pkg/controllers/localbuild/controller.go @@ -10,6 +10,7 @@ import ( "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/apps" "github.com/cnoe-io/idpbuilder/pkg/resources/localbuild" + "github.com/cnoe-io/idpbuilder/pkg/util" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -21,11 +22,10 @@ import ( ) const ( - defaultArgoCDProjectName string = "default" - EmbeddedGitServerName string = "embedded" - gitServerDeploymentContainerName string = "httpd" - gitServerIngressHostnameBase string = ".cnoe.localtest.me" - repoUrlFmt string = "http://%s.%s.svc/idpbuilder-resources.git" + defaultArgoCDProjectName string = "default" + EmbeddedGitServerName string = "embedded" + gitServerIngressHostnameBase string = ".cnoe.localtest.me" + repoUrlFmt string = "http://%s.%s.svc/idpbuilder-resources.git" ) func getRepoUrl(resource *v1alpha1.GitServer) string { @@ -279,20 +279,91 @@ func (r *LocalbuildReconciler) SetupWithManager(mgr ctrl.Manager) error { func (r *LocalbuildReconciler) ReconcileArgoAppsWithGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { logger := log.FromContext(ctx) - logger.Info("TODO(nimak): enable installing Argo Apps") + logger.Info("installing bootstrap apps to ArgoCD") + // push bootstrap app manifests to Gitea. let ArgoCD take over + // will need a way to filter them based on user input + _, err := r.reconcileBootstrapApps(ctx, req, resource) + if err != nil { + return ctrl.Result{}, fmt.Errorf("reconciling bootstrap apps %w", err) + } + _, err = r.reconcileEmbeddedApps(ctx, req, resource) + if err != nil { + return ctrl.Result{}, fmt.Errorf("reconciling embedded apps %w", err) + } + // TODO: this needs to be removed for local file syncs. r.shouldShutdown = true return ctrl.Result{}, nil } +func (r *LocalbuildReconciler) reconcileEmbeddedApps(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { + return ctrl.Result{}, nil +} + +func (r *LocalbuildReconciler) reconcileBootstrapApps(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { + bootStrapApps := []string{"argocd", "nginx", "gitea"} + for _, n := range bootStrapApps { + repo := v1alpha1.GitRepository{ + ObjectMeta: metav1.ObjectMeta{ + Name: n, + Namespace: globals.GetProjectNamespace(resource.Name), + }, + Spec: v1alpha1.GitRepositorySpec{ + Source: v1alpha1.GitRepositorySource{ + EmbeddedAppName: n, + }, + GitURL: resource.Status.Gitea.ExternalURL, + }, + } + + _, err := controllerutil.CreateOrUpdate(ctx, r.Client, &repo, func() error { + err := controllerutil.SetOwnerReference(resource, &repo, r.Scheme) + if err != nil { + return err + } + return nil + }) + if err != nil { + return ctrl.Result{}, fmt.Errorf("creating %s repo CR", n) + } + + app := &argov1alpha1.Application{ + ObjectMeta: metav1.ObjectMeta{ + Name: n, + Namespace: "argocd", + }, + } + localbuild.SetApplicationSpec( + app, + resource.Status.Gitea.InternalURL, + ".", + defaultArgoCDProjectName, + nil, + ) + _, err = controllerutil.CreateOrUpdate(ctx, r.Client, app, func() error { + err := controllerutil.SetOwnerReference(resource, &repo, r.Scheme) + if err != nil { + return err + } + return nil + }) + if err != nil { + return ctrl.Result{}, fmt.Errorf("creating %s argo app CR", n) + } + } + return ctrl.Result{}, nil +} + func GetEmbeddedRawInstallResources(name string) ([][]byte, error) { switch name { case "argocd": return RawArgocdInstallResources() - case "nginx": - return RawNginxInstallResources() + case "backstage", "crossplane": + return util.ConvertFSToBytes(apps.EmbeddedAppsFS, name) case "gitea": return RawGiteaInstallResources() + case "nginx": + return RawNginxInstallResources() default: return nil, fmt.Errorf("unsupported embedded app name %s", name) } diff --git a/pkg/controllers/localbuild/gitea.go b/pkg/controllers/localbuild/gitea.go index fca54f93..50c74250 100644 --- a/pkg/controllers/localbuild/gitea.go +++ b/pkg/controllers/localbuild/gitea.go @@ -11,9 +11,13 @@ import ( ) const ( - // hardcoded secret name and namespace from what we have in the yaml installation file. + // hardcoded values from what we have in the yaml installation file. giteaNamespace = "gitea" giteaAdminSecret = "gitea-admin-secret" + // this is the URL accessible outside cluster. resolves to localhost + giteaIngressURL = "http://gitea.cnoe.localtest.me:3000" + // this is the URL accessible within cluster for ArgoCD to fetch resources + giteaSvcURL = "http://my-gitea-http.gitea.svc.cluster.local:3000" ) //go:embed resources/gitea/k8s/* @@ -41,9 +45,10 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ if result, err := gitea.Install(ctx, req, resource, r.Client, r.Scheme); err != nil { return result, err } - - resource.Status.GiteaSecretName = giteaAdminSecret - resource.Status.GiteaSecretNamespace = giteaNamespace - resource.Status.GiteaAvailable = true + resource.Status.Gitea.ExternalURL = giteaIngressURL + resource.Status.Gitea.InternalURL = giteaSvcURL + resource.Status.Gitea.AdminUserSecretName = giteaAdminSecret + resource.Status.Gitea.AdminUserSecretNamespace = giteaNamespace + resource.Status.Gitea.Available = true return ctrl.Result{}, nil } diff --git a/pkg/controllers/resources/idpbuilder.cnoe.io_gitrepositories.yaml b/pkg/controllers/resources/idpbuilder.cnoe.io_gitrepositories.yaml index d6c26453..19b2fba7 100644 --- a/pkg/controllers/resources/idpbuilder.cnoe.io_gitrepositories.yaml +++ b/pkg/controllers/resources/idpbuilder.cnoe.io_gitrepositories.yaml @@ -32,14 +32,17 @@ spec: type: object spec: properties: - giteaURL: - description: GitURL is the base URL of GitTea server + gitURL: + description: GitURL is the base URL of Git server + pattern: ^https?:\/\/.+$ type: string source: properties: embeddedAppName: enum: - argocd + - backstage + - crossplane - gitea - nginx type: string @@ -59,7 +62,7 @@ spec: - type type: object required: - - giteaURL + - gitURL type: object status: properties: diff --git a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml index 9ba0dda8..1723d4f8 100644 --- a/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml +++ b/pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml @@ -70,12 +70,19 @@ spec: type: boolean gitServerAvailable: type: boolean - giteaAvailable: - type: boolean - giteaSecret: - type: string - giteaSecretNamespace: - type: string + giteaStatus: + properties: + adminUserSecretNameecret: + type: string + adminUserSecretNamespace: + type: string + available: + type: boolean + externalURL: + type: string + internalURL: + type: string + type: object nginxAvailable: type: boolean observedGeneration: diff --git a/pkg/controllers/run.go b/pkg/controllers/run.go index 6b39223a..13976d56 100644 --- a/pkg/controllers/run.go +++ b/pkg/controllers/run.go @@ -46,7 +46,7 @@ func RunControllers(ctx context.Context, mgr manager.Manager, exitCh chan error, GiteaClientFunc: gitrepository.NewGiteaClient, }).SetupWithManager(mgr, nil) if err != nil { - log.Error(err, "unable to create ") + log.Error(err, "unable to create repo controller") } // Start our manager in another goroutine