From c3f6d4efa01ebbaaf92dc5e0aae8ccb684dde819 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 13 Aug 2024 22:34:46 +0200 Subject: [PATCH 01/30] feat(controller-info): reflect controller-info, update urls via api --- PROJECT | 11 +- Tiltfile | 3 +- api/v1alpha1/garmserverconfig_types.go | 68 ++++++ api/v1alpha1/zz_generated.deepcopy.go | 89 +++++++ cmd/main.go | 16 +- ...r.mercedes-benz.com_garmserverconfigs.yaml | 119 ++++++++++ config/crd/kustomization.yaml | 3 + .../patches/cainjection_in_controllers.yaml | 7 + .../cainjection_in_garmserverconfigs.yaml | 7 + .../crd/patches/webhook_in_controllers.yaml | 16 ++ .../patches/webhook_in_garmserverconfigs.yaml | 16 ++ config/manager/kustomization.yaml | 6 + config/rbac/garmserverconfig_editor_role.yaml | 31 +++ config/rbac/garmserverconfig_viewer_role.yaml | 27 +++ config/rbac/role.yaml | 26 +++ .../garm-operator_v1alpha1_controller.yaml | 12 + ...rm-operator_v1alpha1_garmserverconfig.yaml | 12 + config/samples/kustomization.yaml | 1 + go.mod | 22 +- go.sum | 44 ++-- .../controller/garmserverconfig_controller.go | 221 ++++++++++++++++++ .../garmserverconfig_controller_test.go | 1 + pkg/client/controller.go | 46 ++++ pkg/client/key/key.go | 16 +- pkg/util/util.go | 5 + 25 files changed, 780 insertions(+), 45 deletions(-) create mode 100644 api/v1alpha1/garmserverconfig_types.go create mode 100644 config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml create mode 100644 config/crd/patches/cainjection_in_controllers.yaml create mode 100644 config/crd/patches/cainjection_in_garmserverconfigs.yaml create mode 100644 config/crd/patches/webhook_in_controllers.yaml create mode 100644 config/crd/patches/webhook_in_garmserverconfigs.yaml create mode 100644 config/rbac/garmserverconfig_editor_role.yaml create mode 100644 config/rbac/garmserverconfig_viewer_role.yaml create mode 100644 config/samples/garm-operator_v1alpha1_controller.yaml create mode 100644 config/samples/garm-operator_v1alpha1_garmserverconfig.yaml create mode 100644 internal/controller/garmserverconfig_controller.go create mode 100644 internal/controller/garmserverconfig_controller_test.go create mode 100644 pkg/client/controller.go create mode 100644 pkg/util/util.go diff --git a/PROJECT b/PROJECT index 3608e28c..a6747053 100644 --- a/PROJECT +++ b/PROJECT @@ -1,5 +1,3 @@ -# SPDX-License-Identifier: MIT - # Code generated by tool. DO NOT EDIT. # This file is used to track the info used to scaffold your project # and allow the plugins properly work. @@ -71,4 +69,13 @@ resources: kind: Runner path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: GarmServerConfig + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 version: "3" diff --git a/Tiltfile b/Tiltfile index 937c36bd..f7956104 100644 --- a/Tiltfile +++ b/Tiltfile @@ -18,7 +18,7 @@ deploy_cert_manager( # the manager binary and the dlv debug port will be exposed # # for more details, please read the DEVELOPMENT.md -mode = 'local' +mode = 'debug' # kustomize overlays templated_yaml = kustomize('config/overlays/' + mode) @@ -36,6 +36,7 @@ k8s_resource( 'pools.garm-operator.mercedes-benz.com:customresourcedefinition', 'runners.garm-operator.mercedes-benz.com:customresourcedefinition', 'repositories.garm-operator.mercedes-benz.com:customresourcedefinition', + 'garmserverconfigs.garm-operator.mercedes-benz.com:customresourcedefinition', 'garm-operator-controller-manager:serviceaccount', 'garm-operator-leader-election-role:role', 'garm-operator-manager-role:clusterrole', diff --git a/api/v1alpha1/garmserverconfig_types.go b/api/v1alpha1/garmserverconfig_types.go new file mode 100644 index 00000000..4c0b7109 --- /dev/null +++ b/api/v1alpha1/garmserverconfig_types.go @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GarmServerConfigSpec defines the desired state of GarmServerConfig +type GarmServerConfigSpec struct { + MetadataURL string `json:"metadataURL,omitempty"` + CallbackURL string `json:"callbackURL,omitempty"` + WebhookURL string `json:"webhookURL,omitempty"` +} + +// GarmServerConfigStatus defines the observed state of GarmServerConfig +type GarmServerConfigStatus struct { + ControllerID string `json:"controllerID"` + Hostname string `json:"hostname"` + MetadataURL string `json:"metadataURL"` + CallbackURL string `json:"callbackURL"` + WebhookURL string `json:"webhookURL"` + ControllerWebhookURL string `json:"controllerWebhookURL"` + MinimumJobAgeBackoff uint `json:"minimumJobAgeBackoff"` + Version string `json:"version"` + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=garmserverconfigs,scope=Namespaced,categories=garm,shortName=server +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.controllerID",description="Controller ID" +//+kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description="Garm Version" +//+kubebuilder:printcolumn:name="MetadataURL",type="string",JSONPath=".status.metadataURL",description="MetadataURL",priority=1 +//+kubebuilder:printcolumn:name="CallbackURL",type="string",JSONPath=".status.callbackURL",description="CallbackURL",priority=1 +//+kubebuilder:printcolumn:name="WebhookURL",type="string",JSONPath=".status.webhookURL",description="WebhookURL",priority=1 +//+kubebuilder:printcolumn:name="ControllerWebhookURL",type="string",JSONPath=".status.controllerWebhookURL",description="ControllerWebhookURL",priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GarmServerConfig" + +// GarmServerConfig is the Schema for the garmserverconfigs API +type GarmServerConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GarmServerConfigSpec `json:"spec,omitempty"` + Status GarmServerConfigStatus `json:"status,omitempty"` +} + +func (g *GarmServerConfig) SetConditions(conditions []metav1.Condition) { + g.Status.Conditions = conditions +} + +func (g *GarmServerConfig) GetConditions() []metav1.Condition { + return g.Status.Conditions +} + +//+kubebuilder:object:root=true + +// GarmServerConfigList contains a list of GarmServerConfig +type GarmServerConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GarmServerConfig `json:"items"` +} + +func init() { + SchemeBuilder.Register(&GarmServerConfig{}, &GarmServerConfigList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2aeca9cc..b8f3aba8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -109,6 +109,95 @@ func (in *EnterpriseStatus) DeepCopy() *EnterpriseStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. +func (in *GarmServerConfig) DeepCopy() *GarmServerConfig { + if in == nil { + return nil + } + out := new(GarmServerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GarmServerConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigList) DeepCopyInto(out *GarmServerConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GarmServerConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigList. +func (in *GarmServerConfigList) DeepCopy() *GarmServerConfigList { + if in == nil { + return nil + } + out := new(GarmServerConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigSpec) DeepCopyInto(out *GarmServerConfigSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigSpec. +func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { + if in == nil { + return nil + } + out := new(GarmServerConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. +func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { + if in == nil { + return nil + } + out := new(GarmServerConfigStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Image) DeepCopyInto(out *Image) { *out = *in diff --git a/cmd/main.go b/cmd/main.go index b6fe64a8..231feef8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "log" + "os" "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/runtime" @@ -188,14 +189,14 @@ func run() error { } if config.Config.Operator.RunnerReconciliation { - eventChan := make(chan event.GenericEvent) + runnerEvents := make(chan event.GenericEvent) runnerReconciler := &garmcontroller.RunnerReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), } - // setup controller so it can reconcile if events from eventChan are queued - if err = runnerReconciler.SetupWithManager(mgr, eventChan, + // setup controller so it can reconcile if events from runnerEvents are queued + if err = runnerReconciler.SetupWithManager(mgr, runnerEvents, controller.Options{ MaxConcurrentReconciles: config.Config.Operator.RunnerConcurrency, }, @@ -205,10 +206,17 @@ func run() error { // fetch runner instances periodically and enqueue reconcile events for runner ctrl if external system has changed ctx, cancel := context.WithCancel(ctx) - go runnerReconciler.PollRunnerInstances(ctx, eventChan) + go runnerReconciler.PollRunnerInstances(ctx, runnerEvents) defer cancel() } + if err = (&garmcontroller.GarmServerConfigReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "GarmServerConfig") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml new file mode 100644 index 00000000..60a016d6 --- /dev/null +++ b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml @@ -0,0 +1,119 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: garmserverconfigs.garm-operator.mercedes-benz.com +spec: + group: garm-operator.mercedes-benz.com + names: + categories: + - garm + kind: GarmServerConfig + listKind: GarmServerConfigList + plural: garmserverconfigs + shortNames: + - server + singular: garmserverconfig + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Controller ID + jsonPath: .status.controllerID + name: ID + type: string + - description: Garm Version + jsonPath: .status.version + name: Version + type: string + - description: MetadataURL + jsonPath: .status.metadataURL + name: MetadataURL + priority: 1 + type: string + - description: CallbackURL + jsonPath: .status.callbackURL + name: CallbackURL + priority: 1 + type: string + - description: WebhookURL + jsonPath: .status.webhookURL + name: WebhookURL + priority: 1 + type: string + - description: ControllerWebhookURL + jsonPath: .status.controllerWebhookURL + name: ControllerWebhookURL + priority: 1 + type: string + - description: Time duration since creation of GarmServerConfig + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: GarmServerConfig is the Schema for the garmserverconfigs API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GarmServerConfigSpec defines the desired state of GarmServerConfig + properties: + callbackURL: + type: string + metadataURL: + type: string + webhookURL: + type: string + type: object + status: + description: GarmServerConfigStatus defines the observed state of GarmServerConfig + properties: + callbackURL: + type: string + controllerID: + type: string + controllerWebhookURL: + type: string + hostname: + type: string + metadataURL: + type: string + minimumJobAgeBackoff: + type: integer + version: + type: string + webhookURL: + type: string + required: + - callbackURL + - controllerID + - controllerWebhookURL + - hostname + - metadataURL + - minimumJobAgeBackoff + - version + - webhookURL + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 13048f1a..5c6d48d0 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -8,6 +8,7 @@ resources: - bases/garm-operator.mercedes-benz.com_images.yaml - bases/garm-operator.mercedes-benz.com_repositories.yaml - bases/garm-operator.mercedes-benz.com_runners.yaml +- bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: @@ -18,6 +19,7 @@ patches: - path: patches/webhook_in_organizations.yaml - path: patches/webhook_in_repositories.yaml #- path: patches/webhook_in_runners.yaml +#- path: patches/webhook_in_garmserverconfigs.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -28,6 +30,7 @@ patches: #- path: patches/cainjection_in_images.yaml - path: patches/cainjection_in_repositories.yaml #- path: patches/cainjection_in_runners.yaml +#- path: patches/cainjection_in_garmserverconfigs.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_controllers.yaml b/config/crd/patches/cainjection_in_controllers.yaml new file mode 100644 index 00000000..cb1481fc --- /dev/null +++ b/config/crd/patches/cainjection_in_controllers.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: controllers.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/cainjection_in_garmserverconfigs.yaml b/config/crd/patches/cainjection_in_garmserverconfigs.yaml new file mode 100644 index 00000000..d44d781b --- /dev/null +++ b/config/crd/patches/cainjection_in_garmserverconfigs.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: garmserverconfigs.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/webhook_in_controllers.yaml b/config/crd/patches/webhook_in_controllers.yaml new file mode 100644 index 00000000..66b57a03 --- /dev/null +++ b/config/crd/patches/webhook_in_controllers.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: controllers.garm-operator.mercedes-benz.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/crd/patches/webhook_in_garmserverconfigs.yaml b/config/crd/patches/webhook_in_garmserverconfigs.yaml new file mode 100644 index 00000000..933dd9dd --- /dev/null +++ b/config/crd/patches/webhook_in_garmserverconfigs.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: garmserverconfigs.garm-operator.mercedes-benz.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5c5f0b84..ad13e96b 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,2 +1,8 @@ resources: - manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: controller + newTag: latest diff --git a/config/rbac/garmserverconfig_editor_role.yaml b/config/rbac/garmserverconfig_editor_role.yaml new file mode 100644 index 00000000..80602278 --- /dev/null +++ b/config/rbac/garmserverconfig_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit garmserverconfigs. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: garmserverconfig-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: garmserverconfig-editor-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs/status + verbs: + - get diff --git a/config/rbac/garmserverconfig_viewer_role.yaml b/config/rbac/garmserverconfig_viewer_role.yaml new file mode 100644 index 00000000..5147500f --- /dev/null +++ b/config/rbac/garmserverconfig_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view garmserverconfigs. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: garmserverconfig-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: garmserverconfig-viewer-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs + verbs: + - get + - list + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index c787d4af..b64ee0f1 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -52,6 +52,32 @@ rules: - get - patch - update +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs/finalizers + verbs: + - update +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - garmserverconfigs/status + verbs: + - get + - patch + - update - apiGroups: - garm-operator.mercedes-benz.com resources: diff --git a/config/samples/garm-operator_v1alpha1_controller.yaml b/config/samples/garm-operator_v1alpha1_controller.yaml new file mode 100644 index 00000000..796866e8 --- /dev/null +++ b/config/samples/garm-operator_v1alpha1_controller.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1alpha1 +kind: Controller +metadata: + labels: + app.kubernetes.io/name: controller + app.kubernetes.io/instance: controller-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: controller-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml new file mode 100644 index 00000000..a524e450 --- /dev/null +++ b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1alpha1 +kind: GarmServerConfig +metadata: + labels: + app.kubernetes.io/name: garmserverconfig + app.kubernetes.io/instance: garmserverconfig-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: garmserverconfig-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index a3b8f74a..97037e92 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -6,4 +6,5 @@ resources: - garm-operator_v1alpha1_image.yaml - garm-operator_v1alpha1_repository.yaml - garm-operator_v1alpha1_runner.yaml + - garm-operator_v1alpha1_garmserverconfig.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/go.mod b/go.mod index 63665ec2..555c96b3 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ module github.com/mercedes-benz/garm-operator go 1.22.5 require ( - github.com/cloudbase/garm v0.1.4 - github.com/cloudbase/garm-provider-common v0.1.2 + github.com/cloudbase/garm v0.1.5 + github.com/cloudbase/garm-provider-common v0.1.3 github.com/go-openapi/runtime v0.28.0 github.com/go-playground/validator/v10 v10.22.1 github.com/golang-jwt/jwt/v4 v4.5.0 @@ -32,6 +32,7 @@ require ( require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bradleyfalzon/ghinstallation/v2 v2.10.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect @@ -60,6 +61,7 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v57 v57.0.0 // indirect + github.com/google/go-github/v60 v60.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect @@ -71,7 +73,7 @@ require ( github.com/knadh/koanf/maps v0.1.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/minio/sio v0.3.1 // indirect + github.com/minio/sio v0.4.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -85,17 +87,17 @@ require ( github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect - go.mongodb.org/mongo-driver v1.14.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + go.mongodb.org/mongo-driver v1.15.0 // indirect + go.opentelemetry.io/otel v1.25.0 // indirect + go.opentelemetry.io/otel/metric v1.25.0 // indirect + go.opentelemetry.io/otel/trace v1.25.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.26.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 09a9101f..de7997fa 100644 --- a/go.sum +++ b/go.sum @@ -2,12 +2,14 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradleyfalzon/ghinstallation/v2 v2.10.0 h1:XWuWBRFEpqVrHepQob9yPS3Xg4K3Wr9QCx4fu8HbUNg= +github.com/bradleyfalzon/ghinstallation/v2 v2.10.0/go.mod h1:qoGA4DxWPaYTgVCrmEspVSjlTu4WYAiSxMIhorMRXXc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cloudbase/garm v0.1.4 h1:hknw8d4VPdHWGhnPkcKU2+tj3BjV6+M2mcjMU9z76yw= -github.com/cloudbase/garm v0.1.4/go.mod h1:yalSeTH2GX6bZ5L4I2YaynhBFqYIHW1ZaiaQ/tq0GIE= -github.com/cloudbase/garm-provider-common v0.1.2 h1:EqSpUjw9rzo4PiUmteHkFtZNWCnRi0QXHRKZ+VA1IPo= -github.com/cloudbase/garm-provider-common v0.1.2/go.mod h1:igxJRT3OlykERYc6ssdRQXcb+BCaeSfnucg6I0OSoDc= +github.com/cloudbase/garm v0.1.5 h1:PunOEqBBk0Hwmf8IEUoU2mc5hhF7+G8HaE5qGIHT0ig= +github.com/cloudbase/garm v0.1.5/go.mod h1:gnWVWqefhdOSWdn68GfMnfuNTA+F24TsoLceXe6M3CQ= +github.com/cloudbase/garm-provider-common v0.1.3 h1:8pHSRs2ljwLHgtDrge68dZ7ILUW97VF5h2ZA2fQubGQ= +github.com/cloudbase/garm-provider-common v0.1.3/go.mod h1:VIJzbcg5iwyD4ac99tnnwcActfwibn/VOt2MYOFjf2c= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -78,6 +80,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs= github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw= +github.com/google/go-github/v60 v60.0.0 h1:oLG98PsLauFvvu4D/YPxq374jhSxFYdzQGNCyONLfn8= +github.com/google/go-github/v60 v60.0.0/go.mod h1:ByhX2dP9XT9o/ll2yXAu2VD8l5eNVg8hD4Cr0S/LmQk= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -123,8 +127,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/minio/sio v0.3.1 h1:d59r5RTHb1OsQaSl1EaTWurzMMDRLA5fgNmjzD4eVu4= -github.com/minio/sio v0.3.1/go.mod h1:S0ovgVgc+sTlQyhiXA1ppBLv7REM7TYi5yyq2qL/Y6o= +github.com/minio/sio v0.4.0 h1:u4SWVEm5lXSqU42ZWawV0D9I5AZ5YMmo2RXpEQ/kRhc= +github.com/minio/sio v0.4.0/go.mod h1:oBSjJeGbBdRMZZwna07sX9EFzZy+ywu5aofRiV1g79I= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -171,16 +175,16 @@ github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLq github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= +go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= +go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= +go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= @@ -192,8 +196,8 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -202,8 +206,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -216,8 +220,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go new file mode 100644 index 00000000..18a84809 --- /dev/null +++ b/internal/controller/garmserverconfig_controller.go @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: MIT + +package controller + +import ( + "context" + "reflect" + + garmController "github.com/cloudbase/garm/client/controller" + "github.com/cloudbase/garm/params" + "github.com/mercedes-benz/garm-operator/pkg/annotations" + garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/config" + "github.com/mercedes-benz/garm-operator/pkg/util" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/source" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" +) + +// GarmServerConfigReconciler reconciles a GarmServerConfig object +type GarmServerConfigReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=garmserverconfigs,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=garmserverconfigs/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=garmserverconfigs/finalizers,verbs=update + +func (r *GarmServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + controllerClient := garmClient.NewControllerClient() + return r.reconcile(ctx, req, controllerClient) +} + +func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Request, controllerClient garmClient.ControllerClient) (ctrl.Result, error) { + log := log.FromContext(ctx) + log.Info("Reconciling GarmServerConfig") + + controllerInfo, err := controllerClient.GetControllerInfo() + if err != nil { + log.Error(err, "Failed to get controller info") + return ctrl.Result{}, err + } + + // initially create GarmServerConfig CR reflecting values from garm-server controller info + garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{} + if err := r.Get(ctx, req.NamespacedName, garmServerConfig); err != nil { + return r.handleCreateGarmServerConfigCR(ctx, req, err, &controllerInfo.Payload) + } + + // Ignore objects that are paused + if annotations.IsPaused(garmServerConfig) { + log.Info("Reconciliation is paused for GarmServerConfig: %s", garmServerConfig.Name) + return ctrl.Result{}, nil + } + + // sync applied spec with controller info in garm + newControllerInfo, err := r.updateControllerInfo(ctx, controllerClient, garmServerConfig, &controllerInfo.Payload) + if err != nil { + return ctrl.Result{}, err + } + + // update CR with new state from garm + if err := r.updateGarmServerConfigStatus(ctx, newControllerInfo, garmServerConfig); err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} + +func (r *GarmServerConfigReconciler) handleCreateGarmServerConfigCR(ctx context.Context, req ctrl.Request, fetchErr error, controllerInfo *params.ControllerInfo) (ctrl.Result, error) { + log := log.FromContext(ctx) + if apierrors.IsNotFound(fetchErr) { + log.Info("GarmServerConfig was not found") + if err := r.createGarmServerConfigCR(ctx, controllerInfo, req.Name, req.Namespace); err != nil { + return ctrl.Result{}, err + } + } + + return ctrl.Result{}, nil +} + +func (r *GarmServerConfigReconciler) createGarmServerConfigCR(ctx context.Context, controllerInfo *params.ControllerInfo, name, namespace string) error { + log := log.FromContext(ctx) + log.Info("Creating GarmServerConfig CR") + + garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ + MetadataURL: controllerInfo.MetadataURL, + CallbackURL: controllerInfo.CallbackURL, + WebhookURL: controllerInfo.WebhookURL, + }, + } + + err := r.Create(ctx, garmServerConfig) + if err != nil { + log.Error(err, "Failed to create GarmServerConfig CR") + return err + } + return nil +} + +func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmClient.ControllerClient, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { + log := log.FromContext(ctx) + + if garmServerConfigCR.Spec.MetadataURL == controllerInfo.MetadataURL && + garmServerConfigCR.Spec.CallbackURL == controllerInfo.CallbackURL && + garmServerConfigCR.Spec.WebhookURL == controllerInfo.WebhookURL { + log.Info("Controller info is up to date") + return controllerInfo, nil + } + + params := garmController.NewUpdateControllerParams().WithBody(params.UpdateControllerParams{ + MetadataURL: util.StringPtr(garmServerConfigCR.Spec.MetadataURL), + CallbackURL: util.StringPtr(garmServerConfigCR.Spec.CallbackURL), + WebhookURL: util.StringPtr(garmServerConfigCR.Spec.WebhookURL), + }) + + log.Info("Updating controller info in garm") + response, err := client.UpdateController(params) + if err != nil { + log.Error(err, "Failed to update controller info") + return nil, err + } + return &response.Payload, nil +} + +func (r *GarmServerConfigReconciler) updateGarmServerConfigStatus(ctx context.Context, controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig) error { + log := log.FromContext(ctx) + + if !r.needsStatusUpdate(controllerInfo, garmServerConfigCR) { + log.Info("GarmServerConfig CR up to date") + return nil + } + + log.Info("Updating GarmServerConfig CR") + garmServerConfigStatus := garmoperatorv1alpha1.GarmServerConfigStatus{ + ControllerID: controllerInfo.ControllerID.String(), + Hostname: controllerInfo.Hostname, + MetadataURL: controllerInfo.MetadataURL, + CallbackURL: controllerInfo.CallbackURL, + WebhookURL: controllerInfo.WebhookURL, + ControllerWebhookURL: controllerInfo.ControllerWebhookURL, + MinimumJobAgeBackoff: controllerInfo.MinimumJobAgeBackoff, + Version: controllerInfo.Version, + } + + garmServerConfigCR.Status = garmServerConfigStatus + err := r.Status().Update(ctx, garmServerConfigCR) + if err != nil { + log.Error(err, "Failed to update GarmServerConfig CR") + return err + } + return nil +} + +func (r *GarmServerConfigReconciler) needsStatusUpdate(controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig) bool { + tempStatus := garmoperatorv1alpha1.GarmServerConfigStatus{ + ControllerID: controllerInfo.ControllerID.String(), + Hostname: controllerInfo.Hostname, + MetadataURL: controllerInfo.MetadataURL, + CallbackURL: controllerInfo.CallbackURL, + WebhookURL: controllerInfo.WebhookURL, + ControllerWebhookURL: controllerInfo.ControllerWebhookURL, + MinimumJobAgeBackoff: controllerInfo.MinimumJobAgeBackoff, + Version: controllerInfo.Version, + } + + return !reflect.DeepEqual(garmServerConfigCR.Status, tempStatus) +} + +func (r *GarmServerConfigReconciler) ensureFinalizer(ctx context.Context, garmServerConfig *garmoperatorv1alpha1.GarmServerConfig) error { + if !controllerutil.ContainsFinalizer(garmServerConfig, key.RunnerFinalizerName) { + controllerutil.AddFinalizer(garmServerConfig, key.RunnerFinalizerName) + return r.Update(ctx, garmServerConfig) + } + return nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *GarmServerConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { + c, err := ctrl.NewControllerManagedBy(mgr). + For(&garmoperatorv1alpha1.GarmServerConfig{}). + WithOptions(controller.Options{}). + Build(r) + if err != nil { + return err + } + + eventChan := make(chan event.GenericEvent) + go func() { + eventChan <- event.GenericEvent{ + Object: &garmoperatorv1alpha1.GarmServerConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "garm-server-config", + Namespace: config.Config.Operator.WatchNamespace, + }, + }, + } + close(eventChan) + }() + + return c.Watch(&source.Channel{Source: eventChan}, &handler.EnqueueRequestForObject{}) +} diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go new file mode 100644 index 00000000..b0b429f8 --- /dev/null +++ b/internal/controller/garmserverconfig_controller_test.go @@ -0,0 +1 @@ +package controller diff --git a/pkg/client/controller.go b/pkg/client/controller.go new file mode 100644 index 00000000..6dbc659d --- /dev/null +++ b/pkg/client/controller.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/cloudbase/garm/client/controller" + "github.com/mercedes-benz/garm-operator/pkg/metrics" +) +import "github.com/cloudbase/garm/client/controller_info" + +type ControllerClient interface { + GetControllerInfo() (*controller_info.ControllerInfoOK, error) + UpdateController(params *controller.UpdateControllerParams) (*controller.UpdateControllerOK, error) +} + +type controllerClient struct { + GarmClient +} + +func NewControllerClient() ControllerClient { + return &controllerClient{ + Client, + } +} + +func (s controllerClient) GetControllerInfo() (*controller_info.ControllerInfoOK, error) { + return EnsureAuth(func() (*controller_info.ControllerInfoOK, error) { + metrics.TotalGarmCalls.WithLabelValues("controller.Info").Inc() + controllerInfo, err := s.GarmAPI().ControllerInfo.ControllerInfo(&controller_info.ControllerInfoParams{}, s.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("controller.Info").Inc() + return nil, err + } + return controllerInfo, nil + }) +} + +func (s controllerClient) UpdateController(param *controller.UpdateControllerParams) (*controller.UpdateControllerOK, error) { + return EnsureAuth(func() (*controller.UpdateControllerOK, error) { + metrics.TotalGarmCalls.WithLabelValues("controller.Update").Inc() + enterprise, err := s.GarmAPI().Controller.UpdateController(param, s.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("controller.Update").Inc() + return nil, err + } + return enterprise, nil + }) +} diff --git a/pkg/client/key/key.go b/pkg/client/key/key.go index b6358d36..ebb62591 100644 --- a/pkg/client/key/key.go +++ b/pkg/client/key/key.go @@ -3,12 +3,12 @@ package key const ( - groupName = "garm-operator.mercedes-benz.com" - EnterpriseFinalizerName = groupName + "/enterprise" - OrganizationFinalizerName = groupName + "/organization" - RepositoryFinalizerName = groupName + "/repository" - PoolFinalizerName = groupName + "/pool" - RunnerFinalizerName = groupName + "/runner" - PausedAnnotation = groupName + "/paused" - LastSyncTimeAnnotation = groupName + "/last-sync-time" + groupName = "garm-operator.mercedes-benz.com" + EnterpriseFinalizerName = groupName + "/enterprise" + OrganizationFinalizerName = groupName + "/organization" + RepositoryFinalizerName = groupName + "/repository" + PoolFinalizerName = groupName + "/pool" + RunnerFinalizerName = groupName + "/runner" + GarmServerConfigFinalizerName = groupName + "/garm-server-config" + PausedAnnotation = groupName + "/paused" ) diff --git a/pkg/util/util.go b/pkg/util/util.go new file mode 100644 index 00000000..a7000633 --- /dev/null +++ b/pkg/util/util.go @@ -0,0 +1,5 @@ +package util + +func StringPtr(s string) *string { + return &s +} From d2b95d067499c4e56a28b028664a939729903036 Mon Sep 17 00:00:00 2001 From: rthalho Date: Wed, 14 Aug 2024 10:13:27 +0200 Subject: [PATCH 02/30] feat(endpoint): implement endpoint api --- PROJECT | 9 + api/v1alpha1/endpoint_types.go | 59 +++++ api/v1alpha1/zz_generated.deepcopy.go | 110 +++++++- cmd/main.go | 9 + ...-operator.mercedes-benz.com_endpoints.yaml | 151 +++++++++++ ...r.mercedes-benz.com_garmserverconfigs.yaml | 69 +++++ config/crd/kustomization.yaml | 3 + .../crd/patches/cainjection_in_endpoints.yaml | 7 + config/crd/patches/webhook_in_endpoints.yaml | 16 ++ config/rbac/endpoint_editor_role.yaml | 31 +++ config/rbac/endpoint_viewer_role.yaml | 27 ++ config/rbac/role.yaml | 26 ++ .../garm-operator_v1alpha1_endpoint.yaml | 16 ++ ...rm-operator_v1alpha1_garmserverconfig.yaml | 4 +- config/samples/kustomization.yaml | 1 + internal/controller/endpoint_controller.go | 237 ++++++++++++++++++ internal/controller/enterprise_controller.go | 8 +- .../controller/garmserverconfig_controller.go | 4 +- internal/controller/suite_test.go | 66 +++++ pkg/client/client.go | 8 + pkg/client/controller.go | 4 +- pkg/client/endpoint.go | 84 +++++++ pkg/client/key/key.go | 16 +- pkg/conditions/condition_types.go | 1 + 24 files changed, 949 insertions(+), 17 deletions(-) create mode 100644 api/v1alpha1/endpoint_types.go create mode 100644 config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml create mode 100644 config/crd/patches/cainjection_in_endpoints.yaml create mode 100644 config/crd/patches/webhook_in_endpoints.yaml create mode 100644 config/rbac/endpoint_editor_role.yaml create mode 100644 config/rbac/endpoint_viewer_role.yaml create mode 100644 config/samples/garm-operator_v1alpha1_endpoint.yaml create mode 100644 internal/controller/endpoint_controller.go create mode 100644 internal/controller/suite_test.go create mode 100644 pkg/client/endpoint.go diff --git a/PROJECT b/PROJECT index a6747053..299ee194 100644 --- a/PROJECT +++ b/PROJECT @@ -78,4 +78,13 @@ resources: kind: GarmServerConfig path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Endpoint + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 version: "3" diff --git a/api/v1alpha1/endpoint_types.go b/api/v1alpha1/endpoint_types.go new file mode 100644 index 00000000..a9c34f4c --- /dev/null +++ b/api/v1alpha1/endpoint_types.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EndpointSpec defines the desired state of Endpoint +type EndpointSpec struct { + Description string `json:"description,omitempty"` + APIBaseURL string `json:"apiBaseURL,omitempty"` + UploadBaseURL string `json:"uploadBaseURL,omitempty"` + BaseURL string `json:"baseURL,omitempty"` + CACertBundle []byte `json:"caCertBundle,omitempty"` +} + +// EndpointStatus defines the observed state of Endpoint +type EndpointStatus struct { + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=endpoints,scope=Namespaced,categories=garm,shortName=gep +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".spec.apiBaseURL",description="API Base URL" +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Endpoint" + +// Endpoint is the Schema for the endpoints API +type Endpoint struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec EndpointSpec `json:"spec,omitempty"` + Status EndpointStatus `json:"status,omitempty"` +} + +func (e *Endpoint) SetConditions(conditions []metav1.Condition) { + e.Status.Conditions = conditions +} + +func (e *Endpoint) GetConditions() []metav1.Condition { + return e.Status.Conditions +} + +//+kubebuilder:object:root=true + +// EndpointList contains a list of Endpoint +type EndpointList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Endpoint `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Endpoint{}, &EndpointList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index b8f3aba8..d667f4fd 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -12,6 +12,107 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Endpoint) DeepCopyInto(out *Endpoint) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. +func (in *Endpoint) DeepCopy() *Endpoint { + if in == nil { + return nil + } + out := new(Endpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Endpoint) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndpointList) DeepCopyInto(out *EndpointList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Endpoint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointList. +func (in *EndpointList) DeepCopy() *EndpointList { + if in == nil { + return nil + } + out := new(EndpointList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EndpointList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndpointSpec) DeepCopyInto(out *EndpointSpec) { + *out = *in + if in.CACertBundle != nil { + in, out := &in.CACertBundle, &out.CACertBundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointSpec. +func (in *EndpointSpec) DeepCopy() *EndpointSpec { + if in == nil { + return nil + } + out := new(EndpointSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointStatus. +func (in *EndpointStatus) DeepCopy() *EndpointStatus { + if in == nil { + return nil + } + out := new(EndpointStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Enterprise) DeepCopyInto(out *Enterprise) { *out = *in @@ -115,7 +216,7 @@ func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. @@ -186,6 +287,13 @@ func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. diff --git a/cmd/main.go b/cmd/main.go index 231feef8..d70f2ae2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -217,6 +217,15 @@ func run() error { setupLog.Error(err, "unable to create controller", "controller", "GarmServerConfig") os.Exit(1) } + + if err = (&garmcontroller.EndpointReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("organization-controller"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Endpoint") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml new file mode 100644 index 00000000..b08abb02 --- /dev/null +++ b/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml @@ -0,0 +1,151 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: endpoints.garm-operator.mercedes-benz.com +spec: + group: garm-operator.mercedes-benz.com + names: + categories: + - garm + kind: Endpoint + listKind: EndpointList + plural: endpoints + shortNames: + - gep + singular: endpoint + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: API Base URL + jsonPath: .spec.apiBaseURL + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - description: Time duration since creation of Endpoint + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Endpoint is the Schema for the endpoints API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: EndpointSpec defines the desired state of Endpoint + properties: + apiBaseURL: + type: string + baseURL: + type: string + caCertBundle: + format: byte + type: string + description: + type: string + uploadBaseURL: + type: string + type: object + status: + description: EndpointStatus defines the observed state of Endpoint + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml index 60a016d6..bd6aeaf9 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml @@ -88,6 +88,75 @@ spec: properties: callbackURL: type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array controllerID: type: string controllerWebhookURL: diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 5c6d48d0..df430852 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -9,6 +9,7 @@ resources: - bases/garm-operator.mercedes-benz.com_repositories.yaml - bases/garm-operator.mercedes-benz.com_runners.yaml - bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml +- bases/garm-operator.mercedes-benz.com_endpoints.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: @@ -20,6 +21,7 @@ patches: - path: patches/webhook_in_repositories.yaml #- path: patches/webhook_in_runners.yaml #- path: patches/webhook_in_garmserverconfigs.yaml +#- path: patches/webhook_in_endpoints.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -31,6 +33,7 @@ patches: - path: patches/cainjection_in_repositories.yaml #- path: patches/cainjection_in_runners.yaml #- path: patches/cainjection_in_garmserverconfigs.yaml +#- path: patches/cainjection_in_endpoints.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_endpoints.yaml b/config/crd/patches/cainjection_in_endpoints.yaml new file mode 100644 index 00000000..80f233b2 --- /dev/null +++ b/config/crd/patches/cainjection_in_endpoints.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: endpoints.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/webhook_in_endpoints.yaml b/config/crd/patches/webhook_in_endpoints.yaml new file mode 100644 index 00000000..c99460e4 --- /dev/null +++ b/config/crd/patches/webhook_in_endpoints.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: endpoints.garm-operator.mercedes-benz.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/endpoint_editor_role.yaml b/config/rbac/endpoint_editor_role.yaml new file mode 100644 index 00000000..106ffce4 --- /dev/null +++ b/config/rbac/endpoint_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit endpoints. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: endpoint-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: endpoint-editor-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints/status + verbs: + - get diff --git a/config/rbac/endpoint_viewer_role.yaml b/config/rbac/endpoint_viewer_role.yaml new file mode 100644 index 00000000..d0dfab51 --- /dev/null +++ b/config/rbac/endpoint_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view endpoints. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: endpoint-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: endpoint-viewer-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints + verbs: + - get + - list + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index b64ee0f1..d6254d3d 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -26,6 +26,32 @@ rules: - get - list - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints/finalizers + verbs: + - update +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - endpoints/status + verbs: + - get + - patch + - update - apiGroups: - garm-operator.mercedes-benz.com resources: diff --git a/config/samples/garm-operator_v1alpha1_endpoint.yaml b/config/samples/garm-operator_v1alpha1_endpoint.yaml new file mode 100644 index 00000000..63178345 --- /dev/null +++ b/config/samples/garm-operator_v1alpha1_endpoint.yaml @@ -0,0 +1,16 @@ +apiVersion: garm-operator.mercedes-benz.com/v1alpha1 +kind: Endpoint +metadata: + labels: + app.kubernetes.io/name: endpoint + app.kubernetes.io/instance: endpoint-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: github-enterprise +spec: + description: "GitHub Enterprise endpoint" + apiBaseURL: "https://github.enterprise.com" + uploadBaseURL: "https://github.enterprise.com" + baseURL: "https://github.enterprise.com" + caCertBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFb3pDQ0JFbWdBd0lCQWdJUVRpajNoclpzR2p1VUxOTEVEcmRDcFRBS0JnZ3Foa2pPUFFRREFqQ0JqekVMDQpNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdURWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFDQpCeE1IVTJGc1ptOXlaREVZTUJZR0ExVUVDaE1QVTJWamRHbG5ieUJNYVcxcGRHVmtNVGN3TlFZRFZRUURFeTVUDQpaV04wYVdkdklFVkRReUJFYjIxaGFXNGdWbUZzYVdSaGRHbHZiaUJUWldOMWNtVWdVMlZ5ZG1WeUlFTkJNQjRYDQpEVEkwTURNd056QXdNREF3TUZvWERUSTFNRE13TnpJek5UazFPVm93RlRFVE1CRUdBMVVFQXhNS1oybDBhSFZpDQpMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkFSTy9IbzlYZGtZMXFoOW1BZ2pPVWtXDQptWFRiMDVqZ1J1bEtjaU1WQnVLQjNaSGV4dkNkeW9pQ1JIRU1CZkZYb1poV2tRVk1vZ05Mby9sVzIxNVgzcEdqDQpnZ0wrTUlJQytqQWZCZ05WSFNNRUdEQVdnQlQyaFFvN0VZYmhCSDBPcWdzczB1N01aSHQ3cmpBZEJnTlZIUTRFDQpGZ1FVTzJnL05EcjFSelRLNzZaT1BacTlYbTU2eko4d0RnWURWUjBQQVFIL0JBUURBZ2VBTUF3R0ExVWRFd0VCDQovd1FDTUFBd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNRWtHQTFVZElBUkNNRUF3DQpOQVlMS3dZQkJBR3lNUUVDQWdjd0pUQWpCZ2dyQmdFRkJRY0NBUllYYUhSMGNITTZMeTl6WldOMGFXZHZMbU52DQpiUzlEVUZNd0NBWUdaNEVNQVFJQk1JR0VCZ2dyQmdFRkJRY0JBUVI0TUhZd1R3WUlLd1lCQlFVSE1BS0dRMmgwDQpkSEE2THk5amNuUXVjMlZqZEdsbmJ5NWpiMjB2VTJWamRHbG5iMFZEUTBSdmJXRnBibFpoYkdsa1lYUnBiMjVUDQpaV04xY21WVFpYSjJaWEpEUVM1amNuUXdJd1lJS3dZQkJRVUhNQUdHRjJoMGRIQTZMeTl2WTNOd0xuTmxZM1JwDQpaMjh1WTI5dE1JSUJnQVlLS3dZQkJBSFdlUUlFQWdTQ0FYQUVnZ0ZzQVdvQWR3RFBFVmJ1MVM1OHIvT0hXOWxwDQpMcHZwR25GblNyQVg3S3dCMGx0M3pzdzdDQUFBQVk0V092QVpBQUFFQXdCSU1FWUNJUUQ3b056LzJvTzhWR2FXDQpXcnFyc0JRQnpRSDBoUmhNTG0xMW9lTXBnMWZOYXdJaEFLV2MwcTdaK214RFZZVi82b3Y3Zi9pMEgvYUFjSFNDDQpJaS9RSmNFQ3JhT3BBSFlBb3VNSzVFWHZ2YTJiZmpqdFIyZDNVOWVDVzRTVTF5dGVHeXpFdVZDa1IrY0FBQUdPDQpGanJ2K0FBQUJBTUFSekJGQWlFQXl1cEVJVkFNazBjOEJWVnBGMFFiaXNmb0V3eTV4SlFLUU9lOEV2TVU0VzhDDQpJR0FJSXV6anhCRmxIcGtxY3NhN1VaeTI0eS9CNnhabmt0VXcvTmU1cTVoQ0FIY0FUbldqSjF5YUVNTTRXMnpVDQozejlTNngzdzRJNGJqV25Bc2Zwa3NXS2FPZDhBQUFHT0ZqcnY5d0FBQkFNQVNEQkdBaUVBKzhPdlF6cGdSZjMxDQp1TEJzQ0U4a3RDVWZ2c2lSVDd6V1NxZVhsaUEwOVRVQ0lRRGNCN1huOTdhRURNQktYSWJkbTVLWjlHanZSeW9GDQo5c2tENS80R25lb01XekFsQmdOVkhSRUVIakFjZ2dwbmFYUm9kV0l1WTI5dGdnNTNkM2N1WjJsMGFIVmlMbU52DQpiVEFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBcnUyTWNQcjBlTndjV051REVZMGEvckd6WFJmUnJtKzZYZlplDQpTemhZWmV3Q0lCcTRUVUVCQ2dhcHY3eHZBdFJLZFZkaS9iNG0zNlV5ZWoxZ2d5SnNpZXNBDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo= diff --git a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml index a524e450..e0b5b66f 100644 --- a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml +++ b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml @@ -9,4 +9,6 @@ metadata: app.kubernetes.io/created-by: garm-operator name: garmserverconfig-sample spec: - # TODO(user): Add fields here + callbackURL: http://garm-server.garm-server.svc:9997/api/v1/callback + metadataURL: http://garm-server.garm-server.svc:9997/api/v1/metadata + webhookURL: http://garm-server.garm-server.svc:9997/api/v1/webhook diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 97037e92..b6c85191 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -7,4 +7,5 @@ resources: - garm-operator_v1alpha1_repository.yaml - garm-operator_v1alpha1_runner.yaml - garm-operator_v1alpha1_garmserverconfig.yaml +- garm-operator_v1alpha1_endpoint.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/internal/controller/endpoint_controller.go b/internal/controller/endpoint_controller.go new file mode 100644 index 00000000..33501873 --- /dev/null +++ b/internal/controller/endpoint_controller.go @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MIT + +package controller + +import ( + "context" + "fmt" + "github.com/cloudbase/garm/client/endpoints" + "github.com/cloudbase/garm/params" + garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/event" + "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/tools/record" + "reflect" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" +) + +// EndpointReconciler reconciles a Endpoint object +type EndpointReconciler struct { + client.Client + Scheme *runtime.Scheme + Recorder record.EventRecorder +} + +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints/finalizers,verbs=update +// +kubebuilder:rbac:groups="",namespace=xxxxx,resources=secrets,verbs=get;list;watch; + +func (r *EndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := log.FromContext(ctx) + + endpoint := &garmoperatorv1alpha1.Endpoint{} + if err := r.Get(ctx, req.NamespacedName, endpoint); err != nil { + if apierrors.IsNotFound(err) { + log.Info("Endpoint resource not found.") + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + + // Ignore objects that are paused + if annotations.IsPaused(endpoint) { + log.Info("Reconciliation is paused for this object") + return ctrl.Result{}, nil + } + + endpointClient := garmClient.NewEndpointClient() + + // Handle deleted endpoints + if !endpoint.DeletionTimestamp.IsZero() { + return r.reconcileDelete(ctx, endpointClient, endpoint) + } + + return r.reconcileNormal(ctx, endpointClient, endpoint) +} + +func (r *EndpointReconciler) reconcileNormal(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (ctrl.Result, error) { + log := log.FromContext(ctx) + log.WithValues("endpoint", endpoint.Name) + + // If the Endpoint doesn't have our finalizer, add it. + if err := r.ensureFinalizer(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + + // get endpoint in garm db with resource name + garmEndpoint, err := r.getExistingEndpoint(client, endpoint.Name) + if err != nil { + event.Error(r.Recorder, endpoint, err.Error()) + conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + // if not found, create endpoint in garm db + if reflect.ValueOf(garmEndpoint).IsZero() { + garmEndpoint, err = r.createEndpoint(ctx, client, endpoint) + if err != nil { + event.Error(r.Recorder, endpoint, err.Error()) + conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + } + + // update endpoint cr anytime the endpoint in garm db changes + garmEndpoint, err = r.updateEndpoint(ctx, client, endpoint) + if err != nil { + event.Error(r.Recorder, endpoint, err.Error()) + conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + // set and update endpoint status + conditions.MarkTrue(endpoint, conditions.ReadyCondition, conditions.SuccessfulReconcileReason, "") + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + + log.Info("reconciling endpoint successfully done") + return ctrl.Result{}, nil +} + +func (r *EndpointReconciler) getExistingEndpoint(client garmClient.EndpointClient, name string) (params.GithubEndpoint, error) { + endpoint, err := client.GetEndpoint(endpoints.NewGetGithubEndpointParams().WithName(name)) + if err != nil && garmClient.IsNotFoundError(err) { + return params.GithubEndpoint{}, nil + } + + if err != nil { + return params.GithubEndpoint{}, err + } + + return endpoint.Payload, nil +} + +func (r *EndpointReconciler) createEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (params.GithubEndpoint, error) { + log := log.FromContext(ctx) + log.WithValues("endpoint", endpoint.Name) + + log.Info("Endpoint doesn't exist on garm side. Creating new endpoint in garm.") + event.Creating(r.Recorder, endpoint, "endpoint doesn't exist on garm side") + + retValue, err := client.CreateEndpoint(endpoints.NewCreateGithubEndpointParams().WithBody(params.CreateGithubEndpointParams{ + Name: endpoint.Name, + Description: endpoint.Spec.Description, + APIBaseURL: endpoint.Spec.APIBaseURL, + UploadBaseURL: endpoint.Spec.UploadBaseURL, + BaseURL: endpoint.Spec.BaseURL, + CACertBundle: endpoint.Spec.CACertBundle, + })) + if err != nil { + log.V(1).Info(fmt.Sprintf("client.CreateEndpoint error: %s", err)) + return params.GithubEndpoint{}, err + } + + log.V(1).Info(fmt.Sprintf("endpoint %s created - return Value %v", endpoint.Name, retValue)) + + log.Info("creating endpoint in garm succeeded") + event.Info(r.Recorder, endpoint, "creating endpoint in garm succeeded") + + return retValue.Payload, nil +} + +func (r *EndpointReconciler) updateEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (params.GithubEndpoint, error) { + log := log.FromContext(ctx) + log.V(1).Info("update endpoint") + + retValue, err := client.UpdateEndpoint( + endpoints.NewUpdateGithubEndpointParams(). + WithName(endpoint.Name). + WithBody(params.UpdateGithubEndpointParams{ + Description: util.StringPtr(endpoint.Spec.Description), + APIBaseURL: util.StringPtr(endpoint.Spec.APIBaseURL), + UploadBaseURL: util.StringPtr(endpoint.Spec.UploadBaseURL), + BaseURL: util.StringPtr(endpoint.Spec.BaseURL), + CACertBundle: endpoint.Spec.CACertBundle, + })) + if err != nil { + log.V(1).Info(fmt.Sprintf("client.UpdateEndpoint error: %s", err)) + return params.GithubEndpoint{}, err + } + + return retValue.Payload, nil +} + +func (r *EndpointReconciler) reconcileDelete(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (ctrl.Result, error) { + log := log.FromContext(ctx) + log.WithValues("endpoint", endpoint.Name) + + log.Info("starting endpoint deletion") + event.Deleting(r.Recorder, endpoint, "starting endpoint deletion") + conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.DeletingReason, conditions.DeletingEndpointMsg) + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + + err := client.DeleteEndpoint( + endpoints.NewDeleteGithubEndpointParams(). + WithName(endpoint.Name), + ) + if err != nil { + log.V(1).Info(fmt.Sprintf("client.DeleteEndpoint error: %s", err)) + event.Error(r.Recorder, endpoint, err.Error()) + conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + if controllerutil.ContainsFinalizer(endpoint, key.EndpointFinalizerName) { + controllerutil.RemoveFinalizer(endpoint, key.EndpointFinalizerName) + if err := r.Update(ctx, endpoint); err != nil { + return ctrl.Result{}, err + } + } + + log.Info("endpoint deletion done") + + return ctrl.Result{}, nil +} + +func (r *EndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1alpha1.Endpoint) error { + if !controllerutil.ContainsFinalizer(endpoint, key.EndpointFinalizerName) { + controllerutil.AddFinalizer(endpoint, key.EndpointFinalizerName) + return r.Update(ctx, endpoint) + } + return nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *EndpointReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&garmoperatorv1alpha1.Endpoint{}). + Complete(r) +} diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index 6aaac0aa..85058145 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -250,10 +250,10 @@ func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1alpha1.Enterprise) error { - if !controllerutil.ContainsFinalizer(pool, key.EnterpriseFinalizerName) { - controllerutil.AddFinalizer(pool, key.EnterpriseFinalizerName) - return r.Update(ctx, pool) +func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise *garmoperatorv1alpha1.Enterprise) error { + if !controllerutil.ContainsFinalizer(enterprise, key.EnterpriseFinalizerName) { + controllerutil.AddFinalizer(enterprise, key.EnterpriseFinalizerName) + return r.Update(ctx, enterprise) } return nil } diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go index 18a84809..719a4a61 100644 --- a/internal/controller/garmserverconfig_controller.go +++ b/internal/controller/garmserverconfig_controller.go @@ -15,6 +15,7 @@ import ( "github.com/mercedes-benz/garm-operator/pkg/util" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" @@ -32,7 +33,8 @@ import ( // GarmServerConfigReconciler reconciles a GarmServerConfig object type GarmServerConfigReconciler struct { client.Client - Scheme *runtime.Scheme + Scheme *runtime.Scheme + Recorder record.EventRecorder } //+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go new file mode 100644 index 00000000..84948041 --- /dev/null +++ b/internal/controller/suite_test.go @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT + +package controller + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestControllers(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = garmoperatorv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/pkg/client/client.go b/pkg/client/client.go index 46eb2837..292beb55 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -192,6 +192,14 @@ func IsUnauthenticatedError(err interface{}) bool { return apiErr.IsCode(401) } +func IsNotFoundError(err interface{}) bool { + apiErr, ok := err.(runtime.ClientResponseStatus) + if !ok { + return false + } + return apiErr.IsCode(404) +} + type Func[T interface{}] func() (T, error) func EnsureAuth[T interface{}](f Func[T]) (T, error) { diff --git a/pkg/client/controller.go b/pkg/client/controller.go index 6dbc659d..9d9e3a5d 100644 --- a/pkg/client/controller.go +++ b/pkg/client/controller.go @@ -21,7 +21,7 @@ func NewControllerClient() ControllerClient { } } -func (s controllerClient) GetControllerInfo() (*controller_info.ControllerInfoOK, error) { +func (s *controllerClient) GetControllerInfo() (*controller_info.ControllerInfoOK, error) { return EnsureAuth(func() (*controller_info.ControllerInfoOK, error) { metrics.TotalGarmCalls.WithLabelValues("controller.Info").Inc() controllerInfo, err := s.GarmAPI().ControllerInfo.ControllerInfo(&controller_info.ControllerInfoParams{}, s.Token()) @@ -33,7 +33,7 @@ func (s controllerClient) GetControllerInfo() (*controller_info.ControllerInfoOK }) } -func (s controllerClient) UpdateController(param *controller.UpdateControllerParams) (*controller.UpdateControllerOK, error) { +func (s *controllerClient) UpdateController(param *controller.UpdateControllerParams) (*controller.UpdateControllerOK, error) { return EnsureAuth(func() (*controller.UpdateControllerOK, error) { metrics.TotalGarmCalls.WithLabelValues("controller.Update").Inc() enterprise, err := s.GarmAPI().Controller.UpdateController(param, s.Token()) diff --git a/pkg/client/endpoint.go b/pkg/client/endpoint.go new file mode 100644 index 00000000..fd276096 --- /dev/null +++ b/pkg/client/endpoint.go @@ -0,0 +1,84 @@ +package client + +import ( + "github.com/cloudbase/garm/client/endpoints" + "github.com/mercedes-benz/garm-operator/pkg/metrics" +) + +type EndpointClient interface { + GetEndpoint(params *endpoints.GetGithubEndpointParams) (*endpoints.GetGithubEndpointOK, error) + ListEndpoints(params *endpoints.ListGithubEndpointsParams) (*endpoints.ListGithubEndpointsOK, error) + CreateEndpoint(params *endpoints.CreateGithubEndpointParams) (*endpoints.CreateGithubEndpointOK, error) + UpdateEndpoint(params *endpoints.UpdateGithubEndpointParams) (*endpoints.UpdateGithubEndpointOK, error) + DeleteEndpoint(params *endpoints.DeleteGithubEndpointParams) error +} + +type endpointClient struct { + GarmClient +} + +func (e *endpointClient) GetEndpoint(params *endpoints.GetGithubEndpointParams) (*endpoints.GetGithubEndpointOK, error) { + return EnsureAuth(func() (*endpoints.GetGithubEndpointOK, error) { + metrics.TotalGarmCalls.WithLabelValues("endpoints.Get").Inc() + endpoint, err := e.GarmAPI().Endpoints.GetGithubEndpoint(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("endpoints.Get").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *endpointClient) ListEndpoints(params *endpoints.ListGithubEndpointsParams) (*endpoints.ListGithubEndpointsOK, error) { + return EnsureAuth(func() (*endpoints.ListGithubEndpointsOK, error) { + metrics.TotalGarmCalls.WithLabelValues("endpoints.List").Inc() + endpoints, err := e.GarmAPI().Endpoints.ListGithubEndpoints(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("endpoints.List").Inc() + return nil, err + } + return endpoints, nil + }) +} + +func (e *endpointClient) CreateEndpoint(params *endpoints.CreateGithubEndpointParams) (*endpoints.CreateGithubEndpointOK, error) { + return EnsureAuth(func() (*endpoints.CreateGithubEndpointOK, error) { + metrics.TotalGarmCalls.WithLabelValues("endpoints.Create").Inc() + endpoint, err := e.GarmAPI().Endpoints.CreateGithubEndpoint(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("endpoints.Create").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *endpointClient) UpdateEndpoint(params *endpoints.UpdateGithubEndpointParams) (*endpoints.UpdateGithubEndpointOK, error) { + return EnsureAuth(func() (*endpoints.UpdateGithubEndpointOK, error) { + metrics.TotalGarmCalls.WithLabelValues("endpoints.Update").Inc() + endpoint, err := e.GarmAPI().Endpoints.UpdateGithubEndpoint(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("endpoints.Update").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *endpointClient) DeleteEndpoint(params *endpoints.DeleteGithubEndpointParams) error { + _, err := EnsureAuth(func() (interface{}, error) { + metrics.TotalGarmCalls.WithLabelValues("endpoints.Delete").Inc() + if err := e.GarmAPI().Endpoints.DeleteGithubEndpoint(params, e.Token()); err != nil { + metrics.GarmCallErrors.WithLabelValues("endpoints.Delete").Inc() + return nil, err + } + return nil, nil + }) + return err +} + +func NewEndpointClient() EndpointClient { + return &endpointClient{ + Client, + } +} diff --git a/pkg/client/key/key.go b/pkg/client/key/key.go index ebb62591..ae02d78b 100644 --- a/pkg/client/key/key.go +++ b/pkg/client/key/key.go @@ -3,12 +3,12 @@ package key const ( - groupName = "garm-operator.mercedes-benz.com" - EnterpriseFinalizerName = groupName + "/enterprise" - OrganizationFinalizerName = groupName + "/organization" - RepositoryFinalizerName = groupName + "/repository" - PoolFinalizerName = groupName + "/pool" - RunnerFinalizerName = groupName + "/runner" - GarmServerConfigFinalizerName = groupName + "/garm-server-config" - PausedAnnotation = groupName + "/paused" + groupName = "garm-operator.mercedes-benz.com" + EnterpriseFinalizerName = groupName + "/enterprise" + OrganizationFinalizerName = groupName + "/organization" + RepositoryFinalizerName = groupName + "/repository" + PoolFinalizerName = groupName + "/pool" + RunnerFinalizerName = groupName + "/runner" + EndpointFinalizerName = groupName + "/endpoint" + PausedAnnotation = groupName + "/paused" ) diff --git a/pkg/conditions/condition_types.go b/pkg/conditions/condition_types.go index 561e2d8d..ee089ef3 100644 --- a/pkg/conditions/condition_types.go +++ b/pkg/conditions/condition_types.go @@ -48,4 +48,5 @@ const ( DeletingOrgMsg string = "Deleting organization" DeletingRepoMsg string = "Deleting repository" DeletingPoolMsg string = "Deleting pool" + DeletingEndpointMsg string = "Deleting endpoint" ) From c7dd84655019a4151c9b3885ee35b9adb76fee44 Mon Sep 17 00:00:00 2001 From: rthalho Date: Wed, 14 Aug 2024 16:20:53 +0200 Subject: [PATCH 03/30] feat(githubcredentials): implement credentials api --- PROJECT | 9 + api/v1alpha1/enterprise_types.go | 5 +- api/v1alpha1/githubcredentials_types.go | 75 ++++ api/v1alpha1/organization_types.go | 5 +- api/v1alpha1/repository_types.go | 7 +- api/v1alpha1/zz_generated.deepcopy.go | 107 +++++- cmd/main.go | 10 +- ...perator.mercedes-benz.com_enterprises.yaml | 26 +- ...r.mercedes-benz.com_githubcredentials.yaml | 214 +++++++++++ ...rator.mercedes-benz.com_organizations.yaml | 26 +- ...erator.mercedes-benz.com_repositories.yaml | 26 +- config/crd/kustomization.yaml | 3 + .../cainjection_in_githubcredentials.yaml | 7 + .../patches/webhook_in_githubcredentials.yaml | 16 + .../rbac/githubcredentials_editor_role.yaml | 31 ++ .../rbac/githubcredentials_viewer_role.yaml | 27 ++ config/rbac/role.yaml | 26 ++ .../garm-operator_v1alpha1_enterprise.yaml | 5 +- ...m-operator_v1alpha1_githubcredentials.yaml | 30 ++ .../garm-operator_v1alpha1_organization.yaml | 5 +- .../garm-operator_v1alpha1_repository.yaml | 5 +- config/samples/kustomization.yaml | 1 + go.mod | 2 + go.sum | 5 + internal/controller/enterprise_controller.go | 70 +++- .../githubcredentials_controller.go | 341 ++++++++++++++++++ .../controller/organization_controller.go | 74 +++- internal/controller/repository_controller.go | 66 +++- pkg/client/credentials.go | 84 +++++ pkg/client/key/key.go | 1 + pkg/conditions/condition_types.go | 12 + 31 files changed, 1287 insertions(+), 34 deletions(-) create mode 100644 api/v1alpha1/githubcredentials_types.go create mode 100644 config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml create mode 100644 config/crd/patches/cainjection_in_githubcredentials.yaml create mode 100644 config/crd/patches/webhook_in_githubcredentials.yaml create mode 100644 config/rbac/githubcredentials_editor_role.yaml create mode 100644 config/rbac/githubcredentials_viewer_role.yaml create mode 100644 config/samples/garm-operator_v1alpha1_githubcredentials.yaml create mode 100644 internal/controller/githubcredentials_controller.go create mode 100644 pkg/client/credentials.go diff --git a/PROJECT b/PROJECT index 299ee194..7a4d63a2 100644 --- a/PROJECT +++ b/PROJECT @@ -87,4 +87,13 @@ resources: kind: Endpoint path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: GitHubCredentials + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 version: "3" diff --git a/api/v1alpha1/enterprise_types.go b/api/v1alpha1/enterprise_types.go index 976e4db4..efab3367 100644 --- a/api/v1alpha1/enterprise_types.go +++ b/api/v1alpha1/enterprise_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -10,7 +11,7 @@ import ( // EnterpriseSpec defines the desired state of Enterprise type EnterpriseSpec struct { - CredentialsName string `json:"credentialsName"` + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` // WebhookSecretRef represents a secret that should be used for the webhook WebhookSecretRef SecretRef `json:"webhookSecretRef"` @@ -49,7 +50,7 @@ func (e *Enterprise) GetConditions() []metav1.Condition { } func (e *Enterprise) GetCredentialsName() string { - return e.Spec.CredentialsName + return e.Spec.CredentialsRef.Name } func (e *Enterprise) GetID() string { diff --git a/api/v1alpha1/githubcredentials_types.go b/api/v1alpha1/githubcredentials_types.go new file mode 100644 index 00000000..b161757d --- /dev/null +++ b/api/v1alpha1/githubcredentials_types.go @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + "github.com/cloudbase/garm/params" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GitHubCredentialsSpec defines the desired state of GitHubCredentials +type GitHubCredentialsSpec struct { + Description string `json:"description"` + EndpointRef corev1.TypedLocalObjectReference `json:"endpointRef"` + + // either pat or app + AuthType params.GithubAuthType `json:"authType"` + + // if AuthType is app + AppID int64 `json:"appID,omitempty"` + InstallationID int64 `json:"installationID,omitempty"` + + // containing either privateKey or pat token + SecretRef SecretRef `json:"secretRef,omitempty"` +} + +// GitHubCredentialsStatus defines the observed state of GitHubCredentials +type GitHubCredentialsStatus struct { + ID int64 `json:"id"` + APIBaseURL string `json:"apiBaseURL"` + UploadBaseURL string `json:"uploadBaseURL"` + BaseURL string `json:"baseURL"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=githubcredentials,scope=Namespaced,categories=garm,shortName=creds +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Credentials ID" +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="AuthType",type="string",JSONPath=`.spec.authType`,description="Authentication type" +//+kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=`.spec.endpointRef.name`,description="Endpoint name these credentials are tied to" +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GitHubCredentials" + +// GitHubCredentials is the Schema for the githubcredentials API +type GitHubCredentials struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GitHubCredentialsSpec `json:"spec,omitempty"` + Status GitHubCredentialsStatus `json:"status,omitempty"` +} + +func (g *GitHubCredentials) SetConditions(conditions []metav1.Condition) { + g.Status.Conditions = conditions +} + +func (g *GitHubCredentials) GetConditions() []metav1.Condition { + return g.Status.Conditions +} + +//+kubebuilder:object:root=true + +// GitHubCredentialsList contains a list of GitHubCredentials +type GitHubCredentialsList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GitHubCredentials `json:"items"` +} + +func init() { + SchemeBuilder.Register(&GitHubCredentials{}, &GitHubCredentialsList{}) +} diff --git a/api/v1alpha1/organization_types.go b/api/v1alpha1/organization_types.go index 996f534b..664260f5 100644 --- a/api/v1alpha1/organization_types.go +++ b/api/v1alpha1/organization_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -10,7 +11,7 @@ import ( // OrganizationSpec defines the desired state of Organization type OrganizationSpec struct { - CredentialsName string `json:"credentialsName"` + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` // WebhookSecretRef represents a secret that should be used for the webhook WebhookSecretRef SecretRef `json:"webhookSecretRef"` @@ -49,7 +50,7 @@ func (o *Organization) GetConditions() []metav1.Condition { } func (o *Organization) GetCredentialsName() string { - return o.Spec.CredentialsName + return o.Spec.CredentialsRef.Name } func (o *Organization) GetID() string { diff --git a/api/v1alpha1/repository_types.go b/api/v1alpha1/repository_types.go index c84f085a..9fc58d97 100644 --- a/api/v1alpha1/repository_types.go +++ b/api/v1alpha1/repository_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -10,8 +11,8 @@ import ( // RepositorySpec defines the desired state of Repository type RepositorySpec struct { - CredentialsName string `json:"credentialsName"` - Owner string `json:"owner"` + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + Owner string `json:"owner"` // WebhookSecretRef represents a secret that should be used for the webhook WebhookSecretRef SecretRef `json:"webhookSecretRef"` @@ -50,7 +51,7 @@ func (r *Repository) GetConditions() []metav1.Condition { } func (r *Repository) GetCredentialsName() string { - return r.Spec.CredentialsName + return r.Spec.CredentialsRef.Name } func (r *Repository) GetID() string { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index d667f4fd..6b604df8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -118,7 +118,7 @@ func (in *Enterprise) DeepCopyInto(out *Enterprise) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } @@ -175,6 +175,7 @@ func (in *EnterpriseList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnterpriseSpec) DeepCopyInto(out *EnterpriseSpec) { *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } @@ -306,6 +307,104 @@ func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. +func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { + if in == nil { + return nil + } + out := new(GitHubCredentials) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubCredentials) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GitHubCredentials, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. +func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { + if in == nil { + return nil + } + out := new(GitHubCredentialsList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { + *out = *in + in.EndpointRef.DeepCopyInto(&out.EndpointRef) + out.SecretRef = in.SecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. +func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { + if in == nil { + return nil + } + out := new(GitHubCredentialsSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. +func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { + if in == nil { + return nil + } + out := new(GitHubCredentialsStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Image) DeepCopyInto(out *Image) { *out = *in @@ -400,7 +499,7 @@ func (in *Organization) DeepCopyInto(out *Organization) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } @@ -457,6 +556,7 @@ func (in *OrganizationList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OrganizationSpec) DeepCopyInto(out *OrganizationSpec) { *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } @@ -599,7 +699,7 @@ func (in *Repository) DeepCopyInto(out *Repository) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } @@ -656,6 +756,7 @@ func (in *RepositoryList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RepositorySpec) DeepCopyInto(out *RepositorySpec) { *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } diff --git a/cmd/main.go b/cmd/main.go index d70f2ae2..cecfe287 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -221,11 +221,19 @@ func run() error { if err = (&garmcontroller.EndpointReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("organization-controller"), + Recorder: mgr.GetEventRecorderFor("endpoint-controller"), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Endpoint") os.Exit(1) } + if err = (&garmcontroller.GitHubCredentialsReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("credentials-controller"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "GitHubCredentials") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml index e68f97d2..7cf1c964 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml @@ -63,8 +63,28 @@ spec: spec: description: EnterpriseSpec defines the desired state of Enterprise properties: - credentialsName: - type: string + credentialsRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic webhookSecretRef: description: WebhookSecretRef represents a secret that should be used for the webhook @@ -81,7 +101,7 @@ spec: - name type: object required: - - credentialsName + - credentialsRef - webhookSecretRef type: object status: diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml new file mode 100644 index 00000000..76b40243 --- /dev/null +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml @@ -0,0 +1,214 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: githubcredentials.garm-operator.mercedes-benz.com +spec: + group: garm-operator.mercedes-benz.com + names: + categories: + - garm + kind: GitHubCredentials + listKind: GitHubCredentialsList + plural: githubcredentials + shortNames: + - creds + singular: githubcredentials + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Credentials ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - description: Authentication type + jsonPath: .spec.authType + name: AuthType + type: string + - description: Endpoint name these credentials are tied to + jsonPath: .spec.endpointRef.name + name: Endpoint + type: string + - description: Time duration since creation of GitHubCredentials + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: GitHubCredentials is the Schema for the githubcredentials API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GitHubCredentialsSpec defines the desired state of GitHubCredentials + properties: + appID: + description: if AuthType is app + format: int64 + type: integer + authType: + description: either pat or app + type: string + description: + type: string + endpointRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + installationID: + format: int64 + type: integer + secretRef: + description: containing either privateKey or pat token + properties: + key: + description: Key is the key in the secret's data map for this + value + type: string + name: + description: Name of the kubernetes secret to use + type: string + required: + - key + - name + type: object + required: + - authType + - description + - endpointRef + type: object + status: + description: GitHubCredentialsStatus defines the observed state of GitHubCredentials + properties: + apiBaseURL: + type: string + baseURL: + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + format: int64 + type: integer + uploadBaseURL: + type: string + required: + - apiBaseURL + - baseURL + - id + - uploadBaseURL + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml index 034ec234..6ef12b10 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml @@ -63,8 +63,28 @@ spec: spec: description: OrganizationSpec defines the desired state of Organization properties: - credentialsName: - type: string + credentialsRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic webhookSecretRef: description: WebhookSecretRef represents a secret that should be used for the webhook @@ -81,7 +101,7 @@ spec: - name type: object required: - - credentialsName + - credentialsRef - webhookSecretRef type: object status: diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml index 16a09d3c..608e2376 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml @@ -63,8 +63,28 @@ spec: spec: description: RepositorySpec defines the desired state of Repository properties: - credentialsName: - type: string + credentialsRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic owner: type: string webhookSecretRef: @@ -83,7 +103,7 @@ spec: - name type: object required: - - credentialsName + - credentialsRef - owner - webhookSecretRef type: object diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index df430852..37ca0d20 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -10,6 +10,7 @@ resources: - bases/garm-operator.mercedes-benz.com_runners.yaml - bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml - bases/garm-operator.mercedes-benz.com_endpoints.yaml +- bases/garm-operator.mercedes-benz.com_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: @@ -22,6 +23,7 @@ patches: #- path: patches/webhook_in_runners.yaml #- path: patches/webhook_in_garmserverconfigs.yaml #- path: patches/webhook_in_endpoints.yaml +#- path: patches/webhook_in_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -34,6 +36,7 @@ patches: #- path: patches/cainjection_in_runners.yaml #- path: patches/cainjection_in_garmserverconfigs.yaml #- path: patches/cainjection_in_endpoints.yaml +#- path: patches/cainjection_in_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_githubcredentials.yaml b/config/crd/patches/cainjection_in_githubcredentials.yaml new file mode 100644 index 00000000..95397d02 --- /dev/null +++ b/config/crd/patches/cainjection_in_githubcredentials.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: githubcredentials.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/webhook_in_githubcredentials.yaml b/config/crd/patches/webhook_in_githubcredentials.yaml new file mode 100644 index 00000000..93bd0f14 --- /dev/null +++ b/config/crd/patches/webhook_in_githubcredentials.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: githubcredentials.garm-operator.mercedes-benz.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/githubcredentials_editor_role.yaml b/config/rbac/githubcredentials_editor_role.yaml new file mode 100644 index 00000000..040f2fb0 --- /dev/null +++ b/config/rbac/githubcredentials_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit githubcredentials. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: githubcredentials-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: githubcredentials-editor-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials/status + verbs: + - get diff --git a/config/rbac/githubcredentials_viewer_role.yaml b/config/rbac/githubcredentials_viewer_role.yaml new file mode 100644 index 00000000..7bbc6fca --- /dev/null +++ b/config/rbac/githubcredentials_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view githubcredentials. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: githubcredentials-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: githubcredentials-viewer-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials + verbs: + - get + - list + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index d6254d3d..4be340bc 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -104,6 +104,32 @@ rules: - get - patch - update +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials/finalizers + verbs: + - update +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredentials/status + verbs: + - get + - patch + - update - apiGroups: - garm-operator.mercedes-benz.com resources: diff --git a/config/samples/garm-operator_v1alpha1_enterprise.yaml b/config/samples/garm-operator_v1alpha1_enterprise.yaml index 87e4f840..b7ba75a7 100644 --- a/config/samples/garm-operator_v1alpha1_enterprise.yaml +++ b/config/samples/garm-operator_v1alpha1_enterprise.yaml @@ -10,7 +10,10 @@ metadata: name: enterprise-sample namespace: garm-operator-system spec: - credentialsName: GitHub-Actions + credentialsRef: + apiGroup: garm-operator.mercedes-benz.com + kind: GitHubCredentials + name: github-pat webhookSecretRef: key: "webhookSecret" name: "enterprise-webhook-secret" diff --git a/config/samples/garm-operator_v1alpha1_githubcredentials.yaml b/config/samples/garm-operator_v1alpha1_githubcredentials.yaml new file mode 100644 index 00000000..214068b1 --- /dev/null +++ b/config/samples/garm-operator_v1alpha1_githubcredentials.yaml @@ -0,0 +1,30 @@ +apiVersion: garm-operator.mercedes-benz.com/v1alpha1 +kind: GitHubCredentials +metadata: + labels: + app.kubernetes.io/name: githubcredentials + app.kubernetes.io/instance: githubcredentials-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: github-pat +spec: + description: credentials for mercedes-benz github + endpointRef: + apiGroup: garm-operator.mercedes-benz.com + kind: Endpoint + name: github-enterprise + authType: pat + secretRef: + name: github-pat + key: token +--- +apiVersion: v1 +kind: Secret +metadata: + name: github-pat + namespace: garm-operator-system +data: + token: gh_mysecrettoken + + diff --git a/config/samples/garm-operator_v1alpha1_organization.yaml b/config/samples/garm-operator_v1alpha1_organization.yaml index 5706116a..413d8300 100644 --- a/config/samples/garm-operator_v1alpha1_organization.yaml +++ b/config/samples/garm-operator_v1alpha1_organization.yaml @@ -13,7 +13,10 @@ spec: webhookSecretRef: key: "webhookSecret" name: "org-webhook-secret" - credentialsName: "GitHub-Actions" + credentialsRef: + apiGroup: garm-operator.mercedes-benz.com + kind: GitHubCredentials + name: github-pat --- apiVersion: v1 kind: Secret diff --git a/config/samples/garm-operator_v1alpha1_repository.yaml b/config/samples/garm-operator_v1alpha1_repository.yaml index 142884e2..d698330f 100644 --- a/config/samples/garm-operator_v1alpha1_repository.yaml +++ b/config/samples/garm-operator_v1alpha1_repository.yaml @@ -13,7 +13,10 @@ spec: webhookSecretRef: key: "webhookSecret" name: "org-webhook-secret" - credentialsName: "GitHub-Actions" + credentialsRef: + apiGroup: garm-operator.mercedes-benz.com + kind: GitHubCredentials + name: github-pat owner: "mercedes-benz" --- apiVersion: v1 diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index b6c85191..9bf95717 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -8,4 +8,5 @@ resources: - garm-operator_v1alpha1_runner.yaml - garm-operator_v1alpha1_garmserverconfig.yaml - garm-operator_v1alpha1_endpoint.yaml +- garm-operator_v1alpha1_githubcredentials.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/go.mod b/go.mod index 555c96b3..41a523f8 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( ) require ( + github.com/BurntSushi/toml v1.3.2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bradleyfalzon/ghinstallation/v2 v2.10.0 // indirect @@ -80,6 +81,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect diff --git a/go.sum b/go.sum index de7997fa..6ceb005f 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -142,6 +144,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= @@ -168,6 +172,7 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index 85058145..d7d2ccbb 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -5,7 +5,12 @@ package controller import ( "context" "fmt" + "k8s.io/apimachinery/pkg/types" "reflect" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/enterprises" @@ -83,7 +88,9 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC if err != nil { conditions.MarkFalse(enterprise, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkFalse(enterprise, conditions.SecretReference, conditions.FetchingSecretRefFailedReason, err.Error()) - conditions.MarkUnknown(enterprise, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + if conditions.Get(enterprise, conditions.PoolManager) == nil { + conditions.MarkUnknown(enterprise, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + } if err := r.Status().Update(ctx, enterprise); err != nil { return ctrl.Result{}, err } @@ -91,6 +98,20 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC } conditions.MarkTrue(enterprise, conditions.SecretReference, conditions.FetchingSecretRefSuccessReason, "") + credentials, err := r.getCredentialsRef(ctx, enterprise) + if err != nil { + conditions.MarkFalse(enterprise, conditions.ReadyCondition, conditions.FetchingCredentialsRefFailedReason, err.Error()) + conditions.MarkFalse(enterprise, conditions.CredentialsReference, conditions.FetchingCredentialsRefFailedReason, err.Error()) + if conditions.Get(enterprise, conditions.PoolManager) == nil { + conditions.MarkUnknown(enterprise, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + } + if err := r.Status().Update(ctx, enterprise); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + conditions.MarkTrue(enterprise, conditions.CredentialsReference, conditions.FetchingCredentialsRefSuccessReason, "") + garmEnterprise, err := r.getExistingGarmEnterprise(ctx, client, enterprise) if err != nil { event.Error(r.Recorder, enterprise, err.Error()) @@ -115,7 +136,7 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC } // update enterprise anytime - garmEnterprise, err = r.updateEnterprise(ctx, client, garmEnterprise.ID, webhookSecret, enterprise.Spec.CredentialsName) + garmEnterprise, err = r.updateEnterprise(ctx, client, garmEnterprise.ID, webhookSecret, credentials.Name) if err != nil { event.Error(r.Recorder, enterprise, err.Error()) conditions.MarkFalse(enterprise, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -154,7 +175,7 @@ func (r *EnterpriseReconciler) createEnterprise(ctx context.Context, client garm enterprises.NewCreateEnterpriseParams(). WithBody(params.CreateEnterpriseParams{ Name: enterprise.Name, - CredentialsName: enterprise.Spec.CredentialsName, + CredentialsName: enterprise.GetCredentialsName(), WebhookSecret: webhookSecret, // gh hook secret })) if err != nil { @@ -250,6 +271,18 @@ func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } +func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise *garmoperatorv1alpha1.Enterprise) (*garmoperatorv1alpha1.GitHubCredentials, error) { + creds := &garmoperatorv1alpha1.GitHubCredentials{} + err := r.Get(ctx, types.NamespacedName{ + Namespace: enterprise.Namespace, + Name: enterprise.Spec.CredentialsRef.Name, + }, creds) + if err != nil { + return creds, err + } + return creds, nil +} + func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise *garmoperatorv1alpha1.Enterprise) error { if !controllerutil.ContainsFinalizer(enterprise, key.EnterpriseFinalizerName) { controllerutil.AddFinalizer(enterprise, key.EnterpriseFinalizerName) @@ -258,10 +291,41 @@ func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise * return nil } +func (r *EnterpriseReconciler) findEnterprisesForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { + credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + if !ok { + return nil + } + + var enterprises garmoperatorv1alpha1.EnterpriseList + if err := r.List(ctx, &enterprises); err != nil { + return nil + } + + var requests []reconcile.Request + for _, enterprise := range enterprises.Items { + if enterprise.GetCredentialsName() == credentials.Name { + requests = append(requests, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: enterprise.Namespace, + Name: enterprise.Name, + }, + }) + } + } + + return requests +} + // SetupWithManager sets up the controller with the Manager. func (r *EnterpriseReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1alpha1.Enterprise{}). + Watches( + &garmoperatorv1alpha1.GitHubCredentials{}, + handler.EnqueueRequestsFromMapFunc(r.findEnterprisesForCredentials), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). WithOptions(options). Complete(r) } diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go new file mode 100644 index 00000000..4e28e81f --- /dev/null +++ b/internal/controller/githubcredentials_controller.go @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: MIT + +package controller + +import ( + "context" + "fmt" + garmcredentials "github.com/cloudbase/garm/client/credentials" + garmconfig "github.com/cloudbase/garm/config" + "github.com/cloudbase/garm/params" + garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/event" + "github.com/mercedes-benz/garm-operator/pkg/secret" + "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "reflect" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" +) + +// GitHubCredentialsReconciler reconciles a GitHubCredentials object +type GitHubCredentialsReconciler struct { + client.Client + Scheme *runtime.Scheme + Recorder record.EventRecorder +} + +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials/finalizers,verbs=update +//+kubebuilder:rbac:groups="",namespace=xxxxx,resources=secrets,verbs=get;list;watch; + +func (r *GitHubCredentialsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := log.FromContext(ctx) + + credentials := &garmoperatorv1alpha1.GitHubCredentials{} + if err := r.Get(ctx, req.NamespacedName, credentials); err != nil { + if apierrors.IsNotFound(err) { + log.Info("GitHubCredentials resource not found.") + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + + // Ignore objects that are paused + if annotations.IsPaused(credentials) { + log.Info("Reconciliation is paused for this object") + return ctrl.Result{}, nil + } + + credentialsClient := garmClient.NewCredentialsClient() + + // Handle deleted credentials + if !credentials.DeletionTimestamp.IsZero() { + return r.reconcileDelete(ctx, credentialsClient, credentials) + } + + return r.reconcileNormal(ctx, credentialsClient, credentials) +} + +func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials) (ctrl.Result, error) { + log := log.FromContext(ctx) + log.WithValues("credentials", credentials.Name) + + // If the GitHubCredentials doesn't have our finalizer, add it. + if err := r.ensureFinalizer(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + + // get credentials in garm db with resource name + garmGitHubCreds, err := r.getExistingCredentials(client, credentials.Name) + if err != nil { + event.Error(r.Recorder, credentials, err.Error()) + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + //fetch endpoint resource + endpoint, err := r.getEndpointRef(ctx, credentials) + if err != nil { + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.FetchingEndpointRefFailedReason, err.Error()) + conditions.MarkFalse(credentials, conditions.EndpointReference, conditions.FetchingEndpointRefFailedReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + conditions.MarkTrue(credentials, conditions.EndpointReference, conditions.FetchingEndpointRefSuccessReason, "Successfully fetched Endpoint CR Ref") + + //fetch secret + githubSecret, err := secret.FetchRef(ctx, r.Client, &credentials.Spec.SecretRef, credentials.Namespace) + if err != nil { + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) + conditions.MarkFalse(credentials, conditions.SecretReference, conditions.FetchingSecretRefFailedReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + conditions.MarkTrue(credentials, conditions.SecretReference, conditions.FetchingSecretRefSuccessReason, "") + + // if not found, create credentials in garm db + if reflect.ValueOf(garmGitHubCreds).IsZero() { + garmGitHubCreds, err = r.createCredentials(ctx, client, credentials, endpoint.Name, githubSecret) + if err != nil { + event.Error(r.Recorder, credentials, err.Error()) + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + } + + // update credentials cr anytime the credentials in garm db changes + garmGitHubCreds, err = r.updateCredentials(ctx, client, int64(garmGitHubCreds.ID), credentials, githubSecret) + if err != nil { + event.Error(r.Recorder, credentials, err.Error()) + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + // set and update credentials status + credentials.Status.ID = int64(garmGitHubCreds.ID) + credentials.Status.BaseURL = garmGitHubCreds.BaseURL + credentials.Status.APIBaseURL = garmGitHubCreds.APIBaseURL + credentials.Status.UploadBaseURL = garmGitHubCreds.UploadBaseURL + conditions.MarkTrue(credentials, conditions.ReadyCondition, conditions.SuccessfulReconcileReason, "") + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + + log.Info("reconciling credentials successfully done") + return ctrl.Result{}, nil +} + +func (r *GitHubCredentialsReconciler) getExistingCredentials(client garmClient.CredentialsClient, name string) (params.GithubCredentials, error) { + credentials, err := client.ListCredentials(garmcredentials.NewListCredentialsParams()) + if err != nil { + return params.GithubCredentials{}, err + } + + for _, creds := range credentials.Payload { + if creds.Name == name { + return creds, nil + } + } + + return params.GithubCredentials{}, nil +} + +func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials, endpoint, githubSecret string) (params.GithubCredentials, error) { + log := log.FromContext(ctx) + log.WithValues("credentials", credentials.Name) + + log.Info("GitHubCredentials doesn't exist on garm side. Creating new credentials in garm.") + event.Creating(r.Recorder, credentials, "credentials doesn't exist on garm side") + + req := params.CreateGithubCredentialsParams{ + Name: credentials.Name, + Description: credentials.Spec.Description, + AuthType: credentials.Spec.AuthType, + Endpoint: endpoint, + } + + switch credentials.Spec.AuthType { + case params.GithubAuthType(garmconfig.GithubAuthTypePAT): + req.PAT.OAuth2Token = githubSecret + case params.GithubAuthType(garmconfig.GithubAuthTypeApp): + req.App.AppID = credentials.Spec.AppID + req.App.InstallationID = credentials.Spec.InstallationID + req.App.PrivateKeyBytes = []byte(githubSecret) + default: + return params.GithubCredentials{}, fmt.Errorf("invalid auth type %s", credentials.Spec.AuthType) + } + + garmCredentials, err := client.CreateCredentials(garmcredentials.NewCreateCredentialsParams().WithBody(req)) + + if err != nil { + log.V(1).Info(fmt.Sprintf("client.CreateCredentials error: %s", err)) + return params.GithubCredentials{}, err + } + + log.V(1).Info(fmt.Sprintf("credentials %s created - return Value %v", credentials.Name, garmCredentials)) + + log.Info("creating credentials in garm succeeded") + event.Info(r.Recorder, credentials, "creating credentials in garm succeeded") + + return garmCredentials.Payload, nil +} + +func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, client garmClient.CredentialsClient, credentialsID int64, credentials *garmoperatorv1alpha1.GitHubCredentials, githubSecret string) (params.GithubCredentials, error) { + log := log.FromContext(ctx) + log.V(1).Info("update credentials") + + req := params.UpdateGithubCredentialsParams{ + Name: util.StringPtr(credentials.Name), + Description: util.StringPtr(credentials.Spec.Description), + } + + switch credentials.Spec.AuthType { + case params.GithubAuthType(garmconfig.GithubAuthTypePAT): + req.PAT = ¶ms.GithubPAT{OAuth2Token: githubSecret} + case params.GithubAuthType(garmconfig.GithubAuthTypeApp): + req.App = ¶ms.GithubApp{ + AppID: credentials.Spec.AppID, + InstallationID: credentials.Spec.InstallationID, + PrivateKeyBytes: []byte(githubSecret), + } + default: + return params.GithubCredentials{}, fmt.Errorf("invalid auth type %s", credentials.Spec.AuthType) + } + + retValue, err := client.UpdateCredentials( + garmcredentials.NewUpdateCredentialsParams(). + WithID(credentialsID). + WithBody(req)) + if err != nil { + log.V(1).Info(fmt.Sprintf("client.UpdateCredentials error: %s", err)) + return params.GithubCredentials{}, err + } + + return retValue.Payload, nil +} + +func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials) (ctrl.Result, error) { + log := log.FromContext(ctx) + log.WithValues("credentials", credentials.Name) + + log.Info("starting credentials deletion") + event.Deleting(r.Recorder, credentials, "starting credentials deletion") + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.DeletingReason, conditions.DeletingCredentialsMsg) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + + if err := client.DeleteCredentials( + garmcredentials.NewDeleteCredentialsParams(). + WithID(credentials.Status.ID), + ); err != nil { + log.V(1).Info(fmt.Sprintf("client.DeleteCredentials error: %s", err)) + event.Error(r.Recorder, credentials, err.Error()) + conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) + if err := r.Status().Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + + if controllerutil.ContainsFinalizer(credentials, key.CredentialsFinalizerName) { + controllerutil.RemoveFinalizer(credentials, key.CredentialsFinalizerName) + if err := r.Update(ctx, credentials); err != nil { + return ctrl.Result{}, err + } + } + + log.Info("credentials deletion done") + + return ctrl.Result{}, nil +} + +func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) (*garmoperatorv1alpha1.Endpoint, error) { + endpoint := &garmoperatorv1alpha1.Endpoint{} + err := r.Get(ctx, types.NamespacedName{ + Namespace: credentials.Namespace, + Name: credentials.Spec.EndpointRef.Name, + }, endpoint) + if err != nil { + return endpoint, err + } + return endpoint, nil +} + +func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) error { + if !controllerutil.ContainsFinalizer(credentials, key.EndpointFinalizerName) { + controllerutil.AddFinalizer(credentials, key.EndpointFinalizerName) + return r.Update(ctx, credentials) + } + return nil +} + +func (r *GitHubCredentialsReconciler) findCredentialsForSecret(ctx context.Context, obj client.Object) []reconcile.Request { + secret, ok := obj.(*corev1.Secret) + if !ok { + return nil + } + + var creds garmoperatorv1alpha1.GitHubCredentialsList + if err := r.List(ctx, &creds); err != nil { + return nil + } + + var requests []reconcile.Request + for _, c := range creds.Items { + if c.Spec.SecretRef.Name == secret.Name { + requests = append(requests, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: c.Namespace, + Name: c.Name, + }, + }) + } + } + + return requests +} + +// SetupWithManager sets up the controller with the Manager. +func (r *GitHubCredentialsReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&garmoperatorv1alpha1.GitHubCredentials{}). + Watches( + &corev1.Secret{}, + handler.EnqueueRequestsFromMapFunc(r.findCredentialsForSecret), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). + Complete(r) +} diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index 1eb4b2f2..b1ef023d 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -5,7 +5,12 @@ package controller import ( "context" "fmt" + "k8s.io/apimachinery/pkg/types" "reflect" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/organizations" @@ -90,6 +95,20 @@ func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client gar } conditions.MarkTrue(organization, conditions.SecretReference, conditions.FetchingSecretRefSuccessReason, "") + credentials, err := r.getCredentialsRef(ctx, organization) + if err != nil { + conditions.MarkFalse(organization, conditions.ReadyCondition, conditions.FetchingCredentialsRefFailedReason, err.Error()) + conditions.MarkFalse(organization, conditions.CredentialsReference, conditions.FetchingCredentialsRefFailedReason, err.Error()) + if conditions.Get(organization, conditions.PoolManager) == nil { + conditions.MarkUnknown(organization, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + } + if err := r.Status().Update(ctx, organization); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + conditions.MarkTrue(organization, conditions.CredentialsReference, conditions.FetchingCredentialsRefSuccessReason, "") + garmOrganization, err := r.getExistingGarmOrg(ctx, client, organization) if err != nil { event.Error(r.Recorder, organization, err.Error()) @@ -114,7 +133,7 @@ func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client gar } // update organization anytime - garmOrganization, err = r.updateOrganization(ctx, client, garmOrganization.ID, webhookSecret, organization.Spec.CredentialsName) + garmOrganization, err = r.updateOrganization(ctx, client, garmOrganization.ID, webhookSecret, credentials.Name) if err != nil { event.Error(r.Recorder, organization, err.Error()) conditions.MarkFalse(organization, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -154,7 +173,7 @@ func (r *OrganizationReconciler) createOrganization(ctx context.Context, client organizations.NewCreateOrgParams(). WithBody(params.CreateOrgParams{ Name: organization.Name, - CredentialsName: organization.Spec.CredentialsName, + CredentialsName: organization.GetCredentialsName(), WebhookSecret: webhookSecret, // gh hook secret })) if err != nil { @@ -250,18 +269,61 @@ func (r *OrganizationReconciler) reconcileDelete(ctx context.Context, client gar return ctrl.Result{}, nil } -func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1alpha1.Organization) error { - if !controllerutil.ContainsFinalizer(pool, key.OrganizationFinalizerName) { - controllerutil.AddFinalizer(pool, key.OrganizationFinalizerName) - return r.Update(ctx, pool) +func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *garmoperatorv1alpha1.Organization) (*garmoperatorv1alpha1.GitHubCredentials, error) { + creds := &garmoperatorv1alpha1.GitHubCredentials{} + err := r.Get(ctx, types.NamespacedName{ + Namespace: org.Namespace, + Name: org.Spec.CredentialsRef.Name, + }, creds) + if err != nil { + return creds, err + } + return creds, nil +} + +func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, org *garmoperatorv1alpha1.Organization) error { + if !controllerutil.ContainsFinalizer(org, key.OrganizationFinalizerName) { + controllerutil.AddFinalizer(org, key.OrganizationFinalizerName) + return r.Update(ctx, org) } return nil } +func (r *OrganizationReconciler) findOrgsForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { + credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + if !ok { + return nil + } + + var orgs garmoperatorv1alpha1.OrganizationList + if err := r.List(ctx, &orgs); err != nil { + return nil + } + + var requests []reconcile.Request + for _, org := range orgs.Items { + if org.GetCredentialsName() == credentials.Name { + requests = append(requests, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: org.Namespace, + Name: org.Name, + }, + }) + } + } + + return requests +} + // SetupWithManager sets up the controller with the Manager. func (r *OrganizationReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1alpha1.Organization{}). + Watches( + &garmoperatorv1alpha1.GitHubCredentials{}, + handler.EnqueueRequestsFromMapFunc(r.findOrgsForCredentials), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). WithOptions(options). Complete(r) } diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index 4e4e6396..9ef1016c 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -5,7 +5,12 @@ package controller import ( "context" "fmt" + "k8s.io/apimachinery/pkg/types" "reflect" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/repositories" @@ -90,6 +95,20 @@ func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmC } conditions.MarkTrue(repository, conditions.SecretReference, conditions.FetchingSecretRefSuccessReason, "") + credentials, err := r.getCredentialsRef(ctx, repository) + if err != nil { + conditions.MarkFalse(repository, conditions.ReadyCondition, conditions.FetchingCredentialsRefFailedReason, err.Error()) + conditions.MarkFalse(repository, conditions.CredentialsReference, conditions.FetchingCredentialsRefFailedReason, err.Error()) + if conditions.Get(repository, conditions.PoolManager) == nil { + conditions.MarkUnknown(repository, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + } + if err := r.Status().Update(ctx, repository); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + conditions.MarkTrue(repository, conditions.CredentialsReference, conditions.FetchingCredentialsRefSuccessReason, "") + garmRepository, err := r.getExistingGarmRepo(ctx, client, repository) if err != nil { event.Error(r.Recorder, repository, err.Error()) @@ -114,7 +133,7 @@ func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmC } // update repository anytime - garmRepository, err = r.updateRepository(ctx, client, garmRepository.ID, webhookSecret, repository.Spec.CredentialsName) + garmRepository, err = r.updateRepository(ctx, client, garmRepository.ID, webhookSecret, credentials.Name) if err != nil { event.Error(r.Recorder, repository, err.Error()) conditions.MarkFalse(repository, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -154,7 +173,7 @@ func (r *RepositoryReconciler) createRepository(ctx context.Context, client garm repositories.NewCreateRepoParams(). WithBody(params.CreateRepoParams{ Name: repository.Name, - CredentialsName: repository.Spec.CredentialsName, + CredentialsName: repository.GetCredentialsName(), Owner: repository.Spec.Owner, WebhookSecret: webhookSecret, // gh hook secret })) @@ -251,6 +270,18 @@ func (r *RepositoryReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } +func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository *garmoperatorv1alpha1.Repository) (*garmoperatorv1alpha1.GitHubCredentials, error) { + creds := &garmoperatorv1alpha1.GitHubCredentials{} + err := r.Get(ctx, types.NamespacedName{ + Namespace: repository.Namespace, + Name: repository.Spec.CredentialsRef.Name, + }, creds) + if err != nil { + return creds, err + } + return creds, nil +} + func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1alpha1.Repository) error { if !controllerutil.ContainsFinalizer(pool, key.RepositoryFinalizerName) { controllerutil.AddFinalizer(pool, key.RepositoryFinalizerName) @@ -259,10 +290,41 @@ func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmop return nil } +func (r *RepositoryReconciler) findReposForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { + credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + if !ok { + return nil + } + + var repos garmoperatorv1alpha1.RepositoryList + if err := r.List(ctx, &repos); err != nil { + return nil + } + + var requests []reconcile.Request + for _, repo := range repos.Items { + if repo.GetCredentialsName() == credentials.Name { + requests = append(requests, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: repo.Namespace, + Name: repo.Name, + }, + }) + } + } + + return requests +} + // SetupWithManager sets up the controller with the Manager. func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1alpha1.Repository{}). + Watches( + &garmoperatorv1alpha1.GitHubCredentials{}, + handler.EnqueueRequestsFromMapFunc(r.findReposForCredentials), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). WithOptions(options). Complete(r) } diff --git a/pkg/client/credentials.go b/pkg/client/credentials.go new file mode 100644 index 00000000..4e54799e --- /dev/null +++ b/pkg/client/credentials.go @@ -0,0 +1,84 @@ +package client + +import ( + "github.com/cloudbase/garm/client/credentials" + "github.com/mercedes-benz/garm-operator/pkg/metrics" +) + +type CredentialsClient interface { + GetCredentials(params *credentials.GetCredentialsParams) (*credentials.GetCredentialsOK, error) + ListCredentials(params *credentials.ListCredentialsParams) (*credentials.ListCredentialsOK, error) + CreateCredentials(params *credentials.CreateCredentialsParams) (*credentials.CreateCredentialsOK, error) + UpdateCredentials(params *credentials.UpdateCredentialsParams) (*credentials.UpdateCredentialsOK, error) + DeleteCredentials(params *credentials.DeleteCredentialsParams) error +} + +type credentialClient struct { + GarmClient +} + +func (e *credentialClient) GetCredentials(params *credentials.GetCredentialsParams) (*credentials.GetCredentialsOK, error) { + return EnsureAuth(func() (*credentials.GetCredentialsOK, error) { + metrics.TotalGarmCalls.WithLabelValues("credentials.Get").Inc() + endpoint, err := e.GarmAPI().Credentials.GetCredentials(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("credentials.Get").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *credentialClient) ListCredentials(params *credentials.ListCredentialsParams) (*credentials.ListCredentialsOK, error) { + return EnsureAuth(func() (*credentials.ListCredentialsOK, error) { + metrics.TotalGarmCalls.WithLabelValues("credentials.List").Inc() + credentials, err := e.GarmAPI().Credentials.ListCredentials(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("credentials.List").Inc() + return nil, err + } + return credentials, nil + }) +} + +func (e *credentialClient) CreateCredentials(params *credentials.CreateCredentialsParams) (*credentials.CreateCredentialsOK, error) { + return EnsureAuth(func() (*credentials.CreateCredentialsOK, error) { + metrics.TotalGarmCalls.WithLabelValues("credentials.Create").Inc() + endpoint, err := e.GarmAPI().Credentials.CreateCredentials(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("credentials.Create").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *credentialClient) UpdateCredentials(params *credentials.UpdateCredentialsParams) (*credentials.UpdateCredentialsOK, error) { + return EnsureAuth(func() (*credentials.UpdateCredentialsOK, error) { + metrics.TotalGarmCalls.WithLabelValues("credentials.Update").Inc() + endpoint, err := e.GarmAPI().Credentials.UpdateCredentials(params, e.Token()) + if err != nil { + metrics.GarmCallErrors.WithLabelValues("credentials.Update").Inc() + return nil, err + } + return endpoint, nil + }) +} + +func (e *credentialClient) DeleteCredentials(params *credentials.DeleteCredentialsParams) error { + _, err := EnsureAuth(func() (interface{}, error) { + metrics.TotalGarmCalls.WithLabelValues("credentials.Delete").Inc() + if err := e.GarmAPI().Credentials.DeleteCredentials(params, e.Token()); err != nil { + metrics.GarmCallErrors.WithLabelValues("credentials.Delete").Inc() + return nil, err + } + return nil, nil + }) + return err +} + +func NewCredentialsClient() CredentialsClient { + return &credentialClient{ + Client, + } +} diff --git a/pkg/client/key/key.go b/pkg/client/key/key.go index ae02d78b..8730af1e 100644 --- a/pkg/client/key/key.go +++ b/pkg/client/key/key.go @@ -10,5 +10,6 @@ const ( PoolFinalizerName = groupName + "/pool" RunnerFinalizerName = groupName + "/runner" EndpointFinalizerName = groupName + "/endpoint" + CredentialsFinalizerName = groupName + "/credentials" PausedAnnotation = groupName + "/paused" ) diff --git a/pkg/conditions/condition_types.go b/pkg/conditions/condition_types.go index ee089ef3..9c43b839 100644 --- a/pkg/conditions/condition_types.go +++ b/pkg/conditions/condition_types.go @@ -40,6 +40,17 @@ const ( SecretReference ConditionType = "SecretReference" FetchingSecretRefSuccessReason ConditionReason = "FetchingSecretRefSuccess" FetchingSecretRefFailedReason ConditionReason = "FetchingSecretRefFailed" + + CredentialsReference ConditionType = "CredentialsReference" + FetchingCredentialsRefSuccessReason ConditionReason = "CredentialsRefSuccess" + FetchingCredentialsRefFailedReason ConditionReason = "CredentialsRefFailed" +) + +// Credential Conditions +const ( + EndpointReference ConditionType = "EndpointReference" + FetchingEndpointRefSuccessReason ConditionReason = "FetchingEndpointRefSuccess" + FetchingEndpointRefFailedReason ConditionReason = "FetchingEndpointRefFailed" ) const ( @@ -49,4 +60,5 @@ const ( DeletingRepoMsg string = "Deleting repository" DeletingPoolMsg string = "Deleting pool" DeletingEndpointMsg string = "Deleting endpoint" + DeletingCredentialsMsg string = "Deleting credentials" ) From 540e52b90d1fbb7b465f65ea91944ae53d61693e Mon Sep 17 00:00:00 2001 From: rthalho Date: Thu, 15 Aug 2024 16:22:18 +0200 Subject: [PATCH 04/30] fixes --- Tiltfile | 2 +- api/v1alpha1/image_types.go | 2 +- cmd/main.go | 5 +- ...arm-operator.mercedes-benz.com_images.yaml | 1 - ...rm-operator_v1alpha1_garmserverconfig.yaml | 2 +- ...m-operator_v1alpha1_githubcredentials.yaml | 4 +- config/samples/kustomization.yaml | 4 +- .../controller/garmserverconfig_controller.go | 91 ++++++++----------- .../githubcredentials_controller.go | 4 +- 9 files changed, 53 insertions(+), 62 deletions(-) diff --git a/Tiltfile b/Tiltfile index f7956104..dc0719af 100644 --- a/Tiltfile +++ b/Tiltfile @@ -18,7 +18,7 @@ deploy_cert_manager( # the manager binary and the dlv debug port will be exposed # # for more details, please read the DEVELOPMENT.md -mode = 'debug' +mode = 'local' # kustomize overlays templated_yaml = kustomize('config/overlays/' + mode) diff --git a/api/v1alpha1/image_types.go b/api/v1alpha1/image_types.go index 3729a22f..b15044b9 100644 --- a/api/v1alpha1/image_types.go +++ b/api/v1alpha1/image_types.go @@ -31,7 +31,7 @@ type ImageStatus struct { //+kubebuilder:object:root=true //+kubebuilder:resource:path=images,scope=Namespaced,categories=garm -//+kubebuilder:printcolumn:name="Tag",type=string,JSONPath=`.spec.tag`,priority=1 +//+kubebuilder:printcolumn:name="Tag",type=string,JSONPath=`.spec.tag` //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // Image is the Schema for the images API diff --git a/cmd/main.go b/cmd/main.go index cecfe287..dda99666 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -211,8 +211,9 @@ func run() error { } if err = (&garmcontroller.GarmServerConfigReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("garm-server-config-controller"), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "GarmServerConfig") os.Exit(1) diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml index fff55165..31edba16 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml @@ -19,7 +19,6 @@ spec: - additionalPrinterColumns: - jsonPath: .spec.tag name: Tag - priority: 1 type: string - jsonPath: .metadata.creationTimestamp name: Age diff --git a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml index e0b5b66f..4a29d517 100644 --- a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml +++ b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml @@ -9,6 +9,6 @@ metadata: app.kubernetes.io/created-by: garm-operator name: garmserverconfig-sample spec: - callbackURL: http://garm-server.garm-server.svc:9997/api/v1/callback + callbackURL: http://garm-server.garm-server.svc:9997/api/v1/callbacks metadataURL: http://garm-server.garm-server.svc:9997/api/v1/metadata webhookURL: http://garm-server.garm-server.svc:9997/api/v1/webhook diff --git a/config/samples/garm-operator_v1alpha1_githubcredentials.yaml b/config/samples/garm-operator_v1alpha1_githubcredentials.yaml index 214068b1..b5e4e514 100644 --- a/config/samples/garm-operator_v1alpha1_githubcredentials.yaml +++ b/config/samples/garm-operator_v1alpha1_githubcredentials.yaml @@ -25,6 +25,8 @@ metadata: name: github-pat namespace: garm-operator-system data: - token: gh_mysecrettoken + # just a base64 encoded string for demonstration purposes, use your own github pat. + # Make sure there is no \n at the end of the string, use: echo -n "gh_mysecrettoken" | base64 + token: Z2hfbXlzZWNyZXR0b2tlbg== diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 9bf95717..85ac1266 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -7,6 +7,6 @@ resources: - garm-operator_v1alpha1_repository.yaml - garm-operator_v1alpha1_runner.yaml - garm-operator_v1alpha1_garmserverconfig.yaml -- garm-operator_v1alpha1_endpoint.yaml -- garm-operator_v1alpha1_githubcredentials.yaml + - garm-operator_v1alpha1_endpoint.yaml + - garm-operator_v1alpha1_githubcredentials.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go index 719a4a61..b1d82684 100644 --- a/internal/controller/garmserverconfig_controller.go +++ b/internal/controller/garmserverconfig_controller.go @@ -4,27 +4,25 @@ package controller import ( "context" + "errors" "reflect" - garmController "github.com/cloudbase/garm/client/controller" + garmapiserverparams "github.com/cloudbase/garm/apiserver/params" + garmcontroller "github.com/cloudbase/garm/client/controller" + "github.com/cloudbase/garm/client/controller_info" "github.com/cloudbase/garm/params" - "github.com/mercedes-benz/garm-operator/pkg/annotations" - garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + garmclient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" - "github.com/mercedes-benz/garm-operator/pkg/config" "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/tools/record" - "sigs.k8s.io/controller-runtime/pkg/controller" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/source" - "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" @@ -43,24 +41,27 @@ type GarmServerConfigReconciler struct { //+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=garmserverconfigs/finalizers,verbs=update func (r *GarmServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - controllerClient := garmClient.NewControllerClient() + controllerClient := garmclient.NewControllerClient() return r.reconcile(ctx, req, controllerClient) } -func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Request, controllerClient garmClient.ControllerClient) (ctrl.Result, error) { +func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Request, controllerClient garmclient.ControllerClient) (ctrl.Result, error) { log := log.FromContext(ctx) log.Info("Reconciling GarmServerConfig") - controllerInfo, err := controllerClient.GetControllerInfo() + controllerInfo, err := r.getControllerInfo(controllerClient) if err != nil { log.Error(err, "Failed to get controller info") return ctrl.Result{}, err } - // initially create GarmServerConfig CR reflecting values from garm-server controller info garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{} if err := r.Get(ctx, req.NamespacedName, garmServerConfig); err != nil { - return r.handleCreateGarmServerConfigCR(ctx, req, err, &controllerInfo.Payload) + if apierrors.IsNotFound(err) { + log.Info("object was not found") + return ctrl.Result{}, nil + } + return ctrl.Result{}, err } // Ignore objects that are paused @@ -70,7 +71,7 @@ func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Req } // sync applied spec with controller info in garm - newControllerInfo, err := r.updateControllerInfo(ctx, controllerClient, garmServerConfig, &controllerInfo.Payload) + newControllerInfo, err := r.updateControllerInfo(ctx, controllerClient, garmServerConfig, &controllerInfo) if err != nil { return ctrl.Result{}, err } @@ -83,18 +84,6 @@ func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, nil } -func (r *GarmServerConfigReconciler) handleCreateGarmServerConfigCR(ctx context.Context, req ctrl.Request, fetchErr error, controllerInfo *params.ControllerInfo) (ctrl.Result, error) { - log := log.FromContext(ctx) - if apierrors.IsNotFound(fetchErr) { - log.Info("GarmServerConfig was not found") - if err := r.createGarmServerConfigCR(ctx, controllerInfo, req.Name, req.Namespace); err != nil { - return ctrl.Result{}, err - } - } - - return ctrl.Result{}, nil -} - func (r *GarmServerConfigReconciler) createGarmServerConfigCR(ctx context.Context, controllerInfo *params.ControllerInfo, name, namespace string) error { log := log.FromContext(ctx) log.Info("Creating GarmServerConfig CR") @@ -119,7 +108,7 @@ func (r *GarmServerConfigReconciler) createGarmServerConfigCR(ctx context.Contex return nil } -func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmClient.ControllerClient, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { +func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmclient.ControllerClient, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { log := log.FromContext(ctx) if garmServerConfigCR.Spec.MetadataURL == controllerInfo.MetadataURL && @@ -129,7 +118,7 @@ func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, c return controllerInfo, nil } - params := garmController.NewUpdateControllerParams().WithBody(params.UpdateControllerParams{ + params := garmcontroller.NewUpdateControllerParams().WithBody(params.UpdateControllerParams{ MetadataURL: util.StringPtr(garmServerConfigCR.Spec.MetadataURL), CallbackURL: util.StringPtr(garmServerConfigCR.Spec.CallbackURL), WebhookURL: util.StringPtr(garmServerConfigCR.Spec.WebhookURL), @@ -196,28 +185,28 @@ func (r *GarmServerConfigReconciler) ensureFinalizer(ctx context.Context, garmSe return nil } +func (r *GarmServerConfigReconciler) getControllerInfo(client garmclient.ControllerClient) (params.ControllerInfo, error) { + controllerInfo, err := client.GetControllerInfo() + if err == nil { + return controllerInfo.Payload, nil + } + + var conflictErr *controller_info.ControllerInfoConflict + if !errors.As(err, &conflictErr) { + return params.ControllerInfo{}, err + } + + if reflect.DeepEqual(conflictErr.Payload, garmapiserverparams.URLsRequired) { + return params.ControllerInfo{}, nil + } + + return params.ControllerInfo{}, err +} + // SetupWithManager sets up the controller with the Manager. func (r *GarmServerConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { - c, err := ctrl.NewControllerManagedBy(mgr). + return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1alpha1.GarmServerConfig{}). WithOptions(controller.Options{}). - Build(r) - if err != nil { - return err - } - - eventChan := make(chan event.GenericEvent) - go func() { - eventChan <- event.GenericEvent{ - Object: &garmoperatorv1alpha1.GarmServerConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: "garm-server-config", - Namespace: config.Config.Operator.WatchNamespace, - }, - }, - } - close(eventChan) - }() - - return c.Watch(&source.Channel{Source: eventChan}, &handler.EnqueueRequestForObject{}) + Complete(r) } diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go index 4e28e81f..7177c754 100644 --- a/internal/controller/githubcredentials_controller.go +++ b/internal/controller/githubcredentials_controller.go @@ -295,8 +295,8 @@ func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, creden } func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) error { - if !controllerutil.ContainsFinalizer(credentials, key.EndpointFinalizerName) { - controllerutil.AddFinalizer(credentials, key.EndpointFinalizerName) + if !controllerutil.ContainsFinalizer(credentials, key.CredentialsFinalizerName) { + controllerutil.AddFinalizer(credentials, key.CredentialsFinalizerName) return r.Update(ctx, credentials) } return nil From a22f25e9c7df21ab9a096a66dddbda9ec46a4445 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 20 Aug 2024 10:09:49 +0200 Subject: [PATCH 05/30] fix(controller): organization tests --- .../controller/organization_controller.go | 1 + .../organization_controller_test.go | 274 ++++++++++++++++-- pkg/conditions/condition_types.go | 15 +- 3 files changed, 253 insertions(+), 37 deletions(-) diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index b1ef023d..719ece89 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -88,6 +88,7 @@ func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client gar conditions.MarkFalse(organization, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkFalse(organization, conditions.SecretReference, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkUnknown(organization, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + conditions.MarkUnknown(organization, conditions.CredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg) if err := r.Status().Update(ctx, organization); err != nil { return ctrl.Result{}, err } diff --git a/internal/controller/organization_controller_test.go b/internal/controller/organization_controller_test.go index 713777fa..85d1156a 100644 --- a/internal/controller/organization_controller_test.go +++ b/internal/controller/organization_controller_test.go @@ -48,7 +48,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -68,6 +72,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -78,7 +97,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -94,6 +117,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -123,13 +153,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.UpdateOrganization(organizations.NewUpdateOrgParams(). WithOrgID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.UpdateOrgOK{ Payload: params.Organization{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -146,7 +176,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "has-changed", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -166,6 +200,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "has-changed", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -176,7 +225,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "has-changed", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -192,6 +245,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -244,7 +304,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -264,6 +328,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -274,7 +353,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -290,6 +373,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -312,20 +402,20 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.UpdateOrganization(organizations.NewUpdateOrgParams(). WithOrgID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.UpdateOrgOK{ Payload: params.Organization{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", PoolManagerStatus: params.PoolManagerStatus{ IsRunning: false, @@ -343,7 +433,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -360,6 +454,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -370,7 +479,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -386,6 +499,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -415,12 +535,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.CreateOrganization(organizations.NewCreateOrgParams().WithBody( params.CreateOrgParams{ Name: "new-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.CreateOrgOK{ Payload: params.Organization{ Name: "new-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", }, @@ -428,13 +548,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.UpdateOrganization(organizations.NewUpdateOrgParams(). WithOrgID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.UpdateOrgOK{ Payload: params.Organization{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "new-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -448,7 +568,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -465,6 +589,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -475,7 +614,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -491,6 +634,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -519,13 +669,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.UpdateOrganization(organizations.NewUpdateOrgParams(). WithOrgID("e1dbf9a6-a9f6-4594-a5ac-12345"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.UpdateOrgOK{ Payload: params.Organization{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Name: "new-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -542,7 +692,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -562,6 +716,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Organization{ ObjectMeta: metav1.ObjectMeta{ @@ -572,7 +741,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -588,6 +761,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -612,12 +792,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.CreateOrganization(organizations.NewCreateOrgParams().WithBody( params.CreateOrgParams{ Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.CreateOrgOK{ Payload: params.Organization{ Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", }, @@ -625,13 +805,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { m.UpdateOrganization(organizations.NewUpdateOrgParams(). WithOrgID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&organizations.UpdateOrgOK{ Payload: params.Organization{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "existing-organization", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -648,7 +828,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -666,7 +850,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -681,6 +869,13 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Message: "secrets \"my-webhook-secret\" not found", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.UnknownReason), + Status: metav1.ConditionUnknown, + Message: "credentials not reconciled yet", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.UnknownReason), @@ -773,7 +968,11 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.OrganizationSpec{ - CredentialsName: "totally-insecure", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -793,6 +992,21 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectGarmRequest: func(m *mock.MockOrganizationClientMockRecorder) { m.DeleteOrganization( diff --git a/pkg/conditions/condition_types.go b/pkg/conditions/condition_types.go index 9c43b839..9f6c241d 100644 --- a/pkg/conditions/condition_types.go +++ b/pkg/conditions/condition_types.go @@ -54,11 +54,12 @@ const ( ) const ( - GarmServerNotReconciledYetMsg string = "GARM server not reconciled yet" - DeletingEnterpriseMsg string = "Deleting enterprise" - DeletingOrgMsg string = "Deleting organization" - DeletingRepoMsg string = "Deleting repository" - DeletingPoolMsg string = "Deleting pool" - DeletingEndpointMsg string = "Deleting endpoint" - DeletingCredentialsMsg string = "Deleting credentials" + GarmServerNotReconciledYetMsg string = "GARM server not reconciled yet" + CredentialsNotReconciledYetMsg string = "credentials not reconciled yet" + DeletingEnterpriseMsg string = "Deleting enterprise" + DeletingOrgMsg string = "Deleting organization" + DeletingRepoMsg string = "Deleting repository" + DeletingPoolMsg string = "Deleting pool" + DeletingEndpointMsg string = "Deleting endpoint" + DeletingCredentialsMsg string = "Deleting credentials" ) From 6c2168c7d9fb7eaaf02e6b68bf71b67ab701c76a Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 20 Aug 2024 10:18:10 +0200 Subject: [PATCH 06/30] fix(controller): enterprise tests --- internal/controller/enterprise_controller.go | 1 + .../controller/enterprise_controller_test.go | 283 +++++++++++++++--- 2 files changed, 249 insertions(+), 35 deletions(-) diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index d7d2ccbb..42bace77 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -88,6 +88,7 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC if err != nil { conditions.MarkFalse(enterprise, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkFalse(enterprise, conditions.SecretReference, conditions.FetchingSecretRefFailedReason, err.Error()) + conditions.MarkUnknown(enterprise, conditions.CredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg) if conditions.Get(enterprise, conditions.PoolManager) == nil { conditions.MarkUnknown(enterprise, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) } diff --git a/internal/controller/enterprise_controller_test.go b/internal/controller/enterprise_controller_test.go index 66f21626..fd942e20 100644 --- a/internal/controller/enterprise_controller_test.go +++ b/internal/controller/enterprise_controller_test.go @@ -48,7 +48,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -68,6 +72,21 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ @@ -78,7 +97,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -94,6 +117,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -116,20 +146,20 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.UpdateEnterprise(enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.UpdateEnterpriseOK{ Payload: params.Enterprise{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -146,7 +176,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "has-changed", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -166,6 +200,21 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "has-changed", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ @@ -176,7 +225,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "has-changed", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -192,6 +245,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -214,7 +274,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) @@ -244,7 +304,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -263,7 +327,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -279,6 +347,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -306,26 +381,41 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectGarmRequest: func(m *mock.MockEnterpriseClientMockRecorder) { m.ListEnterprises(enterprises.NewListEnterprisesParams()).Return(&enterprises.ListEnterprisesOK{Payload: params.Enterprises{ { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.UpdateEnterprise(enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.UpdateEnterpriseOK{ Payload: params.Enterprise{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", PoolManagerStatus: params.PoolManagerStatus{ IsRunning: false, @@ -343,7 +433,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -359,7 +453,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -375,6 +473,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -402,39 +507,53 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }}, expectGarmRequest: func(m *mock.MockEnterpriseClientMockRecorder) { m.ListEnterprises(enterprises.NewListEnterprisesParams()).Return(&enterprises.ListEnterprisesOK{Payload: params.Enterprises{ { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.CreateEnterprise(enterprises.NewCreateEnterpriseParams().WithBody( params.CreateEnterpriseParams{ Name: "new-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.CreateEnterpriseOK{ Payload: params.Enterprise{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "new-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) m.UpdateEnterprise(enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.UpdateEnterpriseOK{ Payload: params.Enterprise{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "new-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -448,7 +567,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "totally-insecure", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -464,7 +587,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "totally-insecure", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -480,6 +607,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -507,6 +641,21 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectGarmRequest: func(m *mock.MockEnterpriseClientMockRecorder) { m.ListEnterprises(enterprises.NewListEnterprisesParams()).Return(&enterprises.ListEnterprisesOK{Payload: params.Enterprises{ @@ -519,13 +668,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { m.UpdateEnterprise(enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID("e1dbf9a6-a9f6-4594-a5ac-12345"). WithBody(params.UpdateEntityParams{ - CredentialsName: "totally-insecure", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.UpdateEnterpriseOK{ Payload: params.Enterprise{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Name: "new-enterprise", - CredentialsName: "totally-insecure", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -542,7 +691,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -562,6 +715,21 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ @@ -572,7 +740,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -588,6 +760,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "Pool Manager is not running", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -612,12 +791,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { m.CreateEnterprise(enterprises.NewCreateEnterpriseParams().WithBody( params.CreateEnterpriseParams{ Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.CreateEnterpriseOK{ Payload: params.Enterprise{ Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", }, @@ -625,13 +804,13 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { m.UpdateEnterprise(enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&enterprises.UpdateEnterpriseOK{ Payload: params.Enterprise{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "existing-enterprise", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -648,7 +827,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -666,7 +849,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -681,11 +868,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Message: "secrets \"my-webhook-secret\" not found", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.UnknownReason), + Status: metav1.ConditionUnknown, + Message: conditions.CredentialsNotReconciledYetMsg, + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.UnknownReason), Status: metav1.ConditionUnknown, - Message: "GARM server not reconciled yet", + Message: conditions.GarmServerNotReconciledYetMsg, LastTransitionTime: metav1.NewTime(time.Now()), }, { @@ -773,7 +967,11 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "totally-insecure", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -793,6 +991,21 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectGarmRequest: func(m *mock.MockEnterpriseClientMockRecorder) { m.DeleteEnterprise( From 4a6e3745fae4ed7318b8f2f166efa6b51c11ecf4 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 20 Aug 2024 10:25:19 +0200 Subject: [PATCH 07/30] fix(controller): repository tests --- internal/controller/repository_controller.go | 1 + .../controller/repository_controller_test.go | 306 +++++++++++++++--- 2 files changed, 261 insertions(+), 46 deletions(-) diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index 9ef1016c..cd625f39 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -88,6 +88,7 @@ func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmC conditions.MarkFalse(repository, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkFalse(repository, conditions.SecretReference, conditions.FetchingSecretRefFailedReason, err.Error()) conditions.MarkUnknown(repository, conditions.PoolManager, conditions.UnknownReason, conditions.GarmServerNotReconciledYetMsg) + conditions.MarkUnknown(repository, conditions.CredentialsReference, conditions.UnknownReason, conditions.CredentialsNotReconciledYetMsg) if err := r.Status().Update(ctx, repository); err != nil { return ctrl.Result{}, err } diff --git a/internal/controller/repository_controller_test.go b/internal/controller/repository_controller_test.go index dd0b933e..6335d1fb 100644 --- a/internal/controller/repository_controller_test.go +++ b/internal/controller/repository_controller_test.go @@ -48,8 +48,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -69,6 +73,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -79,8 +98,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -96,6 +119,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -119,21 +149,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.UpdateRepository(repositories.NewUpdateRepoParams(). WithRepoID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&repositories.UpdateRepoOK{ Payload: params.Repository{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -150,8 +180,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "has-changed", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -171,6 +205,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "has-changed", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -181,8 +230,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "has-changed", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "has-changed", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -198,6 +251,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -221,7 +281,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) @@ -252,8 +312,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -273,6 +337,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -283,8 +362,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -300,6 +383,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -323,21 +413,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.UpdateRepository(repositories.NewUpdateRepoParams(). WithRepoID("e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&repositories.UpdateRepoOK{ Payload: params.Repository{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", PoolManagerStatus: params.PoolManagerStatus{ IsRunning: false, @@ -355,8 +445,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -373,6 +467,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -383,8 +492,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -400,6 +513,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -423,14 +543,14 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }}, nil) m.CreateRepository(repositories.NewCreateRepoParams().WithBody( params.CreateRepoParams{ Name: "new-repository", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", Owner: "test-repo", })).Return(&repositories.CreateRepoOK{ @@ -438,21 +558,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Name: "new-repository", ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) m.UpdateRepository(repositories.NewUpdateRepoParams(). WithRepoID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&repositories.UpdateRepoOK{ Payload: params.Repository{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "new-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -466,8 +586,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Namespace: "default", }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -484,6 +608,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -494,8 +633,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -511,6 +654,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.PoolManagerFailureReason), @@ -540,14 +690,14 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { m.UpdateRepository(repositories.NewUpdateRepoParams(). WithRepoID("e1dbf9a6-a9f6-4594-a5ac-12345"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&repositories.UpdateRepoOK{ Payload: params.Repository{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Name: "new-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -564,8 +714,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -585,6 +739,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectedObject: &garmoperatorv1alpha1.Repository{ ObjectMeta: metav1.ObjectMeta{ @@ -595,8 +764,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", - Owner: "test-repo", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, + Owner: "test-repo", WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -612,6 +785,13 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { LastTransitionTime: metav1.NewTime(time.Now()), Message: "Pool Manager is not running", }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.FetchingCredentialsRefSuccessReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Status: metav1.ConditionFalse, @@ -636,7 +816,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { m.CreateRepository(repositories.NewCreateRepoParams().WithBody( params.CreateRepoParams{ Name: "existing-repository", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", Owner: "test-repo", })).Return(&repositories.CreateRepoOK{ @@ -644,21 +824,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Name: "existing-repository", ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) m.UpdateRepository(repositories.NewUpdateRepoParams(). WithRepoID("9e0da3cb-130b-428d-aa8a-e314d955060e"). WithBody(params.UpdateEntityParams{ - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", })).Return(&repositories.UpdateRepoOK{ Payload: params.Repository{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Name: "existing-repository", Owner: "test-repo", - CredentialsName: "foobar", + CredentialsName: "github-creds", WebhookSecret: "foobar", }, }, nil) @@ -675,7 +855,11 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -693,7 +877,11 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -708,11 +896,18 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Message: "secrets \"my-webhook-secret\" not found", LastTransitionTime: metav1.NewTime(time.Now()), }, + { + Type: string(conditions.CredentialsReference), + Reason: string(conditions.UnknownReason), + Status: metav1.ConditionUnknown, + Message: conditions.CredentialsNotReconciledYetMsg, + LastTransitionTime: metav1.NewTime(time.Now()), + }, { Type: string(conditions.PoolManager), Reason: string(conditions.UnknownReason), Status: metav1.ConditionUnknown, - Message: "GARM server not reconciled yet", + Message: conditions.GarmServerNotReconciledYetMsg, LastTransitionTime: metav1.NewTime(time.Now()), }, { @@ -800,7 +995,11 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { }, }, Spec: garmoperatorv1alpha1.RepositorySpec{ - CredentialsName: "totally-insecure", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -820,6 +1019,21 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, + &garmoperatorv1alpha1.GitHubCredentials{ + ObjectMeta: metav1.ObjectMeta{ + Name: "github-creds", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Description: "github-creds", + EndpointRef: corev1.TypedLocalObjectReference{}, + AuthType: "pat", + SecretRef: garmoperatorv1alpha1.SecretRef{ + Name: "github-secret", + Key: "token", + }, + }, + }, }, expectGarmRequest: func(m *mock.MockRepositoryClientMockRecorder) { m.DeleteRepository( From 05619427835cc58dcdc08e33e1ce5f94996c98d8 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 20 Aug 2024 10:26:17 +0200 Subject: [PATCH 08/30] fix(controller): pool tests --- .../samples/garm-operator_v1alpha1_image.yaml | 3 +- internal/controller/pool_controller_test.go | 49 +++++++++++++++---- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/config/samples/garm-operator_v1alpha1_image.yaml b/config/samples/garm-operator_v1alpha1_image.yaml index 920c22e7..7634d50f 100644 --- a/config/samples/garm-operator_v1alpha1_image.yaml +++ b/config/samples/garm-operator_v1alpha1_image.yaml @@ -10,4 +10,5 @@ metadata: name: runner-default namespace: garm-operator-system spec: - tag: default-runner:linux-ubuntu-22.04-amd64-main-e4de304 + tag: localhost:5000/runner:linux-ubuntu-22:04-x86_64 + diff --git a/internal/controller/pool_controller_test.go b/internal/controller/pool_controller_test.go index 97b25d5f..e24dd1a1 100644 --- a/internal/controller/pool_controller_test.go +++ b/internal/controller/pool_controller_test.go @@ -167,7 +167,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -376,7 +380,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -564,7 +572,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -851,7 +863,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -1235,7 +1251,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -1298,7 +1318,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, Status: garmoperatorv1alpha1.PoolStatus{ ID: poolID, - // LastSyncError: "", }, }, expectedObject: &garmoperatorv1alpha1.Pool{ @@ -1381,7 +1400,11 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -1828,7 +1851,11 @@ func TestPoolController_ReconcileDelete(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", @@ -2041,7 +2068,11 @@ func TestPoolController_ReconcileDelete(t *testing.T) { Namespace: namespaceName, }, Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", + CredentialsRef: corev1.TypedLocalObjectReference{ + APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + Kind: "GitHubCredentials", + Name: "github-creds", + }, WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", From c790b09da351e0504156f3c3ba6ad9d442b979dd Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 20 Aug 2024 11:53:35 +0200 Subject: [PATCH 09/30] fix: linter --- api/v1alpha1/endpoint_types.go | 8 +-- api/v1alpha1/garmserverconfig_types.go | 32 ++++----- api/v1alpha1/githubcredentials_types.go | 10 +-- cmd/main.go | 10 +-- ...-operator.mercedes-benz.com_endpoints.yaml | 8 +-- ...r.mercedes-benz.com_garmserverconfigs.yaml | 35 ++++------ ...r.mercedes-benz.com_githubcredentials.yaml | 16 ++--- internal/controller/endpoint_controller.go | 23 +++---- internal/controller/enterprise_controller.go | 10 +-- .../controller/enterprise_controller_test.go | 3 +- .../controller/garmserverconfig_controller.go | 43 ++---------- .../githubcredentials_controller.go | 31 +++++---- .../controller/organization_controller.go | 10 +-- internal/controller/repository_controller.go | 10 +-- internal/controller/suite_test.go | 66 ------------------- pkg/client/controller.go | 3 +- pkg/client/credentials.go | 1 + pkg/client/endpoint.go | 1 + pkg/conditions/condition_types.go | 2 +- 19 files changed, 106 insertions(+), 216 deletions(-) delete mode 100644 internal/controller/suite_test.go diff --git a/api/v1alpha1/endpoint_types.go b/api/v1alpha1/endpoint_types.go index a9c34f4c..ca7d0b10 100644 --- a/api/v1alpha1/endpoint_types.go +++ b/api/v1alpha1/endpoint_types.go @@ -9,9 +9,9 @@ import ( // EndpointSpec defines the desired state of Endpoint type EndpointSpec struct { Description string `json:"description,omitempty"` - APIBaseURL string `json:"apiBaseURL,omitempty"` - UploadBaseURL string `json:"uploadBaseURL,omitempty"` - BaseURL string `json:"baseURL,omitempty"` + APIBaseURL string `json:"apiBaseUrl,omitempty"` + UploadBaseURL string `json:"uploadBaseUrl,omitempty"` + BaseURL string `json:"baseUrl,omitempty"` CACertBundle []byte `json:"caCertBundle,omitempty"` } @@ -23,7 +23,7 @@ type EndpointStatus struct { //+kubebuilder:object:root=true //+kubebuilder:resource:path=endpoints,scope=Namespaced,categories=garm,shortName=gep //+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".spec.apiBaseURL",description="API Base URL" +//+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".spec.apiBaseUrl",description="API Base URL" //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Endpoint" diff --git a/api/v1alpha1/garmserverconfig_types.go b/api/v1alpha1/garmserverconfig_types.go index 4c0b7109..6cee8e2b 100644 --- a/api/v1alpha1/garmserverconfig_types.go +++ b/api/v1alpha1/garmserverconfig_types.go @@ -8,33 +8,33 @@ import ( // GarmServerConfigSpec defines the desired state of GarmServerConfig type GarmServerConfigSpec struct { - MetadataURL string `json:"metadataURL,omitempty"` - CallbackURL string `json:"callbackURL,omitempty"` - WebhookURL string `json:"webhookURL,omitempty"` + MetadataURL string `json:"metadataUrl,omitempty"` + CallbackURL string `json:"callbackUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` } // GarmServerConfigStatus defines the observed state of GarmServerConfig type GarmServerConfigStatus struct { - ControllerID string `json:"controllerID"` - Hostname string `json:"hostname"` - MetadataURL string `json:"metadataURL"` - CallbackURL string `json:"callbackURL"` - WebhookURL string `json:"webhookURL"` - ControllerWebhookURL string `json:"controllerWebhookURL"` - MinimumJobAgeBackoff uint `json:"minimumJobAgeBackoff"` - Version string `json:"version"` + ControllerID string `json:"controllerId,omitempty"` + Hostname string `json:"hostname,omitempty"` + MetadataURL string `json:"metadataUrl,omitempty"` + CallbackURL string `json:"callbackUrl,omitempty"` + WebhookURL string `json:"webhookUrl,omitempty"` + ControllerWebhookURL string `json:"controllerWebhookUrl,omitempty"` + MinimumJobAgeBackoff uint `json:"minimumJobAgeBackoff,omitempty"` + Version string `json:"version,omitempty"` Conditions []metav1.Condition `json:"conditions,omitempty"` } //+kubebuilder:object:root=true //+kubebuilder:resource:path=garmserverconfigs,scope=Namespaced,categories=garm,shortName=server //+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.controllerID",description="Controller ID" +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.controllerId",description="Controller ID" //+kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description="Garm Version" -//+kubebuilder:printcolumn:name="MetadataURL",type="string",JSONPath=".status.metadataURL",description="MetadataURL",priority=1 -//+kubebuilder:printcolumn:name="CallbackURL",type="string",JSONPath=".status.callbackURL",description="CallbackURL",priority=1 -//+kubebuilder:printcolumn:name="WebhookURL",type="string",JSONPath=".status.webhookURL",description="WebhookURL",priority=1 -//+kubebuilder:printcolumn:name="ControllerWebhookURL",type="string",JSONPath=".status.controllerWebhookURL",description="ControllerWebhookURL",priority=1 +//+kubebuilder:printcolumn:name="MetadataURL",type="string",JSONPath=".status.metadataUrl",description="MetadataURL",priority=1 +//+kubebuilder:printcolumn:name="CallbackURL",type="string",JSONPath=".status.callbackUrl",description="CallbackURL",priority=1 +//+kubebuilder:printcolumn:name="WebhookURL",type="string",JSONPath=".status.webhookUrl",description="WebhookURL",priority=1 +//+kubebuilder:printcolumn:name="ControllerWebhookURL",type="string",JSONPath=".status.controllerWebhookUrl",description="ControllerWebhookURL",priority=1 //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GarmServerConfig" // GarmServerConfig is the Schema for the garmserverconfigs API diff --git a/api/v1alpha1/githubcredentials_types.go b/api/v1alpha1/githubcredentials_types.go index b161757d..c45d1ded 100644 --- a/api/v1alpha1/githubcredentials_types.go +++ b/api/v1alpha1/githubcredentials_types.go @@ -17,8 +17,8 @@ type GitHubCredentialsSpec struct { AuthType params.GithubAuthType `json:"authType"` // if AuthType is app - AppID int64 `json:"appID,omitempty"` - InstallationID int64 `json:"installationID,omitempty"` + AppID int64 `json:"appId,omitempty"` + InstallationID int64 `json:"installationId,omitempty"` // containing either privateKey or pat token SecretRef SecretRef `json:"secretRef,omitempty"` @@ -27,9 +27,9 @@ type GitHubCredentialsSpec struct { // GitHubCredentialsStatus defines the observed state of GitHubCredentials type GitHubCredentialsStatus struct { ID int64 `json:"id"` - APIBaseURL string `json:"apiBaseURL"` - UploadBaseURL string `json:"uploadBaseURL"` - BaseURL string `json:"baseURL"` + APIBaseURL string `json:"apiBaseUrl"` + UploadBaseURL string `json:"uploadBaseUrl"` + BaseURL string `json:"baseUrl"` Conditions []metav1.Condition `json:"conditions,omitempty"` } diff --git a/cmd/main.go b/cmd/main.go index dda99666..ac3f0ca5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -6,7 +6,6 @@ import ( "context" "fmt" "log" - "os" "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/runtime" @@ -215,8 +214,7 @@ func run() error { Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("garm-server-config-controller"), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "GarmServerConfig") - os.Exit(1) + return fmt.Errorf("unable to create controller GarmServerConfig: %w", err) } if err = (&garmcontroller.EndpointReconciler{ @@ -224,16 +222,14 @@ func run() error { Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("endpoint-controller"), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Endpoint") - os.Exit(1) + return fmt.Errorf("unable to create controller Endpoint: %w", err) } if err = (&garmcontroller.GitHubCredentialsReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("credentials-controller"), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "GitHubCredentials") - os.Exit(1) + return fmt.Errorf("unable to create controller GitHubCredentials: %w", err) } //+kubebuilder:scaffold:builder diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml index b08abb02..96312c9a 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml @@ -20,7 +20,7 @@ spec: versions: - additionalPrinterColumns: - description: API Base URL - jsonPath: .spec.apiBaseURL + jsonPath: .spec.apiBaseUrl name: URL type: string - jsonPath: .status.conditions[?(@.type=='Ready')].status @@ -59,16 +59,16 @@ spec: spec: description: EndpointSpec defines the desired state of Endpoint properties: - apiBaseURL: + apiBaseUrl: type: string - baseURL: + baseUrl: type: string caCertBundle: format: byte type: string description: type: string - uploadBaseURL: + uploadBaseUrl: type: string type: object status: diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml index bd6aeaf9..1139288b 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml @@ -20,7 +20,7 @@ spec: versions: - additionalPrinterColumns: - description: Controller ID - jsonPath: .status.controllerID + jsonPath: .status.controllerId name: ID type: string - description: Garm Version @@ -28,22 +28,22 @@ spec: name: Version type: string - description: MetadataURL - jsonPath: .status.metadataURL + jsonPath: .status.metadataUrl name: MetadataURL priority: 1 type: string - description: CallbackURL - jsonPath: .status.callbackURL + jsonPath: .status.callbackUrl name: CallbackURL priority: 1 type: string - description: WebhookURL - jsonPath: .status.webhookURL + jsonPath: .status.webhookUrl name: WebhookURL priority: 1 type: string - description: ControllerWebhookURL - jsonPath: .status.controllerWebhookURL + jsonPath: .status.controllerWebhookUrl name: ControllerWebhookURL priority: 1 type: string @@ -76,17 +76,17 @@ spec: spec: description: GarmServerConfigSpec defines the desired state of GarmServerConfig properties: - callbackURL: + callbackUrl: type: string - metadataURL: + metadataUrl: type: string - webhookURL: + webhookUrl: type: string type: object status: description: GarmServerConfigStatus defines the observed state of GarmServerConfig properties: - callbackURL: + callbackUrl: type: string conditions: items: @@ -157,29 +157,20 @@ spec: - type type: object type: array - controllerID: + controllerId: type: string - controllerWebhookURL: + controllerWebhookUrl: type: string hostname: type: string - metadataURL: + metadataUrl: type: string minimumJobAgeBackoff: type: integer version: type: string - webhookURL: + webhookUrl: type: string - required: - - callbackURL - - controllerID - - controllerWebhookURL - - hostname - - metadataURL - - minimumJobAgeBackoff - - version - - webhookURL type: object type: object served: true diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml index 76b40243..e85d1eb6 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml @@ -67,7 +67,7 @@ spec: spec: description: GitHubCredentialsSpec defines the desired state of GitHubCredentials properties: - appID: + appId: description: if AuthType is app format: int64 type: integer @@ -98,7 +98,7 @@ spec: - name type: object x-kubernetes-map-type: atomic - installationID: + installationId: format: int64 type: integer secretRef: @@ -123,9 +123,9 @@ spec: status: description: GitHubCredentialsStatus defines the observed state of GitHubCredentials properties: - apiBaseURL: + apiBaseUrl: type: string - baseURL: + baseUrl: type: string conditions: items: @@ -199,13 +199,13 @@ spec: id: format: int64 type: integer - uploadBaseURL: + uploadBaseUrl: type: string required: - - apiBaseURL - - baseURL + - apiBaseUrl + - baseUrl - id - - uploadBaseURL + - uploadBaseUrl type: object type: object served: true diff --git a/internal/controller/endpoint_controller.go b/internal/controller/endpoint_controller.go index 33501873..e9d254d8 100644 --- a/internal/controller/endpoint_controller.go +++ b/internal/controller/endpoint_controller.go @@ -5,25 +5,25 @@ package controller import ( "context" "fmt" + "reflect" + "github.com/cloudbase/garm/client/endpoints" "github.com/cloudbase/garm/params" - garmClient "github.com/mercedes-benz/garm-operator/pkg/client" - "github.com/mercedes-benz/garm-operator/pkg/client/key" - "github.com/mercedes-benz/garm-operator/pkg/event" - "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/client-go/tools/record" - "reflect" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/event" + "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" ) // EndpointReconciler reconciles a Endpoint object @@ -89,7 +89,7 @@ func (r *EndpointReconciler) reconcileNormal(ctx context.Context, client garmCli // if not found, create endpoint in garm db if reflect.ValueOf(garmEndpoint).IsZero() { - garmEndpoint, err = r.createEndpoint(ctx, client, endpoint) + garmEndpoint, err = r.createEndpoint(ctx, client, endpoint) // nolint:wastedassign if err != nil { event.Error(r.Recorder, endpoint, err.Error()) conditions.MarkFalse(endpoint, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -113,6 +113,7 @@ func (r *EndpointReconciler) reconcileNormal(ctx context.Context, client garmCli // set and update endpoint status conditions.MarkTrue(endpoint, conditions.ReadyCondition, conditions.SuccessfulReconcileReason, "") + log.Info("reconciling endpoint successfully done", "endpoint", garmEndpoint.Name) if err := r.Status().Update(ctx, endpoint); err != nil { return ctrl.Result{}, err } diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index 42bace77..ccdb3db5 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -5,24 +5,24 @@ package controller import ( "context" "fmt" - "k8s.io/apimachinery/pkg/types" "reflect" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/enterprises" "github.com/cloudbase/garm/params" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" "github.com/mercedes-benz/garm-operator/pkg/annotations" diff --git a/internal/controller/enterprise_controller_test.go b/internal/controller/enterprise_controller_test.go index fd942e20..308328bd 100644 --- a/internal/controller/enterprise_controller_test.go +++ b/internal/controller/enterprise_controller_test.go @@ -521,7 +521,8 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Key: "token", }, }, - }}, + }, + }, expectGarmRequest: func(m *mock.MockEnterpriseClientMockRecorder) { m.ListEnterprises(enterprises.NewListEnterprisesParams()).Return(&enterprises.ListEnterprisesOK{Payload: params.Enterprises{ { diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go index b1d82684..92501397 100644 --- a/internal/controller/garmserverconfig_controller.go +++ b/internal/controller/garmserverconfig_controller.go @@ -11,21 +11,18 @@ import ( garmcontroller "github.com/cloudbase/garm/client/controller" "github.com/cloudbase/garm/client/controller_info" "github.com/cloudbase/garm/params" - garmclient "github.com/mercedes-benz/garm-operator/pkg/client" - "github.com/mercedes-benz/garm-operator/pkg/client/key" - "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmclient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" ) // GarmServerConfigReconciler reconciles a GarmServerConfig object @@ -66,7 +63,7 @@ func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Req // Ignore objects that are paused if annotations.IsPaused(garmServerConfig) { - log.Info("Reconciliation is paused for GarmServerConfig: %s", garmServerConfig.Name) + log.Info("Reconciliation is paused for GarmServerConfig") return ctrl.Result{}, nil } @@ -84,30 +81,6 @@ func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, nil } -func (r *GarmServerConfigReconciler) createGarmServerConfigCR(ctx context.Context, controllerInfo *params.ControllerInfo, name, namespace string) error { - log := log.FromContext(ctx) - log.Info("Creating GarmServerConfig CR") - - garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ - MetadataURL: controllerInfo.MetadataURL, - CallbackURL: controllerInfo.CallbackURL, - WebhookURL: controllerInfo.WebhookURL, - }, - } - - err := r.Create(ctx, garmServerConfig) - if err != nil { - log.Error(err, "Failed to create GarmServerConfig CR") - return err - } - return nil -} - func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmclient.ControllerClient, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { log := log.FromContext(ctx) @@ -177,14 +150,6 @@ func (r *GarmServerConfigReconciler) needsStatusUpdate(controllerInfo *params.Co return !reflect.DeepEqual(garmServerConfigCR.Status, tempStatus) } -func (r *GarmServerConfigReconciler) ensureFinalizer(ctx context.Context, garmServerConfig *garmoperatorv1alpha1.GarmServerConfig) error { - if !controllerutil.ContainsFinalizer(garmServerConfig, key.RunnerFinalizerName) { - controllerutil.AddFinalizer(garmServerConfig, key.RunnerFinalizerName) - return r.Update(ctx, garmServerConfig) - } - return nil -} - func (r *GarmServerConfigReconciler) getControllerInfo(client garmclient.ControllerClient) (params.ControllerInfo, error) { controllerInfo, err := client.GetControllerInfo() if err == nil { diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go index 7177c754..d8e5220a 100644 --- a/internal/controller/githubcredentials_controller.go +++ b/internal/controller/githubcredentials_controller.go @@ -5,33 +5,33 @@ package controller import ( "context" "fmt" + "reflect" + garmcredentials "github.com/cloudbase/garm/client/credentials" garmconfig "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/params" - garmClient "github.com/mercedes-benz/garm-operator/pkg/client" - "github.com/mercedes-benz/garm-operator/pkg/client/key" - "github.com/mercedes-benz/garm-operator/pkg/event" - "github.com/mercedes-benz/garm-operator/pkg/secret" - "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" - "reflect" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmClient "github.com/mercedes-benz/garm-operator/pkg/client" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/event" + "github.com/mercedes-benz/garm-operator/pkg/secret" + "github.com/mercedes-benz/garm-operator/pkg/util" + "github.com/mercedes-benz/garm-operator/pkg/util/annotations" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" ) // GitHubCredentialsReconciler reconciles a GitHubCredentials object @@ -95,7 +95,7 @@ func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, clien return ctrl.Result{}, err } - //fetch endpoint resource + // fetch endpoint resource endpoint, err := r.getEndpointRef(ctx, credentials) if err != nil { conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.FetchingEndpointRefFailedReason, err.Error()) @@ -107,7 +107,7 @@ func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, clien } conditions.MarkTrue(credentials, conditions.EndpointReference, conditions.FetchingEndpointRefSuccessReason, "Successfully fetched Endpoint CR Ref") - //fetch secret + // fetch secret githubSecret, err := secret.FetchRef(ctx, r.Client, &credentials.Spec.SecretRef, credentials.Namespace) if err != nil { conditions.MarkFalse(credentials, conditions.ReadyCondition, conditions.FetchingSecretRefFailedReason, err.Error()) @@ -198,7 +198,6 @@ func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, cli } garmCredentials, err := client.CreateCredentials(garmcredentials.NewCreateCredentialsParams().WithBody(req)) - if err != nil { log.V(1).Info(fmt.Sprintf("client.CreateCredentials error: %s", err)) return params.GithubCredentials{}, err diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index 719ece89..0b2792a3 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -5,24 +5,24 @@ package controller import ( "context" "fmt" - "k8s.io/apimachinery/pkg/types" "reflect" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/organizations" "github.com/cloudbase/garm/params" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" "github.com/mercedes-benz/garm-operator/pkg/annotations" diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index cd625f39..0a1f8c0c 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -5,24 +5,24 @@ package controller import ( "context" "fmt" - "k8s.io/apimachinery/pkg/types" "reflect" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/reconcile" "strings" "github.com/cloudbase/garm/client/repositories" "github.com/cloudbase/garm/params" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" "github.com/mercedes-benz/garm-operator/pkg/annotations" diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go deleted file mode 100644 index 84948041..00000000 --- a/internal/controller/suite_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT - -package controller - -import ( - "path/filepath" - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" - //+kubebuilder:scaffold:imports -) - -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment - -func TestControllers(t *testing.T) { - RegisterFailHandler(Fail) - - RunSpecs(t, "Controller Suite") -} - -var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) - - By("bootstrapping test environment") - testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, - ErrorIfCRDPathMissing: true, - } - - var err error - // cfg is defined in this file globally. - cfg, err = testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) - - err = garmoperatorv1alpha1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - - //+kubebuilder:scaffold:scheme - - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) - -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/pkg/client/controller.go b/pkg/client/controller.go index 9d9e3a5d..99b47eea 100644 --- a/pkg/client/controller.go +++ b/pkg/client/controller.go @@ -2,9 +2,10 @@ package client import ( "github.com/cloudbase/garm/client/controller" + "github.com/cloudbase/garm/client/controller_info" + "github.com/mercedes-benz/garm-operator/pkg/metrics" ) -import "github.com/cloudbase/garm/client/controller_info" type ControllerClient interface { GetControllerInfo() (*controller_info.ControllerInfoOK, error) diff --git a/pkg/client/credentials.go b/pkg/client/credentials.go index 4e54799e..ea6cd362 100644 --- a/pkg/client/credentials.go +++ b/pkg/client/credentials.go @@ -2,6 +2,7 @@ package client import ( "github.com/cloudbase/garm/client/credentials" + "github.com/mercedes-benz/garm-operator/pkg/metrics" ) diff --git a/pkg/client/endpoint.go b/pkg/client/endpoint.go index fd276096..975c698b 100644 --- a/pkg/client/endpoint.go +++ b/pkg/client/endpoint.go @@ -2,6 +2,7 @@ package client import ( "github.com/cloudbase/garm/client/endpoints" + "github.com/mercedes-benz/garm-operator/pkg/metrics" ) diff --git a/pkg/conditions/condition_types.go b/pkg/conditions/condition_types.go index 9f6c241d..097ae173 100644 --- a/pkg/conditions/condition_types.go +++ b/pkg/conditions/condition_types.go @@ -61,5 +61,5 @@ const ( DeletingRepoMsg string = "Deleting repository" DeletingPoolMsg string = "Deleting pool" DeletingEndpointMsg string = "Deleting endpoint" - DeletingCredentialsMsg string = "Deleting credentials" + DeletingCredentialsMsg string = "Deleting credentials" // #nosec G101 ) From 37040b8eaa5a586b03a1ac9eeb4b1df882e106f5 Mon Sep 17 00:00:00 2001 From: rthalho Date: Sun, 25 Aug 2024 22:08:47 +0200 Subject: [PATCH 10/30] fix(api): rename endpoint crd to github_endpoint crd --- PROJECT | 2 +- Tiltfile | 2 + api/v1alpha1/githubcredentials_types.go | 2 +- ...point_types.go => githubendpoint_types.go} | 34 ++-- api/v1alpha1/zz_generated.deepcopy.go | 174 +++++++++--------- cmd/main.go | 9 +- ...r.mercedes-benz.com_githubcredentials.yaml | 4 +- ...or.mercedes-benz.com_githubendpoints.yaml} | 18 +- config/crd/kustomization.yaml | 6 +- ...ml => cainjection_in_githubendpoints.yaml} | 2 +- ...s.yaml => webhook_in_githubendpoints.yaml} | 2 +- config/rbac/endpoint_editor_role.yaml | 31 ---- config/rbac/endpoint_viewer_role.yaml | 27 --- config/rbac/role.yaml | 24 +-- ...arm-operator_v1alpha1_githubendpoint.yaml} | 0 config/samples/kustomization.yaml | 2 +- .../githubcredentials_controller.go | 6 +- ...roller.go => githubendpoint_controller.go} | 36 ++-- 18 files changed, 163 insertions(+), 218 deletions(-) rename api/v1alpha1/{endpoint_types.go => githubendpoint_types.go} (56%) rename config/crd/bases/{garm-operator.mercedes-benz.com_endpoints.yaml => garm-operator.mercedes-benz.com_githubendpoints.yaml} (92%) rename config/crd/patches/{cainjection_in_endpoints.yaml => cainjection_in_githubendpoints.yaml} (81%) rename config/crd/patches/{webhook_in_endpoints.yaml => webhook_in_githubendpoints.yaml} (86%) delete mode 100644 config/rbac/endpoint_editor_role.yaml delete mode 100644 config/rbac/endpoint_viewer_role.yaml rename config/samples/{garm-operator_v1alpha1_endpoint.yaml => garm-operator_v1alpha1_githubendpoint.yaml} (100%) rename internal/controller/{endpoint_controller.go => githubendpoint_controller.go} (80%) diff --git a/PROJECT b/PROJECT index 7a4d63a2..7e18a698 100644 --- a/PROJECT +++ b/PROJECT @@ -84,7 +84,7 @@ resources: controller: true domain: mercedes-benz.com group: garm-operator - kind: Endpoint + kind: GitHubEndpoint path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 - api: diff --git a/Tiltfile b/Tiltfile index dc0719af..7cf3cbba 100644 --- a/Tiltfile +++ b/Tiltfile @@ -37,6 +37,8 @@ k8s_resource( 'runners.garm-operator.mercedes-benz.com:customresourcedefinition', 'repositories.garm-operator.mercedes-benz.com:customresourcedefinition', 'garmserverconfigs.garm-operator.mercedes-benz.com:customresourcedefinition', + 'githubcredentials.garm-operator.mercedes-benz.com:customresourcedefinition', + 'githubendpoints.garm-operator.mercedes-benz.com:customresourcedefinition', 'garm-operator-controller-manager:serviceaccount', 'garm-operator-leader-election-role:role', 'garm-operator-manager-role:clusterrole', diff --git a/api/v1alpha1/githubcredentials_types.go b/api/v1alpha1/githubcredentials_types.go index c45d1ded..7e99d32b 100644 --- a/api/v1alpha1/githubcredentials_types.go +++ b/api/v1alpha1/githubcredentials_types.go @@ -41,7 +41,7 @@ type GitHubCredentialsStatus struct { //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 //+kubebuilder:printcolumn:name="AuthType",type="string",JSONPath=`.spec.authType`,description="Authentication type" -//+kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=`.spec.endpointRef.name`,description="Endpoint name these credentials are tied to" +//+kubebuilder:printcolumn:name="GitHubEndpoint",type="string",JSONPath=`.spec.endpointRef.name`,description="GitHubEndpoint name these credentials are tied to" //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GitHubCredentials" // GitHubCredentials is the Schema for the githubcredentials API diff --git a/api/v1alpha1/endpoint_types.go b/api/v1alpha1/githubendpoint_types.go similarity index 56% rename from api/v1alpha1/endpoint_types.go rename to api/v1alpha1/githubendpoint_types.go index ca7d0b10..67550793 100644 --- a/api/v1alpha1/endpoint_types.go +++ b/api/v1alpha1/githubendpoint_types.go @@ -6,54 +6,54 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EndpointSpec defines the desired state of Endpoint -type EndpointSpec struct { +// GitHubEndpointSpec defines the desired state of GitHubEndpoint +type GitHubEndpointSpec struct { Description string `json:"description,omitempty"` APIBaseURL string `json:"apiBaseUrl,omitempty"` UploadBaseURL string `json:"uploadBaseUrl,omitempty"` BaseURL string `json:"baseUrl,omitempty"` - CACertBundle []byte `json:"caCertBundle,omitempty"` + CACertBundle []byte `json:"caCertBundle,omitempty"` // TODO: This should be a secret reference } -// EndpointStatus defines the observed state of Endpoint -type EndpointStatus struct { +// GitHubEndpointStatus defines the observed state of GitHubEndpoint +type GitHubEndpointStatus struct { Conditions []metav1.Condition `json:"conditions,omitempty"` } //+kubebuilder:object:root=true -//+kubebuilder:resource:path=endpoints,scope=Namespaced,categories=garm,shortName=gep +//+kubebuilder:resource:path=githubendpoints,scope=Namespaced,categories=garm,shortName=gep //+kubebuilder:subresource:status //+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".spec.apiBaseUrl",description="API Base URL" //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 -//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Endpoint" +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GitHubEndpoint" -// Endpoint is the Schema for the endpoints API -type Endpoint struct { +// GitHubEndpoint is the Schema for the githubendpoints API +type GitHubEndpoint struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec EndpointSpec `json:"spec,omitempty"` - Status EndpointStatus `json:"status,omitempty"` + Spec GitHubEndpointSpec `json:"spec,omitempty"` + Status GitHubEndpointStatus `json:"status,omitempty"` } -func (e *Endpoint) SetConditions(conditions []metav1.Condition) { +func (e *GitHubEndpoint) SetConditions(conditions []metav1.Condition) { e.Status.Conditions = conditions } -func (e *Endpoint) GetConditions() []metav1.Condition { +func (e *GitHubEndpoint) GetConditions() []metav1.Condition { return e.Status.Conditions } //+kubebuilder:object:root=true -// EndpointList contains a list of Endpoint -type EndpointList struct { +// GitHubEndpointList contains a list of GitHubEndpoint +type GitHubEndpointList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []Endpoint `json:"items"` + Items []GitHubEndpoint `json:"items"` } func init() { - SchemeBuilder.Register(&Endpoint{}, &EndpointList{}) + SchemeBuilder.Register(&GitHubEndpoint{}, &GitHubEndpointList{}) } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 6b604df8..b6ab0233 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -13,7 +13,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Endpoint) DeepCopyInto(out *Endpoint) { +func (in *Enterprise) DeepCopyInto(out *Enterprise) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -21,18 +21,18 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) { in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. -func (in *Endpoint) DeepCopy() *Endpoint { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Enterprise. +func (in *Enterprise) DeepCopy() *Enterprise { if in == nil { return nil } - out := new(Endpoint) + out := new(Enterprise) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Endpoint) DeepCopyObject() runtime.Object { +func (in *Enterprise) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -40,31 +40,31 @@ func (in *Endpoint) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EndpointList) DeepCopyInto(out *EndpointList) { +func (in *EnterpriseList) DeepCopyInto(out *EnterpriseList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]Endpoint, len(*in)) + *out = make([]Enterprise, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointList. -func (in *EndpointList) DeepCopy() *EndpointList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseList. +func (in *EnterpriseList) DeepCopy() *EnterpriseList { if in == nil { return nil } - out := new(EndpointList) + out := new(EnterpriseList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *EndpointList) DeepCopyObject() runtime.Object { +func (in *EnterpriseList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -72,27 +72,24 @@ func (in *EndpointList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EndpointSpec) DeepCopyInto(out *EndpointSpec) { +func (in *EnterpriseSpec) DeepCopyInto(out *EnterpriseSpec) { *out = *in - if in.CACertBundle != nil { - in, out := &in.CACertBundle, &out.CACertBundle - *out = make([]byte, len(*in)) - copy(*out, *in) - } + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) + out.WebhookSecretRef = in.WebhookSecretRef } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointSpec. -func (in *EndpointSpec) DeepCopy() *EndpointSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseSpec. +func (in *EnterpriseSpec) DeepCopy() *EnterpriseSpec { if in == nil { return nil } - out := new(EndpointSpec) + out := new(EnterpriseSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) { +func (in *EnterpriseStatus) DeepCopyInto(out *EnterpriseStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -103,37 +100,37 @@ func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointStatus. -func (in *EndpointStatus) DeepCopy() *EndpointStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseStatus. +func (in *EnterpriseStatus) DeepCopy() *EnterpriseStatus { if in == nil { return nil } - out := new(EndpointStatus) + out := new(EnterpriseStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Enterprise) DeepCopyInto(out *Enterprise) { +func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Enterprise. -func (in *Enterprise) DeepCopy() *Enterprise { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. +func (in *GarmServerConfig) DeepCopy() *GarmServerConfig { if in == nil { return nil } - out := new(Enterprise) + out := new(GarmServerConfig) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Enterprise) DeepCopyObject() runtime.Object { +func (in *GarmServerConfig) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -141,31 +138,31 @@ func (in *Enterprise) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EnterpriseList) DeepCopyInto(out *EnterpriseList) { +func (in *GarmServerConfigList) DeepCopyInto(out *GarmServerConfigList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]Enterprise, len(*in)) + *out = make([]GarmServerConfig, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseList. -func (in *EnterpriseList) DeepCopy() *EnterpriseList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigList. +func (in *GarmServerConfigList) DeepCopy() *GarmServerConfigList { if in == nil { return nil } - out := new(EnterpriseList) + out := new(GarmServerConfigList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *EnterpriseList) DeepCopyObject() runtime.Object { +func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -173,24 +170,22 @@ func (in *EnterpriseList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EnterpriseSpec) DeepCopyInto(out *EnterpriseSpec) { +func (in *GarmServerConfigSpec) DeepCopyInto(out *GarmServerConfigSpec) { *out = *in - in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) - out.WebhookSecretRef = in.WebhookSecretRef } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseSpec. -func (in *EnterpriseSpec) DeepCopy() *EnterpriseSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigSpec. +func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { if in == nil { return nil } - out := new(EnterpriseSpec) + out := new(GarmServerConfigSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EnterpriseStatus) DeepCopyInto(out *EnterpriseStatus) { +func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -201,37 +196,37 @@ func (in *EnterpriseStatus) DeepCopyInto(out *EnterpriseStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseStatus. -func (in *EnterpriseStatus) DeepCopy() *EnterpriseStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. +func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { if in == nil { return nil } - out := new(EnterpriseStatus) + out := new(GarmServerConfigStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { +func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. -func (in *GarmServerConfig) DeepCopy() *GarmServerConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. +func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { if in == nil { return nil } - out := new(GarmServerConfig) + out := new(GitHubCredentials) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GarmServerConfig) DeepCopyObject() runtime.Object { +func (in *GitHubCredentials) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -239,31 +234,31 @@ func (in *GarmServerConfig) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigList) DeepCopyInto(out *GarmServerConfigList) { +func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]GarmServerConfig, len(*in)) + *out = make([]GitHubCredentials, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigList. -func (in *GarmServerConfigList) DeepCopy() *GarmServerConfigList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. +func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { if in == nil { return nil } - out := new(GarmServerConfigList) + out := new(GitHubCredentialsList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { +func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -271,22 +266,24 @@ func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigSpec) DeepCopyInto(out *GarmServerConfigSpec) { +func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { *out = *in + in.EndpointRef.DeepCopyInto(&out.EndpointRef) + out.SecretRef = in.SecretRef } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigSpec. -func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. +func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { if in == nil { return nil } - out := new(GarmServerConfigSpec) + out := new(GitHubCredentialsSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { +func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -297,18 +294,18 @@ func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. -func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. +func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { if in == nil { return nil } - out := new(GarmServerConfigStatus) + out := new(GitHubCredentialsStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { +func (in *GitHubEndpoint) DeepCopyInto(out *GitHubEndpoint) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -316,18 +313,18 @@ func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. -func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpoint. +func (in *GitHubEndpoint) DeepCopy() *GitHubEndpoint { if in == nil { return nil } - out := new(GitHubCredentials) + out := new(GitHubEndpoint) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentials) DeepCopyObject() runtime.Object { +func (in *GitHubEndpoint) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -335,31 +332,31 @@ func (in *GitHubCredentials) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { +func (in *GitHubEndpointList) DeepCopyInto(out *GitHubEndpointList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]GitHubCredentials, len(*in)) + *out = make([]GitHubEndpoint, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. -func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointList. +func (in *GitHubEndpointList) DeepCopy() *GitHubEndpointList { if in == nil { return nil } - out := new(GitHubCredentialsList) + out := new(GitHubEndpointList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { +func (in *GitHubEndpointList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -367,24 +364,27 @@ func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { +func (in *GitHubEndpointSpec) DeepCopyInto(out *GitHubEndpointSpec) { *out = *in - in.EndpointRef.DeepCopyInto(&out.EndpointRef) - out.SecretRef = in.SecretRef + if in.CACertBundle != nil { + in, out := &in.CACertBundle, &out.CACertBundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. -func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointSpec. +func (in *GitHubEndpointSpec) DeepCopy() *GitHubEndpointSpec { if in == nil { return nil } - out := new(GitHubCredentialsSpec) + out := new(GitHubEndpointSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { +func (in *GitHubEndpointStatus) DeepCopyInto(out *GitHubEndpointStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -395,12 +395,12 @@ func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. -func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointStatus. +func (in *GitHubEndpointStatus) DeepCopy() *GitHubEndpointStatus { if in == nil { return nil } - out := new(GitHubCredentialsStatus) + out := new(GitHubEndpointStatus) in.DeepCopyInto(out) return out } diff --git a/cmd/main.go b/cmd/main.go index ac3f0ca5..9b41ee99 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -217,17 +217,18 @@ func run() error { return fmt.Errorf("unable to create controller GarmServerConfig: %w", err) } - if err = (&garmcontroller.EndpointReconciler{ + if err = (&garmcontroller.GitHubEndpointReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("endpoint-controller"), + Recorder: mgr.GetEventRecorderFor("github-endpoint-controller"), }).SetupWithManager(mgr); err != nil { - return fmt.Errorf("unable to create controller Endpoint: %w", err) + return fmt.Errorf("unable to create controller GitHubEndpoint: %w", err) } + if err = (&garmcontroller.GitHubCredentialsReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("credentials-controller"), + Recorder: mgr.GetEventRecorderFor("github-credentials-controller"), }).SetupWithManager(mgr); err != nil { return fmt.Errorf("unable to create controller GitHubCredentials: %w", err) } diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml index e85d1eb6..6d85c9b3 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml @@ -34,9 +34,9 @@ spec: jsonPath: .spec.authType name: AuthType type: string - - description: Endpoint name these credentials are tied to + - description: GitHubEndpoint name these credentials are tied to jsonPath: .spec.endpointRef.name - name: Endpoint + name: GitHubEndpoint type: string - description: Time duration since creation of GitHubCredentials jsonPath: .metadata.creationTimestamp diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml similarity index 92% rename from config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml rename to config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml index 96312c9a..c884b1ef 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_endpoints.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml @@ -4,18 +4,18 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.15.0 - name: endpoints.garm-operator.mercedes-benz.com + name: githubendpoints.garm-operator.mercedes-benz.com spec: group: garm-operator.mercedes-benz.com names: categories: - garm - kind: Endpoint - listKind: EndpointList - plural: endpoints + kind: GitHubEndpoint + listKind: GitHubEndpointList + plural: githubendpoints shortNames: - gep - singular: endpoint + singular: githubendpoint scope: Namespaced versions: - additionalPrinterColumns: @@ -30,14 +30,14 @@ spec: name: Error priority: 1 type: string - - description: Time duration since creation of Endpoint + - description: Time duration since creation of GitHubEndpoint jsonPath: .metadata.creationTimestamp name: Age type: date name: v1alpha1 schema: openAPIV3Schema: - description: Endpoint is the Schema for the endpoints API + description: GitHubEndpoint is the Schema for the githubendpoints API properties: apiVersion: description: |- @@ -57,7 +57,7 @@ spec: metadata: type: object spec: - description: EndpointSpec defines the desired state of Endpoint + description: GitHubEndpointSpec defines the desired state of GitHubEndpoint properties: apiBaseUrl: type: string @@ -72,7 +72,7 @@ spec: type: string type: object status: - description: EndpointStatus defines the observed state of Endpoint + description: GitHubEndpointStatus defines the observed state of GitHubEndpoint properties: conditions: items: diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 37ca0d20..95454ebe 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -9,7 +9,7 @@ resources: - bases/garm-operator.mercedes-benz.com_repositories.yaml - bases/garm-operator.mercedes-benz.com_runners.yaml - bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml -- bases/garm-operator.mercedes-benz.com_endpoints.yaml +- bases/garm-operator.mercedes-benz.com_githubendpoints.yaml - bases/garm-operator.mercedes-benz.com_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizeresource @@ -22,7 +22,7 @@ patches: - path: patches/webhook_in_repositories.yaml #- path: patches/webhook_in_runners.yaml #- path: patches/webhook_in_garmserverconfigs.yaml -#- path: patches/webhook_in_endpoints.yaml +#- path: patches/webhook_in_githubendpoints.yaml #- path: patches/webhook_in_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch @@ -35,7 +35,7 @@ patches: - path: patches/cainjection_in_repositories.yaml #- path: patches/cainjection_in_runners.yaml #- path: patches/cainjection_in_garmserverconfigs.yaml -#- path: patches/cainjection_in_endpoints.yaml +#- path: patches/cainjection_in_githubendpoints.yaml #- path: patches/cainjection_in_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch diff --git a/config/crd/patches/cainjection_in_endpoints.yaml b/config/crd/patches/cainjection_in_githubendpoints.yaml similarity index 81% rename from config/crd/patches/cainjection_in_endpoints.yaml rename to config/crd/patches/cainjection_in_githubendpoints.yaml index 80f233b2..a7eec53d 100644 --- a/config/crd/patches/cainjection_in_endpoints.yaml +++ b/config/crd/patches/cainjection_in_githubendpoints.yaml @@ -4,4 +4,4 @@ kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME - name: endpoints.garm-operator.mercedes-benz.com + name: githubendpoints.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/webhook_in_endpoints.yaml b/config/crd/patches/webhook_in_githubendpoints.yaml similarity index 86% rename from config/crd/patches/webhook_in_endpoints.yaml rename to config/crd/patches/webhook_in_githubendpoints.yaml index c99460e4..eed1eba2 100644 --- a/config/crd/patches/webhook_in_endpoints.yaml +++ b/config/crd/patches/webhook_in_githubendpoints.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: endpoints.garm-operator.mercedes-benz.com + name: githubendpoints.garm-operator.mercedes-benz.com spec: conversion: strategy: Webhook diff --git a/config/rbac/endpoint_editor_role.yaml b/config/rbac/endpoint_editor_role.yaml deleted file mode 100644 index 106ffce4..00000000 --- a/config/rbac/endpoint_editor_role.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# permissions for end users to edit endpoints. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: endpoint-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: garm-operator - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - name: endpoint-editor-role -rules: -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - endpoints - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - endpoints/status - verbs: - - get diff --git a/config/rbac/endpoint_viewer_role.yaml b/config/rbac/endpoint_viewer_role.yaml deleted file mode 100644 index d0dfab51..00000000 --- a/config/rbac/endpoint_viewer_role.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# permissions for end users to view endpoints. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: endpoint-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: garm-operator - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - name: endpoint-viewer-role -rules: -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - endpoints - verbs: - - get - - list - - watch -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - endpoints/status - verbs: - - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 4be340bc..78deb244 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -29,7 +29,7 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - endpoints + - enterprises verbs: - create - delete @@ -41,13 +41,13 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - endpoints/finalizers + - enterprises/finalizers verbs: - update - apiGroups: - garm-operator.mercedes-benz.com resources: - - endpoints/status + - enterprises/status verbs: - get - patch @@ -55,7 +55,7 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - enterprises + - garmserverconfigs verbs: - create - delete @@ -67,13 +67,13 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - enterprises/finalizers + - garmserverconfigs/finalizers verbs: - update - apiGroups: - garm-operator.mercedes-benz.com resources: - - enterprises/status + - garmserverconfigs/status verbs: - get - patch @@ -81,7 +81,7 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - garmserverconfigs + - githubcredentials verbs: - create - delete @@ -93,13 +93,13 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - garmserverconfigs/finalizers + - githubcredentials/finalizers verbs: - update - apiGroups: - garm-operator.mercedes-benz.com resources: - - garmserverconfigs/status + - githubcredentials/status verbs: - get - patch @@ -107,7 +107,7 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials + - githubendpoints verbs: - create - delete @@ -119,13 +119,13 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials/finalizers + - githubendpoints/finalizers verbs: - update - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials/status + - githubendpoints/status verbs: - get - patch diff --git a/config/samples/garm-operator_v1alpha1_endpoint.yaml b/config/samples/garm-operator_v1alpha1_githubendpoint.yaml similarity index 100% rename from config/samples/garm-operator_v1alpha1_endpoint.yaml rename to config/samples/garm-operator_v1alpha1_githubendpoint.yaml diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 85ac1266..f611d7cd 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -7,6 +7,6 @@ resources: - garm-operator_v1alpha1_repository.yaml - garm-operator_v1alpha1_runner.yaml - garm-operator_v1alpha1_garmserverconfig.yaml - - garm-operator_v1alpha1_endpoint.yaml + - garm-operator_v1alpha1_githubendpoint.yaml - garm-operator_v1alpha1_githubcredentials.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go index d8e5220a..da405c99 100644 --- a/internal/controller/githubcredentials_controller.go +++ b/internal/controller/githubcredentials_controller.go @@ -105,7 +105,7 @@ func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, clien } return ctrl.Result{}, err } - conditions.MarkTrue(credentials, conditions.EndpointReference, conditions.FetchingEndpointRefSuccessReason, "Successfully fetched Endpoint CR Ref") + conditions.MarkTrue(credentials, conditions.EndpointReference, conditions.FetchingEndpointRefSuccessReason, "Successfully fetched GitHubEndpoint CR Ref") // fetch secret githubSecret, err := secret.FetchRef(ctx, r.Client, &credentials.Spec.SecretRef, credentials.Namespace) @@ -281,8 +281,8 @@ func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, clien return ctrl.Result{}, nil } -func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) (*garmoperatorv1alpha1.Endpoint, error) { - endpoint := &garmoperatorv1alpha1.Endpoint{} +func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) (*garmoperatorv1alpha1.GitHubEndpoint, error) { + endpoint := &garmoperatorv1alpha1.GitHubEndpoint{} err := r.Get(ctx, types.NamespacedName{ Namespace: credentials.Namespace, Name: credentials.Spec.EndpointRef.Name, diff --git a/internal/controller/endpoint_controller.go b/internal/controller/githubendpoint_controller.go similarity index 80% rename from internal/controller/endpoint_controller.go rename to internal/controller/githubendpoint_controller.go index e9d254d8..bc808949 100644 --- a/internal/controller/endpoint_controller.go +++ b/internal/controller/githubendpoint_controller.go @@ -26,26 +26,26 @@ import ( "github.com/mercedes-benz/garm-operator/pkg/util/conditions" ) -// EndpointReconciler reconciles a Endpoint object -type EndpointReconciler struct { +// GitHubEndpointReconciler reconciles a GitHubEndpoint object +type GitHubEndpointReconciler struct { client.Client Scheme *runtime.Scheme Recorder record.EventRecorder } //+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=endpoints/finalizers,verbs=update +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubendpoints,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubendpoints/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubendpoints/finalizers,verbs=update // +kubebuilder:rbac:groups="",namespace=xxxxx,resources=secrets,verbs=get;list;watch; -func (r *EndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *GitHubEndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - endpoint := &garmoperatorv1alpha1.Endpoint{} + endpoint := &garmoperatorv1alpha1.GitHubEndpoint{} if err := r.Get(ctx, req.NamespacedName, endpoint); err != nil { if apierrors.IsNotFound(err) { - log.Info("Endpoint resource not found.") + log.Info("GitHubEndpoint resource not found.") return ctrl.Result{}, nil } return ctrl.Result{}, err @@ -67,11 +67,11 @@ func (r *EndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c return r.reconcileNormal(ctx, endpointClient, endpoint) } -func (r *EndpointReconciler) reconcileNormal(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (ctrl.Result, error) { +func (r *GitHubEndpointReconciler) reconcileNormal(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) - // If the Endpoint doesn't have our finalizer, add it. + // If the GitHubEndpoint doesn't have our finalizer, add it. if err := r.ensureFinalizer(ctx, endpoint); err != nil { return ctrl.Result{}, err } @@ -122,7 +122,7 @@ func (r *EndpointReconciler) reconcileNormal(ctx context.Context, client garmCli return ctrl.Result{}, nil } -func (r *EndpointReconciler) getExistingEndpoint(client garmClient.EndpointClient, name string) (params.GithubEndpoint, error) { +func (r *GitHubEndpointReconciler) getExistingEndpoint(client garmClient.EndpointClient, name string) (params.GithubEndpoint, error) { endpoint, err := client.GetEndpoint(endpoints.NewGetGithubEndpointParams().WithName(name)) if err != nil && garmClient.IsNotFoundError(err) { return params.GithubEndpoint{}, nil @@ -135,11 +135,11 @@ func (r *EndpointReconciler) getExistingEndpoint(client garmClient.EndpointClien return endpoint.Payload, nil } -func (r *EndpointReconciler) createEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (params.GithubEndpoint, error) { +func (r *GitHubEndpointReconciler) createEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (params.GithubEndpoint, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) - log.Info("Endpoint doesn't exist on garm side. Creating new endpoint in garm.") + log.Info("GitHubEndpoint doesn't exist on garm side. Creating new endpoint in garm.") event.Creating(r.Recorder, endpoint, "endpoint doesn't exist on garm side") retValue, err := client.CreateEndpoint(endpoints.NewCreateGithubEndpointParams().WithBody(params.CreateGithubEndpointParams{ @@ -163,7 +163,7 @@ func (r *EndpointReconciler) createEndpoint(ctx context.Context, client garmClie return retValue.Payload, nil } -func (r *EndpointReconciler) updateEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (params.GithubEndpoint, error) { +func (r *GitHubEndpointReconciler) updateEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (params.GithubEndpoint, error) { log := log.FromContext(ctx) log.V(1).Info("update endpoint") @@ -185,7 +185,7 @@ func (r *EndpointReconciler) updateEndpoint(ctx context.Context, client garmClie return retValue.Payload, nil } -func (r *EndpointReconciler) reconcileDelete(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.Endpoint) (ctrl.Result, error) { +func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) @@ -222,7 +222,7 @@ func (r *EndpointReconciler) reconcileDelete(ctx context.Context, client garmCli return ctrl.Result{}, nil } -func (r *EndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1alpha1.Endpoint) error { +func (r *GitHubEndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1alpha1.GitHubEndpoint) error { if !controllerutil.ContainsFinalizer(endpoint, key.EndpointFinalizerName) { controllerutil.AddFinalizer(endpoint, key.EndpointFinalizerName) return r.Update(ctx, endpoint) @@ -231,8 +231,8 @@ func (r *EndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garm } // SetupWithManager sets up the controller with the Manager. -func (r *EndpointReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *GitHubEndpointReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Endpoint{}). + For(&garmoperatorv1alpha1.GitHubEndpoint{}). Complete(r) } From 1abee195817ff59fbfd84176c5f35232b7374d19 Mon Sep 17 00:00:00 2001 From: rthalho Date: Mon, 26 Aug 2024 23:00:14 +0200 Subject: [PATCH 11/30] feat(test): add github_endpoint reconciler tests --- .../garmserverconfig_controller_test.go | 117 +++++ .../controller/githubendpoint_controller.go | 8 +- .../githubendpoint_controller_test.go | 493 ++++++++++++++++++ internal/controller/pool_controller_test.go | 6 +- pkg/client/key/key.go | 18 +- pkg/client/mock/controller.go | 72 +++ pkg/client/mock/credentials.go | 115 ++++ pkg/client/mock/doc.go | 6 + pkg/client/mock/endpoint.go | 115 ++++ 9 files changed, 932 insertions(+), 18 deletions(-) create mode 100644 internal/controller/githubendpoint_controller_test.go create mode 100644 pkg/client/mock/controller.go create mode 100644 pkg/client/mock/credentials.go create mode 100644 pkg/client/mock/endpoint.go diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go index b0b429f8..5dbbd24e 100644 --- a/internal/controller/garmserverconfig_controller_test.go +++ b/internal/controller/garmserverconfig_controller_test.go @@ -1 +1,118 @@ package controller + +import ( + "context" + "github.com/cloudbase/garm/client/controller_info" + "github.com/cloudbase/garm/params" + "github.com/google/uuid" + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + "github.com/mercedes-benz/garm-operator/pkg/client/mock" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" + "go.uber.org/mock/gomock" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" + "reflect" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "testing" +) + +var controllerId = uuid.New() + +func TestGarmServerConfig_reconcile(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + tests := []struct { + name string + object *garmoperatorv1alpha1.GarmServerConfig + expectGarmRequest func(m *mock.MockControllerClientMockRecorder) + runtimeObjects []runtime.Object + wantErr bool + expectedObject *garmoperatorv1alpha1.GarmServerConfig + }{ + { + name: "sync controller info to GarmServerConfig", + object: &garmoperatorv1alpha1.GarmServerConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "garm-server-config", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ + MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", + CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", + WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", + }, + }, + expectedObject: &garmoperatorv1alpha1.GarmServerConfig{}, + runtimeObjects: []runtime.Object{}, + wantErr: false, + expectGarmRequest: func(m *mock.MockControllerClientMockRecorder) { + m.GetControllerInfo().Return(&controller_info.ControllerInfoOK{Payload: params.ControllerInfo{ + ControllerID: controllerId, + Hostname: "garm.server.com", + MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", + CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", + WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", + ControllerWebhookURL: " http://garm-server.garm-server.svc:9997/api/v1/webhook/BE4B3620-D424-43AC-8EDD-5760DBD516BF", + MinimumJobAgeBackoff: 30, + Version: "v0.1.5", + }}, nil) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + schemeBuilder := runtime.SchemeBuilder{ + garmoperatorv1alpha1.AddToScheme, + } + + err := schemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + t.Fatal(err) + } + runtimeObjects := []runtime.Object{tt.object} + runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GarmServerConfig{}).Build() + + // create a fake reconciler + reconciler := &GarmServerConfigReconciler{ + Client: client, + Recorder: record.NewFakeRecorder(3), + } + + garmServerConfig := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GarmServerConfig) + + mockController := mock.NewMockControllerClient(mockCtrl) + tt.expectGarmRequest(mockController.EXPECT()) + + _, err = reconciler.reconcile(context.Background(), ctrl.Request{ + NamespacedName: types.NamespacedName{ + Namespace: tt.object.Namespace, + Name: tt.object.Name, + }, + }, mockController) + if (err != nil) != tt.wantErr { + t.Errorf("EnterpriseReconciler.reconcileNormal() error = %v, wantErr %v", err, tt.wantErr) + return + } + + // clear out annotations to avoid comparison errors + garmServerConfig.ObjectMeta.Annotations = nil + + // empty resource version to avoid comparison errors + garmServerConfig.ObjectMeta.ResourceVersion = "" + + // clear conditions lastTransitionTime to avoid comparison errors + conditions.NilLastTransitionTime(tt.expectedObject) + conditions.NilLastTransitionTime(garmServerConfig) + + if !reflect.DeepEqual(garmServerConfig, tt.expectedObject) { + t.Errorf("EnterpriseReconciler.reconcileNormal() \ngot = %#v\n want %#v", garmServerConfig, tt.expectedObject) + } + }) + } +} diff --git a/internal/controller/githubendpoint_controller.go b/internal/controller/githubendpoint_controller.go index bc808949..3a50a4db 100644 --- a/internal/controller/githubendpoint_controller.go +++ b/internal/controller/githubendpoint_controller.go @@ -210,8 +210,8 @@ func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client g return ctrl.Result{}, err } - if controllerutil.ContainsFinalizer(endpoint, key.EndpointFinalizerName) { - controllerutil.RemoveFinalizer(endpoint, key.EndpointFinalizerName) + if controllerutil.ContainsFinalizer(endpoint, key.GitHubEndpointFinalizerName) { + controllerutil.RemoveFinalizer(endpoint, key.GitHubEndpointFinalizerName) if err := r.Update(ctx, endpoint); err != nil { return ctrl.Result{}, err } @@ -223,8 +223,8 @@ func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client g } func (r *GitHubEndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1alpha1.GitHubEndpoint) error { - if !controllerutil.ContainsFinalizer(endpoint, key.EndpointFinalizerName) { - controllerutil.AddFinalizer(endpoint, key.EndpointFinalizerName) + if !controllerutil.ContainsFinalizer(endpoint, key.GitHubEndpointFinalizerName) { + controllerutil.AddFinalizer(endpoint, key.GitHubEndpointFinalizerName) return r.Update(ctx, endpoint) } return nil diff --git a/internal/controller/githubendpoint_controller_test.go b/internal/controller/githubendpoint_controller_test.go new file mode 100644 index 00000000..a3f5f12a --- /dev/null +++ b/internal/controller/githubendpoint_controller_test.go @@ -0,0 +1,493 @@ +// SPDX-License-Identifier: MIT + +package controller + +import ( + "context" + "github.com/cloudbase/garm/client/endpoints" + "github.com/mercedes-benz/garm-operator/pkg/util" + "reflect" + "testing" + "time" + + "github.com/cloudbase/garm/params" + "go.uber.org/mock/gomock" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/client/mock" + "github.com/mercedes-benz/garm-operator/pkg/util/conditions" +) + +func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + tests := []struct { + name string + object runtime.Object + expectGarmRequest func(m *mock.MockEndpointClientMockRecorder) + runtimeObjects []runtime.Object + wantErr bool + expectedObject *garmoperatorv1alpha1.GitHubEndpoint + }{ + { + name: "github-endpoint exist - update", + object: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, + runtimeObjects: []runtime.Object{}, + expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.SuccessfulReconcileReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { + m.GetEndpoint(endpoints.NewGetGithubEndpointParams().WithName("existing-github-endpoint")).Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). + WithName("existing-github-endpoint"). + WithBody(params.UpdateGithubEndpointParams{ + Description: util.StringPtr("existing-github-endpoint"), + APIBaseURL: util.StringPtr("https://api.github.com"), + UploadBaseURL: util.StringPtr("https://uploads.github.com"), + BaseURL: util.StringPtr("https://github.com"), + CACertBundle: nil, + })).Return(&endpoints.UpdateGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + }, + wantErr: false, + }, + { + name: "github-endpoint exist but spec has changed - update", + object: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "has-changed", + APIBaseURL: "https://api.github-enterprise.com", + UploadBaseURL: "https://uploads.github-enterprise.com", + BaseURL: "https://github-enterprise.com", + CACertBundle: nil, + }, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.SuccessfulReconcileReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + runtimeObjects: []runtime.Object{}, + expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "has-changed", + APIBaseURL: "https://api.github-enterprise.com", + UploadBaseURL: "https://uploads.github-enterprise.com", + BaseURL: "https://github-enterprise.com", + CACertBundle: nil, + }, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.SuccessfulReconcileReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { + m.GetEndpoint(endpoints.NewGetGithubEndpointParams(). + WithName("existing-github-endpoint")). + Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). + WithName("existing-github-endpoint"). + WithBody(params.UpdateGithubEndpointParams{ + Description: util.StringPtr("has-changed"), + APIBaseURL: util.StringPtr("https://api.github-enterprise.com"), + UploadBaseURL: util.StringPtr("https://uploads.github-enterprise.com"), + BaseURL: util.StringPtr("https://github-enterprise.com"), + CACertBundle: nil, + })).Return(&endpoints.UpdateGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "has-changed", + APIBaseURL: "https://api.github-enterprise.com", + UploadBaseURL: "https://uploads.github-enterprise.com", + BaseURL: "https://github-enterprise.com", + CACertBundle: nil, + }, + }, nil) + }, + wantErr: false, + }, + { + name: "github-endpoint does not exist - create and update", + object: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "new-github-endpoint", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "new github endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, + expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "new-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "new github endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.SuccessfulReconcileReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + runtimeObjects: []runtime.Object{}, + expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { + m.GetEndpoint(endpoints.NewGetGithubEndpointParams(). + WithName("new-github-endpoint")). + Return(nil, endpoints.NewGetGithubEndpointDefault(404)) + m.CreateEndpoint(endpoints.NewCreateGithubEndpointParams(). + WithBody(params.CreateGithubEndpointParams{ + Name: "new-github-endpoint", + Description: "new github endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + })).Return(&endpoints.CreateGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "new-github-endpoint", + Description: "new github endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). + WithName("new-github-endpoint"). + WithBody(params.UpdateGithubEndpointParams{ + Description: util.StringPtr("new github endpoint"), + APIBaseURL: util.StringPtr("https://api.github.com"), + UploadBaseURL: util.StringPtr("https://uploads.github.com"), + BaseURL: util.StringPtr("https://github.com"), + CACertBundle: nil, + })).Return(&endpoints.UpdateGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "new-github-endpoint", + Description: "new github endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + }, + wantErr: false, + }, + { + name: "github-endpoint update - bad request error", + object: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "", + APIBaseURL: "", + UploadBaseURL: "", + BaseURL: "", + CACertBundle: nil, + }, + }, + expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{}, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.GarmAPIErrorReason), + Status: metav1.ConditionFalse, + Message: "[PUT /github/endpoints/{name}][400] UpdateGithubEndpoint default {\"error\":\"\",\"details\":\"\"}", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + runtimeObjects: []runtime.Object{}, + expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { + m.GetEndpoint(endpoints.NewGetGithubEndpointParams(). + WithName("existing-github-endpoint")). + Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, + }, nil) + m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). + WithName("existing-github-endpoint"). + WithBody(params.UpdateGithubEndpointParams{ + Description: util.StringPtr(""), + APIBaseURL: util.StringPtr(""), + UploadBaseURL: util.StringPtr(""), + BaseURL: util.StringPtr(""), + CACertBundle: nil, + })).Return(nil, endpoints.NewUpdateGithubEndpointDefault(400)) + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + schemeBuilder := runtime.SchemeBuilder{ + garmoperatorv1alpha1.AddToScheme, + } + + err := schemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + t.Fatal(err) + } + runtimeObjects := []runtime.Object{tt.object} + runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GitHubEndpoint{}).Build() + + // create a fake reconciler + reconciler := &GitHubEndpointReconciler{ + Client: client, + Recorder: record.NewFakeRecorder(3), + } + + githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GitHubEndpoint) + + mockGitHubEndpoint := mock.NewMockEndpointClient(mockCtrl) + tt.expectGarmRequest(mockGitHubEndpoint.EXPECT()) + + _, err = reconciler.reconcileNormal(context.Background(), mockGitHubEndpoint, githubEndpoint) + if (err != nil) != tt.wantErr { + t.Errorf("GitHubEndpointReconciler.reconcileNormal() error = %v, wantErr %v", err, tt.wantErr) + return + } + + // clear out annotations to avoid comparison errors + githubEndpoint.ObjectMeta.Annotations = nil + + // empty resource version to avoid comparison errors + githubEndpoint.ObjectMeta.ResourceVersion = "" + + // clear conditions lastTransitionTime to avoid comparison errors + conditions.NilLastTransitionTime(tt.expectedObject) + conditions.NilLastTransitionTime(githubEndpoint) + + if !reflect.DeepEqual(githubEndpoint, tt.expectedObject) { + t.Errorf("GitHubEndpointReconciler.reconcileNormal() \ngot = %#v\n want %#v", githubEndpoint, tt.expectedObject) + } + }) + } +} + +func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + tests := []struct { + name string + object runtime.Object + runtimeObjects []runtime.Object + expectGarmRequest func(m *mock.MockEndpointClientMockRecorder) + wantErr bool + expectedObject *garmoperatorv1alpha1.GitHubEndpoint + }{ + { + name: "delete github-endpoint", + object: &garmoperatorv1alpha1.GitHubEndpoint{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-github-endpoint", + Namespace: "default", + Finalizers: []string{ + key.GitHubEndpointFinalizerName, + }, + }, + Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: []byte(""), + }, + Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Conditions: []metav1.Condition{ + { + Type: string(conditions.ReadyCondition), + Reason: string(conditions.SuccessfulReconcileReason), + Status: metav1.ConditionTrue, + Message: "", + LastTransitionTime: metav1.NewTime(time.Now()), + }, + }, + }, + }, + runtimeObjects: []runtime.Object{}, + expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { + m.DeleteEndpoint( + endpoints.NewDeleteGithubEndpointParams(). + WithName("existing-github-endpoint"), + ).Return(nil) + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + schemeBuilder := runtime.SchemeBuilder{ + garmoperatorv1alpha1.AddToScheme, + } + + err := schemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + t.Fatal(err) + } + + runtimeObjects := []runtime.Object{tt.object} + runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GitHubEndpoint{}).Build() + + // create a fake reconciler + reconciler := &GitHubEndpointReconciler{ + Client: client, + Recorder: record.NewFakeRecorder(3), + } + + githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GitHubEndpoint) + + mockGitHubEndpoint := mock.NewMockEndpointClient(mockCtrl) + tt.expectGarmRequest(mockGitHubEndpoint.EXPECT()) + + _, err = reconciler.reconcileDelete(context.Background(), mockGitHubEndpoint, githubEndpoint) + if (err != nil) != tt.wantErr { + t.Errorf("GitHubEndpointReconciler.reconcileDelete() error = %v, wantErr %v", err, tt.wantErr) + return + } + + // check for mandatory finalizer + if controllerutil.ContainsFinalizer(githubEndpoint, key.GitHubEndpointFinalizerName) { + t.Errorf("GitHubEndpointReconciler.Reconcile() finalizer still exist") + return + } + }) + } +} diff --git a/internal/controller/pool_controller_test.go b/internal/controller/pool_controller_test.go index e24dd1a1..56608ae6 100644 --- a/internal/controller/pool_controller_test.go +++ b/internal/controller/pool_controller_test.go @@ -489,7 +489,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, Status: garmoperatorv1alpha1.PoolStatus{ ID: poolID, - // LastSyncError: "", }, }, expectedObject: &garmoperatorv1alpha1.Pool{ @@ -779,7 +778,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Status: garmoperatorv1alpha1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 3, - // LastSyncError: "", }, }, expectedObject: &garmoperatorv1alpha1.Pool{ @@ -1777,7 +1775,6 @@ func TestPoolController_ReconcileDelete(t *testing.T) { }, Status: garmoperatorv1alpha1.PoolStatus{ ID: poolID, - // LastSyncError: "", }, }, expectedObject: &garmoperatorv1alpha1.Pool{ @@ -1993,8 +1990,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { GitHubRunnerGroup: "", }, Status: garmoperatorv1alpha1.PoolStatus{ - ID: poolID, - // LastSyncError: "", + ID: poolID, LongRunningIdleRunners: 0, }, }, diff --git a/pkg/client/key/key.go b/pkg/client/key/key.go index 8730af1e..fd7787ae 100644 --- a/pkg/client/key/key.go +++ b/pkg/client/key/key.go @@ -3,13 +3,13 @@ package key const ( - groupName = "garm-operator.mercedes-benz.com" - EnterpriseFinalizerName = groupName + "/enterprise" - OrganizationFinalizerName = groupName + "/organization" - RepositoryFinalizerName = groupName + "/repository" - PoolFinalizerName = groupName + "/pool" - RunnerFinalizerName = groupName + "/runner" - EndpointFinalizerName = groupName + "/endpoint" - CredentialsFinalizerName = groupName + "/credentials" - PausedAnnotation = groupName + "/paused" + groupName = "garm-operator.mercedes-benz.com" + EnterpriseFinalizerName = groupName + "/enterprise" + OrganizationFinalizerName = groupName + "/organization" + RepositoryFinalizerName = groupName + "/repository" + PoolFinalizerName = groupName + "/pool" + RunnerFinalizerName = groupName + "/runner" + GitHubEndpointFinalizerName = groupName + "/endpoint" + CredentialsFinalizerName = groupName + "/credentials" + PausedAnnotation = groupName + "/paused" ) diff --git a/pkg/client/mock/controller.go b/pkg/client/mock/controller.go new file mode 100644 index 00000000..ef4031c1 --- /dev/null +++ b/pkg/client/mock/controller.go @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +// Code generated by MockGen. DO NOT EDIT. +// Source: ../controller.go +// +// Generated by this command: +// +// mockgen -package mock -destination=controller.go -source=../controller.go GarmServerConfig +// + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + controller "github.com/cloudbase/garm/client/controller" + controller_info "github.com/cloudbase/garm/client/controller_info" + gomock "go.uber.org/mock/gomock" +) + +// MockControllerClient is a mock of ControllerClient interface. +type MockControllerClient struct { + ctrl *gomock.Controller + recorder *MockControllerClientMockRecorder +} + +// MockControllerClientMockRecorder is the mock recorder for MockControllerClient. +type MockControllerClientMockRecorder struct { + mock *MockControllerClient +} + +// NewMockControllerClient creates a new mock instance. +func NewMockControllerClient(ctrl *gomock.Controller) *MockControllerClient { + mock := &MockControllerClient{ctrl: ctrl} + mock.recorder = &MockControllerClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockControllerClient) EXPECT() *MockControllerClientMockRecorder { + return m.recorder +} + +// GetControllerInfo mocks base method. +func (m *MockControllerClient) GetControllerInfo() (*controller_info.ControllerInfoOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetControllerInfo") + ret0, _ := ret[0].(*controller_info.ControllerInfoOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetControllerInfo indicates an expected call of GetControllerInfo. +func (mr *MockControllerClientMockRecorder) GetControllerInfo() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetControllerInfo", reflect.TypeOf((*MockControllerClient)(nil).GetControllerInfo)) +} + +// UpdateController mocks base method. +func (m *MockControllerClient) UpdateController(params *controller.UpdateControllerParams) (*controller.UpdateControllerOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateController", params) + ret0, _ := ret[0].(*controller.UpdateControllerOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateController indicates an expected call of UpdateController. +func (mr *MockControllerClientMockRecorder) UpdateController(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateController", reflect.TypeOf((*MockControllerClient)(nil).UpdateController), params) +} diff --git a/pkg/client/mock/credentials.go b/pkg/client/mock/credentials.go new file mode 100644 index 00000000..7f2bc8f2 --- /dev/null +++ b/pkg/client/mock/credentials.go @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +// Code generated by MockGen. DO NOT EDIT. +// Source: ../credentials.go +// +// Generated by this command: +// +// mockgen -package mock -destination=credentials.go -source=../credentials.go GithubCredentials +// + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + credentials "github.com/cloudbase/garm/client/credentials" + gomock "go.uber.org/mock/gomock" +) + +// MockCredentialsClient is a mock of CredentialsClient interface. +type MockCredentialsClient struct { + ctrl *gomock.Controller + recorder *MockCredentialsClientMockRecorder +} + +// MockCredentialsClientMockRecorder is the mock recorder for MockCredentialsClient. +type MockCredentialsClientMockRecorder struct { + mock *MockCredentialsClient +} + +// NewMockCredentialsClient creates a new mock instance. +func NewMockCredentialsClient(ctrl *gomock.Controller) *MockCredentialsClient { + mock := &MockCredentialsClient{ctrl: ctrl} + mock.recorder = &MockCredentialsClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCredentialsClient) EXPECT() *MockCredentialsClientMockRecorder { + return m.recorder +} + +// CreateCredentials mocks base method. +func (m *MockCredentialsClient) CreateCredentials(params *credentials.CreateCredentialsParams) (*credentials.CreateCredentialsOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateCredentials", params) + ret0, _ := ret[0].(*credentials.CreateCredentialsOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateCredentials indicates an expected call of CreateCredentials. +func (mr *MockCredentialsClientMockRecorder) CreateCredentials(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCredentials", reflect.TypeOf((*MockCredentialsClient)(nil).CreateCredentials), params) +} + +// DeleteCredentials mocks base method. +func (m *MockCredentialsClient) DeleteCredentials(params *credentials.DeleteCredentialsParams) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteCredentials", params) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteCredentials indicates an expected call of DeleteCredentials. +func (mr *MockCredentialsClientMockRecorder) DeleteCredentials(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCredentials", reflect.TypeOf((*MockCredentialsClient)(nil).DeleteCredentials), params) +} + +// GetCredentials mocks base method. +func (m *MockCredentialsClient) GetCredentials(params *credentials.GetCredentialsParams) (*credentials.GetCredentialsOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCredentials", params) + ret0, _ := ret[0].(*credentials.GetCredentialsOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCredentials indicates an expected call of GetCredentials. +func (mr *MockCredentialsClientMockRecorder) GetCredentials(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCredentials", reflect.TypeOf((*MockCredentialsClient)(nil).GetCredentials), params) +} + +// ListCredentials mocks base method. +func (m *MockCredentialsClient) ListCredentials(params *credentials.ListCredentialsParams) (*credentials.ListCredentialsOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListCredentials", params) + ret0, _ := ret[0].(*credentials.ListCredentialsOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListCredentials indicates an expected call of ListCredentials. +func (mr *MockCredentialsClientMockRecorder) ListCredentials(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListCredentials", reflect.TypeOf((*MockCredentialsClient)(nil).ListCredentials), params) +} + +// UpdateCredentials mocks base method. +func (m *MockCredentialsClient) UpdateCredentials(params *credentials.UpdateCredentialsParams) (*credentials.UpdateCredentialsOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateCredentials", params) + ret0, _ := ret[0].(*credentials.UpdateCredentialsOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateCredentials indicates an expected call of UpdateCredentials. +func (mr *MockCredentialsClientMockRecorder) UpdateCredentials(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateCredentials", reflect.TypeOf((*MockCredentialsClient)(nil).UpdateCredentials), params) +} diff --git a/pkg/client/mock/doc.go b/pkg/client/mock/doc.go index 38566751..356873b2 100644 --- a/pkg/client/mock/doc.go +++ b/pkg/client/mock/doc.go @@ -18,3 +18,9 @@ package mock //go:generate /usr/bin/env bash -c "cat ../../../hack/boilerplate.go.txt repository.go > _repository.go && mv _repository.go repository.go" //go:generate ../../../bin/mockgen -package mock -destination=client.go -source=../client.go GarmClient //go:generate /usr/bin/env bash -c "cat ../../../hack/boilerplate.go.txt client.go > _client.go && mv _client.go client.go" +//go:generate ../../../bin/mockgen -package mock -destination=endpoint.go -source=../endpoint.go Endpoint +//go:generate /usr/bin/env bash -c "cat ../../../hack/boilerplate.go.txt endpoint.go > _endpoint.go && mv _endpoint.go endpoint.go" +//go:generate ../../../bin/mockgen -package mock -destination=credentials.go -source=../credentials.go GithubCredentials +//go:generate /usr/bin/env bash -c "cat ../../../hack/boilerplate.go.txt credentials.go > _credentials.go && mv _credentials.go credentials.go" +//go:generate ../../../bin/mockgen -package mock -destination=controller.go -source=../controller.go GarmServerConfig +//go:generate /usr/bin/env bash -c "cat ../../../hack/boilerplate.go.txt controller.go > _controller.go && mv _controller.go controller.go" diff --git a/pkg/client/mock/endpoint.go b/pkg/client/mock/endpoint.go new file mode 100644 index 00000000..2574e9d3 --- /dev/null +++ b/pkg/client/mock/endpoint.go @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +// Code generated by MockGen. DO NOT EDIT. +// Source: ../endpoint.go +// +// Generated by this command: +// +// mockgen -package mock -destination=endpoint.go -source=../endpoint.go Endpoint +// + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + endpoints "github.com/cloudbase/garm/client/endpoints" + gomock "go.uber.org/mock/gomock" +) + +// MockEndpointClient is a mock of EndpointClient interface. +type MockEndpointClient struct { + ctrl *gomock.Controller + recorder *MockEndpointClientMockRecorder +} + +// MockEndpointClientMockRecorder is the mock recorder for MockEndpointClient. +type MockEndpointClientMockRecorder struct { + mock *MockEndpointClient +} + +// NewMockEndpointClient creates a new mock instance. +func NewMockEndpointClient(ctrl *gomock.Controller) *MockEndpointClient { + mock := &MockEndpointClient{ctrl: ctrl} + mock.recorder = &MockEndpointClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEndpointClient) EXPECT() *MockEndpointClientMockRecorder { + return m.recorder +} + +// CreateEndpoint mocks base method. +func (m *MockEndpointClient) CreateEndpoint(params *endpoints.CreateGithubEndpointParams) (*endpoints.CreateGithubEndpointOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateEndpoint", params) + ret0, _ := ret[0].(*endpoints.CreateGithubEndpointOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateEndpoint indicates an expected call of CreateEndpoint. +func (mr *MockEndpointClientMockRecorder) CreateEndpoint(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateEndpoint", reflect.TypeOf((*MockEndpointClient)(nil).CreateEndpoint), params) +} + +// DeleteEndpoint mocks base method. +func (m *MockEndpointClient) DeleteEndpoint(params *endpoints.DeleteGithubEndpointParams) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteEndpoint", params) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteEndpoint indicates an expected call of DeleteEndpoint. +func (mr *MockEndpointClientMockRecorder) DeleteEndpoint(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteEndpoint", reflect.TypeOf((*MockEndpointClient)(nil).DeleteEndpoint), params) +} + +// GetEndpoint mocks base method. +func (m *MockEndpointClient) GetEndpoint(params *endpoints.GetGithubEndpointParams) (*endpoints.GetGithubEndpointOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEndpoint", params) + ret0, _ := ret[0].(*endpoints.GetGithubEndpointOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetEndpoint indicates an expected call of GetEndpoint. +func (mr *MockEndpointClientMockRecorder) GetEndpoint(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEndpoint", reflect.TypeOf((*MockEndpointClient)(nil).GetEndpoint), params) +} + +// ListEndpoints mocks base method. +func (m *MockEndpointClient) ListEndpoints(params *endpoints.ListGithubEndpointsParams) (*endpoints.ListGithubEndpointsOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListEndpoints", params) + ret0, _ := ret[0].(*endpoints.ListGithubEndpointsOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListEndpoints indicates an expected call of ListEndpoints. +func (mr *MockEndpointClientMockRecorder) ListEndpoints(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListEndpoints", reflect.TypeOf((*MockEndpointClient)(nil).ListEndpoints), params) +} + +// UpdateEndpoint mocks base method. +func (m *MockEndpointClient) UpdateEndpoint(params *endpoints.UpdateGithubEndpointParams) (*endpoints.UpdateGithubEndpointOK, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateEndpoint", params) + ret0, _ := ret[0].(*endpoints.UpdateGithubEndpointOK) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateEndpoint indicates an expected call of UpdateEndpoint. +func (mr *MockEndpointClientMockRecorder) UpdateEndpoint(params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateEndpoint", reflect.TypeOf((*MockEndpointClient)(nil).UpdateEndpoint), params) +} From 08a6a652f90d65f77f1aad0222bc31aff8ccadaf Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 10 Sep 2024 10:56:32 +0200 Subject: [PATCH 12/30] fix: garm-server-config tests --- .../controller/garmserverconfig_controller.go | 23 ++++++------ .../garmserverconfig_controller_test.go | 35 +++++++++++++------ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go index 92501397..fb8d8987 100644 --- a/internal/controller/garmserverconfig_controller.go +++ b/internal/controller/garmserverconfig_controller.go @@ -38,19 +38,10 @@ type GarmServerConfigReconciler struct { //+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=garmserverconfigs/finalizers,verbs=update func (r *GarmServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - controllerClient := garmclient.NewControllerClient() - return r.reconcile(ctx, req, controllerClient) -} - -func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Request, controllerClient garmclient.ControllerClient) (ctrl.Result, error) { log := log.FromContext(ctx) log.Info("Reconciling GarmServerConfig") - controllerInfo, err := r.getControllerInfo(controllerClient) - if err != nil { - log.Error(err, "Failed to get controller info") - return ctrl.Result{}, err - } + controllerClient := garmclient.NewControllerClient() garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{} if err := r.Get(ctx, req.NamespacedName, garmServerConfig); err != nil { @@ -67,6 +58,18 @@ func (r *GarmServerConfigReconciler) reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, nil } + return r.reconcileNormal(ctx, controllerClient, garmServerConfig) +} + +func (r *GarmServerConfigReconciler) reconcileNormal(ctx context.Context, controllerClient garmclient.ControllerClient, garmServerConfig *garmoperatorv1alpha1.GarmServerConfig) (ctrl.Result, error) { + log := log.FromContext(ctx) + + controllerInfo, err := r.getControllerInfo(controllerClient) + if err != nil { + log.Error(err, "Failed to get controller info") + return ctrl.Result{}, err + } + // sync applied spec with controller info in garm newControllerInfo, err := r.updateControllerInfo(ctx, controllerClient, garmServerConfig, &controllerInfo) if err != nil { diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go index 5dbbd24e..5f1b9ff2 100644 --- a/internal/controller/garmserverconfig_controller_test.go +++ b/internal/controller/garmserverconfig_controller_test.go @@ -11,11 +11,9 @@ import ( "go.uber.org/mock/gomock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/record" "reflect" - ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" "testing" ) @@ -47,7 +45,27 @@ func TestGarmServerConfig_reconcile(t *testing.T) { WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", }, }, - expectedObject: &garmoperatorv1alpha1.GarmServerConfig{}, + expectedObject: &garmoperatorv1alpha1.GarmServerConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "garm-server-config", + Namespace: "default", + }, + Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ + MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", + CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", + WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", + }, + Status: garmoperatorv1alpha1.GarmServerConfigStatus{ + ControllerID: controllerId.String(), + Hostname: "garm.server.com", + MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", + CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", + WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", + ControllerWebhookURL: " http://garm-server.garm-server.svc:9997/api/v1/webhook/BE4B3620-D424-43AC-8EDD-5760DBD516BF", + MinimumJobAgeBackoff: 30, + Version: "v0.1.5", + }, + }, runtimeObjects: []runtime.Object{}, wantErr: false, expectGarmRequest: func(m *mock.MockControllerClientMockRecorder) { @@ -89,14 +107,9 @@ func TestGarmServerConfig_reconcile(t *testing.T) { mockController := mock.NewMockControllerClient(mockCtrl) tt.expectGarmRequest(mockController.EXPECT()) - _, err = reconciler.reconcile(context.Background(), ctrl.Request{ - NamespacedName: types.NamespacedName{ - Namespace: tt.object.Namespace, - Name: tt.object.Name, - }, - }, mockController) + _, err = reconciler.reconcileNormal(context.Background(), mockController, garmServerConfig) if (err != nil) != tt.wantErr { - t.Errorf("EnterpriseReconciler.reconcileNormal() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GarmServerConfigReconciler.reconcileNormal() error = %v, wantErr %v", err, tt.wantErr) return } @@ -111,7 +124,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { conditions.NilLastTransitionTime(garmServerConfig) if !reflect.DeepEqual(garmServerConfig, tt.expectedObject) { - t.Errorf("EnterpriseReconciler.reconcileNormal() \ngot = %#v\n want %#v", garmServerConfig, tt.expectedObject) + t.Errorf("GarmServerConfigReconciler.reconcileNormal() \ngot = %#v\n want %#v", garmServerConfig, tt.expectedObject) } }) } From 75c3b40c99dd75d9ec2f4b02afda0e5d61cdd099 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 10 Sep 2024 11:04:25 +0200 Subject: [PATCH 13/30] feat: add poolBalancerType field to enterprise, org and repo --- api/v1alpha1/enterprise_types.go | 4 +++- api/v1alpha1/organization_types.go | 4 +++- api/v1alpha1/repository_types.go | 4 +++- ...perator.mercedes-benz.com_enterprises.yaml | 2 ++ ...rator.mercedes-benz.com_organizations.yaml | 2 ++ ...erator.mercedes-benz.com_repositories.yaml | 2 ++ internal/controller/enterprise_controller.go | 20 +++++++++-------- .../controller/organization_controller.go | 20 +++++++++-------- internal/controller/repository_controller.go | 22 ++++++++++--------- 9 files changed, 49 insertions(+), 31 deletions(-) diff --git a/api/v1alpha1/enterprise_types.go b/api/v1alpha1/enterprise_types.go index efab3367..fe18fe2e 100644 --- a/api/v1alpha1/enterprise_types.go +++ b/api/v1alpha1/enterprise_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + "github.com/cloudbase/garm/params" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,7 +15,8 @@ type EnterpriseSpec struct { CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` } // EnterpriseStatus defines the observed state of Enterprise diff --git a/api/v1alpha1/organization_types.go b/api/v1alpha1/organization_types.go index 664260f5..8b07fe7b 100644 --- a/api/v1alpha1/organization_types.go +++ b/api/v1alpha1/organization_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + "github.com/cloudbase/garm/params" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,7 +15,8 @@ type OrganizationSpec struct { CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` } // OrganizationStatus defines the observed state of Organization diff --git a/api/v1alpha1/repository_types.go b/api/v1alpha1/repository_types.go index 9fc58d97..75a25169 100644 --- a/api/v1alpha1/repository_types.go +++ b/api/v1alpha1/repository_types.go @@ -3,6 +3,7 @@ package v1alpha1 import ( + "github.com/cloudbase/garm/params" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -15,7 +16,8 @@ type RepositorySpec struct { Owner string `json:"owner"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` } // RepositoryStatus defines the observed state of Repository diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml index 7cf1c964..801ab1a4 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml @@ -85,6 +85,8 @@ spec: - name type: object x-kubernetes-map-type: atomic + poolBalancerType: + type: string webhookSecretRef: description: WebhookSecretRef represents a secret that should be used for the webhook diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml index 6ef12b10..bcb42f5f 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml @@ -85,6 +85,8 @@ spec: - name type: object x-kubernetes-map-type: atomic + poolBalancerType: + type: string webhookSecretRef: description: WebhookSecretRef represents a secret that should be used for the webhook diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml index 608e2376..e142983c 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml @@ -87,6 +87,8 @@ spec: x-kubernetes-map-type: atomic owner: type: string + poolBalancerType: + type: string webhookSecretRef: description: WebhookSecretRef represents a secret that should be used for the webhook diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index ccdb3db5..c3b64eb0 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -137,7 +137,11 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC } // update enterprise anytime - garmEnterprise, err = r.updateEnterprise(ctx, client, garmEnterprise.ID, webhookSecret, credentials.Name) + garmEnterprise, err = r.updateEnterprise(ctx, client, garmEnterprise.ID, params.UpdateEntityParams{ + CredentialsName: credentials.Name, + WebhookSecret: webhookSecret, + PoolBalancerType: enterprise.Spec.PoolBalancerType, + }) if err != nil { event.Error(r.Recorder, enterprise, err.Error()) conditions.MarkFalse(enterprise, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -175,9 +179,10 @@ func (r *EnterpriseReconciler) createEnterprise(ctx context.Context, client garm retValue, err := client.CreateEnterprise( enterprises.NewCreateEnterpriseParams(). WithBody(params.CreateEnterpriseParams{ - Name: enterprise.Name, - CredentialsName: enterprise.GetCredentialsName(), - WebhookSecret: webhookSecret, // gh hook secret + Name: enterprise.Name, + CredentialsName: enterprise.GetCredentialsName(), + WebhookSecret: webhookSecret, // gh hook secret + PoolBalancerType: enterprise.Spec.PoolBalancerType, })) if err != nil { log.V(1).Info(fmt.Sprintf("client.CreateEnterprise error: %s", err)) @@ -192,7 +197,7 @@ func (r *EnterpriseReconciler) createEnterprise(ctx context.Context, client garm return retValue.Payload, nil } -func (r *EnterpriseReconciler) updateEnterprise(ctx context.Context, client garmClient.EnterpriseClient, statusID, webhookSecret, credentialsName string) (params.Enterprise, error) { +func (r *EnterpriseReconciler) updateEnterprise(ctx context.Context, client garmClient.EnterpriseClient, statusID string, updateParams params.UpdateEntityParams) (params.Enterprise, error) { log := log.FromContext(ctx) log.V(1).Info("update credentials and webhook secret in garm enterprise") @@ -200,10 +205,7 @@ func (r *EnterpriseReconciler) updateEnterprise(ctx context.Context, client garm retValue, err := client.UpdateEnterprise( enterprises.NewUpdateEnterpriseParams(). WithEnterpriseID(statusID). - WithBody(params.UpdateEntityParams{ - CredentialsName: credentialsName, - WebhookSecret: webhookSecret, // gh hook secret - })) + WithBody(updateParams)) if err != nil { log.V(1).Info(fmt.Sprintf("client.UpdateEnterprise error: %s", err)) return params.Enterprise{}, err diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index 0b2792a3..9a89cb82 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -134,7 +134,11 @@ func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client gar } // update organization anytime - garmOrganization, err = r.updateOrganization(ctx, client, garmOrganization.ID, webhookSecret, credentials.Name) + garmOrganization, err = r.updateOrganization(ctx, client, garmOrganization.ID, params.UpdateEntityParams{ + CredentialsName: credentials.Name, + WebhookSecret: webhookSecret, + PoolBalancerType: organization.Spec.PoolBalancerType, + }) if err != nil { event.Error(r.Recorder, organization, err.Error()) conditions.MarkFalse(organization, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -173,9 +177,10 @@ func (r *OrganizationReconciler) createOrganization(ctx context.Context, client retValue, err := client.CreateOrganization( organizations.NewCreateOrgParams(). WithBody(params.CreateOrgParams{ - Name: organization.Name, - CredentialsName: organization.GetCredentialsName(), - WebhookSecret: webhookSecret, // gh hook secret + Name: organization.Name, + CredentialsName: organization.GetCredentialsName(), + WebhookSecret: webhookSecret, // gh hook secret + PoolBalancerType: organization.Spec.PoolBalancerType, })) if err != nil { log.V(1).Info(fmt.Sprintf("client.CreateOrganization error: %s", err)) @@ -190,7 +195,7 @@ func (r *OrganizationReconciler) createOrganization(ctx context.Context, client return retValue.Payload, nil } -func (r *OrganizationReconciler) updateOrganization(ctx context.Context, client garmClient.OrganizationClient, statusID, webhookSecret, credentialsName string) (params.Organization, error) { +func (r *OrganizationReconciler) updateOrganization(ctx context.Context, client garmClient.OrganizationClient, statusID string, updateParams params.UpdateEntityParams) (params.Organization, error) { log := log.FromContext(ctx) log.V(1).Info("update credentials and webhook secret in garm organization") @@ -198,10 +203,7 @@ func (r *OrganizationReconciler) updateOrganization(ctx context.Context, client retValue, err := client.UpdateOrganization( organizations.NewUpdateOrgParams(). WithOrgID(statusID). - WithBody(params.UpdateEntityParams{ - CredentialsName: credentialsName, - WebhookSecret: webhookSecret, // gh hook secret - })) + WithBody(updateParams)) if err != nil { log.V(1).Info(fmt.Sprintf("client.UpdateOrganization error: %s", err)) return params.Organization{}, err diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index 0a1f8c0c..313cdcf6 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -134,7 +134,11 @@ func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmC } // update repository anytime - garmRepository, err = r.updateRepository(ctx, client, garmRepository.ID, webhookSecret, credentials.Name) + garmRepository, err = r.updateRepository(ctx, client, garmRepository.ID, params.UpdateEntityParams{ + CredentialsName: credentials.Name, + WebhookSecret: webhookSecret, + PoolBalancerType: repository.Spec.PoolBalancerType, + }) if err != nil { event.Error(r.Recorder, repository, err.Error()) conditions.MarkFalse(repository, conditions.ReadyCondition, conditions.GarmAPIErrorReason, err.Error()) @@ -173,10 +177,11 @@ func (r *RepositoryReconciler) createRepository(ctx context.Context, client garm retValue, err := client.CreateRepository( repositories.NewCreateRepoParams(). WithBody(params.CreateRepoParams{ - Name: repository.Name, - CredentialsName: repository.GetCredentialsName(), - Owner: repository.Spec.Owner, - WebhookSecret: webhookSecret, // gh hook secret + Name: repository.Name, + CredentialsName: repository.GetCredentialsName(), + Owner: repository.Spec.Owner, + WebhookSecret: webhookSecret, // gh hook secret + PoolBalancerType: repository.Spec.PoolBalancerType, })) if err != nil { log.V(1).Info(fmt.Sprintf("client.CreateRepository error: %s", err)) @@ -191,7 +196,7 @@ func (r *RepositoryReconciler) createRepository(ctx context.Context, client garm return retValue.Payload, nil } -func (r *RepositoryReconciler) updateRepository(ctx context.Context, client garmClient.RepositoryClient, statusID, webhookSecret, credentialsName string) (params.Repository, error) { +func (r *RepositoryReconciler) updateRepository(ctx context.Context, client garmClient.RepositoryClient, statusID string, updateParams params.UpdateEntityParams) (params.Repository, error) { log := log.FromContext(ctx) log.V(1).Info("update credentials and webhook secret in garm repository") @@ -199,10 +204,7 @@ func (r *RepositoryReconciler) updateRepository(ctx context.Context, client garm retValue, err := client.UpdateRepository( repositories.NewUpdateRepoParams(). WithRepoID(statusID). - WithBody(params.UpdateEntityParams{ - CredentialsName: credentialsName, - WebhookSecret: webhookSecret, // gh hook secret - })) + WithBody(updateParams)) if err != nil { log.V(1).Info(fmt.Sprintf("client.UpdateRepository error: %s", err)) return params.Repository{}, err From 06690d8c7026a27834799a5b1228892ae2c4e77c Mon Sep 17 00:00:00 2001 From: rthalho Date: Mon, 16 Sep 2024 08:54:16 +0200 Subject: [PATCH 14/30] feat: introduce v1beta1 api type --- PROJECT | 72 ++ api/v1alpha1/enterprise_types.go | 9 +- api/v1alpha1/organization_types.go | 9 +- api/v1alpha1/repository_types.go | 11 +- api/v1alpha1/zz_generated.deepcopy.go | 304 +----- api/v1beta1/enterprise_types.go | 104 ++ .../garmserverconfig_types.go | 3 +- .../githubcredentials_types.go | 3 +- .../githubendpoint_types.go | 3 +- api/v1beta1/groupversion_info.go | 22 + api/v1beta1/image_types.go | 56 ++ api/v1beta1/image_webhook.go | 78 ++ api/v1beta1/organization_types.go | 104 ++ api/v1beta1/pool_helper.go | 57 ++ api/v1beta1/pool_types.go | 101 ++ api/v1beta1/pool_types_test.go | 148 +++ api/v1beta1/pool_webhook.go | 139 +++ api/v1beta1/repository_types.go | 105 ++ api/v1beta1/repository_webhook.go | 75 ++ api/v1beta1/runner_types.go | 109 +++ api/v1beta1/shared.go | 46 + api/v1beta1/zz_generated.deepcopy.go | 902 ++++++++++++++++++ cmd/main.go | 4 +- ...perator.mercedes-benz.com_enterprises.yaml | 148 +++ ...r.mercedes-benz.com_garmserverconfigs.yaml | 2 +- ...r.mercedes-benz.com_githubcredentials.yaml | 2 +- ...tor.mercedes-benz.com_githubendpoints.yaml | 2 +- ...arm-operator.mercedes-benz.com_images.yaml | 47 + ...rator.mercedes-benz.com_organizations.yaml | 148 +++ ...garm-operator.mercedes-benz.com_pools.yaml | 228 +++++ ...erator.mercedes-benz.com_repositories.yaml | 151 +++ ...rm-operator.mercedes-benz.com_runners.yaml | 137 +++ config/crd/kustomization.yaml | 9 + config/rbac/githubendpoint_editor_role.yaml | 31 + config/rbac/githubendpoint_viewer_role.yaml | 27 + ... => garm-operator_v1beta1_enterprise.yaml} | 10 +- ...arm-operator_v1beta1_garmserverconfig.yaml | 12 + ...rm-operator_v1beta1_githubcredentials.yaml | 12 + .../garm-operator_v1beta1_githubendpoint.yaml | 12 + .../samples/garm-operator_v1beta1_image.yaml | 12 + .../garm-operator_v1beta1_organization.yaml | 12 + .../samples/garm-operator_v1beta1_pool.yaml | 12 + .../garm-operator_v1beta1_repository.yaml | 12 + .../samples/garm-operator_v1beta1_runner.yaml | 12 + config/samples/kustomization.yaml | 9 + config/webhook/manifests.yaml | 61 ++ go.mod | 2 +- internal/controller/enterprise_controller.go | 26 +- .../controller/enterprise_controller_test.go | 206 ++-- .../controller/garmserverconfig_controller.go | 24 +- .../garmserverconfig_controller_test.go | 29 +- .../githubcredentials_controller.go | 26 +- .../controller/githubendpoint_controller.go | 20 +- .../githubendpoint_controller_test.go | 68 +- .../controller/organization_controller.go | 26 +- .../organization_controller_test.go | 206 ++-- internal/controller/pool_controller.go | 67 +- internal/controller/pool_controller_test.go | 521 ++++------ internal/controller/repository_controller.go | 26 +- .../controller/repository_controller_test.go | 206 ++-- internal/controller/runner_controller.go | 34 +- internal/controller/runner_controller_test.go | 72 +- pkg/pools/pools.go | 21 +- pkg/pools/predicate.go | 10 +- pkg/runners/runners.go | 4 +- pkg/secret/secret.go | 5 +- 66 files changed, 3938 insertions(+), 1233 deletions(-) create mode 100644 api/v1beta1/enterprise_types.go rename api/{v1alpha1 => v1beta1}/garmserverconfig_types.go (98%) rename api/{v1alpha1 => v1beta1}/githubcredentials_types.go (98%) rename api/{v1alpha1 => v1beta1}/githubendpoint_types.go (97%) create mode 100644 api/v1beta1/groupversion_info.go create mode 100644 api/v1beta1/image_types.go create mode 100644 api/v1beta1/image_webhook.go create mode 100644 api/v1beta1/organization_types.go create mode 100644 api/v1beta1/pool_helper.go create mode 100644 api/v1beta1/pool_types.go create mode 100644 api/v1beta1/pool_types_test.go create mode 100644 api/v1beta1/pool_webhook.go create mode 100644 api/v1beta1/repository_types.go create mode 100644 api/v1beta1/repository_webhook.go create mode 100644 api/v1beta1/runner_types.go create mode 100644 api/v1beta1/shared.go create mode 100644 api/v1beta1/zz_generated.deepcopy.go create mode 100644 config/rbac/githubendpoint_editor_role.yaml create mode 100644 config/rbac/githubendpoint_viewer_role.yaml rename config/samples/{garm-operator_v1alpha1_controller.yaml => garm-operator_v1beta1_enterprise.yaml} (51%) create mode 100644 config/samples/garm-operator_v1beta1_garmserverconfig.yaml create mode 100644 config/samples/garm-operator_v1beta1_githubcredentials.yaml create mode 100644 config/samples/garm-operator_v1beta1_githubendpoint.yaml create mode 100644 config/samples/garm-operator_v1beta1_image.yaml create mode 100644 config/samples/garm-operator_v1beta1_organization.yaml create mode 100644 config/samples/garm-operator_v1beta1_pool.yaml create mode 100644 config/samples/garm-operator_v1beta1_repository.yaml create mode 100644 config/samples/garm-operator_v1beta1_runner.yaml diff --git a/PROJECT b/PROJECT index 7e18a698..2c02ba99 100644 --- a/PROJECT +++ b/PROJECT @@ -96,4 +96,76 @@ resources: kind: GitHubCredentials path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Enterprise + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Organization + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Repository + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Pool + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Runner + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Image + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GitHubEndpoint + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GitHubCredentials + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GarmServerConfig + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 version: "3" diff --git a/api/v1alpha1/enterprise_types.go b/api/v1alpha1/enterprise_types.go index fe18fe2e..976e4db4 100644 --- a/api/v1alpha1/enterprise_types.go +++ b/api/v1alpha1/enterprise_types.go @@ -3,8 +3,6 @@ package v1alpha1 import ( - "github.com/cloudbase/garm/params" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -12,11 +10,10 @@ import ( // EnterpriseSpec defines the desired state of Enterprise type EnterpriseSpec struct { - CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + CredentialsName string `json:"credentialsName"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` - PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` } // EnterpriseStatus defines the observed state of Enterprise @@ -52,7 +49,7 @@ func (e *Enterprise) GetConditions() []metav1.Condition { } func (e *Enterprise) GetCredentialsName() string { - return e.Spec.CredentialsRef.Name + return e.Spec.CredentialsName } func (e *Enterprise) GetID() string { diff --git a/api/v1alpha1/organization_types.go b/api/v1alpha1/organization_types.go index 8b07fe7b..996f534b 100644 --- a/api/v1alpha1/organization_types.go +++ b/api/v1alpha1/organization_types.go @@ -3,8 +3,6 @@ package v1alpha1 import ( - "github.com/cloudbase/garm/params" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -12,11 +10,10 @@ import ( // OrganizationSpec defines the desired state of Organization type OrganizationSpec struct { - CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + CredentialsName string `json:"credentialsName"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` - PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` } // OrganizationStatus defines the observed state of Organization @@ -52,7 +49,7 @@ func (o *Organization) GetConditions() []metav1.Condition { } func (o *Organization) GetCredentialsName() string { - return o.Spec.CredentialsRef.Name + return o.Spec.CredentialsName } func (o *Organization) GetID() string { diff --git a/api/v1alpha1/repository_types.go b/api/v1alpha1/repository_types.go index 75a25169..c84f085a 100644 --- a/api/v1alpha1/repository_types.go +++ b/api/v1alpha1/repository_types.go @@ -3,8 +3,6 @@ package v1alpha1 import ( - "github.com/cloudbase/garm/params" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -12,12 +10,11 @@ import ( // RepositorySpec defines the desired state of Repository type RepositorySpec struct { - CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` - Owner string `json:"owner"` + CredentialsName string `json:"credentialsName"` + Owner string `json:"owner"` // WebhookSecretRef represents a secret that should be used for the webhook - WebhookSecretRef SecretRef `json:"webhookSecretRef"` - PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` + WebhookSecretRef SecretRef `json:"webhookSecretRef"` } // RepositoryStatus defines the observed state of Repository @@ -53,7 +50,7 @@ func (r *Repository) GetConditions() []metav1.Condition { } func (r *Repository) GetCredentialsName() string { - return r.Spec.CredentialsRef.Name + return r.Spec.CredentialsName } func (r *Repository) GetID() string { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index b6ab0233..2aeca9cc 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -17,7 +17,7 @@ func (in *Enterprise) DeepCopyInto(out *Enterprise) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } @@ -74,7 +74,6 @@ func (in *EnterpriseList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EnterpriseSpec) DeepCopyInto(out *EnterpriseSpec) { *out = *in - in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } @@ -110,301 +109,6 @@ func (in *EnterpriseStatus) DeepCopy() *EnterpriseStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. -func (in *GarmServerConfig) DeepCopy() *GarmServerConfig { - if in == nil { - return nil - } - out := new(GarmServerConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GarmServerConfig) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigList) DeepCopyInto(out *GarmServerConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]GarmServerConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigList. -func (in *GarmServerConfigList) DeepCopy() *GarmServerConfigList { - if in == nil { - return nil - } - out := new(GarmServerConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigSpec) DeepCopyInto(out *GarmServerConfigSpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigSpec. -func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { - if in == nil { - return nil - } - out := new(GarmServerConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. -func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { - if in == nil { - return nil - } - out := new(GarmServerConfigStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. -func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { - if in == nil { - return nil - } - out := new(GitHubCredentials) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentials) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]GitHubCredentials, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. -func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { - if in == nil { - return nil - } - out := new(GitHubCredentialsList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { - *out = *in - in.EndpointRef.DeepCopyInto(&out.EndpointRef) - out.SecretRef = in.SecretRef -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. -func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { - if in == nil { - return nil - } - out := new(GitHubCredentialsSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. -func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { - if in == nil { - return nil - } - out := new(GitHubCredentialsStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubEndpoint) DeepCopyInto(out *GitHubEndpoint) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpoint. -func (in *GitHubEndpoint) DeepCopy() *GitHubEndpoint { - if in == nil { - return nil - } - out := new(GitHubEndpoint) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubEndpoint) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubEndpointList) DeepCopyInto(out *GitHubEndpointList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]GitHubEndpoint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointList. -func (in *GitHubEndpointList) DeepCopy() *GitHubEndpointList { - if in == nil { - return nil - } - out := new(GitHubEndpointList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubEndpointList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubEndpointSpec) DeepCopyInto(out *GitHubEndpointSpec) { - *out = *in - if in.CACertBundle != nil { - in, out := &in.CACertBundle, &out.CACertBundle - *out = make([]byte, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointSpec. -func (in *GitHubEndpointSpec) DeepCopy() *GitHubEndpointSpec { - if in == nil { - return nil - } - out := new(GitHubEndpointSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubEndpointStatus) DeepCopyInto(out *GitHubEndpointStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointStatus. -func (in *GitHubEndpointStatus) DeepCopy() *GitHubEndpointStatus { - if in == nil { - return nil - } - out := new(GitHubEndpointStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Image) DeepCopyInto(out *Image) { *out = *in @@ -499,7 +203,7 @@ func (in *Organization) DeepCopyInto(out *Organization) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } @@ -556,7 +260,6 @@ func (in *OrganizationList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OrganizationSpec) DeepCopyInto(out *OrganizationSpec) { *out = *in - in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } @@ -699,7 +402,7 @@ func (in *Repository) DeepCopyInto(out *Repository) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) + out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } @@ -756,7 +459,6 @@ func (in *RepositoryList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RepositorySpec) DeepCopyInto(out *RepositorySpec) { *out = *in - in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) out.WebhookSecretRef = in.WebhookSecretRef } diff --git a/api/v1beta1/enterprise_types.go b/api/v1beta1/enterprise_types.go new file mode 100644 index 00000000..6a9c2e32 --- /dev/null +++ b/api/v1beta1/enterprise_types.go @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "github.com/cloudbase/garm/params" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/mercedes-benz/garm-operator/pkg/conditions" +) + +// EnterpriseSpec defines the desired state of Enterprise +type EnterpriseSpec struct { + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + + // WebhookSecretRef represents a secret that should be used for the webhook + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` +} + +// EnterpriseStatus defines the observed state of Enterprise +type EnterpriseStatus struct { + ID string `json:"id"` + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=enterprises,scope=Namespaced,categories=garm,shortName=ent +//+kubebuilder:subresource:status +//+kubebuilder:storageversion +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Enterprise ID" +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="Pool_Manager_Failure",type="string",JSONPath=`.status.conditions[?(@.reason=='PoolManagerFailure')].message`,priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Enterprise" + +// Enterprise is the Schema for the enterprises API +type Enterprise struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec EnterpriseSpec `json:"spec,omitempty"` + Status EnterpriseStatus `json:"status,omitempty"` +} + +func (e *Enterprise) SetConditions(conditions []metav1.Condition) { + e.Status.Conditions = conditions +} + +func (e *Enterprise) GetConditions() []metav1.Condition { + return e.Status.Conditions +} + +func (e *Enterprise) GetCredentialsName() string { + return e.Spec.CredentialsRef.Name +} + +func (e *Enterprise) GetID() string { + return e.Status.ID +} + +func (e *Enterprise) GetName() string { + return e.ObjectMeta.Name +} + +func (e *Enterprise) GetPoolManagerIsRunning() bool { + condition := conditions.Get(e, conditions.PoolManager) + if condition == nil { + return false + } + + return condition.Status == TrueAsString +} + +func (e *Enterprise) GetPoolManagerFailureReason() string { + condition := conditions.Get(e, conditions.PoolManager) + if condition == nil { + return "" + } + + if condition.Reason == string(conditions.PoolManagerFailureReason) { + return condition.Message + } + + return "" +} + +func (e *Enterprise) GetKind() string { + return e.Kind +} + +//+kubebuilder:object:root=true + +// EnterpriseList contains a list of Enterprise +type EnterpriseList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Enterprise `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Enterprise{}, &EnterpriseList{}) +} diff --git a/api/v1alpha1/garmserverconfig_types.go b/api/v1beta1/garmserverconfig_types.go similarity index 98% rename from api/v1alpha1/garmserverconfig_types.go rename to api/v1beta1/garmserverconfig_types.go index 6cee8e2b..1f671597 100644 --- a/api/v1alpha1/garmserverconfig_types.go +++ b/api/v1beta1/garmserverconfig_types.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -package v1alpha1 +package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,6 +29,7 @@ type GarmServerConfigStatus struct { //+kubebuilder:object:root=true //+kubebuilder:resource:path=garmserverconfigs,scope=Namespaced,categories=garm,shortName=server //+kubebuilder:subresource:status +//+kubebuilder:storageversion //+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.controllerId",description="Controller ID" //+kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description="Garm Version" //+kubebuilder:printcolumn:name="MetadataURL",type="string",JSONPath=".status.metadataUrl",description="MetadataURL",priority=1 diff --git a/api/v1alpha1/githubcredentials_types.go b/api/v1beta1/githubcredentials_types.go similarity index 98% rename from api/v1alpha1/githubcredentials_types.go rename to api/v1beta1/githubcredentials_types.go index 7e99d32b..d0053315 100644 --- a/api/v1alpha1/githubcredentials_types.go +++ b/api/v1beta1/githubcredentials_types.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -package v1alpha1 +package v1beta1 import ( "github.com/cloudbase/garm/params" @@ -37,6 +37,7 @@ type GitHubCredentialsStatus struct { //+kubebuilder:object:root=true //+kubebuilder:resource:path=githubcredentials,scope=Namespaced,categories=garm,shortName=creds //+kubebuilder:subresource:status +//+kubebuilder:storageversion //+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Credentials ID" //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 diff --git a/api/v1alpha1/githubendpoint_types.go b/api/v1beta1/githubendpoint_types.go similarity index 97% rename from api/v1alpha1/githubendpoint_types.go rename to api/v1beta1/githubendpoint_types.go index 67550793..21d1fd55 100644 --- a/api/v1alpha1/githubendpoint_types.go +++ b/api/v1beta1/githubendpoint_types.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -package v1alpha1 +package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -23,6 +23,7 @@ type GitHubEndpointStatus struct { //+kubebuilder:object:root=true //+kubebuilder:resource:path=githubendpoints,scope=Namespaced,categories=garm,shortName=gep //+kubebuilder:subresource:status +//+kubebuilder:storageversion //+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".spec.apiBaseUrl",description="API Base URL" //+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go new file mode 100644 index 00000000..0a0621df --- /dev/null +++ b/api/v1beta1/groupversion_info.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT + +// Package v1alpha1 contains API Schema definitions for the garm-operator v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=garm-operator.mercedes-benz.com +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "garm-operator.mercedes-benz.com", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1beta1/image_types.go b/api/v1beta1/image_types.go new file mode 100644 index 00000000..5064817a --- /dev/null +++ b/api/v1beta1/image_types.go @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// ImageSpec defines the desired state of Image +type ImageSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Tag is the Name of the image in its registry + // e.g. + // - in openstack it can be the image name or id + // - in k8s it can be the docker image name + tag + Tag string `json:"tag,omitempty"` +} + +// ImageStatus defines the observed state of Image +type ImageStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:resource:path=images,scope=Namespaced,categories=garm +//+kubebuilder:printcolumn:name="Tag",type=string,JSONPath=`.spec.tag` +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// Image is the Schema for the images API +type Image struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ImageSpec `json:"spec,omitempty"` + Status ImageStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ImageList contains a list of Image +type ImageList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Image `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Image{}, &ImageList{}) +} diff --git a/api/v1beta1/image_webhook.go b/api/v1beta1/image_webhook.go new file mode 100644 index 00000000..2b2642f5 --- /dev/null +++ b/api/v1beta1/image_webhook.go @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "context" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var imagelog = logf.Log.WithName("image-resource") + +func (i *Image) SetupWebhookWithManager(mgr ctrl.Manager) error { + c = mgr.GetClient() + return ctrl.NewWebhookManagedBy(mgr). + For(i). + Complete() +} + +//+kubebuilder:webhook:path=/validate-garm-operator-mercedes-benz-com-v1alpha1-image,mutating=false,failurePolicy=fail,sideEffects=None,groups=garm-operator.mercedes-benz.com,resources=images,verbs=create;update;delete,versions=v1alpha1,name=validate.image.garm-operator.mercedes-benz.com,admissionReviewVersions=v1 + +var _ webhook.Validator = &Image{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (i *Image) ValidateCreate() (admission.Warnings, error) { + imagelog.Info("validate create", "name", i.Name) + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (i *Image) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { + imagelog.Info("validate update", "name", i.Name) + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (i *Image) ValidateDelete() (admission.Warnings, error) { + imagelog.Info("validate delete", "name", i.Name) + var msg string + + pools, err := i.attachedPools(context.Background()) + if err != nil { + msg = fmt.Sprintf("imagename=%s with tag=%s can not be deleted, failed to fetch pools: %s", i.Name, i.Spec.Tag, err.Error()) + return nil, apierrors.NewBadRequest(msg) + } + + if len(pools) > 0 { + msg = fmt.Sprintf("imagename=%s with tag=%s can not be deleted, as it is still referenced by at least one pool", i.Name, i.Spec.Tag) + return nil, apierrors.NewBadRequest(msg) + } + return nil, nil +} + +func (i *Image) attachedPools(ctx context.Context) ([]Pool, error) { + var pools PoolList + var result []Pool + if err := c.List(ctx, &pools); err != nil { + return result, err + } + + for _, pool := range pools.Items { + // we do not care about pools that are already deleted + if pool.GetDeletionTimestamp() == nil { + if pool.Spec.ImageName == i.Name { + result = append(result, pool) + } + } + } + + return result, nil +} diff --git a/api/v1beta1/organization_types.go b/api/v1beta1/organization_types.go new file mode 100644 index 00000000..55b962f2 --- /dev/null +++ b/api/v1beta1/organization_types.go @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "github.com/cloudbase/garm/params" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/mercedes-benz/garm-operator/pkg/conditions" +) + +// OrganizationSpec defines the desired state of Organization +type OrganizationSpec struct { + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + + // WebhookSecretRef represents a secret that should be used for the webhook + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` +} + +// OrganizationStatus defines the observed state of Organization +type OrganizationStatus struct { + ID string `json:"id"` + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=organizations,scope=Namespaced,categories=garm,shortName=org +//+kubebuilder:subresource:status +//+kubebuilder:storageversion +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Organization ID" +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="Pool_Manager_Failure",type="string",JSONPath=`.status.conditions[?(@.reason=='PoolManagerFailure')].message`,priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Organization" + +// Organization is the Schema for the organizations API +type Organization struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec OrganizationSpec `json:"spec,omitempty"` + Status OrganizationStatus `json:"status,omitempty"` +} + +func (o *Organization) SetConditions(conditions []metav1.Condition) { + o.Status.Conditions = conditions +} + +func (o *Organization) GetConditions() []metav1.Condition { + return o.Status.Conditions +} + +func (o *Organization) GetCredentialsName() string { + return o.Spec.CredentialsRef.Name +} + +func (o *Organization) GetID() string { + return o.Status.ID +} + +func (o *Organization) GetName() string { + return o.ObjectMeta.Name +} + +func (o *Organization) GetPoolManagerIsRunning() bool { + condition := conditions.Get(o, conditions.PoolManager) + if condition == nil { + return false + } + + return condition.Status == TrueAsString +} + +func (o *Organization) GetPoolManagerFailureReason() string { + condition := conditions.Get(o, conditions.PoolManager) + if condition == nil { + return "" + } + + if condition.Reason == string(conditions.PoolManagerFailureReason) { + return condition.Message + } + + return "" +} + +func (o *Organization) GetKind() string { + return o.Kind +} + +//+kubebuilder:object:root=true + +// OrganizationList contains a list of Organization +type OrganizationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Organization `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Organization{}, &OrganizationList{}) +} diff --git a/api/v1beta1/pool_helper.go b/api/v1beta1/pool_helper.go new file mode 100644 index 00000000..28d797b5 --- /dev/null +++ b/api/v1beta1/pool_helper.go @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "context" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/mercedes-benz/garm-operator/pkg/filter" +) + +func (p *Pool) GetImageCR(ctx context.Context, client client.Client) (*Image, error) { + image := &Image{} + if p.Spec.ImageName != "" { + if err := client.Get(ctx, types.NamespacedName{Name: p.Spec.ImageName, Namespace: p.Namespace}, image); err != nil { + return nil, err + } + } + return image, nil +} + +func MatchesImage(image string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Spec.ImageName == image + } +} + +func MatchesFlavor(flavor string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Spec.Flavor == flavor + } +} + +func MatchesProvider(provider string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Spec.ProviderName == provider + } +} + +func MatchesGitHubScope(name, kind string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Spec.GitHubScopeRef.Name == name && p.Spec.GitHubScopeRef.Kind == kind + } +} + +func MatchesID(id string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Status.ID == id + } +} + +func NotMatchingName(name string) filter.Predicate[Pool] { + return func(p Pool) bool { + return p.Name != name + } +} diff --git a/api/v1beta1/pool_types.go b/api/v1beta1/pool_types.go new file mode 100644 index 00000000..b38fe36e --- /dev/null +++ b/api/v1beta1/pool_types.go @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + commonParams "github.com/cloudbase/garm-provider-common/params" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// PoolSpec defines the desired state of Pool +// See: https://github.com/cloudbase/garm/blob/main/params/requests.go#L142 + +// +kubebuilder:validation:Required +// +kubebuilder:validation:XValidation:rule="self.minIdleRunners <= self.maxRunners",message="minIdleRunners must be less than or equal to maxRunners" +type PoolSpec struct { + // Defines in which Scope Runners a registered. Has a reference to either an Enterprise, Org or Repo CRD + GitHubScopeRef corev1.TypedLocalObjectReference `json:"githubScopeRef"` + ProviderName string `json:"providerName"` + MaxRunners uint `json:"maxRunners"` + // +kubebuilder:default=0 + MinIdleRunners uint `json:"minIdleRunners"` + Flavor string `json:"flavor"` + OSType commonParams.OSType `json:"osType"` + OSArch commonParams.OSArch `json:"osArch"` + Tags []string `json:"tags"` + Enabled bool `json:"enabled"` + RunnerBootstrapTimeout uint `json:"runnerBootstrapTimeout"` + + // The name of the image resource, this image resource must exists in the same namespace as the pool + ImageName string `json:"imageName"` + + // +optional + ExtraSpecs string `json:"extraSpecs"` + + // +optional + GitHubRunnerGroup string `json:"githubRunnerGroup"` + + // +optional + RunnerPrefix string `json:"runnerPrefix"` +} + +// PoolStatus defines the observed state of Pool +type PoolStatus struct { + ID string `json:"id"` + LongRunningIdleRunners uint `json:"longRunningIdleRunners"` + Selector string `json:"selector"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +func (p *Pool) SetConditions(conditions []metav1.Condition) { + p.Status.Conditions = conditions +} + +func (p *Pool) GetConditions() []metav1.Condition { + return p.Status.Conditions +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion +//+kubebuilder:subresource:scale:specpath=.spec.minIdleRunners,statuspath=.status.longRunningIdleRunners,selectorpath=.status.selector +//+kubebuilder:resource:path=pools,scope=Namespaced,categories=garm +//+kubebuilder:printcolumn:name="ID",type=string,JSONPath=`.status.id` +//+kubebuilder:printcolumn:name="MinIdleRunners",type=string,JSONPath=`.spec.minIdleRunners` +//+kubebuilder:printcolumn:name="MaxRunners",type=string,JSONPath=`.spec.maxRunners` +//+kubebuilder:printcolumn:name="ImageName",type=string,JSONPath=`.spec.imageName`,priority=1 +//+kubebuilder:printcolumn:name="Flavor",type=string,JSONPath=`.spec.flavor`,priority=1 +//+kubebuilder:printcolumn:name="Provider",type=string,JSONPath=`.spec.providerName`,priority=1 +//+kubebuilder:printcolumn:name="ScopeType",type=string,JSONPath=`.spec.githubScopeRef.kind`,priority=1 +//+kubebuilder:printcolumn:name="ScopeName",type=string,JSONPath=`.spec.githubScopeRef.name`,priority=1 +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="Enabled",type=boolean,JSONPath=`.spec.enabled`,priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// Pool is the Schema for the pools API +type Pool struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec PoolSpec `json:"spec,omitempty"` + Status PoolStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// PoolList contains a list of Pool +type PoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Pool `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Pool{}, &PoolList{}) +} diff --git a/api/v1beta1/pool_types_test.go b/api/v1beta1/pool_types_test.go new file mode 100644 index 00000000..84255328 --- /dev/null +++ b/api/v1beta1/pool_types_test.go @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +func TestPoolList_FilterByFields(t *testing.T) { + type fields struct { + TypeMeta metav1.TypeMeta + ListMeta metav1.ListMeta + Items []Pool + } + type args struct { + predicates []Predicate + } + tests := []struct { + name string + fields fields + args args + length int + }{ + { + name: "pool with spec already exist", + fields: fields{ + TypeMeta: metav1.TypeMeta{}, + ListMeta: metav1.ListMeta{}, + Items: []Pool{ + { + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "ubuntu-2004-large", + Namespace: "test", + }, + Spec: PoolSpec{ + ImageName: "ubuntu-2004", + Flavor: "large", + ProviderName: "openstack", + GitHubScopeRef: corev1.TypedLocalObjectReference{ + Name: "test", + Kind: "Enterprise", + APIGroup: ptr.To[string]("github.com"), + }, + }, + }, + { + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "ubuntu-2204-large", + Namespace: "test", + }, + Spec: PoolSpec{ + ImageName: "ubuntu-2204", + Flavor: "large", + ProviderName: "openstack", + GitHubScopeRef: corev1.TypedLocalObjectReference{ + Name: "test", + Kind: "Enterprise", + APIGroup: ptr.To[string]("github.com"), + }, + }, + }, + }, + }, + args: args{ + predicates: []Predicate{ + MatchesImage("ubuntu-2204"), + MatchesFlavor("large"), + MatchesProvider("openstack"), + MatchesGitHubScope("test", "Enterprise"), + }, + }, + length: 1, + }, + { + name: "pool with spec does not exist", + fields: fields{ + TypeMeta: metav1.TypeMeta{}, + ListMeta: metav1.ListMeta{}, + Items: []Pool{ + { + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "ubuntu-2004-large", + Namespace: "test", + }, + Spec: PoolSpec{ + ImageName: "ubuntu-2004", + Flavor: "large", + ProviderName: "openstack", + GitHubScopeRef: corev1.TypedLocalObjectReference{ + Name: "test", + Kind: "Enterprise", + APIGroup: ptr.To[string]("github.com"), + }, + }, + }, + { + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "ubuntu-2204-large", + Namespace: "test", + }, + Spec: PoolSpec{ + ImageName: "ubuntu-2204", + Flavor: "large", + ProviderName: "openstack", + GitHubScopeRef: corev1.TypedLocalObjectReference{ + Name: "test", + Kind: "Enterprise", + APIGroup: ptr.To[string]("github.com"), + }, + }, + }, + }, + }, + args: args{ + predicates: []Predicate{ + MatchesImage("ubuntu-2404"), + MatchesFlavor("large"), + MatchesProvider("openstack"), + MatchesGitHubScope("test", "Enterprise"), + }, + }, + length: 0, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &PoolList{ + TypeMeta: tt.fields.TypeMeta, + ListMeta: tt.fields.ListMeta, + Items: tt.fields.Items, + } + + p.FilterByFields(tt.args.predicates...) + + if len(p.Items) != tt.length { + t.Errorf("FilterByFields() = %v, want %v", len(p.Items), tt.length) + } + }) + } +} diff --git a/api/v1beta1/pool_webhook.go b/api/v1beta1/pool_webhook.go new file mode 100644 index 00000000..a47e8648 --- /dev/null +++ b/api/v1beta1/pool_webhook.go @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "encoding/json" + "fmt" + "reflect" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var ( + poollog = logf.Log.WithName("pool-resource") + c client.Client +) + +func (r *Pool) SetupWebhookWithManager(mgr ctrl.Manager) error { + c = mgr.GetClient() + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-garm-operator-mercedes-benz-com-v1alpha1-pool,mutating=false,failurePolicy=fail,sideEffects=None,groups=garm-operator.mercedes-benz.com,resources=pools,verbs=create;update,versions=v1alpha1,name=validate.pool.garm-operator.mercedes-benz.com,admissionReviewVersions=v1 + +var _ webhook.Validator = &Pool{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Pool) ValidateCreate() (admission.Warnings, error) { + poollog.Info("validate create", "name", r.Name) + + if err := r.validateExtraSpec(); err != nil { + return nil, apierrors.NewInvalid(schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, + r.Name, + field.ErrorList{err}, + ) + } + + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Pool) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + poollog.Info("validate update", "name", r.Name, "namespace", r.Namespace) + + oldCRD, ok := old.(*Pool) + if !ok { + return nil, apierrors.NewBadRequest("failed to convert runtime.Object to Pool CRD") + } + + // if the object is being deleted, skip validation + if r.GetDeletionTimestamp() == nil { + if err := r.validateExtraSpec(); err != nil { + return nil, apierrors.NewInvalid(schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, + r.Name, + field.ErrorList{err}, + ) + } + + if err := r.validateProviderName(oldCRD); err != nil { + return nil, apierrors.NewInvalid( + schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, + r.Name, + field.ErrorList{err}, + ) + } + + if err := r.validateGitHubScope(oldCRD); err != nil { + return nil, apierrors.NewInvalid( + schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, + r.Name, + field.ErrorList{err}, + ) + } + } + + return nil, nil +} + +func (r *Pool) validateProviderName(old *Pool) *field.Error { + poollog.Info("validate spec.providerName", "spec.providerName", r.Spec.ProviderName) + fieldPath := field.NewPath("spec").Child("providerName") + n := r.Spec.ProviderName + o := old.Spec.ProviderName + if n != o { + return field.Invalid( + fieldPath, + r.Spec.ProviderName, + fmt.Errorf("can not change provider of an existing pool. Old name: %s, new name: %s", o, n).Error(), + ) + } + return nil +} + +func (r *Pool) validateExtraSpec() *field.Error { + extraSpecs := json.RawMessage([]byte{}) + fieldPath := field.NewPath("spec").Child("extraSpecs") + err := json.Unmarshal([]byte(r.Spec.ExtraSpecs), &extraSpecs) + if err != nil { + return field.Invalid( + fieldPath, + r.Spec.ExtraSpecs, + fmt.Errorf("can not unmarshal extraSpecs: %s", err.Error()).Error(), + ) + } + + return nil +} + +func (r *Pool) validateGitHubScope(old *Pool) *field.Error { + poollog.Info("validate spec.githubScopeRef", "spec.githubScopeRef", r.Spec.GitHubScopeRef) + fieldPath := field.NewPath("spec").Child("githubScopeRef") + n := r.Spec.GitHubScopeRef + o := old.Spec.GitHubScopeRef + if !reflect.DeepEqual(n, o) { + return field.Invalid( + fieldPath, + r.Spec.ProviderName, + fmt.Errorf("can not change githubScopeRef of an existing pool. Old name: %+v, new name: %+v", o, n).Error(), + ) + } + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Pool) ValidateDelete() (admission.Warnings, error) { + poollog.Info("validate delete", "name", r.Name) + return nil, nil +} diff --git a/api/v1beta1/repository_types.go b/api/v1beta1/repository_types.go new file mode 100644 index 00000000..adfb9574 --- /dev/null +++ b/api/v1beta1/repository_types.go @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "github.com/cloudbase/garm/params" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/mercedes-benz/garm-operator/pkg/conditions" +) + +// RepositorySpec defines the desired state of Repository +type RepositorySpec struct { + CredentialsRef corev1.TypedLocalObjectReference `json:"credentialsRef"` + Owner string `json:"owner"` + + // WebhookSecretRef represents a secret that should be used for the webhook + WebhookSecretRef SecretRef `json:"webhookSecretRef"` + PoolBalancerType params.PoolBalancerType `json:"poolBalancerType,omitempty"` +} + +// RepositoryStatus defines the observed state of Repository +type RepositoryStatus struct { + ID string `json:"id"` + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=repositories,scope=Namespaced,categories=garm,shortName=repo +//+kubebuilder:subresource:status +//+kubebuilder:storageversion +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Repository ID" +//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +//+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 +//+kubebuilder:printcolumn:name="Pool_Manager_Failure",type="string",JSONPath=`.status.conditions[?(@.reason=='PoolManagerFailure')].message`,priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Repository" + +// Repository is the Schema for the repositories API +type Repository struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RepositorySpec `json:"spec,omitempty"` + Status RepositoryStatus `json:"status,omitempty"` +} + +func (r *Repository) SetConditions(conditions []metav1.Condition) { + r.Status.Conditions = conditions +} + +func (r *Repository) GetConditions() []metav1.Condition { + return r.Status.Conditions +} + +func (r *Repository) GetCredentialsName() string { + return r.Spec.CredentialsRef.Name +} + +func (r *Repository) GetID() string { + return r.Status.ID +} + +func (r *Repository) GetName() string { + return r.ObjectMeta.Name +} + +func (r *Repository) GetPoolManagerIsRunning() bool { + condition := conditions.Get(r, conditions.PoolManager) + if condition == nil { + return false + } + + return condition.Status == TrueAsString +} + +func (r *Repository) GetPoolManagerFailureReason() string { + condition := conditions.Get(r, conditions.PoolManager) + if condition == nil { + return "" + } + + if condition.Reason == string(conditions.PoolManagerFailureReason) { + return condition.Message + } + + return "" +} + +func (r *Repository) GetKind() string { + return r.Kind +} + +//+kubebuilder:object:root=true + +// RepositoryList contains a list of Repository +type RepositoryList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Repository `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Repository{}, &RepositoryList{}) +} diff --git a/api/v1beta1/repository_webhook.go b/api/v1beta1/repository_webhook.go new file mode 100644 index 00000000..ab645959 --- /dev/null +++ b/api/v1beta1/repository_webhook.go @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var repositorylog = logf.Log.WithName("repository-resource") + +func (r *Repository) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-garm-operator-mercedes-benz-com-v1alpha1-repository,mutating=false,failurePolicy=fail,sideEffects=None,groups=garm-operator.mercedes-benz.com,resources=repositories,verbs=create;update,versions=v1alpha1,name=validate.repository.garm-operator.mercedes-benz.com,admissionReviewVersions=v1 + +var _ webhook.Validator = &Repository{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Repository) ValidateCreate() (admission.Warnings, error) { + repositorylog.Info("validate create", "name", r.Name) + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Repository) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + repositorylog.Info("validate update", "name", r.Name) + + oldCRD, ok := old.(*Repository) + if !ok { + return nil, apierrors.NewBadRequest("failed to convert runtime.Object to Repository CRD") + } + + if err := r.validateRepoOwnerName(oldCRD); err != nil { + return nil, apierrors.NewInvalid( + schema.GroupKind{Group: GroupVersion.Group, Kind: "Repository"}, + r.Name, + field.ErrorList{err}, + ) + } + return nil, nil +} + +func (r *Repository) validateRepoOwnerName(old *Repository) *field.Error { + repositorylog.Info("validate spec.owner", "spec.owner", r.Spec.Owner) + fieldPath := field.NewPath("spec").Child("owner") + n := r.Spec.Owner + o := old.Spec.Owner + if n != o { + return field.Invalid( + fieldPath, + r.Spec.Owner, + fmt.Errorf("cannot change owner of repository resource. Old name: %s, new name: %s", o, n).Error(), + ) + } + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Repository) ValidateDelete() (admission.Warnings, error) { + repositorylog.Info("validate delete", "name", r.Name) + return nil, nil +} diff --git a/api/v1beta1/runner_types.go b/api/v1beta1/runner_types.go new file mode 100644 index 00000000..55288156 --- /dev/null +++ b/api/v1beta1/runner_types.go @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/cloudbase/garm/params" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// RunnerSpec defines the desired state of Runner +type RunnerSpec struct{} + +// RunnerStatus defines the observed state of Runner +type RunnerStatus struct { + // ID is the database ID of this instance. + ID string `json:"id,omitempty"` + + // PeoviderID is the unique ID the provider associated + // with the compute instance. We use this to identify the + // instance in the provider. + ProviderID string `json:"providerId,omitempty"` + + // AgentID is the github runner agent ID. + AgentID int64 `json:"agentId"` + + // Name is the name associated with an instance. Depending on + // the provider, this may or may not be useful in the context of + // the provider, but we can use it internally to identify the + // instance. + Name string `json:"name,omitempty"` + + // OSType is the operating system type. For now, only Linux and + // Windows are supported. + OSType commonParams.OSType `json:"osType,omitempty"` + + // OSName is the name of the OS. Eg: ubuntu, centos, etc. + OSName string `json:"osName,omitempty"` + + // OSVersion is the version of the operating system. + OSVersion string `json:"osVersion,omitempty"` + + // OSArch is the operating system architecture. + OSArch commonParams.OSArch `json:"osArch,omitempty"` + + // Addresses is a list of IP addresses the provider reports + // for this instance. + Addresses []commonParams.Address `json:"addresses,omitempty"` + + // Status is the status of the instance inside the provider (eg: running, stopped, etc) + Status commonParams.InstanceStatus `json:"status,omitempty"` + + // RunnerStatus is the github runner status as it appears on GitHub. + InstanceStatus params.RunnerStatus `json:"instanceStatus,omitempty"` + + // PoolID is the ID of the garm pool to which a runner belongs. + PoolID string `json:"poolId,omitempty"` + + // ProviderFault holds any error messages captured from the IaaS provider that is + // responsible for managing the lifecycle of the runner. + ProviderFault string `json:"providerFault,omitempty"` + + // StatusMessages is a list of status messages sent back by the runner as it sets itself + // up. + + //// UpdatedAt is the timestamp of the last update to this runner. + // UpdatedAt time.Time `json:"updated_at"` + + // GithubRunnerGroup is the github runner group to which the runner belongs. + // The runner group must be created by someone with access to the enterprise. + GitHubRunnerGroup string `json:"githubRunnerGroup"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:path=runners,scope=Namespaced,categories=garm,shortName=run +//+kubebuilder:subresource:status +//+kubebuilder:storageversion +//+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Runner ID" +//+kubebuilder:printcolumn:name="Pool",type="string",JSONPath=".status.poolId",description="Pool CR Name" +//+kubebuilder:printcolumn:name="Garm Runner Status",type="string",JSONPath=".status.status",description="Garm Runner Status" +//+kubebuilder:printcolumn:name="Provider Runner Status",type="string",JSONPath=".status.instanceStatus",description="Provider Runner Status" +//+kubebuilder:printcolumn:name="Provider ID",type="string",JSONPath=".status.providerId",description="Provider ID",priority=1 +//+kubebuilder:printcolumn:name="Agent ID",type="string",JSONPath=".status.agentId",description="Agent ID",priority=1 +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// Runner is the Schema for the runners API +type Runner struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RunnerSpec `json:"spec,omitempty"` + Status RunnerStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RunnerList contains a list of Runner +type RunnerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Runner `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Runner{}, &RunnerList{}) +} diff --git a/api/v1beta1/shared.go b/api/v1beta1/shared.go new file mode 100644 index 00000000..90086eb6 --- /dev/null +++ b/api/v1beta1/shared.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT + +package v1beta1 + +import ( + "fmt" +) + +type GitHubScopeKind string + +const ( + EnterpriseScope GitHubScopeKind = "Enterprise" + OrganizationScope GitHubScopeKind = "Organization" + RepositoryScope GitHubScopeKind = "Repository" +) + +// +k8s:deepcopy-gen=false +type GitHubScope interface { + GetKind() string + GetCredentialsName() string + GetID() string + GetName() string + GetPoolManagerIsRunning() bool + GetPoolManagerFailureReason() string +} + +func ToGitHubScopeKind(kind string) (GitHubScopeKind, error) { + switch kind { + case string(EnterpriseScope), string(OrganizationScope), string(RepositoryScope): + return GitHubScopeKind(kind), nil + default: + return GitHubScopeKind(""), fmt.Errorf("can not convert kind %s to valid GitHubScopeKind: Enterprise, Organization, Repository", kind) + } +} + +type SecretRef struct { + // Name of the kubernetes secret to use + Name string `json:"name"` + // Key is the key in the secret's data map for this value + Key string `json:"key"` +} + +const ( + TrueAsString = "True" + FalseAsString = "False" +) diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 00000000..5ef29fb1 --- /dev/null +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,902 @@ +//go:build !ignore_autogenerated + +// SPDX-License-Identifier: MIT + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "github.com/cloudbase/garm-provider-common/params" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Enterprise) DeepCopyInto(out *Enterprise) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Enterprise. +func (in *Enterprise) DeepCopy() *Enterprise { + if in == nil { + return nil + } + out := new(Enterprise) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Enterprise) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnterpriseList) DeepCopyInto(out *EnterpriseList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Enterprise, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseList. +func (in *EnterpriseList) DeepCopy() *EnterpriseList { + if in == nil { + return nil + } + out := new(EnterpriseList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EnterpriseList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnterpriseSpec) DeepCopyInto(out *EnterpriseSpec) { + *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) + out.WebhookSecretRef = in.WebhookSecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseSpec. +func (in *EnterpriseSpec) DeepCopy() *EnterpriseSpec { + if in == nil { + return nil + } + out := new(EnterpriseSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnterpriseStatus) DeepCopyInto(out *EnterpriseStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnterpriseStatus. +func (in *EnterpriseStatus) DeepCopy() *EnterpriseStatus { + if in == nil { + return nil + } + out := new(EnterpriseStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfig) DeepCopyInto(out *GarmServerConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfig. +func (in *GarmServerConfig) DeepCopy() *GarmServerConfig { + if in == nil { + return nil + } + out := new(GarmServerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GarmServerConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigList) DeepCopyInto(out *GarmServerConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GarmServerConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigList. +func (in *GarmServerConfigList) DeepCopy() *GarmServerConfigList { + if in == nil { + return nil + } + out := new(GarmServerConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GarmServerConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigSpec) DeepCopyInto(out *GarmServerConfigSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigSpec. +func (in *GarmServerConfigSpec) DeepCopy() *GarmServerConfigSpec { + if in == nil { + return nil + } + out := new(GarmServerConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GarmServerConfigStatus) DeepCopyInto(out *GarmServerConfigStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarmServerConfigStatus. +func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { + if in == nil { + return nil + } + out := new(GarmServerConfigStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. +func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { + if in == nil { + return nil + } + out := new(GitHubCredentials) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubCredentials) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GitHubCredentials, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. +func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { + if in == nil { + return nil + } + out := new(GitHubCredentialsList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { + *out = *in + in.EndpointRef.DeepCopyInto(&out.EndpointRef) + out.SecretRef = in.SecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. +func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { + if in == nil { + return nil + } + out := new(GitHubCredentialsSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. +func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { + if in == nil { + return nil + } + out := new(GitHubCredentialsStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubEndpoint) DeepCopyInto(out *GitHubEndpoint) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpoint. +func (in *GitHubEndpoint) DeepCopy() *GitHubEndpoint { + if in == nil { + return nil + } + out := new(GitHubEndpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubEndpoint) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubEndpointList) DeepCopyInto(out *GitHubEndpointList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GitHubEndpoint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointList. +func (in *GitHubEndpointList) DeepCopy() *GitHubEndpointList { + if in == nil { + return nil + } + out := new(GitHubEndpointList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GitHubEndpointList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubEndpointSpec) DeepCopyInto(out *GitHubEndpointSpec) { + *out = *in + if in.CACertBundle != nil { + in, out := &in.CACertBundle, &out.CACertBundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointSpec. +func (in *GitHubEndpointSpec) DeepCopy() *GitHubEndpointSpec { + if in == nil { + return nil + } + out := new(GitHubEndpointSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitHubEndpointStatus) DeepCopyInto(out *GitHubEndpointStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubEndpointStatus. +func (in *GitHubEndpointStatus) DeepCopy() *GitHubEndpointStatus { + if in == nil { + return nil + } + out := new(GitHubEndpointStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Image) DeepCopyInto(out *Image) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image. +func (in *Image) DeepCopy() *Image { + if in == nil { + return nil + } + out := new(Image) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Image) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageList) DeepCopyInto(out *ImageList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Image, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageList. +func (in *ImageList) DeepCopy() *ImageList { + if in == nil { + return nil + } + out := new(ImageList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImageList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageSpec) DeepCopyInto(out *ImageSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSpec. +func (in *ImageSpec) DeepCopy() *ImageSpec { + if in == nil { + return nil + } + out := new(ImageSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageStatus) DeepCopyInto(out *ImageStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStatus. +func (in *ImageStatus) DeepCopy() *ImageStatus { + if in == nil { + return nil + } + out := new(ImageStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Organization) DeepCopyInto(out *Organization) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Organization. +func (in *Organization) DeepCopy() *Organization { + if in == nil { + return nil + } + out := new(Organization) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Organization) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OrganizationList) DeepCopyInto(out *OrganizationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Organization, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OrganizationList. +func (in *OrganizationList) DeepCopy() *OrganizationList { + if in == nil { + return nil + } + out := new(OrganizationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OrganizationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OrganizationSpec) DeepCopyInto(out *OrganizationSpec) { + *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) + out.WebhookSecretRef = in.WebhookSecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OrganizationSpec. +func (in *OrganizationSpec) DeepCopy() *OrganizationSpec { + if in == nil { + return nil + } + out := new(OrganizationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OrganizationStatus) DeepCopyInto(out *OrganizationStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OrganizationStatus. +func (in *OrganizationStatus) DeepCopy() *OrganizationStatus { + if in == nil { + return nil + } + out := new(OrganizationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Pool) DeepCopyInto(out *Pool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Pool. +func (in *Pool) DeepCopy() *Pool { + if in == nil { + return nil + } + out := new(Pool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Pool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PoolList) DeepCopyInto(out *PoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Pool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolList. +func (in *PoolList) DeepCopy() *PoolList { + if in == nil { + return nil + } + out := new(PoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PoolList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PoolSpec) DeepCopyInto(out *PoolSpec) { + *out = *in + in.GitHubScopeRef.DeepCopyInto(&out.GitHubScopeRef) + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolSpec. +func (in *PoolSpec) DeepCopy() *PoolSpec { + if in == nil { + return nil + } + out := new(PoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PoolStatus) DeepCopyInto(out *PoolStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolStatus. +func (in *PoolStatus) DeepCopy() *PoolStatus { + if in == nil { + return nil + } + out := new(PoolStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Repository) DeepCopyInto(out *Repository) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repository. +func (in *Repository) DeepCopy() *Repository { + if in == nil { + return nil + } + out := new(Repository) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Repository) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RepositoryList) DeepCopyInto(out *RepositoryList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Repository, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryList. +func (in *RepositoryList) DeepCopy() *RepositoryList { + if in == nil { + return nil + } + out := new(RepositoryList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RepositoryList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RepositorySpec) DeepCopyInto(out *RepositorySpec) { + *out = *in + in.CredentialsRef.DeepCopyInto(&out.CredentialsRef) + out.WebhookSecretRef = in.WebhookSecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositorySpec. +func (in *RepositorySpec) DeepCopy() *RepositorySpec { + if in == nil { + return nil + } + out := new(RepositorySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RepositoryStatus) DeepCopyInto(out *RepositoryStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryStatus. +func (in *RepositoryStatus) DeepCopy() *RepositoryStatus { + if in == nil { + return nil + } + out := new(RepositoryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Runner) DeepCopyInto(out *Runner) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Runner. +func (in *Runner) DeepCopy() *Runner { + if in == nil { + return nil + } + out := new(Runner) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Runner) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunnerList) DeepCopyInto(out *RunnerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Runner, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerList. +func (in *RunnerList) DeepCopy() *RunnerList { + if in == nil { + return nil + } + out := new(RunnerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RunnerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunnerSpec) DeepCopyInto(out *RunnerSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerSpec. +func (in *RunnerSpec) DeepCopy() *RunnerSpec { + if in == nil { + return nil + } + out := new(RunnerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunnerStatus) DeepCopyInto(out *RunnerStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]params.Address, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunnerStatus. +func (in *RunnerStatus) DeepCopy() *RunnerStatus { + if in == nil { + return nil + } + out := new(RunnerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretRef) DeepCopyInto(out *SecretRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. +func (in *SecretRef) DeepCopy() *SecretRef { + if in == nil { + return nil + } + out := new(SecretRef) + in.DeepCopyInto(out) + return out +} diff --git a/cmd/main.go b/cmd/main.go index 9b41ee99..2d4ef825 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,6 +22,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" garmcontroller "github.com/mercedes-benz/garm-operator/internal/controller" "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/config" @@ -37,6 +38,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(garmoperatorv1alpha1.AddToScheme(scheme)) + utilruntime.Must(garmoperatorv1beta1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -71,7 +73,7 @@ func run() error { return nil } - ctrl.SetLogger(textlogger.NewLogger((textlogger.NewConfig(textlogger.Verbosity(config.Config.Operator.LogVerbosityLevel))))) + ctrl.SetLogger(textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(config.Config.Operator.LogVerbosityLevel)))) var watchNamespaces map[string]cache.Config if config.Config.Operator.WatchNamespace != "" { diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml index 801ab1a4..b63264db 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_enterprises.yaml @@ -39,6 +39,154 @@ spec: name: Age type: date name: v1alpha1 + schema: + openAPIV3Schema: + description: Enterprise is the Schema for the enterprises API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: EnterpriseSpec defines the desired state of Enterprise + properties: + credentialsName: + type: string + webhookSecretRef: + description: WebhookSecretRef represents a secret that should be used + for the webhook + properties: + key: + description: Key is the key in the secret's data map for this + value + type: string + name: + description: Name of the kubernetes secret to use + type: string + required: + - key + - name + type: object + required: + - credentialsName + - webhookSecretRef + type: object + status: + description: EnterpriseStatus defines the observed state of Enterprise + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + type: string + required: + - id + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Enterprise ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.reason=='PoolManagerFailure')].message + name: Pool_Manager_Failure + priority: 1 + type: string + - description: Time duration since creation of Enterprise + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 schema: openAPIV3Schema: description: Enterprise is the Schema for the enterprises API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml index 1139288b..13720ce4 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml @@ -51,7 +51,7 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1beta1 schema: openAPIV3Schema: description: GarmServerConfig is the Schema for the garmserverconfigs API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml index 6d85c9b3..cb7f1246 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml @@ -42,7 +42,7 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1beta1 schema: openAPIV3Schema: description: GitHubCredentials is the Schema for the githubcredentials API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml index c884b1ef..28c3d4ae 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml @@ -34,7 +34,7 @@ spec: jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1beta1 schema: openAPIV3Schema: description: GitHubEndpoint is the Schema for the githubendpoints API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml index 31edba16..38523e64 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_images.yaml @@ -61,5 +61,52 @@ spec: type: object type: object served: true + storage: false + subresources: {} + - additionalPrinterColumns: + - jsonPath: .spec.tag + name: Tag + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Image is the Schema for the images API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ImageSpec defines the desired state of Image + properties: + tag: + description: |- + Tag is the Name of the image in its registry + e.g. + - in openstack it can be the image name or id + - in k8s it can be the docker image name + tag + type: string + type: object + status: + description: ImageStatus defines the observed state of Image + type: object + type: object + served: true storage: true subresources: {} diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml index bcb42f5f..bcbcd51b 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_organizations.yaml @@ -39,6 +39,154 @@ spec: name: Age type: date name: v1alpha1 + schema: + openAPIV3Schema: + description: Organization is the Schema for the organizations API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OrganizationSpec defines the desired state of Organization + properties: + credentialsName: + type: string + webhookSecretRef: + description: WebhookSecretRef represents a secret that should be used + for the webhook + properties: + key: + description: Key is the key in the secret's data map for this + value + type: string + name: + description: Name of the kubernetes secret to use + type: string + required: + - key + - name + type: object + required: + - credentialsName + - webhookSecretRef + type: object + status: + description: OrganizationStatus defines the observed state of Organization + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + type: string + required: + - id + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Organization ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.reason=='PoolManagerFailure')].message + name: Pool_Manager_Failure + priority: 1 + type: string + - description: Time duration since creation of Organization + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 schema: openAPIV3Schema: description: Organization is the Schema for the organizations API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_pools.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_pools.yaml index 007dda97..8fb76249 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_pools.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_pools.yaml @@ -237,6 +237,234 @@ spec: type: object type: object served: true + storage: false + subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.minIdleRunners + statusReplicasPath: .status.longRunningIdleRunners + status: {} + - additionalPrinterColumns: + - jsonPath: .status.id + name: ID + type: string + - jsonPath: .spec.minIdleRunners + name: MinIdleRunners + type: string + - jsonPath: .spec.maxRunners + name: MaxRunners + type: string + - jsonPath: .spec.imageName + name: ImageName + priority: 1 + type: string + - jsonPath: .spec.flavor + name: Flavor + priority: 1 + type: string + - jsonPath: .spec.providerName + name: Provider + priority: 1 + type: string + - jsonPath: .spec.githubScopeRef.kind + name: ScopeType + priority: 1 + type: string + - jsonPath: .spec.githubScopeRef.name + name: ScopeName + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - jsonPath: .spec.enabled + name: Enabled + priority: 1 + type: boolean + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Pool is the Schema for the pools API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + enabled: + type: boolean + extraSpecs: + type: string + flavor: + type: string + githubRunnerGroup: + type: string + githubScopeRef: + description: Defines in which Scope Runners a registered. Has a reference + to either an Enterprise, Org or Repo CRD + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + imageName: + description: The name of the image resource, this image resource must + exists in the same namespace as the pool + type: string + maxRunners: + type: integer + minIdleRunners: + default: 0 + type: integer + osArch: + type: string + osType: + type: string + providerName: + type: string + runnerBootstrapTimeout: + type: integer + runnerPrefix: + type: string + tags: + items: + type: string + type: array + required: + - enabled + - flavor + - githubScopeRef + - imageName + - maxRunners + - minIdleRunners + - osArch + - osType + - providerName + - runnerBootstrapTimeout + - tags + type: object + x-kubernetes-validations: + - message: minIdleRunners must be less than or equal to maxRunners + rule: self.minIdleRunners <= self.maxRunners + status: + description: PoolStatus defines the observed state of Pool + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + type: string + longRunningIdleRunners: + type: integer + selector: + type: string + required: + - id + - longRunningIdleRunners + - selector + type: object + type: object + served: true storage: true subresources: scale: diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml index e142983c..a7ac6bf0 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_repositories.yaml @@ -39,6 +39,157 @@ spec: name: Age type: date name: v1alpha1 + schema: + openAPIV3Schema: + description: Repository is the Schema for the repositories API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: RepositorySpec defines the desired state of Repository + properties: + credentialsName: + type: string + owner: + type: string + webhookSecretRef: + description: WebhookSecretRef represents a secret that should be used + for the webhook + properties: + key: + description: Key is the key in the secret's data map for this + value + type: string + name: + description: Name of the kubernetes secret to use + type: string + required: + - key + - name + type: object + required: + - credentialsName + - owner + - webhookSecretRef + type: object + status: + description: RepositoryStatus defines the observed state of Repository + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + type: string + required: + - id + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Repository ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.reason=='PoolManagerFailure')].message + name: Pool_Manager_Failure + priority: 1 + type: string + - description: Time duration since creation of Repository + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 schema: openAPIV3Schema: description: Repository is the Schema for the repositories API diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_runners.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_runners.yaml index 9b0fbc88..d1a94786 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_runners.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_runners.yaml @@ -152,6 +152,143 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Runner ID + jsonPath: .status.id + name: ID + type: string + - description: Pool CR Name + jsonPath: .status.poolId + name: Pool + type: string + - description: Garm Runner Status + jsonPath: .status.status + name: Garm Runner Status + type: string + - description: Provider Runner Status + jsonPath: .status.instanceStatus + name: Provider Runner Status + type: string + - description: Provider ID + jsonPath: .status.providerId + name: Provider ID + priority: 1 + type: string + - description: Agent ID + jsonPath: .status.agentId + name: Agent ID + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Runner is the Schema for the runners API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: RunnerSpec defines the desired state of Runner + type: object + status: + description: RunnerStatus defines the observed state of Runner + properties: + addresses: + description: |- + Addresses is a list of IP addresses the provider reports + for this instance. + items: + properties: + address: + type: string + type: + type: string + required: + - address + - type + type: object + type: array + agentId: + description: AgentID is the github runner agent ID. + format: int64 + type: integer + githubRunnerGroup: + description: |- + GithubRunnerGroup is the github runner group to which the runner belongs. + The runner group must be created by someone with access to the enterprise. + type: string + id: + description: ID is the database ID of this instance. + type: string + instanceStatus: + description: RunnerStatus is the github runner status as it appears + on GitHub. + type: string + name: + description: |- + Name is the name associated with an instance. Depending on + the provider, this may or may not be useful in the context of + the provider, but we can use it internally to identify the + instance. + type: string + osArch: + description: OSArch is the operating system architecture. + type: string + osName: + description: 'OSName is the name of the OS. Eg: ubuntu, centos, etc.' + type: string + osType: + description: |- + OSType is the operating system type. For now, only Linux and + Windows are supported. + type: string + osVersion: + description: OSVersion is the version of the operating system. + type: string + poolId: + description: PoolID is the ID of the garm pool to which a runner belongs. + type: string + providerFault: + description: |- + ProviderFault holds any error messages captured from the IaaS provider that is + responsible for managing the lifecycle of the runner. + type: string + providerId: + description: |- + PeoviderID is the unique ID the provider associated + with the compute instance. We use this to identify the + instance in the provider. + type: string + status: + description: 'Status is the status of the instance inside the provider + (eg: running, stopped, etc)' + type: string + required: + - agentId + - githubRunnerGroup + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 95454ebe..64837e5b 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -24,6 +24,11 @@ patches: #- path: patches/webhook_in_garmserverconfigs.yaml #- path: patches/webhook_in_githubendpoints.yaml #- path: patches/webhook_in_githubcredentials.yaml +#- path: patches/webhook_in_enterprises.yaml +#- path: patches/webhook_in_organizations.yaml +#- path: patches/webhook_in_repositories.yaml +#- path: patches/webhook_in_pools.yaml +#- path: patches/webhook_in_images.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -37,6 +42,10 @@ patches: #- path: patches/cainjection_in_garmserverconfigs.yaml #- path: patches/cainjection_in_githubendpoints.yaml #- path: patches/cainjection_in_githubcredentials.yaml +#- path: patches/cainjection_in_enterprises.yaml +#- path: patches/cainjection_in_organizations.yaml +#- path: patches/cainjection_in_repositories.yaml +#- path: patches/cainjection_in_pools.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/rbac/githubendpoint_editor_role.yaml b/config/rbac/githubendpoint_editor_role.yaml new file mode 100644 index 00000000..0a7d2860 --- /dev/null +++ b/config/rbac/githubendpoint_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit githubendpoints. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: githubendpoint-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: githubendpoint-editor-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubendpoints + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubendpoints/status + verbs: + - get diff --git a/config/rbac/githubendpoint_viewer_role.yaml b/config/rbac/githubendpoint_viewer_role.yaml new file mode 100644 index 00000000..e47ba359 --- /dev/null +++ b/config/rbac/githubendpoint_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view githubendpoints. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: githubendpoint-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: garm-operator + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + name: githubendpoint-viewer-role +rules: +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubendpoints + verbs: + - get + - list + - watch +- apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubendpoints/status + verbs: + - get diff --git a/config/samples/garm-operator_v1alpha1_controller.yaml b/config/samples/garm-operator_v1beta1_enterprise.yaml similarity index 51% rename from config/samples/garm-operator_v1alpha1_controller.yaml rename to config/samples/garm-operator_v1beta1_enterprise.yaml index 796866e8..90a1ea0f 100644 --- a/config/samples/garm-operator_v1alpha1_controller.yaml +++ b/config/samples/garm-operator_v1beta1_enterprise.yaml @@ -1,12 +1,12 @@ -apiVersion: garm-operator.mercedes-benz.com/v1alpha1 -kind: Controller +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Enterprise metadata: labels: - app.kubernetes.io/name: controller - app.kubernetes.io/instance: controller-sample + app.kubernetes.io/name: enterprise + app.kubernetes.io/instance: enterprise-sample app.kubernetes.io/part-of: garm-operator app.kubernetes.io/managed-by: kustomize app.kubernetes.io/created-by: garm-operator - name: controller-sample + name: enterprise-sample spec: # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_garmserverconfig.yaml b/config/samples/garm-operator_v1beta1_garmserverconfig.yaml new file mode 100644 index 00000000..3e7a1148 --- /dev/null +++ b/config/samples/garm-operator_v1beta1_garmserverconfig.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: GarmServerConfig +metadata: + labels: + app.kubernetes.io/name: garmserverconfig + app.kubernetes.io/instance: garmserverconfig-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: garmserverconfig-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_githubcredentials.yaml b/config/samples/garm-operator_v1beta1_githubcredentials.yaml new file mode 100644 index 00000000..f9431ed4 --- /dev/null +++ b/config/samples/garm-operator_v1beta1_githubcredentials.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: GitHubCredentials +metadata: + labels: + app.kubernetes.io/name: githubcredentials + app.kubernetes.io/instance: githubcredentials-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: githubcredentials-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_githubendpoint.yaml b/config/samples/garm-operator_v1beta1_githubendpoint.yaml new file mode 100644 index 00000000..76099a39 --- /dev/null +++ b/config/samples/garm-operator_v1beta1_githubendpoint.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: GitHubEndpoint +metadata: + labels: + app.kubernetes.io/name: githubendpoint + app.kubernetes.io/instance: githubendpoint-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: githubendpoint-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_image.yaml b/config/samples/garm-operator_v1beta1_image.yaml new file mode 100644 index 00000000..c02275e4 --- /dev/null +++ b/config/samples/garm-operator_v1beta1_image.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Image +metadata: + labels: + app.kubernetes.io/name: image + app.kubernetes.io/instance: image-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: image-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_organization.yaml b/config/samples/garm-operator_v1beta1_organization.yaml new file mode 100644 index 00000000..af7d074b --- /dev/null +++ b/config/samples/garm-operator_v1beta1_organization.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Organization +metadata: + labels: + app.kubernetes.io/name: organization + app.kubernetes.io/instance: organization-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: organization-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_pool.yaml b/config/samples/garm-operator_v1beta1_pool.yaml new file mode 100644 index 00000000..c207e01d --- /dev/null +++ b/config/samples/garm-operator_v1beta1_pool.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Pool +metadata: + labels: + app.kubernetes.io/name: pool + app.kubernetes.io/instance: pool-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: pool-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_repository.yaml b/config/samples/garm-operator_v1beta1_repository.yaml new file mode 100644 index 00000000..9dcb8e53 --- /dev/null +++ b/config/samples/garm-operator_v1beta1_repository.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Repository +metadata: + labels: + app.kubernetes.io/name: repository + app.kubernetes.io/instance: repository-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: repository-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/garm-operator_v1beta1_runner.yaml b/config/samples/garm-operator_v1beta1_runner.yaml new file mode 100644 index 00000000..c36ad6ee --- /dev/null +++ b/config/samples/garm-operator_v1beta1_runner.yaml @@ -0,0 +1,12 @@ +apiVersion: garm-operator.mercedes-benz.com/v1beta1 +kind: Runner +metadata: + labels: + app.kubernetes.io/name: runner + app.kubernetes.io/instance: runner-sample + app.kubernetes.io/part-of: garm-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: garm-operator + name: runner-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index f611d7cd..f455d0f4 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -9,4 +9,13 @@ resources: - garm-operator_v1alpha1_garmserverconfig.yaml - garm-operator_v1alpha1_githubendpoint.yaml - garm-operator_v1alpha1_githubcredentials.yaml +- garm-operator_v1beta1_enterprise.yaml +- garm-operator_v1beta1_organization.yaml +- garm-operator_v1beta1_repository.yaml +- garm-operator_v1beta1_pool.yaml +- garm-operator_v1beta1_runner.yaml +- garm-operator_v1beta1_image.yaml +- garm-operator_v1beta1_githubendpoint.yaml +- garm-operator_v1beta1_githubcredentials.yaml +- garm-operator_v1beta1_garmserverconfig.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 13b15fbd..f104c62e 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -65,3 +65,64 @@ webhooks: resources: - repositories sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-garm-operator-mercedes-benz-com-v1alpha1-image + failurePolicy: Fail + name: validate.image.garm-operator.mercedes-benz.com + rules: + - apiGroups: + - garm-operator.mercedes-benz.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - images + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-garm-operator-mercedes-benz-com-v1alpha1-pool + failurePolicy: Fail + name: validate.pool.garm-operator.mercedes-benz.com + rules: + - apiGroups: + - garm-operator.mercedes-benz.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - pools + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-garm-operator-mercedes-benz-com-v1alpha1-repository + failurePolicy: Fail + name: validate.repository.garm-operator.mercedes-benz.com + rules: + - apiGroups: + - garm-operator.mercedes-benz.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - repositories + sideEffects: None diff --git a/go.mod b/go.mod index 41a523f8..5beb8f05 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-openapi/runtime v0.28.0 github.com/go-playground/validator/v10 v10.22.1 github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/google/uuid v1.6.0 github.com/iancoleman/strcase v0.3.0 github.com/knadh/koanf/parsers/yaml v0.1.0 github.com/knadh/koanf/providers/env v1.0.0 @@ -65,7 +66,6 @@ require ( github.com/google/go-github/v60 v60.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index c3b64eb0..c17501b9 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" @@ -49,7 +49,7 @@ type EnterpriseReconciler struct { func (r *EnterpriseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - enterprise := &garmoperatorv1alpha1.Enterprise{} + enterprise := &garmoperatorv1beta1.Enterprise{} err := r.Get(ctx, req.NamespacedName, enterprise) if err != nil { if apierrors.IsNotFound(err) { @@ -75,7 +75,7 @@ func (r *EnterpriseReconciler) Reconcile(ctx context.Context, req ctrl.Request) return r.reconcileNormal(ctx, enterpriseClient, enterprise) } -func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1alpha1.Enterprise) (ctrl.Result, error) { +func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1beta1.Enterprise) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("enterprise", enterprise.Name) @@ -169,7 +169,7 @@ func (r *EnterpriseReconciler) reconcileNormal(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *EnterpriseReconciler) createEnterprise(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1alpha1.Enterprise, webhookSecret string) (params.Enterprise, error) { +func (r *EnterpriseReconciler) createEnterprise(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1beta1.Enterprise, webhookSecret string) (params.Enterprise, error) { log := log.FromContext(ctx) log.WithValues("enterprise", enterprise.Name) @@ -214,7 +214,7 @@ func (r *EnterpriseReconciler) updateEnterprise(ctx context.Context, client garm return retValue.Payload, nil } -func (r *EnterpriseReconciler) getExistingGarmEnterprise(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1alpha1.Enterprise) (params.Enterprise, error) { +func (r *EnterpriseReconciler) getExistingGarmEnterprise(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1beta1.Enterprise) (params.Enterprise, error) { log := log.FromContext(ctx) log.WithValues("enterprise", enterprise.Name) @@ -235,7 +235,7 @@ func (r *EnterpriseReconciler) getExistingGarmEnterprise(ctx context.Context, cl return params.Enterprise{}, nil } -func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1alpha1.Enterprise) (ctrl.Result, error) { +func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmClient.EnterpriseClient, enterprise *garmoperatorv1beta1.Enterprise) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("enterprise", enterprise.Name) @@ -274,8 +274,8 @@ func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise *garmoperatorv1alpha1.Enterprise) (*garmoperatorv1alpha1.GitHubCredentials, error) { - creds := &garmoperatorv1alpha1.GitHubCredentials{} +func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise *garmoperatorv1beta1.Enterprise) (*garmoperatorv1beta1.GitHubCredentials, error) { + creds := &garmoperatorv1beta1.GitHubCredentials{} err := r.Get(ctx, types.NamespacedName{ Namespace: enterprise.Namespace, Name: enterprise.Spec.CredentialsRef.Name, @@ -286,7 +286,7 @@ func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise return creds, nil } -func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise *garmoperatorv1alpha1.Enterprise) error { +func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise *garmoperatorv1beta1.Enterprise) error { if !controllerutil.ContainsFinalizer(enterprise, key.EnterpriseFinalizerName) { controllerutil.AddFinalizer(enterprise, key.EnterpriseFinalizerName) return r.Update(ctx, enterprise) @@ -295,12 +295,12 @@ func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise * } func (r *EnterpriseReconciler) findEnterprisesForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) if !ok { return nil } - var enterprises garmoperatorv1alpha1.EnterpriseList + var enterprises garmoperatorv1beta1.EnterpriseList if err := r.List(ctx, &enterprises); err != nil { return nil } @@ -323,9 +323,9 @@ func (r *EnterpriseReconciler) findEnterprisesForCredentials(ctx context.Context // SetupWithManager sets up the controller with the Manager. func (r *EnterpriseReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Enterprise{}). + For(&garmoperatorv1beta1.Enterprise{}). Watches( - &garmoperatorv1alpha1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredentials{}, handler.EnqueueRequestsFromMapFunc(r.findEnterprisesForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/enterprise_controller_test.go b/internal/controller/enterprise_controller_test.go index 308328bd..d991908d 100644 --- a/internal/controller/enterprise_controller_test.go +++ b/internal/controller/enterprise_controller_test.go @@ -19,7 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -35,11 +35,11 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { expectGarmRequest func(m *mock.MockEnterpriseClientMockRecorder) runtimeObjects []runtime.Object wantErr bool - expectedObject *garmoperatorv1alpha1.Enterprise + expectedObject *garmoperatorv1beta1.Enterprise }{ { name: "enterprise exist - update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -47,18 +47,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -72,23 +72,23 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -96,18 +96,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -167,7 +167,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "enterprise exist but spec has changed - update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -175,18 +175,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -200,23 +200,23 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -224,18 +224,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -295,7 +295,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "enterprise exist but pool status has changed - update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -303,22 +303,22 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -326,18 +326,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -381,16 +381,16 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -427,24 +427,24 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "enterprise does not exist - create and update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", @@ -452,18 +452,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -507,16 +507,16 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -562,24 +562,24 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "enterprise already exist in garm - update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", @@ -587,18 +587,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Conditions: []metav1.Condition{ { @@ -642,16 +642,16 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -683,7 +683,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "enterprise does not exist in garm - create update", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -691,18 +691,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -716,23 +716,23 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-enterprise", Namespace: "default", @@ -740,18 +740,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -819,7 +819,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { }, { name: "secret ref not found condition", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", @@ -827,21 +827,21 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{}, + Status: garmoperatorv1beta1.EnterpriseStatus{}, }, runtimeObjects: []runtime.Object{}, - expectedObject: &garmoperatorv1alpha1.Enterprise{ + expectedObject: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "new-enterprise", Namespace: "default", @@ -849,18 +849,18 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -900,7 +900,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -909,7 +909,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Enterprise{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Enterprise{}).Build() // create a fake reconciler reconciler := &EnterpriseReconciler{ @@ -917,7 +917,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - enterprise := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Enterprise) + enterprise := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Enterprise) mockEnterprise := mock.NewMockEnterpriseClient(mockCtrl) tt.expectGarmRequest(mockEnterprise.EXPECT()) @@ -955,11 +955,11 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockEnterpriseClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Enterprise + expectedObject *garmoperatorv1beta1.Enterprise }{ { name: "delete enterprise", - object: &garmoperatorv1alpha1.Enterprise{ + object: &garmoperatorv1beta1.Enterprise{ ObjectMeta: metav1.ObjectMeta{ Name: "delete-enterprise", Namespace: "default", @@ -967,18 +967,18 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { key.EnterpriseFinalizerName, }, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", }, }, @@ -992,16 +992,16 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -1019,7 +1019,7 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -1029,7 +1029,7 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Enterprise{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Enterprise{}).Build() // create a fake reconciler reconciler := &EnterpriseReconciler{ @@ -1037,7 +1037,7 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - enterprise := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Enterprise) + enterprise := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Enterprise) mockEnterprise := mock.NewMockEnterpriseClient(mockCtrl) tt.expectGarmRequest(mockEnterprise.EXPECT()) diff --git a/internal/controller/garmserverconfig_controller.go b/internal/controller/garmserverconfig_controller.go index fb8d8987..bd02a0af 100644 --- a/internal/controller/garmserverconfig_controller.go +++ b/internal/controller/garmserverconfig_controller.go @@ -19,10 +19,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/log" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + "github.com/mercedes-benz/garm-operator/pkg/annotations" garmclient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" ) // GarmServerConfigReconciler reconciles a GarmServerConfig object @@ -43,7 +43,7 @@ func (r *GarmServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Req controllerClient := garmclient.NewControllerClient() - garmServerConfig := &garmoperatorv1alpha1.GarmServerConfig{} + garmServerConfig := &garmoperatorv1beta1.GarmServerConfig{} if err := r.Get(ctx, req.NamespacedName, garmServerConfig); err != nil { if apierrors.IsNotFound(err) { log.Info("object was not found") @@ -61,7 +61,7 @@ func (r *GarmServerConfigReconciler) Reconcile(ctx context.Context, req ctrl.Req return r.reconcileNormal(ctx, controllerClient, garmServerConfig) } -func (r *GarmServerConfigReconciler) reconcileNormal(ctx context.Context, controllerClient garmclient.ControllerClient, garmServerConfig *garmoperatorv1alpha1.GarmServerConfig) (ctrl.Result, error) { +func (r *GarmServerConfigReconciler) reconcileNormal(ctx context.Context, controllerClient garmclient.ControllerClient, garmServerConfig *garmoperatorv1beta1.GarmServerConfig) (ctrl.Result, error) { log := log.FromContext(ctx) controllerInfo, err := r.getControllerInfo(controllerClient) @@ -84,7 +84,7 @@ func (r *GarmServerConfigReconciler) reconcileNormal(ctx context.Context, contro return ctrl.Result{}, nil } -func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmclient.ControllerClient, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { +func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, client garmclient.ControllerClient, garmServerConfigCR *garmoperatorv1beta1.GarmServerConfig, controllerInfo *params.ControllerInfo) (*params.ControllerInfo, error) { log := log.FromContext(ctx) if garmServerConfigCR.Spec.MetadataURL == controllerInfo.MetadataURL && @@ -94,14 +94,14 @@ func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, c return controllerInfo, nil } - params := garmcontroller.NewUpdateControllerParams().WithBody(params.UpdateControllerParams{ + updateParams := garmcontroller.NewUpdateControllerParams().WithBody(params.UpdateControllerParams{ MetadataURL: util.StringPtr(garmServerConfigCR.Spec.MetadataURL), CallbackURL: util.StringPtr(garmServerConfigCR.Spec.CallbackURL), WebhookURL: util.StringPtr(garmServerConfigCR.Spec.WebhookURL), }) log.Info("Updating controller info in garm") - response, err := client.UpdateController(params) + response, err := client.UpdateController(updateParams) if err != nil { log.Error(err, "Failed to update controller info") return nil, err @@ -109,7 +109,7 @@ func (r *GarmServerConfigReconciler) updateControllerInfo(ctx context.Context, c return &response.Payload, nil } -func (r *GarmServerConfigReconciler) updateGarmServerConfigStatus(ctx context.Context, controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig) error { +func (r *GarmServerConfigReconciler) updateGarmServerConfigStatus(ctx context.Context, controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1beta1.GarmServerConfig) error { log := log.FromContext(ctx) if !r.needsStatusUpdate(controllerInfo, garmServerConfigCR) { @@ -118,7 +118,7 @@ func (r *GarmServerConfigReconciler) updateGarmServerConfigStatus(ctx context.Co } log.Info("Updating GarmServerConfig CR") - garmServerConfigStatus := garmoperatorv1alpha1.GarmServerConfigStatus{ + garmServerConfigStatus := garmoperatorv1beta1.GarmServerConfigStatus{ ControllerID: controllerInfo.ControllerID.String(), Hostname: controllerInfo.Hostname, MetadataURL: controllerInfo.MetadataURL, @@ -138,8 +138,8 @@ func (r *GarmServerConfigReconciler) updateGarmServerConfigStatus(ctx context.Co return nil } -func (r *GarmServerConfigReconciler) needsStatusUpdate(controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1alpha1.GarmServerConfig) bool { - tempStatus := garmoperatorv1alpha1.GarmServerConfigStatus{ +func (r *GarmServerConfigReconciler) needsStatusUpdate(controllerInfo *params.ControllerInfo, garmServerConfigCR *garmoperatorv1beta1.GarmServerConfig) bool { + tempStatus := garmoperatorv1beta1.GarmServerConfigStatus{ ControllerID: controllerInfo.ControllerID.String(), Hostname: controllerInfo.Hostname, MetadataURL: controllerInfo.MetadataURL, @@ -174,7 +174,7 @@ func (r *GarmServerConfigReconciler) getControllerInfo(client garmclient.Control // SetupWithManager sets up the controller with the Manager. func (r *GarmServerConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.GarmServerConfig{}). + For(&garmoperatorv1beta1.GarmServerConfig{}). WithOptions(controller.Options{}). Complete(r) } diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go index 5f1b9ff2..049d9cc1 100644 --- a/internal/controller/garmserverconfig_controller_test.go +++ b/internal/controller/garmserverconfig_controller_test.go @@ -2,20 +2,21 @@ package controller import ( "context" + "reflect" + "testing" + "github.com/cloudbase/garm/client/controller_info" "github.com/cloudbase/garm/params" "github.com/google/uuid" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/mock" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" + "github.com/mercedes-benz/garm-operator/pkg/conditions" "go.uber.org/mock/gomock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/record" - "reflect" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "testing" ) var controllerId = uuid.New() @@ -26,36 +27,36 @@ func TestGarmServerConfig_reconcile(t *testing.T) { tests := []struct { name string - object *garmoperatorv1alpha1.GarmServerConfig + object *garmoperatorv1beta1.GarmServerConfig expectGarmRequest func(m *mock.MockControllerClientMockRecorder) runtimeObjects []runtime.Object wantErr bool - expectedObject *garmoperatorv1alpha1.GarmServerConfig + expectedObject *garmoperatorv1beta1.GarmServerConfig }{ { name: "sync controller info to GarmServerConfig", - object: &garmoperatorv1alpha1.GarmServerConfig{ + object: &garmoperatorv1beta1.GarmServerConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "garm-server-config", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ + Spec: garmoperatorv1beta1.GarmServerConfigSpec{ MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", }, }, - expectedObject: &garmoperatorv1alpha1.GarmServerConfig{ + expectedObject: &garmoperatorv1beta1.GarmServerConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "garm-server-config", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GarmServerConfigSpec{ + Spec: garmoperatorv1beta1.GarmServerConfigSpec{ MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", }, - Status: garmoperatorv1alpha1.GarmServerConfigStatus{ + Status: garmoperatorv1beta1.GarmServerConfigStatus{ ControllerID: controllerId.String(), Hostname: "garm.server.com", MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", @@ -85,7 +86,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -94,7 +95,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GarmServerConfig{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.GarmServerConfig{}).Build() // create a fake reconciler reconciler := &GarmServerConfigReconciler{ @@ -102,7 +103,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - garmServerConfig := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GarmServerConfig) + garmServerConfig := tt.object.DeepCopyObject().(*garmoperatorv1beta1.GarmServerConfig) mockController := mock.NewMockControllerClient(mockCtrl) tt.expectGarmRequest(mockController.EXPECT()) diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go index da405c99..7ebcf651 100644 --- a/internal/controller/githubcredentials_controller.go +++ b/internal/controller/githubcredentials_controller.go @@ -24,14 +24,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/conditions" "github.com/mercedes-benz/garm-operator/pkg/event" "github.com/mercedes-benz/garm-operator/pkg/secret" "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" ) // GitHubCredentialsReconciler reconciles a GitHubCredentials object @@ -50,7 +50,7 @@ type GitHubCredentialsReconciler struct { func (r *GitHubCredentialsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - credentials := &garmoperatorv1alpha1.GitHubCredentials{} + credentials := &garmoperatorv1beta1.GitHubCredentials{} if err := r.Get(ctx, req.NamespacedName, credentials); err != nil { if apierrors.IsNotFound(err) { log.Info("GitHubCredentials resource not found.") @@ -75,7 +75,7 @@ func (r *GitHubCredentialsReconciler) Reconcile(ctx context.Context, req ctrl.Re return r.reconcileNormal(ctx, credentialsClient, credentials) } -func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials) (ctrl.Result, error) { +func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) @@ -172,7 +172,7 @@ func (r *GitHubCredentialsReconciler) getExistingCredentials(client garmClient.C return params.GithubCredentials{}, nil } -func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials, endpoint, githubSecret string) (params.GithubCredentials, error) { +func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials, endpoint, githubSecret string) (params.GithubCredentials, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) @@ -211,7 +211,7 @@ func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, cli return garmCredentials.Payload, nil } -func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, client garmClient.CredentialsClient, credentialsID int64, credentials *garmoperatorv1alpha1.GitHubCredentials, githubSecret string) (params.GithubCredentials, error) { +func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, client garmClient.CredentialsClient, credentialsID int64, credentials *garmoperatorv1beta1.GitHubCredentials, githubSecret string) (params.GithubCredentials, error) { log := log.FromContext(ctx) log.V(1).Info("update credentials") @@ -245,7 +245,7 @@ func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, cli return retValue.Payload, nil } -func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1alpha1.GitHubCredentials) (ctrl.Result, error) { +func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) @@ -281,8 +281,8 @@ func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, clien return ctrl.Result{}, nil } -func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) (*garmoperatorv1alpha1.GitHubEndpoint, error) { - endpoint := &garmoperatorv1alpha1.GitHubEndpoint{} +func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredentials) (*garmoperatorv1beta1.GitHubEndpoint, error) { + endpoint := &garmoperatorv1beta1.GitHubEndpoint{} err := r.Get(ctx, types.NamespacedName{ Namespace: credentials.Namespace, Name: credentials.Spec.EndpointRef.Name, @@ -293,7 +293,7 @@ func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, creden return endpoint, nil } -func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1alpha1.GitHubCredentials) error { +func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredentials) error { if !controllerutil.ContainsFinalizer(credentials, key.CredentialsFinalizerName) { controllerutil.AddFinalizer(credentials, key.CredentialsFinalizerName) return r.Update(ctx, credentials) @@ -307,7 +307,7 @@ func (r *GitHubCredentialsReconciler) findCredentialsForSecret(ctx context.Conte return nil } - var creds garmoperatorv1alpha1.GitHubCredentialsList + var creds garmoperatorv1beta1.GitHubCredentialsList if err := r.List(ctx, &creds); err != nil { return nil } @@ -330,7 +330,7 @@ func (r *GitHubCredentialsReconciler) findCredentialsForSecret(ctx context.Conte // SetupWithManager sets up the controller with the Manager. func (r *GitHubCredentialsReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.GitHubCredentials{}). + For(&garmoperatorv1beta1.GitHubCredentials{}). Watches( &corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.findCredentialsForSecret), diff --git a/internal/controller/githubendpoint_controller.go b/internal/controller/githubendpoint_controller.go index 3a50a4db..d76d5907 100644 --- a/internal/controller/githubendpoint_controller.go +++ b/internal/controller/githubendpoint_controller.go @@ -17,13 +17,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" + "github.com/mercedes-benz/garm-operator/pkg/conditions" "github.com/mercedes-benz/garm-operator/pkg/event" "github.com/mercedes-benz/garm-operator/pkg/util" - "github.com/mercedes-benz/garm-operator/pkg/util/annotations" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" ) // GitHubEndpointReconciler reconciles a GitHubEndpoint object @@ -42,7 +42,7 @@ type GitHubEndpointReconciler struct { func (r *GitHubEndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - endpoint := &garmoperatorv1alpha1.GitHubEndpoint{} + endpoint := &garmoperatorv1beta1.GitHubEndpoint{} if err := r.Get(ctx, req.NamespacedName, endpoint); err != nil { if apierrors.IsNotFound(err) { log.Info("GitHubEndpoint resource not found.") @@ -67,7 +67,7 @@ func (r *GitHubEndpointReconciler) Reconcile(ctx context.Context, req ctrl.Reque return r.reconcileNormal(ctx, endpointClient, endpoint) } -func (r *GitHubEndpointReconciler) reconcileNormal(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (ctrl.Result, error) { +func (r *GitHubEndpointReconciler) reconcileNormal(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1beta1.GitHubEndpoint) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) @@ -135,7 +135,7 @@ func (r *GitHubEndpointReconciler) getExistingEndpoint(client garmClient.Endpoin return endpoint.Payload, nil } -func (r *GitHubEndpointReconciler) createEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (params.GithubEndpoint, error) { +func (r *GitHubEndpointReconciler) createEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1beta1.GitHubEndpoint) (params.GithubEndpoint, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) @@ -163,7 +163,7 @@ func (r *GitHubEndpointReconciler) createEndpoint(ctx context.Context, client ga return retValue.Payload, nil } -func (r *GitHubEndpointReconciler) updateEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (params.GithubEndpoint, error) { +func (r *GitHubEndpointReconciler) updateEndpoint(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1beta1.GitHubEndpoint) (params.GithubEndpoint, error) { log := log.FromContext(ctx) log.V(1).Info("update endpoint") @@ -185,7 +185,7 @@ func (r *GitHubEndpointReconciler) updateEndpoint(ctx context.Context, client ga return retValue.Payload, nil } -func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1alpha1.GitHubEndpoint) (ctrl.Result, error) { +func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client garmClient.EndpointClient, endpoint *garmoperatorv1beta1.GitHubEndpoint) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("endpoint", endpoint.Name) @@ -222,7 +222,7 @@ func (r *GitHubEndpointReconciler) reconcileDelete(ctx context.Context, client g return ctrl.Result{}, nil } -func (r *GitHubEndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1alpha1.GitHubEndpoint) error { +func (r *GitHubEndpointReconciler) ensureFinalizer(ctx context.Context, endpoint *garmoperatorv1beta1.GitHubEndpoint) error { if !controllerutil.ContainsFinalizer(endpoint, key.GitHubEndpointFinalizerName) { controllerutil.AddFinalizer(endpoint, key.GitHubEndpointFinalizerName) return r.Update(ctx, endpoint) @@ -233,6 +233,6 @@ func (r *GitHubEndpointReconciler) ensureFinalizer(ctx context.Context, endpoint // SetupWithManager sets up the controller with the Manager. func (r *GitHubEndpointReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.GitHubEndpoint{}). + For(&garmoperatorv1beta1.GitHubEndpoint{}). Complete(r) } diff --git a/internal/controller/githubendpoint_controller_test.go b/internal/controller/githubendpoint_controller_test.go index a3f5f12a..26892b31 100644 --- a/internal/controller/githubendpoint_controller_test.go +++ b/internal/controller/githubendpoint_controller_test.go @@ -19,10 +19,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" - "github.com/mercedes-benz/garm-operator/pkg/util/conditions" + "github.com/mercedes-benz/garm-operator/pkg/conditions" ) func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { @@ -35,11 +35,11 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { expectGarmRequest func(m *mock.MockEndpointClientMockRecorder) runtimeObjects []runtime.Object wantErr bool - expectedObject *garmoperatorv1alpha1.GitHubEndpoint + expectedObject *garmoperatorv1beta1.GitHubEndpoint }{ { name: "github-endpoint exist - update", - object: &garmoperatorv1alpha1.GitHubEndpoint{ + object: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -47,7 +47,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "existing-github-endpoint", APIBaseURL: "https://api.github.com", UploadBaseURL: "https://uploads.github.com", @@ -56,7 +56,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, }, runtimeObjects: []runtime.Object{}, - expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + expectedObject: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -64,14 +64,14 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "existing-github-endpoint", APIBaseURL: "https://api.github.com", UploadBaseURL: "https://uploads.github.com", BaseURL: "https://github.com", CACertBundle: nil, }, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -116,7 +116,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, { name: "github-endpoint exist but spec has changed - update", - object: &garmoperatorv1alpha1.GitHubEndpoint{ + object: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -124,14 +124,14 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "has-changed", APIBaseURL: "https://api.github-enterprise.com", UploadBaseURL: "https://uploads.github-enterprise.com", BaseURL: "https://github-enterprise.com", CACertBundle: nil, }, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -144,7 +144,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, }, runtimeObjects: []runtime.Object{}, - expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + expectedObject: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -152,14 +152,14 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "has-changed", APIBaseURL: "https://api.github-enterprise.com", UploadBaseURL: "https://uploads.github-enterprise.com", BaseURL: "https://github-enterprise.com", CACertBundle: nil, }, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -206,12 +206,12 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, { name: "github-endpoint does not exist - create and update", - object: &garmoperatorv1alpha1.GitHubEndpoint{ + object: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "new-github-endpoint", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "new github endpoint", APIBaseURL: "https://api.github.com", UploadBaseURL: "https://uploads.github.com", @@ -219,7 +219,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { CACertBundle: nil, }, }, - expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + expectedObject: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "new-github-endpoint", Namespace: "default", @@ -227,14 +227,14 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "new github endpoint", APIBaseURL: "https://api.github.com", UploadBaseURL: "https://uploads.github.com", BaseURL: "https://github.com", CACertBundle: nil, }, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -292,12 +292,12 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, { name: "github-endpoint update - bad request error", - object: &garmoperatorv1alpha1.GitHubEndpoint{ + object: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "", APIBaseURL: "", UploadBaseURL: "", @@ -305,7 +305,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { CACertBundle: nil, }, }, - expectedObject: &garmoperatorv1alpha1.GitHubEndpoint{ + expectedObject: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -313,8 +313,8 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{}, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{}, + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -355,7 +355,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -364,7 +364,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GitHubEndpoint{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.GitHubEndpoint{}).Build() // create a fake reconciler reconciler := &GitHubEndpointReconciler{ @@ -372,7 +372,7 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GitHubEndpoint) + githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1beta1.GitHubEndpoint) mockGitHubEndpoint := mock.NewMockEndpointClient(mockCtrl) tt.expectGarmRequest(mockGitHubEndpoint.EXPECT()) @@ -410,11 +410,11 @@ func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockEndpointClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.GitHubEndpoint + expectedObject *garmoperatorv1beta1.GitHubEndpoint }{ { name: "delete github-endpoint", - object: &garmoperatorv1alpha1.GitHubEndpoint{ + object: &garmoperatorv1beta1.GitHubEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-github-endpoint", Namespace: "default", @@ -422,14 +422,14 @@ func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { key.GitHubEndpointFinalizerName, }, }, - Spec: garmoperatorv1alpha1.GitHubEndpointSpec{ + Spec: garmoperatorv1beta1.GitHubEndpointSpec{ Description: "existing-github-endpoint", APIBaseURL: "https://api.github.com", UploadBaseURL: "https://uploads.github.com", BaseURL: "https://github.com", CACertBundle: []byte(""), }, - Status: garmoperatorv1alpha1.GitHubEndpointStatus{ + Status: garmoperatorv1beta1.GitHubEndpointStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -454,7 +454,7 @@ func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -464,7 +464,7 @@ func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.GitHubEndpoint{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.GitHubEndpoint{}).Build() // create a fake reconciler reconciler := &GitHubEndpointReconciler{ @@ -472,7 +472,7 @@ func TestGitHubEndpointReconciler_reconcileDelete(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.GitHubEndpoint) + githubEndpoint := tt.object.DeepCopyObject().(*garmoperatorv1beta1.GitHubEndpoint) mockGitHubEndpoint := mock.NewMockEndpointClient(mockCtrl) tt.expectGarmRequest(mockGitHubEndpoint.EXPECT()) diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index 9a89cb82..ef03f272 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" @@ -48,7 +48,7 @@ type OrganizationReconciler struct { func (r *OrganizationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - organization := &garmoperatorv1alpha1.Organization{} + organization := &garmoperatorv1beta1.Organization{} err := r.Get(ctx, req.NamespacedName, organization) if err != nil { if apierrors.IsNotFound(err) { @@ -74,7 +74,7 @@ func (r *OrganizationReconciler) Reconcile(ctx context.Context, req ctrl.Request return r.reconcileNormal(ctx, organizationClient, organization) } -func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1alpha1.Organization) (ctrl.Result, error) { +func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1beta1.Organization) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("organization", organization.Name) @@ -167,7 +167,7 @@ func (r *OrganizationReconciler) reconcileNormal(ctx context.Context, client gar return ctrl.Result{}, nil } -func (r *OrganizationReconciler) createOrganization(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1alpha1.Organization, webhookSecret string) (params.Organization, error) { +func (r *OrganizationReconciler) createOrganization(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1beta1.Organization, webhookSecret string) (params.Organization, error) { log := log.FromContext(ctx) log.WithValues("organization", organization.Name) @@ -212,7 +212,7 @@ func (r *OrganizationReconciler) updateOrganization(ctx context.Context, client return retValue.Payload, nil } -func (r *OrganizationReconciler) getExistingGarmOrg(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1alpha1.Organization) (params.Organization, error) { +func (r *OrganizationReconciler) getExistingGarmOrg(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1beta1.Organization) (params.Organization, error) { log := log.FromContext(ctx) log.WithValues("organization", organization.Name) @@ -233,7 +233,7 @@ func (r *OrganizationReconciler) getExistingGarmOrg(ctx context.Context, client return params.Organization{}, nil } -func (r *OrganizationReconciler) reconcileDelete(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1alpha1.Organization) (ctrl.Result, error) { +func (r *OrganizationReconciler) reconcileDelete(ctx context.Context, client garmClient.OrganizationClient, organization *garmoperatorv1beta1.Organization) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("organization", organization.Name) @@ -272,8 +272,8 @@ func (r *OrganizationReconciler) reconcileDelete(ctx context.Context, client gar return ctrl.Result{}, nil } -func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *garmoperatorv1alpha1.Organization) (*garmoperatorv1alpha1.GitHubCredentials, error) { - creds := &garmoperatorv1alpha1.GitHubCredentials{} +func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *garmoperatorv1beta1.Organization) (*garmoperatorv1beta1.GitHubCredentials, error) { + creds := &garmoperatorv1beta1.GitHubCredentials{} err := r.Get(ctx, types.NamespacedName{ Namespace: org.Namespace, Name: org.Spec.CredentialsRef.Name, @@ -284,7 +284,7 @@ func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *gar return creds, nil } -func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, org *garmoperatorv1alpha1.Organization) error { +func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, org *garmoperatorv1beta1.Organization) error { if !controllerutil.ContainsFinalizer(org, key.OrganizationFinalizerName) { controllerutil.AddFinalizer(org, key.OrganizationFinalizerName) return r.Update(ctx, org) @@ -293,12 +293,12 @@ func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, org *garmo } func (r *OrganizationReconciler) findOrgsForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) if !ok { return nil } - var orgs garmoperatorv1alpha1.OrganizationList + var orgs garmoperatorv1beta1.OrganizationList if err := r.List(ctx, &orgs); err != nil { return nil } @@ -321,9 +321,9 @@ func (r *OrganizationReconciler) findOrgsForCredentials(ctx context.Context, obj // SetupWithManager sets up the controller with the Manager. func (r *OrganizationReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Organization{}). + For(&garmoperatorv1beta1.Organization{}). Watches( - &garmoperatorv1alpha1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredentials{}, handler.EnqueueRequestsFromMapFunc(r.findOrgsForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/organization_controller_test.go b/internal/controller/organization_controller_test.go index 85d1156a..9c1435df 100644 --- a/internal/controller/organization_controller_test.go +++ b/internal/controller/organization_controller_test.go @@ -19,7 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -35,11 +35,11 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockOrganizationClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Organization + expectedObject *garmoperatorv1beta1.Organization }{ { name: "organization exist - update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -47,18 +47,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -72,23 +72,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -96,18 +96,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -167,7 +167,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "organization exist but spec has changed - update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -175,18 +175,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -200,23 +200,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -224,18 +224,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -295,7 +295,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "organization exist but pool status has changed - update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -303,18 +303,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -328,23 +328,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -352,18 +352,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -427,18 +427,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "organization does not exist - create and update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, @@ -454,23 +454,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", @@ -478,18 +478,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -562,18 +562,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "organization already exist in garm - update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, @@ -589,23 +589,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", @@ -613,18 +613,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Conditions: []metav1.Condition{ { @@ -683,7 +683,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "organization does not exist in garm - create and update", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -691,18 +691,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -716,23 +716,23 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-organization", Namespace: "default", @@ -740,18 +740,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -819,7 +819,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { }, { name: "secret ref not found condition", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", @@ -827,21 +827,21 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{}, + Status: garmoperatorv1beta1.OrganizationStatus{}, }, runtimeObjects: []runtime.Object{}, - expectedObject: &garmoperatorv1alpha1.Organization{ + expectedObject: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "new-organization", Namespace: "default", @@ -849,18 +849,18 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -900,7 +900,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -909,7 +909,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Organization{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Organization{}).Build() // create a fake reconciler reconciler := &OrganizationReconciler{ @@ -917,7 +917,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - organization := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Organization) + organization := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Organization) mockOrganization := mock.NewMockOrganizationClient(mockCtrl) tt.expectGarmRequest(mockOrganization.EXPECT()) @@ -955,11 +955,11 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockOrganizationClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Organization + expectedObject *garmoperatorv1beta1.Organization }{ { name: "delete organization", - object: &garmoperatorv1alpha1.Organization{ + object: &garmoperatorv1beta1.Organization{ ObjectMeta: metav1.ObjectMeta{ Name: "delete-organization", Namespace: "default", @@ -967,18 +967,18 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { key.OrganizationFinalizerName, }, }, - Spec: garmoperatorv1alpha1.OrganizationSpec{ + Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.OrganizationStatus{ + Status: garmoperatorv1beta1.OrganizationStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", }, }, @@ -992,16 +992,16 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -1019,7 +1019,7 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -1028,7 +1028,7 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Organization{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Organization{}).Build() // create a fake reconciler reconciler := &OrganizationReconciler{ @@ -1036,7 +1036,7 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - organization := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Organization) + organization := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Organization) mockOrganization := mock.NewMockOrganizationClient(mockCtrl) tt.expectGarmRequest(mockOrganization.EXPECT()) diff --git a/internal/controller/pool_controller.go b/internal/controller/pool_controller.go index d398d4b8..10d815e3 100644 --- a/internal/controller/pool_controller.go +++ b/internal/controller/pool_controller.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" @@ -58,7 +58,7 @@ const ( func (r *PoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - pool := &garmoperatorv1alpha1.Pool{} + pool := &garmoperatorv1beta1.Pool{} if err := r.Get(ctx, req.NamespacedName, pool); err != nil { if apierrors.IsNotFound(err) { return ctrl.Result{}, nil @@ -85,7 +85,7 @@ func (r *PoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. return r.reconcileNormal(ctx, poolClient, pool, instanceClient) } -func (r *PoolReconciler) reconcileNormal(ctx context.Context, poolClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { +func (r *PoolReconciler) reconcileNormal(ctx context.Context, poolClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { gitHubScopeRef, err := r.fetchGitHubScopeCRD(ctx, pool) if err != nil { conditions.MarkFalse(pool, conditions.ScopeReference, conditions.FetchingScopeRefFailedReason, err.Error()) @@ -112,7 +112,7 @@ func (r *PoolReconciler) reconcileNormal(ctx context.Context, poolClient garmCli return r.reconcileCreate(ctx, poolClient, pool, gitHubScopeRef) } -func (r *PoolReconciler) reconcileCreate(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, gitHubScopeRef garmoperatorv1alpha1.GitHubScope) (ctrl.Result, error) { +func (r *PoolReconciler) reconcileCreate(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, gitHubScopeRef garmoperatorv1beta1.GitHubScope) (ctrl.Result, error) { log := log.FromContext(ctx) log.Info("Pool doesn't exist on garm side. Creating new pool in garm") @@ -124,17 +124,6 @@ func (r *PoolReconciler) reconcileCreate(ctx context.Context, garmClient garmCli } conditions.MarkTrue(pool, conditions.ImageReference, conditions.FetchingImageRefSuccessReason, "Successfully fetched Image CR Ref") - // check for duplicate pools - duplicate, duplicateName, err := pool.CheckDuplicate(ctx, r.Client, image) - if err != nil { - return r.handleUpdateError(ctx, pool, err, conditions.ReconcileErrorReason) - } - - if duplicate { - err := fmt.Errorf("pool with same image, flavor, provider and github scope already exists: %s", duplicateName) - return r.handleUpdateError(ctx, pool, err, conditions.DuplicatePoolReason) - } - // check if there is already a pool with the same spec on garm side matchingGarmPool, err := poolUtil.GetGarmPoolBySpecs(ctx, garmClient, pool, image, gitHubScopeRef) if err != nil { @@ -164,7 +153,7 @@ func (r *PoolReconciler) reconcileCreate(ctx context.Context, garmClient garmCli return r.handleSuccessfulUpdate(ctx, pool) } -func (r *PoolReconciler) reconcileUpdate(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { +func (r *PoolReconciler) reconcileUpdate(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { log := log.FromContext(ctx). WithName("reconcileUpdate") log.Info("pool on garm side found", "id", pool.Status.ID, "name", pool.Name) @@ -239,7 +228,7 @@ func (r *PoolReconciler) reconcileUpdate(ctx context.Context, garmClient garmCli return r.handleSuccessfulUpdate(ctx, pool) } -func (r *PoolReconciler) reconcileDelete(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { +func (r *PoolReconciler) reconcileDelete(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, instanceClient garmClient.InstanceClient) (ctrl.Result, error) { // pool does not exist in garm database yet as ID in Status is empty, so we can safely delete it log := log.FromContext(ctx) log.Info("Deleting Pool", "pool", pool.Name) @@ -311,7 +300,7 @@ func (r *PoolReconciler) reconcileDelete(ctx context.Context, garmClient garmCli return ctrl.Result{}, nil } -func (r *PoolReconciler) updatePoolCRStatus(ctx context.Context, pool *garmoperatorv1alpha1.Pool) error { +func (r *PoolReconciler) updatePoolCRStatus(ctx context.Context, pool *garmoperatorv1beta1.Pool) error { log := log.FromContext(ctx) if err := r.Status().Update(ctx, pool); err != nil { log.Error(err, "unable to update Pool status") @@ -320,7 +309,7 @@ func (r *PoolReconciler) updatePoolCRStatus(ctx context.Context, pool *garmopera return nil } -func (r *PoolReconciler) handleUpdateError(ctx context.Context, pool *garmoperatorv1alpha1.Pool, err error, conditionReason conditions.ConditionReason) (ctrl.Result, error) { +func (r *PoolReconciler) handleUpdateError(ctx context.Context, pool *garmoperatorv1beta1.Pool, err error, conditionReason conditions.ConditionReason) (ctrl.Result, error) { log := log.FromContext(ctx) log.Error(err, "error") @@ -338,7 +327,7 @@ func (r *PoolReconciler) handleUpdateError(ctx context.Context, pool *garmoperat return ctrl.Result{}, err } -func (r *PoolReconciler) handleSuccessfulUpdate(ctx context.Context, pool *garmoperatorv1alpha1.Pool) (ctrl.Result, error) { +func (r *PoolReconciler) handleSuccessfulUpdate(ctx context.Context, pool *garmoperatorv1beta1.Pool) (ctrl.Result, error) { conditions.MarkTrue(pool, conditions.ReadyCondition, conditions.SuccessfulReconcileReason, "") if err := r.updatePoolCRStatus(ctx, pool); err != nil { @@ -348,7 +337,7 @@ func (r *PoolReconciler) handleSuccessfulUpdate(ctx context.Context, pool *garmo return ctrl.Result{}, nil } -func (r *PoolReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1alpha1.Pool) error { +func (r *PoolReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1beta1.Pool) error { if !controllerutil.ContainsFinalizer(pool, key.PoolFinalizerName) { controllerutil.AddFinalizer(pool, key.PoolFinalizerName) return r.Update(ctx, pool) @@ -356,7 +345,7 @@ func (r *PoolReconciler) ensureFinalizer(ctx context.Context, pool *garmoperator return nil } -func (r *PoolReconciler) comparePoolSpecs(ctx context.Context, pool *garmoperatorv1alpha1.Pool, imageTag string, poolClient garmClient.PoolClient) (bool, []params.Instance, error) { +func (r *PoolReconciler) comparePoolSpecs(ctx context.Context, pool *garmoperatorv1beta1.Pool, imageTag string, poolClient garmClient.PoolClient) (bool, []params.Instance, error) { log := log.FromContext(ctx). WithName("comparePoolSpecs") @@ -407,13 +396,13 @@ func (r *PoolReconciler) comparePoolSpecs(ctx context.Context, pool *garmoperato } switch gitHubScopeRef.GetKind() { - case string(garmoperatorv1alpha1.EnterpriseScope): + case string(garmoperatorv1beta1.EnterpriseScope): tmpGarmPool.EnterpriseID = gitHubScopeRef.GetID() tmpGarmPool.EnterpriseName = gitHubScopeRef.GetName() - case string(garmoperatorv1alpha1.OrganizationScope): + case string(garmoperatorv1beta1.OrganizationScope): tmpGarmPool.OrgID = gitHubScopeRef.GetID() tmpGarmPool.OrgName = gitHubScopeRef.GetName() - case string(garmoperatorv1alpha1.RepositoryScope): + case string(garmoperatorv1beta1.RepositoryScope): tmpGarmPool.RepoID = gitHubScopeRef.GetID() tmpGarmPool.RepoName = gitHubScopeRef.GetName() } @@ -427,7 +416,7 @@ func (r *PoolReconciler) comparePoolSpecs(ctx context.Context, pool *garmoperato return reflect.DeepEqual(tmpGarmPool, garmPool.Payload), idleInstances, nil } -func (r *PoolReconciler) fetchGitHubScopeCRD(ctx context.Context, pool *garmoperatorv1alpha1.Pool) (garmoperatorv1alpha1.GitHubScope, error) { +func (r *PoolReconciler) fetchGitHubScopeCRD(ctx context.Context, pool *garmoperatorv1beta1.Pool) (garmoperatorv1beta1.GitHubScope, error) { gitHubScopeNamespacedName := types.NamespacedName{ Namespace: pool.Namespace, Name: pool.Spec.GitHubScopeRef.Name, @@ -436,20 +425,20 @@ func (r *PoolReconciler) fetchGitHubScopeCRD(ctx context.Context, pool *garmoper var gitHubScope client.Object switch pool.Spec.GitHubScopeRef.Kind { - case string(garmoperatorv1alpha1.EnterpriseScope): - gitHubScope = &garmoperatorv1alpha1.Enterprise{} + case string(garmoperatorv1beta1.EnterpriseScope): + gitHubScope = &garmoperatorv1beta1.Enterprise{} if err := r.Get(ctx, gitHubScopeNamespacedName, gitHubScope); err != nil { return nil, err } - case string(garmoperatorv1alpha1.OrganizationScope): - gitHubScope = &garmoperatorv1alpha1.Organization{} + case string(garmoperatorv1beta1.OrganizationScope): + gitHubScope = &garmoperatorv1beta1.Organization{} if err := r.Get(ctx, gitHubScopeNamespacedName, gitHubScope); err != nil { return nil, err } - case string(garmoperatorv1alpha1.RepositoryScope): - gitHubScope = &garmoperatorv1alpha1.Repository{} + case string(garmoperatorv1beta1.RepositoryScope): + gitHubScope = &garmoperatorv1beta1.Repository{} if err := r.Get(ctx, gitHubScopeNamespacedName, gitHubScope); err != nil { return nil, err } @@ -458,16 +447,16 @@ func (r *PoolReconciler) fetchGitHubScopeCRD(ctx context.Context, pool *garmoper return nil, fmt.Errorf("unsupported GitHubScopeRef kind: %s", pool.Spec.GitHubScopeRef.Kind) } - return gitHubScope.(garmoperatorv1alpha1.GitHubScope), nil + return gitHubScope.(garmoperatorv1beta1.GitHubScope), nil } func (r *PoolReconciler) findPoolsForImage(ctx context.Context, obj client.Object) []reconcile.Request { - image, ok := obj.(*garmoperatorv1alpha1.Image) + image, ok := obj.(*garmoperatorv1beta1.Image) if !ok { return nil } - var pools garmoperatorv1alpha1.PoolList + var pools garmoperatorv1beta1.PoolList if err := r.List(ctx, &pools); err != nil { return nil } @@ -490,8 +479,8 @@ func (r *PoolReconciler) findPoolsForImage(ctx context.Context, obj client.Objec // SetupWithManager sets up the controller with the Manager. func (r *PoolReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { // setup index for image - if err := mgr.GetFieldIndexer().IndexField(context.Background(), &garmoperatorv1alpha1.Pool{}, imageField, func(rawObj client.Object) []string { - pool := rawObj.(*garmoperatorv1alpha1.Pool) + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &garmoperatorv1beta1.Pool{}, imageField, func(rawObj client.Object) []string { + pool := rawObj.(*garmoperatorv1beta1.Pool) if pool.Spec.ImageName == "" { return nil } @@ -501,9 +490,9 @@ func (r *PoolReconciler) SetupWithManager(mgr ctrl.Manager, options controller.O } return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Pool{}). + For(&garmoperatorv1beta1.Pool{}). Watches( - &garmoperatorv1alpha1.Image{}, + &garmoperatorv1beta1.Image{}, handler.EnqueueRequestsFromMapFunc(r.findPoolsForImage), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/pool_controller_test.go b/internal/controller/pool_controller_test.go index 56608ae6..fe8597bb 100644 --- a/internal/controller/pool_controller_test.go +++ b/internal/controller/pool_controller_test.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -52,23 +52,23 @@ func TestPoolController_ReconcileCreate(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(_ *mock.MockPoolClientMockRecorder, instanceClient *mock.MockInstanceClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Pool + expectedObject *garmoperatorv1beta1.Pool }{ { name: "pool does not exist in garm - create", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -85,10 +85,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { GitHubRunnerGroup: "", }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -97,10 +97,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -116,7 +116,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 3, Selector: "", @@ -148,36 +148,36 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -266,19 +266,19 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, { name: "pool with matching specs exists in garm, outdated garmId in pool.Status - sync ids", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -294,14 +294,14 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: outdatedPoolID, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -310,10 +310,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -329,7 +329,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 3, Selector: "", @@ -361,36 +361,36 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -459,19 +459,19 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, { name: "pool.Status has matching id in garm database, pool.Specs changed - update pool in garm", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -487,14 +487,14 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -503,10 +503,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -522,7 +522,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, Conditions: []metav1.Condition{ { @@ -552,36 +552,36 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -747,19 +747,19 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, { name: "scaling idleRunners down to 2 - expect deletion of two old instances", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -775,15 +775,15 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 3, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -792,10 +792,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -811,7 +811,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 2, Conditions: []metav1.Condition{ @@ -842,36 +842,36 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -1147,19 +1147,19 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, { name: "pool does not exist in garm - error no image cr found", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1176,10 +1176,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { GitHubRunnerGroup: "", }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -1188,10 +1188,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1207,7 +1207,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: "", LongRunningIdleRunners: 0, Selector: "", @@ -1239,27 +1239,27 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -1286,19 +1286,19 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, { name: "pool.Status has matching id in garm database, pool.Specs changed to not existent image cr ref - error no image cr found", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1314,14 +1314,14 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -1330,10 +1330,10 @@ func TestPoolController_ReconcileCreate(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1349,7 +1349,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, Conditions: []metav1.Condition{ { @@ -1379,36 +1379,36 @@ func TestPoolController_ReconcileCreate(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -1472,203 +1472,12 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }}, nil) }, }, - { - name: "pool with same image, provider, flavor and github scope applied - do not sync pool", - object: &garmoperatorv1alpha1.Pool{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "my-enterprise-pool", - Namespace: namespaceName, - }, - Spec: garmoperatorv1alpha1.PoolSpec{ - GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), - Name: enterpriseName, - }, - ProviderName: "kubernetes_external", - MaxRunners: 1, - MinIdleRunners: 0, - ImageName: "ubuntu-image", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []string{"kubernetes", "linux", "arm64", "ubuntu"}, - Enabled: true, - RunnerBootstrapTimeout: 20, - ExtraSpecs: "", - GitHubRunnerGroup: "", - }, - }, - expectedObject: &garmoperatorv1alpha1.Pool{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "my-enterprise-pool", - Namespace: namespaceName, - Finalizers: []string{ - key.PoolFinalizerName, - }, - }, - Spec: garmoperatorv1alpha1.PoolSpec{ - GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), - Name: enterpriseName, - }, - ProviderName: "kubernetes_external", - MaxRunners: 1, - MinIdleRunners: 0, - ImageName: "ubuntu-image", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []string{"kubernetes", "linux", "arm64", "ubuntu"}, - Enabled: true, - RunnerBootstrapTimeout: 20, - ExtraSpecs: "", - GitHubRunnerGroup: "", - }, - Status: garmoperatorv1alpha1.PoolStatus{ - Conditions: []metav1.Condition{ - { - Type: string(conditions.ReadyCondition), - Reason: string(conditions.DuplicatePoolReason), - Status: metav1.ConditionFalse, - Message: "pool with same image, flavor, provider and github scope already exists: test-namespace/duplicate-pool", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - { - Type: string(conditions.ImageReference), - Status: metav1.ConditionTrue, - Message: "Successfully fetched Image CR Ref", - Reason: string(conditions.FetchingImageRefSuccessReason), - LastTransitionTime: metav1.NewTime(time.Now()), - }, - }, - }, - }, - runtimeObjects: []runtime.Object{ - &garmoperatorv1alpha1.Pool{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "duplicate-pool", - Namespace: namespaceName, - Finalizers: []string{ - key.PoolFinalizerName, - }, - }, - Spec: garmoperatorv1alpha1.PoolSpec{ - GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), - Name: enterpriseName, - }, - ProviderName: "kubernetes_external", - MaxRunners: 1, - MinIdleRunners: 0, - ImageName: "ubuntu-image", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []string{"kubernetes", "linux", "arm64", "ubuntu"}, - Enabled: true, - RunnerBootstrapTimeout: 20, - ExtraSpecs: "", - GitHubRunnerGroup: "", - }, - Status: garmoperatorv1alpha1.PoolStatus{ - ID: poolID, - Conditions: []metav1.Condition{ - { - Type: string(conditions.ReadyCondition), - Reason: string(conditions.SuccessfulReconcileReason), - Status: metav1.ConditionFalse, - Message: "", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - { - Type: string(conditions.ImageReference), - Status: metav1.ConditionTrue, - Message: "Successfully fetched Image CR Ref", - Reason: string(conditions.FetchingImageRefSuccessReason), - LastTransitionTime: metav1.NewTime(time.Now()), - }, - }, - }, - }, - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespaceName, - Name: "my-webhook-secret", - }, - Data: map[string][]byte{ - "webhookSecret": []byte("supersecretvalue"), - }, - }, - &garmoperatorv1alpha1.Image{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ubuntu-image", - Namespace: namespaceName, - }, - Spec: garmoperatorv1alpha1.ImageSpec{ - Tag: "linux-ubuntu-22.04-arm64", - }, - }, - &garmoperatorv1alpha1.Enterprise{ - TypeMeta: metav1.TypeMeta{ - Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: enterpriseName, - Namespace: namespaceName, - }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ - CredentialsName: "foobar", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ - Name: "my-webhook-secret", - Key: "webhookSecret", - }, - }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ - ID: enterpriseID, - Conditions: []metav1.Condition{ - { - Type: string(conditions.ReadyCondition), - Reason: string(conditions.SuccessfulReconcileReason), - Status: metav1.ConditionTrue, - Message: "", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - { - Type: string(conditions.PoolManager), - Reason: string(conditions.PoolManagerFailureReason), - Status: metav1.ConditionFalse, - Message: "no resources available", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - }, - }, - }, - }, - wantErr: true, - expectGarmRequest: func(_ *mock.MockPoolClientMockRecorder, _ *mock.MockInstanceClientMockRecorder) {}, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -1677,7 +1486,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Pool{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Pool{}).Build() // create a fake reconciler reconciler := &PoolReconciler{ @@ -1685,7 +1494,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - pool := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Pool) + pool := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Pool) mockPoolClient := mock.NewMockPoolClient(mockCtrl) mockInstanceClient := mock.NewMockInstanceClient(mockCtrl) @@ -1738,14 +1547,14 @@ func TestPoolController_ReconcileDelete(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(_ *mock.MockPoolClientMockRecorder, _ *mock.MockInstanceClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Pool + expectedObject *garmoperatorv1beta1.Pool }{ { name: "delete pool - scaling down runners", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -1754,10 +1563,10 @@ func TestPoolController_ReconcileDelete(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1773,23 +1582,23 @@ func TestPoolController_ReconcileDelete(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - // APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + // APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1805,7 +1614,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 0, Conditions: []metav1.Condition{ @@ -1829,36 +1638,36 @@ func TestPoolController_ReconcileDelete(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -1958,10 +1767,10 @@ func TestPoolController_ReconcileDelete(t *testing.T) { }, { name: "delete pool - deleting garm resource", - object: &garmoperatorv1alpha1.Pool{ + object: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", @@ -1970,10 +1779,10 @@ func TestPoolController_ReconcileDelete(t *testing.T) { key.PoolFinalizerName, }, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -1989,24 +1798,24 @@ func TestPoolController_ReconcileDelete(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, LongRunningIdleRunners: 0, }, }, - expectedObject: &garmoperatorv1alpha1.Pool{ + expectedObject: &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - // APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + // APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: enterpriseName, }, ProviderName: "kubernetes_external", @@ -2022,7 +1831,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: poolID, Conditions: []metav1.Condition{ { @@ -2045,36 +1854,36 @@ func TestPoolController_ReconcileDelete(t *testing.T) { "webhookSecret": []byte("supersecretvalue"), }, }, - &garmoperatorv1alpha1.Image{ + &garmoperatorv1beta1.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "ubuntu-image", Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.ImageSpec{ + Spec: garmoperatorv1beta1.ImageSpec{ Tag: "linux-ubuntu-22.04-arm64", }, }, - &garmoperatorv1alpha1.Enterprise{ + &garmoperatorv1beta1.Enterprise{ TypeMeta: metav1.TypeMeta{ Kind: "Enterprise", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: enterpriseName, Namespace: namespaceName, }, - Spec: garmoperatorv1alpha1.EnterpriseSpec{ + Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.EnterpriseStatus{ + Status: garmoperatorv1beta1.EnterpriseStatus{ ID: enterpriseID, Conditions: []metav1.Condition{ { @@ -2159,7 +1968,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -2168,7 +1977,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Pool{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Pool{}).Build() // create a fake reconciler reconciler := &PoolReconciler{ @@ -2176,7 +1985,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - pool := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Pool) + pool := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Pool) mockPoolClient := mock.NewMockPoolClient(mockCtrl) mockInstanceClient := mock.NewMockInstanceClient(mockCtrl) diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index 313cdcf6..89fae5da 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/annotations" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" @@ -48,7 +48,7 @@ type RepositoryReconciler struct { func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - repository := &garmoperatorv1alpha1.Repository{} + repository := &garmoperatorv1beta1.Repository{} err := r.Get(ctx, req.NamespacedName, repository) if err != nil { if apierrors.IsNotFound(err) { @@ -74,7 +74,7 @@ func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) return r.reconcileNormal(ctx, repositoryClient, repository) } -func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1alpha1.Repository) (ctrl.Result, error) { +func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1beta1.Repository) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("repository", repository.Name) @@ -167,7 +167,7 @@ func (r *RepositoryReconciler) reconcileNormal(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *RepositoryReconciler) createRepository(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1alpha1.Repository, webhookSecret string) (params.Repository, error) { +func (r *RepositoryReconciler) createRepository(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1beta1.Repository, webhookSecret string) (params.Repository, error) { log := log.FromContext(ctx) log.WithValues("repository", repository.Name) @@ -213,7 +213,7 @@ func (r *RepositoryReconciler) updateRepository(ctx context.Context, client garm return retValue.Payload, nil } -func (r *RepositoryReconciler) getExistingGarmRepo(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1alpha1.Repository) (params.Repository, error) { +func (r *RepositoryReconciler) getExistingGarmRepo(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1beta1.Repository) (params.Repository, error) { log := log.FromContext(ctx) log.WithValues("repository", repository.Name) @@ -234,7 +234,7 @@ func (r *RepositoryReconciler) getExistingGarmRepo(ctx context.Context, client g return params.Repository{}, nil } -func (r *RepositoryReconciler) reconcileDelete(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1alpha1.Repository) (ctrl.Result, error) { +func (r *RepositoryReconciler) reconcileDelete(ctx context.Context, client garmClient.RepositoryClient, repository *garmoperatorv1beta1.Repository) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("repository", repository.Name) @@ -273,8 +273,8 @@ func (r *RepositoryReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository *garmoperatorv1alpha1.Repository) (*garmoperatorv1alpha1.GitHubCredentials, error) { - creds := &garmoperatorv1alpha1.GitHubCredentials{} +func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository *garmoperatorv1beta1.Repository) (*garmoperatorv1beta1.GitHubCredentials, error) { + creds := &garmoperatorv1beta1.GitHubCredentials{} err := r.Get(ctx, types.NamespacedName{ Namespace: repository.Namespace, Name: repository.Spec.CredentialsRef.Name, @@ -285,7 +285,7 @@ func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository return creds, nil } -func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1alpha1.Repository) error { +func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmoperatorv1beta1.Repository) error { if !controllerutil.ContainsFinalizer(pool, key.RepositoryFinalizerName) { controllerutil.AddFinalizer(pool, key.RepositoryFinalizerName) return r.Update(ctx, pool) @@ -294,12 +294,12 @@ func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmop } func (r *RepositoryReconciler) findReposForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1alpha1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) if !ok { return nil } - var repos garmoperatorv1alpha1.RepositoryList + var repos garmoperatorv1beta1.RepositoryList if err := r.List(ctx, &repos); err != nil { return nil } @@ -322,9 +322,9 @@ func (r *RepositoryReconciler) findReposForCredentials(ctx context.Context, obj // SetupWithManager sets up the controller with the Manager. func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Repository{}). + For(&garmoperatorv1beta1.Repository{}). Watches( - &garmoperatorv1alpha1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredentials{}, handler.EnqueueRequestsFromMapFunc(r.findReposForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/repository_controller_test.go b/internal/controller/repository_controller_test.go index 6335d1fb..b169ac71 100644 --- a/internal/controller/repository_controller_test.go +++ b/internal/controller/repository_controller_test.go @@ -19,7 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/conditions" @@ -35,11 +35,11 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockRepositoryClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Repository + expectedObject *garmoperatorv1beta1.Repository }{ { name: "repository exist - update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -47,19 +47,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -73,23 +73,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -97,19 +97,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -171,7 +171,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "repository exist but spec has changed - update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -179,19 +179,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -205,23 +205,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -229,19 +229,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "has-changed", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -303,7 +303,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "repository exist but pool status has changed - update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -311,19 +311,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -337,23 +337,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -361,19 +361,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", Conditions: []metav1.Condition{ { @@ -439,19 +439,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "repository does not exist - create and update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, @@ -467,23 +467,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", @@ -491,19 +491,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -580,19 +580,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "repository already exist in garm - update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, @@ -608,23 +608,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", @@ -632,19 +632,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", Conditions: []metav1.Condition{ { @@ -705,7 +705,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "repository does not exist in garm - create and update", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -713,19 +713,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-ae78a8f27a3e", }, }, @@ -739,23 +739,23 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, }, }, }, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "existing-repository", Namespace: "default", @@ -763,19 +763,19 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, Owner: "test-repo", - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "9e0da3cb-130b-428d-aa8a-e314d955060e", Conditions: []metav1.Condition{ { @@ -846,7 +846,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { }, { name: "secret ref not found condition", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", @@ -854,21 +854,21 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{}, + Status: garmoperatorv1beta1.RepositoryStatus{}, }, runtimeObjects: []runtime.Object{}, - expectedObject: &garmoperatorv1alpha1.Repository{ + expectedObject: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "new-repository", Namespace: "default", @@ -876,18 +876,18 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ Conditions: []metav1.Condition{ { Type: string(conditions.ReadyCondition), @@ -927,7 +927,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -936,7 +936,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Repository{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Repository{}).Build() // create a fake reconciler reconciler := &RepositoryReconciler{ @@ -944,7 +944,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - repository := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Repository) + repository := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Repository) mockRepository := mock.NewMockRepositoryClient(mockCtrl) tt.expectGarmRequest(mockRepository.EXPECT()) @@ -982,11 +982,11 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockRepositoryClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Repository + expectedObject *garmoperatorv1beta1.Repository }{ { name: "delete repository", - object: &garmoperatorv1alpha1.Repository{ + object: &garmoperatorv1beta1.Repository{ ObjectMeta: metav1.ObjectMeta{ Name: "delete-repository", Namespace: "default", @@ -994,18 +994,18 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { key.RepositoryFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RepositorySpec{ + Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, Kind: "GitHubCredentials", Name: "github-creds", }, - WebhookSecretRef: garmoperatorv1alpha1.SecretRef{ + WebhookSecretRef: garmoperatorv1beta1.SecretRef{ Name: "my-webhook-secret", Key: "webhookSecret", }, }, - Status: garmoperatorv1alpha1.RepositoryStatus{ + Status: garmoperatorv1beta1.RepositoryStatus{ ID: "e1dbf9a6-a9f6-4594-a5ac-12345", }, }, @@ -1019,16 +1019,16 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1alpha1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredentials{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1alpha1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", - SecretRef: garmoperatorv1alpha1.SecretRef{ + SecretRef: garmoperatorv1beta1.SecretRef{ Name: "github-secret", Key: "token", }, @@ -1046,7 +1046,7 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -1055,7 +1055,7 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { } runtimeObjects := []runtime.Object{tt.object} runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Repository{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Repository{}).Build() // create a fake reconciler reconciler := &RepositoryReconciler{ @@ -1063,7 +1063,7 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { Recorder: record.NewFakeRecorder(3), } - repository := tt.object.DeepCopyObject().(*garmoperatorv1alpha1.Repository) + repository := tt.object.DeepCopyObject().(*garmoperatorv1beta1.Repository) mockRepository := mock.NewMockRepositoryClient(mockCtrl) tt.expectGarmRequest(mockRepository.EXPECT()) diff --git a/internal/controller/runner_controller.go b/internal/controller/runner_controller.go index b8c13114..c423087b 100644 --- a/internal/controller/runner_controller.go +++ b/internal/controller/runner_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/source" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/config" @@ -56,7 +56,7 @@ func (r *RunnerReconciler) reconcile(ctx context.Context, req ctrl.Request, inst } // only create RunnerCR if it does not yet exist - runner := &garmoperatorv1alpha1.Runner{} + runner := &garmoperatorv1beta1.Runner{} if err := r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: strings.ToLower(req.Name)}, runner); err != nil { return r.handleCreateRunnerCR(ctx, req, err, garmRunner) } @@ -88,12 +88,12 @@ func (r *RunnerReconciler) createRunnerCR(ctx context.Context, garmRunner *param log := log.FromContext(ctx) log.Info("Creating Runner", "Runner", garmRunner.Name) - runnerObj := &garmoperatorv1alpha1.Runner{ + runnerObj := &garmoperatorv1beta1.Runner{ ObjectMeta: metav1.ObjectMeta{ Name: strings.ToLower(garmRunner.Name), Namespace: namespace, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, + Spec: garmoperatorv1beta1.RunnerSpec{}, } if err := r.Create(ctx, runnerObj); err != nil { @@ -137,7 +137,7 @@ func (r *RunnerReconciler) getGarmRunnerInstanceByName(client garmClient.Instanc return &filteredInstances[0], nil } -func (r *RunnerReconciler) ensureFinalizer(ctx context.Context, runner *garmoperatorv1alpha1.Runner) error { +func (r *RunnerReconciler) ensureFinalizer(ctx context.Context, runner *garmoperatorv1beta1.Runner) error { if !controllerutil.ContainsFinalizer(runner, key.RunnerFinalizerName) { controllerutil.AddFinalizer(runner, key.RunnerFinalizerName) return r.Update(ctx, runner) @@ -145,7 +145,7 @@ func (r *RunnerReconciler) ensureFinalizer(ctx context.Context, runner *garmoper return nil } -func (r *RunnerReconciler) updateRunnerStatus(ctx context.Context, runner *garmoperatorv1alpha1.Runner, garmRunner *params.Instance) (ctrl.Result, error) { +func (r *RunnerReconciler) updateRunnerStatus(ctx context.Context, runner *garmoperatorv1beta1.Runner, garmRunner *params.Instance) (ctrl.Result, error) { if garmRunner == nil { return ctrl.Result{}, nil } @@ -158,10 +158,10 @@ func (r *RunnerReconciler) updateRunnerStatus(ctx context.Context, runner *garmo log.Info("Update runner status...") poolName := garmRunner.PoolID - pools := &garmoperatorv1alpha1.PoolList{} + pools := &garmoperatorv1beta1.PoolList{} err := r.List(ctx, pools) if err == nil { - filteredPools := filter.Match(pools.Items, garmoperatorv1alpha1.MatchesID(garmRunner.PoolID)) + filteredPools := filter.Match(pools.Items, garmoperatorv1beta1.MatchesID(garmRunner.PoolID)) if len(filteredPools) > 0 { poolName = filteredPools[0].Name @@ -194,7 +194,7 @@ func (r *RunnerReconciler) updateRunnerStatus(ctx context.Context, runner *garmo // SetupWithManager sets up the controller with the Manager. func (r *RunnerReconciler) SetupWithManager(mgr ctrl.Manager, eventChan chan event.GenericEvent, options controller.Options) error { c, err := ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1alpha1.Runner{}). + For(&garmoperatorv1beta1.Runner{}). WithOptions(options). Build(r) if err != nil { @@ -248,7 +248,7 @@ func (r *RunnerReconciler) EnqueueRunnerInstances(ctx context.Context, instanceC func enqeueRunnerEvents(garmRunnerInstances params.Instances, eventChan chan event.GenericEvent) { for _, runner := range garmRunnerInstances { - runnerObj := garmoperatorv1alpha1.Runner{ + runnerObj := garmoperatorv1beta1.Runner{ ObjectMeta: metav1.ObjectMeta{ Name: strings.ToLower(runner.Name), Namespace: config.Config.Operator.WatchNamespace, @@ -264,7 +264,7 @@ func enqeueRunnerEvents(garmRunnerInstances params.Instances, eventChan chan eve } func (r *RunnerReconciler) cleanUpNotMatchingRunnerCRs(ctx context.Context, garmRunnerInstances params.Instances) error { - runnerCRList := &garmoperatorv1alpha1.RunnerList{} + runnerCRList := &garmoperatorv1beta1.RunnerList{} err := r.List(ctx, runnerCRList) if err != nil { return err @@ -284,7 +284,7 @@ func (r *RunnerReconciler) cleanUpNotMatchingRunnerCRs(ctx context.Context, garm log.Log.V(1).Info("Deleting runners: ", "Runners", runnersToDelete) for _, runnerName := range runnersToDelete { - runner := &garmoperatorv1alpha1.Runner{} + runner := &garmoperatorv1beta1.Runner{} err := r.Get(ctx, types.NamespacedName{Namespace: config.Config.Operator.WatchNamespace, Name: runnerName}, runner) if err != nil { return err @@ -313,8 +313,8 @@ func (r *RunnerReconciler) cleanUpNotMatchingRunnerCRs(ctx context.Context, garm return nil } -func (r *RunnerReconciler) fetchPools(ctx context.Context) (*garmoperatorv1alpha1.PoolList, error) { - pools := &garmoperatorv1alpha1.PoolList{} +func (r *RunnerReconciler) fetchPools(ctx context.Context) (*garmoperatorv1beta1.PoolList, error) { + pools := &garmoperatorv1beta1.PoolList{} err := r.List(ctx, pools) if err != nil { return nil, err @@ -322,7 +322,7 @@ func (r *RunnerReconciler) fetchPools(ctx context.Context) (*garmoperatorv1alpha return pools, nil } -func (r *RunnerReconciler) fetchRunnerInstancesByNamespacedPools(instanceClient garmClient.InstanceClient, pools *garmoperatorv1alpha1.PoolList) (params.Instances, error) { +func (r *RunnerReconciler) fetchRunnerInstancesByNamespacedPools(instanceClient garmClient.InstanceClient, pools *garmoperatorv1beta1.PoolList) (params.Instances, error) { garmRunnerInstances := params.Instances{} for _, p := range pools.Items { if p.Status.ID == "" { @@ -337,9 +337,9 @@ func (r *RunnerReconciler) fetchRunnerInstancesByNamespacedPools(instanceClient return garmRunnerInstances, nil } -func (r *RunnerReconciler) runnerSpecsEqual(runner garmoperatorv1alpha1.Runner, garmRunner *params.Instance) bool { +func (r *RunnerReconciler) runnerSpecsEqual(runner garmoperatorv1beta1.Runner, garmRunner *params.Instance) bool { runner.Status.PoolID = "" - tmpRunnerStatus := garmoperatorv1alpha1.RunnerStatus{ + tmpRunnerStatus := garmoperatorv1beta1.RunnerStatus{ ID: garmRunner.ID, ProviderID: garmRunner.ProviderID, AgentID: garmRunner.AgentID, diff --git a/internal/controller/runner_controller_test.go b/internal/controller/runner_controller_test.go index 5f15ca80..30e8a781 100644 --- a/internal/controller/runner_controller_test.go +++ b/internal/controller/runner_controller_test.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/event" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/config" @@ -40,7 +40,7 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockInstanceClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Runner + expectedObject *garmoperatorv1beta1.Runner }{ { name: "Create Runner CR", @@ -69,7 +69,7 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { m.ListInstances(instances.NewListInstancesParams()).Return(&instances.ListInstancesOK{Payload: response}, nil) }, wantErr: false, - expectedObject: &garmoperatorv1alpha1.Runner{ + expectedObject: &garmoperatorv1beta1.Runner{ ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-fy5snjcv5dzn", Namespace: "runner", @@ -77,8 +77,8 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { key.RunnerFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, - Status: garmoperatorv1alpha1.RunnerStatus{ + Spec: garmoperatorv1beta1.RunnerSpec{}, + Status: garmoperatorv1beta1.RunnerStatus{ Name: "road-runner-k8s-FY5snJcv5dzn", AgentID: 120, ID: "8215f6c6-486e-4893-84df-3231b185a148", @@ -96,7 +96,7 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -105,7 +105,7 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { } var runtimeObjects []runtime.Object runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Runner{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Runner{}).Build() // create a fake reconciler reconciler := &RunnerReconciler{ @@ -122,7 +122,7 @@ func TestRunnerReconciler_reconcileCreate(t *testing.T) { return } - runner := &garmoperatorv1alpha1.Runner{} + runner := &garmoperatorv1beta1.Runner{} err = client.Get(context.Background(), types.NamespacedName{Namespace: tt.req.Namespace, Name: strings.ToLower(tt.req.Name)}, runner) if (err != nil) != tt.wantErr { t.Errorf("RunnerReconciler.reconcile() error = %v, wantErr %v", err, tt.wantErr) @@ -153,7 +153,7 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { runtimeObjects []runtime.Object expectGarmRequest func(m *mock.MockInstanceClientMockRecorder) wantErr bool - expectedObject *garmoperatorv1alpha1.Runner + expectedObject *garmoperatorv1beta1.Runner }{ { name: "Delete Runner in Garm DB, when Runner CR is marked with deletion timestamp", @@ -164,10 +164,10 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { }, }, runtimeObjects: []runtime.Object{ - &garmoperatorv1alpha1.Runner{ + &garmoperatorv1beta1.Runner{ TypeMeta: metav1.TypeMeta{ Kind: "Runner", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-fy5snjcv5dzn", @@ -177,8 +177,8 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { }, DeletionTimestamp: &now, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, - Status: garmoperatorv1alpha1.RunnerStatus{ + Spec: garmoperatorv1beta1.RunnerSpec{}, + Status: garmoperatorv1beta1.RunnerStatus{ Name: "road-runner-k8s-FY5snJcv5dzn", AgentID: 120, ID: "8215f6c6-486e-4893-84df-3231b185a148", @@ -211,7 +211,7 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { m.DeleteInstance(instances.NewDeleteInstanceParams().WithInstanceName("road-runner-k8s-FY5snJcv5dzn")).Return(nil) }, wantErr: false, - expectedObject: &garmoperatorv1alpha1.Runner{ + expectedObject: &garmoperatorv1beta1.Runner{ ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-fy5snjcv5dzn", Namespace: "runner", @@ -220,8 +220,8 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { }, DeletionTimestamp: &now, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, - Status: garmoperatorv1alpha1.RunnerStatus{ + Spec: garmoperatorv1beta1.RunnerSpec{}, + Status: garmoperatorv1beta1.RunnerStatus{ Name: "road-runner-k8s-FY5snJcv5dzn", AgentID: 120, ID: "8215f6c6-486e-4893-84df-3231b185a148", @@ -239,7 +239,7 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -248,7 +248,7 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { } var runtimeObjects []runtime.Object runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Runner{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Runner{}).Build() // create a fake reconciler reconciler := &RunnerReconciler{ @@ -265,7 +265,7 @@ func TestRunnerReconciler_reconcileDeleteGarmRunner(t *testing.T) { return } - runner := &garmoperatorv1alpha1.Runner{} + runner := &garmoperatorv1beta1.Runner{} err = client.Get(context.Background(), types.NamespacedName{Namespace: tt.req.Namespace, Name: strings.ToLower(tt.req.Name)}, runner) if (err != nil) != tt.wantErr { t.Errorf("RunnerReconciler.reconcile() error = %v, wantErr %v", err, tt.wantErr) @@ -298,10 +298,10 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { }, }, runtimeObjects: []runtime.Object{ - &garmoperatorv1alpha1.Runner{ + &garmoperatorv1beta1.Runner{ TypeMeta: metav1.TypeMeta{ Kind: "Runner", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-fy5snjcv5dzn", @@ -310,8 +310,8 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { key.RunnerFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, - Status: garmoperatorv1alpha1.RunnerStatus{ + Spec: garmoperatorv1beta1.RunnerSpec{}, + Status: garmoperatorv1beta1.RunnerStatus{ Name: "road-runner-k8s-FY5snJcv5dzn", AgentID: 120, ID: "8215f6c6-486e-4893-84df-3231b185a148", @@ -323,10 +323,10 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { InstanceStatus: params.RunnerIdle, }, }, - &garmoperatorv1alpha1.Runner{ + &garmoperatorv1beta1.Runner{ TypeMeta: metav1.TypeMeta{ Kind: "Runner", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-n6kq2mt3k4qr", @@ -335,8 +335,8 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { key.RunnerFinalizerName, }, }, - Spec: garmoperatorv1alpha1.RunnerSpec{}, - Status: garmoperatorv1alpha1.RunnerStatus{ + Spec: garmoperatorv1beta1.RunnerSpec{}, + Status: garmoperatorv1beta1.RunnerStatus{ Name: "road-runner-k8s-n6KQ2Mt3k4qr", AgentID: 130, ID: "13d31cad-588b-4ea8-8015-052a76ad3dd3", @@ -348,19 +348,19 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { InstanceStatus: params.RunnerIdle, }, }, - &garmoperatorv1alpha1.Pool{ + &garmoperatorv1beta1.Pool{ TypeMeta: metav1.TypeMeta{ Kind: "Pool", - APIVersion: garmoperatorv1alpha1.GroupVersion.Group + "/" + garmoperatorv1alpha1.GroupVersion.Version, + APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ Name: "my-enterprise-pool", Namespace: "test-namespace", }, - Spec: garmoperatorv1alpha1.PoolSpec{ + Spec: garmoperatorv1beta1.PoolSpec{ GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1alpha1.GroupVersion.Group, - Kind: string(garmoperatorv1alpha1.EnterpriseScope), + APIGroup: &garmoperatorv1beta1.GroupVersion.Group, + Kind: string(garmoperatorv1beta1.EnterpriseScope), Name: "my-enterprise", }, ProviderName: "kubernetes_external", @@ -376,7 +376,7 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { ExtraSpecs: "", GitHubRunnerGroup: "", }, - Status: garmoperatorv1alpha1.PoolStatus{ + Status: garmoperatorv1beta1.PoolStatus{ ID: "a46553c6-ad87-454b-b5f5-a1c468d78c1e", }, }, @@ -400,7 +400,7 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { wantErr: false, expectedEvents: []event.GenericEvent{ { - Object: &garmoperatorv1alpha1.Runner{ + Object: &garmoperatorv1beta1.Runner{ ObjectMeta: metav1.ObjectMeta{ Name: "road-runner-k8s-fy5snjcv5dzn", Namespace: "test-namespace", @@ -414,7 +414,7 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { schemeBuilder := runtime.SchemeBuilder{ - garmoperatorv1alpha1.AddToScheme, + garmoperatorv1beta1.AddToScheme, } err := schemeBuilder.AddToScheme(scheme.Scheme) @@ -423,7 +423,7 @@ func TestRunnerReconciler_reconcileDeleteCR(t *testing.T) { } var runtimeObjects []runtime.Object runtimeObjects = append(runtimeObjects, tt.runtimeObjects...) - client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1alpha1.Runner{}).Build() + client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(runtimeObjects...).WithStatusSubresource(&garmoperatorv1beta1.Runner{}).Build() // create a fake reconciler reconciler := &RunnerReconciler{ diff --git a/pkg/pools/pools.go b/pkg/pools/pools.go index 5ae19c07..69e9f40a 100644 --- a/pkg/pools/pools.go +++ b/pkg/pools/pools.go @@ -7,7 +7,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/cloudbase/garm/client/enterprises" "github.com/cloudbase/garm/client/organizations" "github.com/cloudbase/garm/client/pools" @@ -15,18 +14,18 @@ import ( "github.com/cloudbase/garm/params" "sigs.k8s.io/controller-runtime/pkg/log" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" "github.com/mercedes-benz/garm-operator/pkg/filter" ) -func GetGarmPoolBySpecs(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, image *garmoperatorv1alpha1.Image, gitHubScopeRef garmoperatorv1alpha1.GitHubScope) (*params.Pool, error) { +func GetGarmPoolBySpecs(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, image *garmoperatorv1beta1.Image, gitHubScopeRef garmoperatorv1beta1.GitHubScope) (*params.Pool, error) { log := log.FromContext(ctx) log.Info("Getting existing garm pools by pool.spec") githubScopeRefID := gitHubScopeRef.GetID() githubScopeRefName := gitHubScopeRef.GetName() - scope, err := garmoperatorv1alpha1.ToGitHubScopeKind(gitHubScopeRef.GetKind()) + scope, err := garmoperatorv1beta1.ToGitHubScopeKind(gitHubScopeRef.GetKind()) if err != nil { return nil, err } @@ -67,7 +66,7 @@ func GetGarmPoolBySpecs(ctx context.Context, garmClient garmClient.PoolClient, p return nil, nil } -func UpdatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, image *garmoperatorv1alpha1.Image) error { +func UpdatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, image *garmoperatorv1beta1.Image) error { log := log.FromContext(ctx). WithName("UpdatePool") @@ -100,7 +99,7 @@ func UpdatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar return nil } -func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool, image *garmoperatorv1alpha1.Image, gitHubScopeRef garmoperatorv1alpha1.GitHubScope) (params.Pool, error) { +func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool, image *garmoperatorv1beta1.Image, gitHubScopeRef garmoperatorv1beta1.GitHubScope) (params.Pool, error) { log := log.FromContext(ctx). WithName("CreatePool") log.Info("creating pool", "pool", pool.Name) @@ -108,7 +107,7 @@ func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar poolResult := params.Pool{} id := gitHubScopeRef.GetID() - scope, err := garmoperatorv1alpha1.ToGitHubScopeKind(gitHubScopeRef.GetKind()) + scope, err := garmoperatorv1beta1.ToGitHubScopeKind(gitHubScopeRef.GetKind()) if err != nil { return poolResult, err } @@ -140,7 +139,7 @@ func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar } switch scope { - case garmoperatorv1alpha1.EnterpriseScope: + case garmoperatorv1beta1.EnterpriseScope: result, err := garmClient.CreateEnterprisePool( enterprises.NewCreateEnterprisePoolParams(). WithEnterpriseID(id). @@ -150,7 +149,7 @@ func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar } poolResult = result.Payload - case garmoperatorv1alpha1.OrganizationScope: + case garmoperatorv1beta1.OrganizationScope: result, err := garmClient.CreateOrgPool( organizations.NewCreateOrgPoolParams(). WithOrgID(id). @@ -159,7 +158,7 @@ func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar return params.Pool{}, err } poolResult = result.Payload - case garmoperatorv1alpha1.RepositoryScope: + case garmoperatorv1beta1.RepositoryScope: result, err := garmClient.CreateRepoPool( repositories.NewCreateRepoPoolParams(). WithRepoID(id). @@ -176,7 +175,7 @@ func CreatePool(ctx context.Context, garmClient garmClient.PoolClient, pool *gar return poolResult, nil } -func GarmPoolExists(garmClient garmClient.PoolClient, pool *garmoperatorv1alpha1.Pool) bool { +func GarmPoolExists(garmClient garmClient.PoolClient, pool *garmoperatorv1beta1.Pool) bool { result, err := garmClient.GetPool(pools.NewGetPoolParams().WithPoolID(pool.Status.ID)) if err != nil { return false diff --git a/pkg/pools/predicate.go b/pkg/pools/predicate.go index 47409090..51c99dc5 100644 --- a/pkg/pools/predicate.go +++ b/pkg/pools/predicate.go @@ -5,21 +5,21 @@ package pools import ( "github.com/cloudbase/garm/params" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" "github.com/mercedes-benz/garm-operator/pkg/filter" ) -func MatchesGitHubScope(scope garmoperatorv1alpha1.GitHubScopeKind, id string) filter.Predicate[params.Pool] { +func MatchesGitHubScope(scope garmoperatorv1beta1.GitHubScopeKind, id string) filter.Predicate[params.Pool] { return func(p params.Pool) bool { - if scope == garmoperatorv1alpha1.EnterpriseScope { + if scope == garmoperatorv1beta1.EnterpriseScope { return p.EnterpriseID == id } - if scope == garmoperatorv1alpha1.OrganizationScope { + if scope == garmoperatorv1beta1.OrganizationScope { return p.OrgID == id } - if scope == garmoperatorv1alpha1.RepositoryScope { + if scope == garmoperatorv1beta1.RepositoryScope { return p.RepoID == id } return false diff --git a/pkg/runners/runners.go b/pkg/runners/runners.go index 5f8380c9..7a00e2f4 100644 --- a/pkg/runners/runners.go +++ b/pkg/runners/runners.go @@ -11,11 +11,11 @@ import ( "github.com/cloudbase/garm/params" "sigs.k8s.io/controller-runtime/pkg/log" - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" garmClient "github.com/mercedes-benz/garm-operator/pkg/client" ) -func GetRunnersByPoolID(ctx context.Context, pool *garmoperatorv1alpha1.Pool, instanceClient garmClient.InstanceClient) ([]params.Instance, error) { +func GetRunnersByPoolID(ctx context.Context, pool *garmoperatorv1beta1.Pool, instanceClient garmClient.InstanceClient) ([]params.Instance, error) { log := log.FromContext(ctx) log.Info("discover idle runners", "pool", pool.Name) diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index 0c2b57ec..32b6b100 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -5,16 +5,15 @@ package secret import ( "context" "fmt" + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" - - garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1" ) // FetchRef fetches a secret for a given garmoperatorv1alpha1.SecretRef and namespace -func FetchRef(ctx context.Context, c client.Client, ref *garmoperatorv1alpha1.SecretRef, namespace string) (string, error) { +func FetchRef(ctx context.Context, c client.Client, ref *garmoperatorv1beta1.SecretRef, namespace string) (string, error) { if ref == nil { return "", nil } From b9c53fde2ea36261d7b553fac7634e5fbc4847f2 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Tue, 17 Sep 2024 13:40:37 +0200 Subject: [PATCH 15/30] feat: add conversion generator this adds the conversion generator from https://github.com/kubernetes/code-generator to generate conversion code Signed-off-by: Mario Constanti --- Makefile | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d2611b58..a1c6a48f 100644 --- a/Makefile +++ b/Makefile @@ -49,8 +49,12 @@ help: ## Display this help. manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases +.PHONY: conversion +conversion: conversion-gen + $(CONVERSION_GEN) --go-header-file hack/boilerplate.go.txt --output-file zz_generated.conversion.go github.com/mercedes-benz/garm-operator/api/v1alpha1 + .PHONY: generate -generate: controller-gen mockgen ## Generate mock client and code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. +generate: controller-gen conversion mockgen ## Generate mock client and code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." go generate ./... @@ -162,6 +166,7 @@ $(LOCALBIN): KUBECTL ?= kubectl KUSTOMIZE ?= $(LOCALBIN)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen +CONVERSION_GEN ?= $(LOCALBIN)/conversion-gen ENVTEST ?= $(LOCALBIN)/setup-envtest GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint MOCKGEN ?= $(LOCALBIN)/mockgen @@ -176,7 +181,8 @@ KIND ?= $(LOCALBIN)/kind ## Tool Versions KUSTOMIZE_VERSION ?= v5.0.1 CONTROLLER_TOOLS_VERSION ?= v0.15.0 -GOLANGCI_LINT_VERSION ?= v1.61.0 +CONVERSION_GEN_VERSION ?= v0.30.5 +GOLANGCI_LINT_VERSION ?= v1.59.1 MOCKGEN_VERSION ?= v0.4.0 GORELEASER_VERSION ?= v1.21.0 MDTOC_VERSION ?= v1.1.0 @@ -200,6 +206,12 @@ $(CONTROLLER_GEN): $(LOCALBIN) test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) +.PHONY: conversion-gen +conversion-gen: $(CONVERSION_GEN) ## Download conversion-gen locally if necessary. If wrong version is installed, it will be overwritten. +$(CONVERSION_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/conversion-gen || \ + GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/conversion-gen@$(CONVERSION_GEN_VERSION) + .PHONY: envtest envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) From 89b0036d9186f68f9826869d2f20c830f08a889f Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Tue, 17 Sep 2024 13:43:00 +0200 Subject: [PATCH 16/30] feat: prepare for conversion code generation Signed-off-by: Mario Constanti --- api/v1alpha1/doc.go | 2 ++ api/v1alpha1/groupversion_info.go | 3 +++ api/v1beta1/conversion.go | 7 +++++++ api/v1beta1/doc.go | 8 ++++++++ 4 files changed, 20 insertions(+) create mode 100644 api/v1alpha1/doc.go create mode 100644 api/v1beta1/conversion.go create mode 100644 api/v1beta1/doc.go diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go new file mode 100644 index 00000000..4d89826d --- /dev/null +++ b/api/v1alpha1/doc.go @@ -0,0 +1,2 @@ +// +k8s:conversion-gen=github.com/mercedes-benz/garm-operator/api/v1beta1 +package v1alpha1 diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go index fd52d008..991d920b 100644 --- a/api/v1alpha1/groupversion_info.go +++ b/api/v1alpha1/groupversion_info.go @@ -19,4 +19,7 @@ var ( // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + // localSchemeBuilder is getting used by the generated conversion + localSchemeBuilder = SchemeBuilder.SchemeBuilder ) diff --git a/api/v1beta1/conversion.go b/api/v1beta1/conversion.go new file mode 100644 index 00000000..38269f7c --- /dev/null +++ b/api/v1beta1/conversion.go @@ -0,0 +1,7 @@ +package v1beta1 + +// Hub marks this type as a conversion hub. +func (*Pool) Hub() {} + +// Hub marks this type as a conversion hub. +func (*Organization) Hub() {} diff --git a/api/v1beta1/doc.go b/api/v1beta1/doc.go new file mode 100644 index 00000000..d4288261 --- /dev/null +++ b/api/v1beta1/doc.go @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT + +// Package v1beta1 contains API Schema definitions for the infrastructure v1alpha7 API group. +// +kubebuilder:object:generate=true +// +groupName=garm-operator.mercedes-benz.com +// +k8s:conversion-gen=github.com/mercedes-benz/garm-operator/api/v1alpha1 +// +k8s:openapi-gen=true +package v1beta1 From f557d7f41988f84472ecec862a039e5190d78970 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Tue, 17 Sep 2024 13:43:36 +0200 Subject: [PATCH 17/30] feat: add generated conversion code code got generated by make conversion Signed-off-by: Mario Constanti --- api/v1alpha1/zz_generated.conversion.go | 978 ++++++++++++++++++++++++ 1 file changed, 978 insertions(+) create mode 100644 api/v1alpha1/zz_generated.conversion.go diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go new file mode 100644 index 00000000..663f9707 --- /dev/null +++ b/api/v1alpha1/zz_generated.conversion.go @@ -0,0 +1,978 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// SPDX-License-Identifier: MIT + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + params "github.com/cloudbase/garm-provider-common/params" + garmparams "github.com/cloudbase/garm/params" + v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*Enterprise)(nil), (*v1beta1.Enterprise)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Enterprise_To_v1beta1_Enterprise(a.(*Enterprise), b.(*v1beta1.Enterprise), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Enterprise)(nil), (*Enterprise)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Enterprise_To_v1alpha1_Enterprise(a.(*v1beta1.Enterprise), b.(*Enterprise), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnterpriseList)(nil), (*v1beta1.EnterpriseList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnterpriseList_To_v1beta1_EnterpriseList(a.(*EnterpriseList), b.(*v1beta1.EnterpriseList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.EnterpriseList)(nil), (*EnterpriseList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EnterpriseList_To_v1alpha1_EnterpriseList(a.(*v1beta1.EnterpriseList), b.(*EnterpriseList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnterpriseSpec)(nil), (*v1beta1.EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(a.(*EnterpriseSpec), b.(*v1beta1.EnterpriseSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.EnterpriseSpec)(nil), (*EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(a.(*v1beta1.EnterpriseSpec), b.(*EnterpriseSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*EnterpriseStatus)(nil), (*v1beta1.EnterpriseStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(a.(*EnterpriseStatus), b.(*v1beta1.EnterpriseStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.EnterpriseStatus)(nil), (*EnterpriseStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus(a.(*v1beta1.EnterpriseStatus), b.(*EnterpriseStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Image)(nil), (*v1beta1.Image)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Image_To_v1beta1_Image(a.(*Image), b.(*v1beta1.Image), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Image)(nil), (*Image)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Image_To_v1alpha1_Image(a.(*v1beta1.Image), b.(*Image), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ImageList)(nil), (*v1beta1.ImageList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ImageList_To_v1beta1_ImageList(a.(*ImageList), b.(*v1beta1.ImageList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ImageList)(nil), (*ImageList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ImageList_To_v1alpha1_ImageList(a.(*v1beta1.ImageList), b.(*ImageList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ImageSpec)(nil), (*v1beta1.ImageSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec(a.(*ImageSpec), b.(*v1beta1.ImageSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ImageSpec)(nil), (*ImageSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec(a.(*v1beta1.ImageSpec), b.(*ImageSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ImageStatus)(nil), (*v1beta1.ImageStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus(a.(*ImageStatus), b.(*v1beta1.ImageStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ImageStatus)(nil), (*ImageStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus(a.(*v1beta1.ImageStatus), b.(*ImageStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Organization)(nil), (*v1beta1.Organization)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Organization_To_v1beta1_Organization(a.(*Organization), b.(*v1beta1.Organization), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Organization)(nil), (*Organization)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Organization_To_v1alpha1_Organization(a.(*v1beta1.Organization), b.(*Organization), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OrganizationList)(nil), (*v1beta1.OrganizationList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_OrganizationList_To_v1beta1_OrganizationList(a.(*OrganizationList), b.(*v1beta1.OrganizationList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OrganizationList)(nil), (*OrganizationList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OrganizationList_To_v1alpha1_OrganizationList(a.(*v1beta1.OrganizationList), b.(*OrganizationList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OrganizationSpec)(nil), (*OrganizationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(a.(*v1beta1.OrganizationSpec), b.(*OrganizationSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*OrganizationStatus)(nil), (*v1beta1.OrganizationStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(a.(*OrganizationStatus), b.(*v1beta1.OrganizationStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.OrganizationStatus)(nil), (*OrganizationStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus(a.(*v1beta1.OrganizationStatus), b.(*OrganizationStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Pool)(nil), (*v1beta1.Pool)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Pool_To_v1beta1_Pool(a.(*Pool), b.(*v1beta1.Pool), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Pool)(nil), (*Pool)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Pool_To_v1alpha1_Pool(a.(*v1beta1.Pool), b.(*Pool), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PoolList)(nil), (*v1beta1.PoolList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PoolList_To_v1beta1_PoolList(a.(*PoolList), b.(*v1beta1.PoolList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.PoolList)(nil), (*PoolList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PoolList_To_v1alpha1_PoolList(a.(*v1beta1.PoolList), b.(*PoolList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PoolSpec)(nil), (*v1beta1.PoolSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec(a.(*PoolSpec), b.(*v1beta1.PoolSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.PoolSpec)(nil), (*PoolSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec(a.(*v1beta1.PoolSpec), b.(*PoolSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PoolStatus)(nil), (*v1beta1.PoolStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus(a.(*PoolStatus), b.(*v1beta1.PoolStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.PoolStatus)(nil), (*PoolStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus(a.(*v1beta1.PoolStatus), b.(*PoolStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Repository)(nil), (*v1beta1.Repository)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Repository_To_v1beta1_Repository(a.(*Repository), b.(*v1beta1.Repository), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Repository)(nil), (*Repository)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Repository_To_v1alpha1_Repository(a.(*v1beta1.Repository), b.(*Repository), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RepositoryList)(nil), (*v1beta1.RepositoryList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RepositoryList_To_v1beta1_RepositoryList(a.(*RepositoryList), b.(*v1beta1.RepositoryList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RepositoryList)(nil), (*RepositoryList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RepositoryList_To_v1alpha1_RepositoryList(a.(*v1beta1.RepositoryList), b.(*RepositoryList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RepositorySpec)(nil), (*v1beta1.RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(a.(*RepositorySpec), b.(*v1beta1.RepositorySpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RepositorySpec)(nil), (*RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(a.(*v1beta1.RepositorySpec), b.(*RepositorySpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RepositoryStatus)(nil), (*v1beta1.RepositoryStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(a.(*RepositoryStatus), b.(*v1beta1.RepositoryStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RepositoryStatus)(nil), (*RepositoryStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus(a.(*v1beta1.RepositoryStatus), b.(*RepositoryStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Runner)(nil), (*v1beta1.Runner)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Runner_To_v1beta1_Runner(a.(*Runner), b.(*v1beta1.Runner), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.Runner)(nil), (*Runner)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Runner_To_v1alpha1_Runner(a.(*v1beta1.Runner), b.(*Runner), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RunnerList)(nil), (*v1beta1.RunnerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RunnerList_To_v1beta1_RunnerList(a.(*RunnerList), b.(*v1beta1.RunnerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RunnerList)(nil), (*RunnerList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RunnerList_To_v1alpha1_RunnerList(a.(*v1beta1.RunnerList), b.(*RunnerList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RunnerSpec)(nil), (*v1beta1.RunnerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec(a.(*RunnerSpec), b.(*v1beta1.RunnerSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RunnerSpec)(nil), (*RunnerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec(a.(*v1beta1.RunnerSpec), b.(*RunnerSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*RunnerStatus)(nil), (*v1beta1.RunnerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus(a.(*RunnerStatus), b.(*v1beta1.RunnerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.RunnerStatus)(nil), (*RunnerStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(a.(*v1beta1.RunnerStatus), b.(*RunnerStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SecretRef)(nil), (*v1beta1.SecretRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef(a.(*SecretRef), b.(*v1beta1.SecretRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.SecretRef)(nil), (*SecretRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef(a.(*v1beta1.SecretRef), b.(*SecretRef), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*OrganizationSpec)(nil), (*v1beta1.OrganizationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(a.(*OrganizationSpec), b.(*v1beta1.OrganizationSpec), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_Enterprise_To_v1beta1_Enterprise(in *Enterprise, out *v1beta1.Enterprise, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Enterprise_To_v1beta1_Enterprise is an autogenerated conversion function. +func Convert_v1alpha1_Enterprise_To_v1beta1_Enterprise(in *Enterprise, out *v1beta1.Enterprise, s conversion.Scope) error { + return autoConvert_v1alpha1_Enterprise_To_v1beta1_Enterprise(in, out, s) +} + +func autoConvert_v1beta1_Enterprise_To_v1alpha1_Enterprise(in *v1beta1.Enterprise, out *Enterprise, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Enterprise_To_v1alpha1_Enterprise is an autogenerated conversion function. +func Convert_v1beta1_Enterprise_To_v1alpha1_Enterprise(in *v1beta1.Enterprise, out *Enterprise, s conversion.Scope) error { + return autoConvert_v1beta1_Enterprise_To_v1alpha1_Enterprise(in, out, s) +} + +func autoConvert_v1alpha1_EnterpriseList_To_v1beta1_EnterpriseList(in *EnterpriseList, out *v1beta1.EnterpriseList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.Enterprise, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Enterprise_To_v1beta1_Enterprise(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_EnterpriseList_To_v1beta1_EnterpriseList is an autogenerated conversion function. +func Convert_v1alpha1_EnterpriseList_To_v1beta1_EnterpriseList(in *EnterpriseList, out *v1beta1.EnterpriseList, s conversion.Scope) error { + return autoConvert_v1alpha1_EnterpriseList_To_v1beta1_EnterpriseList(in, out, s) +} + +func autoConvert_v1beta1_EnterpriseList_To_v1alpha1_EnterpriseList(in *v1beta1.EnterpriseList, out *EnterpriseList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Enterprise, len(*in)) + for i := range *in { + if err := Convert_v1beta1_Enterprise_To_v1alpha1_Enterprise(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_EnterpriseList_To_v1alpha1_EnterpriseList is an autogenerated conversion function. +func Convert_v1beta1_EnterpriseList_To_v1alpha1_EnterpriseList(in *v1beta1.EnterpriseList, out *EnterpriseList, s conversion.Scope) error { + return autoConvert_v1beta1_EnterpriseList_To_v1alpha1_EnterpriseList(in, out, s) +} + +func autoConvert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in *EnterpriseSpec, out *v1beta1.EnterpriseSpec, s conversion.Scope) error { + // WARNING: in.CredentialsName requires manual conversion: does not exist in peer-type + if err := Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(in *v1beta1.EnterpriseSpec, out *EnterpriseSpec, s conversion.Scope) error { + // WARNING: in.CredentialsRef requires manual conversion: does not exist in peer-type + if err := Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + // WARNING: in.PoolBalancerType requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(in *EnterpriseStatus, out *v1beta1.EnterpriseStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus is an autogenerated conversion function. +func Convert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(in *EnterpriseStatus, out *v1beta1.EnterpriseStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(in, out, s) +} + +func autoConvert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus(in *v1beta1.EnterpriseStatus, out *EnterpriseStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus is an autogenerated conversion function. +func Convert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus(in *v1beta1.EnterpriseStatus, out *EnterpriseStatus, s conversion.Scope) error { + return autoConvert_v1beta1_EnterpriseStatus_To_v1alpha1_EnterpriseStatus(in, out, s) +} + +func autoConvert_v1alpha1_Image_To_v1beta1_Image(in *Image, out *v1beta1.Image, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Image_To_v1beta1_Image is an autogenerated conversion function. +func Convert_v1alpha1_Image_To_v1beta1_Image(in *Image, out *v1beta1.Image, s conversion.Scope) error { + return autoConvert_v1alpha1_Image_To_v1beta1_Image(in, out, s) +} + +func autoConvert_v1beta1_Image_To_v1alpha1_Image(in *v1beta1.Image, out *Image, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Image_To_v1alpha1_Image is an autogenerated conversion function. +func Convert_v1beta1_Image_To_v1alpha1_Image(in *v1beta1.Image, out *Image, s conversion.Scope) error { + return autoConvert_v1beta1_Image_To_v1alpha1_Image(in, out, s) +} + +func autoConvert_v1alpha1_ImageList_To_v1beta1_ImageList(in *ImageList, out *v1beta1.ImageList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1beta1.Image)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_ImageList_To_v1beta1_ImageList is an autogenerated conversion function. +func Convert_v1alpha1_ImageList_To_v1beta1_ImageList(in *ImageList, out *v1beta1.ImageList, s conversion.Scope) error { + return autoConvert_v1alpha1_ImageList_To_v1beta1_ImageList(in, out, s) +} + +func autoConvert_v1beta1_ImageList_To_v1alpha1_ImageList(in *v1beta1.ImageList, out *ImageList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Image)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_ImageList_To_v1alpha1_ImageList is an autogenerated conversion function. +func Convert_v1beta1_ImageList_To_v1alpha1_ImageList(in *v1beta1.ImageList, out *ImageList, s conversion.Scope) error { + return autoConvert_v1beta1_ImageList_To_v1alpha1_ImageList(in, out, s) +} + +func autoConvert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec(in *ImageSpec, out *v1beta1.ImageSpec, s conversion.Scope) error { + out.Tag = in.Tag + return nil +} + +// Convert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec is an autogenerated conversion function. +func Convert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec(in *ImageSpec, out *v1beta1.ImageSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_ImageSpec_To_v1beta1_ImageSpec(in, out, s) +} + +func autoConvert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec(in *v1beta1.ImageSpec, out *ImageSpec, s conversion.Scope) error { + out.Tag = in.Tag + return nil +} + +// Convert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec is an autogenerated conversion function. +func Convert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec(in *v1beta1.ImageSpec, out *ImageSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ImageSpec_To_v1alpha1_ImageSpec(in, out, s) +} + +func autoConvert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus(in *ImageStatus, out *v1beta1.ImageStatus, s conversion.Scope) error { + return nil +} + +// Convert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus is an autogenerated conversion function. +func Convert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus(in *ImageStatus, out *v1beta1.ImageStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ImageStatus_To_v1beta1_ImageStatus(in, out, s) +} + +func autoConvert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus(in *v1beta1.ImageStatus, out *ImageStatus, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus is an autogenerated conversion function. +func Convert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus(in *v1beta1.ImageStatus, out *ImageStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ImageStatus_To_v1alpha1_ImageStatus(in, out, s) +} + +func autoConvert_v1alpha1_Organization_To_v1beta1_Organization(in *Organization, out *v1beta1.Organization, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Organization_To_v1beta1_Organization is an autogenerated conversion function. +func Convert_v1alpha1_Organization_To_v1beta1_Organization(in *Organization, out *v1beta1.Organization, s conversion.Scope) error { + return autoConvert_v1alpha1_Organization_To_v1beta1_Organization(in, out, s) +} + +func autoConvert_v1beta1_Organization_To_v1alpha1_Organization(in *v1beta1.Organization, out *Organization, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Organization_To_v1alpha1_Organization is an autogenerated conversion function. +func Convert_v1beta1_Organization_To_v1alpha1_Organization(in *v1beta1.Organization, out *Organization, s conversion.Scope) error { + return autoConvert_v1beta1_Organization_To_v1alpha1_Organization(in, out, s) +} + +func autoConvert_v1alpha1_OrganizationList_To_v1beta1_OrganizationList(in *OrganizationList, out *v1beta1.OrganizationList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.Organization, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Organization_To_v1beta1_Organization(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_OrganizationList_To_v1beta1_OrganizationList is an autogenerated conversion function. +func Convert_v1alpha1_OrganizationList_To_v1beta1_OrganizationList(in *OrganizationList, out *v1beta1.OrganizationList, s conversion.Scope) error { + return autoConvert_v1alpha1_OrganizationList_To_v1beta1_OrganizationList(in, out, s) +} + +func autoConvert_v1beta1_OrganizationList_To_v1alpha1_OrganizationList(in *v1beta1.OrganizationList, out *OrganizationList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Organization, len(*in)) + for i := range *in { + if err := Convert_v1beta1_Organization_To_v1alpha1_Organization(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_OrganizationList_To_v1alpha1_OrganizationList is an autogenerated conversion function. +func Convert_v1beta1_OrganizationList_To_v1alpha1_OrganizationList(in *v1beta1.OrganizationList, out *OrganizationList, s conversion.Scope) error { + return autoConvert_v1beta1_OrganizationList_To_v1alpha1_OrganizationList(in, out, s) +} + +func autoConvert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s conversion.Scope) error { + // WARNING: in.CredentialsName requires manual conversion: does not exist in peer-type + if err := Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(in *v1beta1.OrganizationSpec, out *OrganizationSpec, s conversion.Scope) error { + // WARNING: in.CredentialsRef requires manual conversion: does not exist in peer-type + if err := Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + // WARNING: in.PoolBalancerType requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(in *OrganizationStatus, out *v1beta1.OrganizationStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus is an autogenerated conversion function. +func Convert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(in *OrganizationStatus, out *v1beta1.OrganizationStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(in, out, s) +} + +func autoConvert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus(in *v1beta1.OrganizationStatus, out *OrganizationStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus is an autogenerated conversion function. +func Convert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus(in *v1beta1.OrganizationStatus, out *OrganizationStatus, s conversion.Scope) error { + return autoConvert_v1beta1_OrganizationStatus_To_v1alpha1_OrganizationStatus(in, out, s) +} + +func autoConvert_v1alpha1_Pool_To_v1beta1_Pool(in *Pool, out *v1beta1.Pool, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Pool_To_v1beta1_Pool is an autogenerated conversion function. +func Convert_v1alpha1_Pool_To_v1beta1_Pool(in *Pool, out *v1beta1.Pool, s conversion.Scope) error { + return autoConvert_v1alpha1_Pool_To_v1beta1_Pool(in, out, s) +} + +func autoConvert_v1beta1_Pool_To_v1alpha1_Pool(in *v1beta1.Pool, out *Pool, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Pool_To_v1alpha1_Pool is an autogenerated conversion function. +func Convert_v1beta1_Pool_To_v1alpha1_Pool(in *v1beta1.Pool, out *Pool, s conversion.Scope) error { + return autoConvert_v1beta1_Pool_To_v1alpha1_Pool(in, out, s) +} + +func autoConvert_v1alpha1_PoolList_To_v1beta1_PoolList(in *PoolList, out *v1beta1.PoolList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1beta1.Pool)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_PoolList_To_v1beta1_PoolList is an autogenerated conversion function. +func Convert_v1alpha1_PoolList_To_v1beta1_PoolList(in *PoolList, out *v1beta1.PoolList, s conversion.Scope) error { + return autoConvert_v1alpha1_PoolList_To_v1beta1_PoolList(in, out, s) +} + +func autoConvert_v1beta1_PoolList_To_v1alpha1_PoolList(in *v1beta1.PoolList, out *PoolList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Pool)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_PoolList_To_v1alpha1_PoolList is an autogenerated conversion function. +func Convert_v1beta1_PoolList_To_v1alpha1_PoolList(in *v1beta1.PoolList, out *PoolList, s conversion.Scope) error { + return autoConvert_v1beta1_PoolList_To_v1alpha1_PoolList(in, out, s) +} + +func autoConvert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec(in *PoolSpec, out *v1beta1.PoolSpec, s conversion.Scope) error { + out.GitHubScopeRef = in.GitHubScopeRef + out.ProviderName = in.ProviderName + out.MaxRunners = in.MaxRunners + out.MinIdleRunners = in.MinIdleRunners + out.Flavor = in.Flavor + out.OSType = params.OSType(in.OSType) + out.OSArch = params.OSArch(in.OSArch) + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + out.Enabled = in.Enabled + out.RunnerBootstrapTimeout = in.RunnerBootstrapTimeout + out.ImageName = in.ImageName + out.ExtraSpecs = in.ExtraSpecs + out.GitHubRunnerGroup = in.GitHubRunnerGroup + out.RunnerPrefix = in.RunnerPrefix + return nil +} + +// Convert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec is an autogenerated conversion function. +func Convert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec(in *PoolSpec, out *v1beta1.PoolSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_PoolSpec_To_v1beta1_PoolSpec(in, out, s) +} + +func autoConvert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec(in *v1beta1.PoolSpec, out *PoolSpec, s conversion.Scope) error { + out.GitHubScopeRef = in.GitHubScopeRef + out.ProviderName = in.ProviderName + out.MaxRunners = in.MaxRunners + out.MinIdleRunners = in.MinIdleRunners + out.Flavor = in.Flavor + out.OSType = params.OSType(in.OSType) + out.OSArch = params.OSArch(in.OSArch) + out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) + out.Enabled = in.Enabled + out.RunnerBootstrapTimeout = in.RunnerBootstrapTimeout + out.ImageName = in.ImageName + out.ExtraSpecs = in.ExtraSpecs + out.GitHubRunnerGroup = in.GitHubRunnerGroup + out.RunnerPrefix = in.RunnerPrefix + return nil +} + +// Convert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec is an autogenerated conversion function. +func Convert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec(in *v1beta1.PoolSpec, out *PoolSpec, s conversion.Scope) error { + return autoConvert_v1beta1_PoolSpec_To_v1alpha1_PoolSpec(in, out, s) +} + +func autoConvert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus(in *PoolStatus, out *v1beta1.PoolStatus, s conversion.Scope) error { + out.ID = in.ID + out.LongRunningIdleRunners = in.LongRunningIdleRunners + out.Selector = in.Selector + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus is an autogenerated conversion function. +func Convert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus(in *PoolStatus, out *v1beta1.PoolStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_PoolStatus_To_v1beta1_PoolStatus(in, out, s) +} + +func autoConvert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus(in *v1beta1.PoolStatus, out *PoolStatus, s conversion.Scope) error { + out.ID = in.ID + out.LongRunningIdleRunners = in.LongRunningIdleRunners + out.Selector = in.Selector + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus is an autogenerated conversion function. +func Convert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus(in *v1beta1.PoolStatus, out *PoolStatus, s conversion.Scope) error { + return autoConvert_v1beta1_PoolStatus_To_v1alpha1_PoolStatus(in, out, s) +} + +func autoConvert_v1alpha1_Repository_To_v1beta1_Repository(in *Repository, out *v1beta1.Repository, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Repository_To_v1beta1_Repository is an autogenerated conversion function. +func Convert_v1alpha1_Repository_To_v1beta1_Repository(in *Repository, out *v1beta1.Repository, s conversion.Scope) error { + return autoConvert_v1alpha1_Repository_To_v1beta1_Repository(in, out, s) +} + +func autoConvert_v1beta1_Repository_To_v1alpha1_Repository(in *v1beta1.Repository, out *Repository, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Repository_To_v1alpha1_Repository is an autogenerated conversion function. +func Convert_v1beta1_Repository_To_v1alpha1_Repository(in *v1beta1.Repository, out *Repository, s conversion.Scope) error { + return autoConvert_v1beta1_Repository_To_v1alpha1_Repository(in, out, s) +} + +func autoConvert_v1alpha1_RepositoryList_To_v1beta1_RepositoryList(in *RepositoryList, out *v1beta1.RepositoryList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.Repository, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Repository_To_v1beta1_Repository(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_RepositoryList_To_v1beta1_RepositoryList is an autogenerated conversion function. +func Convert_v1alpha1_RepositoryList_To_v1beta1_RepositoryList(in *RepositoryList, out *v1beta1.RepositoryList, s conversion.Scope) error { + return autoConvert_v1alpha1_RepositoryList_To_v1beta1_RepositoryList(in, out, s) +} + +func autoConvert_v1beta1_RepositoryList_To_v1alpha1_RepositoryList(in *v1beta1.RepositoryList, out *RepositoryList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Repository, len(*in)) + for i := range *in { + if err := Convert_v1beta1_Repository_To_v1alpha1_Repository(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_RepositoryList_To_v1alpha1_RepositoryList is an autogenerated conversion function. +func Convert_v1beta1_RepositoryList_To_v1alpha1_RepositoryList(in *v1beta1.RepositoryList, out *RepositoryList, s conversion.Scope) error { + return autoConvert_v1beta1_RepositoryList_To_v1alpha1_RepositoryList(in, out, s) +} + +func autoConvert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in *RepositorySpec, out *v1beta1.RepositorySpec, s conversion.Scope) error { + // WARNING: in.CredentialsName requires manual conversion: does not exist in peer-type + out.Owner = in.Owner + if err := Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(in *v1beta1.RepositorySpec, out *RepositorySpec, s conversion.Scope) error { + // WARNING: in.CredentialsRef requires manual conversion: does not exist in peer-type + out.Owner = in.Owner + if err := Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef(&in.WebhookSecretRef, &out.WebhookSecretRef, s); err != nil { + return err + } + // WARNING: in.PoolBalancerType requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(in *RepositoryStatus, out *v1beta1.RepositoryStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus is an autogenerated conversion function. +func Convert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(in *RepositoryStatus, out *v1beta1.RepositoryStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(in, out, s) +} + +func autoConvert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus(in *v1beta1.RepositoryStatus, out *RepositoryStatus, s conversion.Scope) error { + out.ID = in.ID + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus is an autogenerated conversion function. +func Convert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus(in *v1beta1.RepositoryStatus, out *RepositoryStatus, s conversion.Scope) error { + return autoConvert_v1beta1_RepositoryStatus_To_v1alpha1_RepositoryStatus(in, out, s) +} + +func autoConvert_v1alpha1_Runner_To_v1beta1_Runner(in *Runner, out *v1beta1.Runner, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_Runner_To_v1beta1_Runner is an autogenerated conversion function. +func Convert_v1alpha1_Runner_To_v1beta1_Runner(in *Runner, out *v1beta1.Runner, s conversion.Scope) error { + return autoConvert_v1alpha1_Runner_To_v1beta1_Runner(in, out, s) +} + +func autoConvert_v1beta1_Runner_To_v1alpha1_Runner(in *v1beta1.Runner, out *Runner, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Runner_To_v1alpha1_Runner is an autogenerated conversion function. +func Convert_v1beta1_Runner_To_v1alpha1_Runner(in *v1beta1.Runner, out *Runner, s conversion.Scope) error { + return autoConvert_v1beta1_Runner_To_v1alpha1_Runner(in, out, s) +} + +func autoConvert_v1alpha1_RunnerList_To_v1beta1_RunnerList(in *RunnerList, out *v1beta1.RunnerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1beta1.Runner)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1alpha1_RunnerList_To_v1beta1_RunnerList is an autogenerated conversion function. +func Convert_v1alpha1_RunnerList_To_v1beta1_RunnerList(in *RunnerList, out *v1beta1.RunnerList, s conversion.Scope) error { + return autoConvert_v1alpha1_RunnerList_To_v1beta1_RunnerList(in, out, s) +} + +func autoConvert_v1beta1_RunnerList_To_v1alpha1_RunnerList(in *v1beta1.RunnerList, out *RunnerList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]Runner)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_RunnerList_To_v1alpha1_RunnerList is an autogenerated conversion function. +func Convert_v1beta1_RunnerList_To_v1alpha1_RunnerList(in *v1beta1.RunnerList, out *RunnerList, s conversion.Scope) error { + return autoConvert_v1beta1_RunnerList_To_v1alpha1_RunnerList(in, out, s) +} + +func autoConvert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec(in *RunnerSpec, out *v1beta1.RunnerSpec, s conversion.Scope) error { + return nil +} + +// Convert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec is an autogenerated conversion function. +func Convert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec(in *RunnerSpec, out *v1beta1.RunnerSpec, s conversion.Scope) error { + return autoConvert_v1alpha1_RunnerSpec_To_v1beta1_RunnerSpec(in, out, s) +} + +func autoConvert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec(in *v1beta1.RunnerSpec, out *RunnerSpec, s conversion.Scope) error { + return nil +} + +// Convert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec is an autogenerated conversion function. +func Convert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec(in *v1beta1.RunnerSpec, out *RunnerSpec, s conversion.Scope) error { + return autoConvert_v1beta1_RunnerSpec_To_v1alpha1_RunnerSpec(in, out, s) +} + +func autoConvert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus(in *RunnerStatus, out *v1beta1.RunnerStatus, s conversion.Scope) error { + out.ID = in.ID + out.ProviderID = in.ProviderID + out.AgentID = in.AgentID + out.Name = in.Name + out.OSType = params.OSType(in.OSType) + out.OSName = in.OSName + out.OSVersion = in.OSVersion + out.OSArch = params.OSArch(in.OSArch) + out.Addresses = *(*[]params.Address)(unsafe.Pointer(&in.Addresses)) + out.Status = params.InstanceStatus(in.Status) + out.InstanceStatus = garmparams.RunnerStatus(in.InstanceStatus) + out.PoolID = in.PoolID + out.ProviderFault = in.ProviderFault + out.GitHubRunnerGroup = in.GitHubRunnerGroup + return nil +} + +// Convert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus is an autogenerated conversion function. +func Convert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus(in *RunnerStatus, out *v1beta1.RunnerStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_RunnerStatus_To_v1beta1_RunnerStatus(in, out, s) +} + +func autoConvert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(in *v1beta1.RunnerStatus, out *RunnerStatus, s conversion.Scope) error { + out.ID = in.ID + out.ProviderID = in.ProviderID + out.AgentID = in.AgentID + out.Name = in.Name + out.OSType = params.OSType(in.OSType) + out.OSName = in.OSName + out.OSVersion = in.OSVersion + out.OSArch = params.OSArch(in.OSArch) + out.Addresses = *(*[]params.Address)(unsafe.Pointer(&in.Addresses)) + out.Status = params.InstanceStatus(in.Status) + out.InstanceStatus = garmparams.RunnerStatus(in.InstanceStatus) + out.PoolID = in.PoolID + out.ProviderFault = in.ProviderFault + out.GitHubRunnerGroup = in.GitHubRunnerGroup + return nil +} + +// Convert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus is an autogenerated conversion function. +func Convert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(in *v1beta1.RunnerStatus, out *RunnerStatus, s conversion.Scope) error { + return autoConvert_v1beta1_RunnerStatus_To_v1alpha1_RunnerStatus(in, out, s) +} + +func autoConvert_v1alpha1_SecretRef_To_v1beta1_SecretRef(in *SecretRef, out *v1beta1.SecretRef, s conversion.Scope) error { + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef is an autogenerated conversion function. +func Convert_v1alpha1_SecretRef_To_v1beta1_SecretRef(in *SecretRef, out *v1beta1.SecretRef, s conversion.Scope) error { + return autoConvert_v1alpha1_SecretRef_To_v1beta1_SecretRef(in, out, s) +} + +func autoConvert_v1beta1_SecretRef_To_v1alpha1_SecretRef(in *v1beta1.SecretRef, out *SecretRef, s conversion.Scope) error { + out.Name = in.Name + out.Key = in.Key + return nil +} + +// Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef is an autogenerated conversion function. +func Convert_v1beta1_SecretRef_To_v1alpha1_SecretRef(in *v1beta1.SecretRef, out *SecretRef, s conversion.Scope) error { + return autoConvert_v1beta1_SecretRef_To_v1alpha1_SecretRef(in, out, s) +} From 79185baa46dd9aec0f89619ca10f9c475c35f7e2 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Tue, 17 Sep 2024 13:44:02 +0200 Subject: [PATCH 18/30] feat: add example manual conversion implementation Signed-off-by: Mario Constanti --- api/v1alpha1/organization_conversion.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 api/v1alpha1/organization_conversion.go diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go new file mode 100644 index 00000000..e26c307d --- /dev/null +++ b/api/v1alpha1/organization_conversion.go @@ -0,0 +1,16 @@ +package v1alpha1 + +import ( + v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + apiconversion "k8s.io/apimachinery/pkg/conversion" +) + +func Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s apiconversion.Scope) error { + + err := autoConvert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in, out, s) + if err != nil { + return err + } + + return nil +} From 4ad8377c53f43db4bb5b952160cb4ecf3d7114df Mon Sep 17 00:00:00 2001 From: rthalho Date: Mon, 30 Sep 2024 10:50:00 +0200 Subject: [PATCH 19/30] feat: add manual conversions for enterprise, org and repo --- api/v1alpha1/enterprise_conversion.go | 23 ++++++++++++ api/v1alpha1/organization_conversion.go | 17 ++++++--- api/v1alpha1/repository_conversion.go | 23 ++++++++++++ api/v1alpha1/zz_generated.conversion.go | 50 ++++++++++++------------- api/v1beta1/conversion.go | 12 ++++++ api/v1beta1/groupversion_info.go | 2 +- 6 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 api/v1alpha1/enterprise_conversion.go create mode 100644 api/v1alpha1/repository_conversion.go diff --git a/api/v1alpha1/enterprise_conversion.go b/api/v1alpha1/enterprise_conversion.go new file mode 100644 index 00000000..8f632980 --- /dev/null +++ b/api/v1alpha1/enterprise_conversion.go @@ -0,0 +1,23 @@ +package v1alpha1 + +import ( + "github.com/mercedes-benz/garm-operator/api/v1beta1" + v1 "k8s.io/api/core/v1" + apiconversion "k8s.io/apimachinery/pkg/conversion" +) + +func Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in *EnterpriseSpec, out *v1beta1.EnterpriseSpec, s apiconversion.Scope) error { + out.CredentialsRef = v1.TypedLocalObjectReference{ + Name: in.CredentialsName, + Kind: "GitHubCredentials", + APIGroup: &v1beta1.GroupVersion.Group, + } + + return autoConvert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in, out, s) +} + +func Convert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(in *v1beta1.EnterpriseSpec, out *EnterpriseSpec, s apiconversion.Scope) error { + out.CredentialsName = in.CredentialsRef.Name + + return autoConvert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(in, out, s) +} diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go index e26c307d..566d0d65 100644 --- a/api/v1alpha1/organization_conversion.go +++ b/api/v1alpha1/organization_conversion.go @@ -2,15 +2,22 @@ package v1alpha1 import ( v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + v1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" ) func Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s apiconversion.Scope) error { - - err := autoConvert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in, out, s) - if err != nil { - return err + out.CredentialsRef = v1.TypedLocalObjectReference{ + Name: in.CredentialsName, + Kind: "GitHubCredentials", + APIGroup: &v1beta1.GroupVersion.Group, } - return nil + return autoConvert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in, out, s) +} + +func Convert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(in *v1beta1.OrganizationSpec, out *OrganizationSpec, s apiconversion.Scope) error { + out.CredentialsName = in.CredentialsRef.Name + + return autoConvert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(in, out, s) } diff --git a/api/v1alpha1/repository_conversion.go b/api/v1alpha1/repository_conversion.go new file mode 100644 index 00000000..54501bab --- /dev/null +++ b/api/v1alpha1/repository_conversion.go @@ -0,0 +1,23 @@ +package v1alpha1 + +import ( + "github.com/mercedes-benz/garm-operator/api/v1beta1" + v1 "k8s.io/api/core/v1" + apiconversion "k8s.io/apimachinery/pkg/conversion" +) + +func Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in *RepositorySpec, out *v1beta1.RepositorySpec, s apiconversion.Scope) error { + out.CredentialsRef = v1.TypedLocalObjectReference{ + Name: in.CredentialsName, + Kind: "GitHubCredentials", + APIGroup: &v1beta1.GroupVersion.Group, + } + + return autoConvert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in, out, s) +} + +func Convert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(in *v1beta1.RepositorySpec, out *RepositorySpec, s apiconversion.Scope) error { + out.CredentialsName = in.CredentialsRef.Name + + return autoConvert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(in, out, s) +} diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go index 663f9707..5d140450 100644 --- a/api/v1alpha1/zz_generated.conversion.go +++ b/api/v1alpha1/zz_generated.conversion.go @@ -45,16 +45,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*EnterpriseSpec)(nil), (*v1beta1.EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(a.(*EnterpriseSpec), b.(*v1beta1.EnterpriseSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1beta1.EnterpriseSpec)(nil), (*EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(a.(*v1beta1.EnterpriseSpec), b.(*EnterpriseSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*EnterpriseStatus)(nil), (*v1beta1.EnterpriseStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_EnterpriseStatus_To_v1beta1_EnterpriseStatus(a.(*EnterpriseStatus), b.(*v1beta1.EnterpriseStatus), scope) }); err != nil { @@ -125,11 +115,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1beta1.OrganizationSpec)(nil), (*OrganizationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(a.(*v1beta1.OrganizationSpec), b.(*OrganizationSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*OrganizationStatus)(nil), (*v1beta1.OrganizationStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_OrganizationStatus_To_v1beta1_OrganizationStatus(a.(*OrganizationStatus), b.(*v1beta1.OrganizationStatus), scope) }); err != nil { @@ -200,16 +185,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*RepositorySpec)(nil), (*v1beta1.RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(a.(*RepositorySpec), b.(*v1beta1.RepositorySpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1beta1.RepositorySpec)(nil), (*RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(a.(*v1beta1.RepositorySpec), b.(*RepositorySpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*RepositoryStatus)(nil), (*v1beta1.RepositoryStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_RepositoryStatus_To_v1beta1_RepositoryStatus(a.(*RepositoryStatus), b.(*v1beta1.RepositoryStatus), scope) }); err != nil { @@ -270,11 +245,36 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*EnterpriseSpec)(nil), (*v1beta1.EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(a.(*EnterpriseSpec), b.(*v1beta1.EnterpriseSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*OrganizationSpec)(nil), (*v1beta1.OrganizationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(a.(*OrganizationSpec), b.(*v1beta1.OrganizationSpec), scope) }); err != nil { return err } + if err := s.AddConversionFunc((*RepositorySpec)(nil), (*v1beta1.RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(a.(*RepositorySpec), b.(*v1beta1.RepositorySpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.EnterpriseSpec)(nil), (*EnterpriseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EnterpriseSpec_To_v1alpha1_EnterpriseSpec(a.(*v1beta1.EnterpriseSpec), b.(*EnterpriseSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.OrganizationSpec)(nil), (*OrganizationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_OrganizationSpec_To_v1alpha1_OrganizationSpec(a.(*v1beta1.OrganizationSpec), b.(*OrganizationSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.RepositorySpec)(nil), (*RepositorySpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RepositorySpec_To_v1alpha1_RepositorySpec(a.(*v1beta1.RepositorySpec), b.(*RepositorySpec), scope) + }); err != nil { + return err + } return nil } diff --git a/api/v1beta1/conversion.go b/api/v1beta1/conversion.go index 38269f7c..5928d54f 100644 --- a/api/v1beta1/conversion.go +++ b/api/v1beta1/conversion.go @@ -3,5 +3,17 @@ package v1beta1 // Hub marks this type as a conversion hub. func (*Pool) Hub() {} +// Hub marks this type as a conversion hub. +func (*Image) Hub() {} + +// Hub marks this type as a conversion hub. +func (*Runner) Hub() {} + +// Hub marks this type as a conversion hub. +func (*Enterprise) Hub() {} + // Hub marks this type as a conversion hub. func (*Organization) Hub() {} + +// Hub marks this type as a conversion hub. +func (*Repository) Hub() {} diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go index 0a0621df..da2b373c 100644 --- a/api/v1beta1/groupversion_info.go +++ b/api/v1beta1/groupversion_info.go @@ -12,7 +12,7 @@ import ( var ( // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "garm-operator.mercedes-benz.com", Version: "v1alpha1"} + GroupVersion = schema.GroupVersion{Group: "garm-operator.mercedes-benz.com", Version: "v1beta1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} From fc51e77a63d15b358305d13defe1942e9f4d0a98 Mon Sep 17 00:00:00 2001 From: rthalho Date: Mon, 30 Sep 2024 10:50:15 +0200 Subject: [PATCH 20/30] fix: v1beta1 tests --- api/v1beta1/pool_types_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/api/v1beta1/pool_types_test.go b/api/v1beta1/pool_types_test.go index 84255328..2facfd6a 100644 --- a/api/v1beta1/pool_types_test.go +++ b/api/v1beta1/pool_types_test.go @@ -3,6 +3,7 @@ package v1beta1 import ( + "github.com/mercedes-benz/garm-operator/pkg/filter" "testing" corev1 "k8s.io/api/core/v1" @@ -17,7 +18,7 @@ func TestPoolList_FilterByFields(t *testing.T) { Items []Pool } type args struct { - predicates []Predicate + predicates []filter.Predicate[Pool] } tests := []struct { name string @@ -68,7 +69,7 @@ func TestPoolList_FilterByFields(t *testing.T) { }, }, args: args{ - predicates: []Predicate{ + predicates: []filter.Predicate[Pool]{ MatchesImage("ubuntu-2204"), MatchesFlavor("large"), MatchesProvider("openstack"), @@ -120,7 +121,7 @@ func TestPoolList_FilterByFields(t *testing.T) { }, }, args: args{ - predicates: []Predicate{ + predicates: []filter.Predicate[Pool]{ MatchesImage("ubuntu-2404"), MatchesFlavor("large"), MatchesProvider("openstack"), @@ -138,9 +139,9 @@ func TestPoolList_FilterByFields(t *testing.T) { Items: tt.fields.Items, } - p.FilterByFields(tt.args.predicates...) + filteredItems := filter.Match(p.Items, tt.args.predicates...) - if len(p.Items) != tt.length { + if len(filteredItems) != tt.length { t.Errorf("FilterByFields() = %v, want %v", len(p.Items), tt.length) } }) From 17df55f74adaafe29764f615f11b5b353589cfd5 Mon Sep 17 00:00:00 2001 From: rthalho Date: Tue, 1 Oct 2024 08:46:07 +0200 Subject: [PATCH 21/30] fix: remove pool adoption and always create pool --- internal/controller/pool_controller.go | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/internal/controller/pool_controller.go b/internal/controller/pool_controller.go index 10d815e3..3ccc8df2 100644 --- a/internal/controller/pool_controller.go +++ b/internal/controller/pool_controller.go @@ -124,22 +124,7 @@ func (r *PoolReconciler) reconcileCreate(ctx context.Context, garmClient garmCli } conditions.MarkTrue(pool, conditions.ImageReference, conditions.FetchingImageRefSuccessReason, "Successfully fetched Image CR Ref") - // check if there is already a pool with the same spec on garm side - matchingGarmPool, err := poolUtil.GetGarmPoolBySpecs(ctx, garmClient, pool, image, gitHubScopeRef) - if err != nil { - return r.handleUpdateError(ctx, pool, err, conditions.ReconcileErrorReason) - } - - if matchingGarmPool != nil { - log.Info("Found garm pool with matching specs, syncing IDs", "garmID", matchingGarmPool.ID) - event.Creating(r.Recorder, pool, fmt.Sprintf("found garm pool with matching specs, syncing IDs: %s", matchingGarmPool.ID)) - - pool.Status.ID = matchingGarmPool.ID - pool.Status.LongRunningIdleRunners = matchingGarmPool.MinIdleRunners - return r.handleSuccessfulUpdate(ctx, pool) - } - - // create new pool in garm + // always create new pool in garm garmPool, err := poolUtil.CreatePool(ctx, garmClient, pool, image, gitHubScopeRef) if err != nil { return r.handleUpdateError(ctx, pool, fmt.Errorf("failed creating pool %s: %s", pool.Name, err.Error()), conditions.ReconcileErrorReason) From 64f6d2f81acae4900481322d75f5a0314c91fe48 Mon Sep 17 00:00:00 2001 From: rthalho Date: Mon, 7 Oct 2024 09:05:40 +0200 Subject: [PATCH 22/30] fix: webhooks and add missing conversions --- PROJECT | 16 ++++++++ Tiltfile | 2 +- api/v1alpha1/enterprise_conversion.go | 11 ++++++ api/v1alpha1/enterprise_types.go | 3 +- api/v1alpha1/enterprise_webhook.go | 17 ++++++++ api/v1alpha1/image_conversion.go | 16 ++++++++ api/v1alpha1/organization_conversion.go | 9 +++++ api/v1alpha1/organization_webhook.go | 17 ++++++++ api/v1alpha1/pool_conversion.go | 16 ++++++++ api/v1alpha1/pool_webhook.go | 19 --------- api/v1alpha1/repository_conversion.go | 11 ++++++ api/v1alpha1/runner_conversion.go | 16 ++++++++ api/v1alpha1/runner_webhook.go | 17 ++++++++ cmd/main.go | 52 ++++++++++++++++++------- 14 files changed, 186 insertions(+), 36 deletions(-) create mode 100644 api/v1alpha1/enterprise_webhook.go create mode 100644 api/v1alpha1/image_conversion.go create mode 100644 api/v1alpha1/organization_webhook.go create mode 100644 api/v1alpha1/pool_conversion.go create mode 100644 api/v1alpha1/runner_conversion.go create mode 100644 api/v1alpha1/runner_webhook.go diff --git a/PROJECT b/PROJECT index 2c02ba99..24b97084 100644 --- a/PROJECT +++ b/PROJECT @@ -17,6 +17,9 @@ resources: kind: Enterprise path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true @@ -26,6 +29,11 @@ resources: kind: Pool path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true @@ -35,6 +43,9 @@ resources: kind: Organization path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true @@ -44,6 +55,7 @@ resources: path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 webhooks: + conversion: true defaulting: true validation: true webhookVersion: v1 @@ -57,6 +69,7 @@ resources: path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 webhooks: + conversion: true defaulting: true validation: true webhookVersion: v1 @@ -69,6 +82,9 @@ resources: kind: Runner path: github.com/mercedes-benz/garm-operator/api/v1alpha1 version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true diff --git a/Tiltfile b/Tiltfile index 7cf3cbba..26193ba2 100644 --- a/Tiltfile +++ b/Tiltfile @@ -10,7 +10,7 @@ allow_k8s_contexts('kind-garm-operator') # as the plugin has already well written readiness checks we can use it to wait for deploy_cert_manager( kind_cluster_name='garm-operator', # just for security reasons ;-) - version='v1.12.0' # the version of cert-manager to deploy + version='v1.15.3' # the version of cert-manager to deploy ) # mode could be either 'local' or 'debug' diff --git a/api/v1alpha1/enterprise_conversion.go b/api/v1alpha1/enterprise_conversion.go index 8f632980..05eff779 100644 --- a/api/v1alpha1/enterprise_conversion.go +++ b/api/v1alpha1/enterprise_conversion.go @@ -4,8 +4,19 @@ import ( "github.com/mercedes-benz/garm-operator/api/v1beta1" v1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" ) +var _ conversion.Convertible = &Enterprise{} + +func (e *Enterprise) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Enterprise_To_v1beta1_Enterprise(e, dstRaw.(*v1beta1.Enterprise), nil) +} + +func (e *Enterprise) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Enterprise_To_v1alpha1_Enterprise(dstRaw.(*v1beta1.Enterprise), e, nil) +} + func Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in *EnterpriseSpec, out *v1beta1.EnterpriseSpec, s apiconversion.Scope) error { out.CredentialsRef = v1.TypedLocalObjectReference{ Name: in.CredentialsName, diff --git a/api/v1alpha1/enterprise_types.go b/api/v1alpha1/enterprise_types.go index 976e4db4..bf597800 100644 --- a/api/v1alpha1/enterprise_types.go +++ b/api/v1alpha1/enterprise_types.go @@ -3,9 +3,8 @@ package v1alpha1 import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/mercedes-benz/garm-operator/pkg/conditions" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EnterpriseSpec defines the desired state of Enterprise diff --git a/api/v1alpha1/enterprise_webhook.go b/api/v1alpha1/enterprise_webhook.go new file mode 100644 index 00000000..f9092da6 --- /dev/null +++ b/api/v1alpha1/enterprise_webhook.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +// log is for logging in this package. +var enterpriselog = logf.Log.WithName("enterprise-resource") + +func (r *Enterprise) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha1/image_conversion.go b/api/v1alpha1/image_conversion.go new file mode 100644 index 00000000..e0b380d9 --- /dev/null +++ b/api/v1alpha1/image_conversion.go @@ -0,0 +1,16 @@ +package v1alpha1 + +import ( + "github.com/mercedes-benz/garm-operator/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Convertible = &Image{} + +func (i *Image) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Image_To_v1beta1_Image(i, dstRaw.(*v1beta1.Image), nil) +} + +func (i *Image) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Image_To_v1alpha1_Image(dstRaw.(*v1beta1.Image), i, nil) +} diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go index 566d0d65..fd97199f 100644 --- a/api/v1alpha1/organization_conversion.go +++ b/api/v1alpha1/organization_conversion.go @@ -4,8 +4,17 @@ import ( v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" v1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" ) +func (o *Organization) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Organization_To_v1beta1_Organization(o, dstRaw.(*v1beta1.Organization), nil) +} + +func (o *Organization) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Organization_To_v1alpha1_Organization(dstRaw.(*v1beta1.Organization), o, nil) +} + func Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s apiconversion.Scope) error { out.CredentialsRef = v1.TypedLocalObjectReference{ Name: in.CredentialsName, diff --git a/api/v1alpha1/organization_webhook.go b/api/v1alpha1/organization_webhook.go new file mode 100644 index 00000000..4172b759 --- /dev/null +++ b/api/v1alpha1/organization_webhook.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +// log is for logging in this package. +var organizationlog = logf.Log.WithName("organization-resource") + +func (r *Organization) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/api/v1alpha1/pool_conversion.go b/api/v1alpha1/pool_conversion.go new file mode 100644 index 00000000..9a115ff1 --- /dev/null +++ b/api/v1alpha1/pool_conversion.go @@ -0,0 +1,16 @@ +package v1alpha1 + +import ( + "github.com/mercedes-benz/garm-operator/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Convertible = &Pool{} + +func (p *Pool) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Pool_To_v1beta1_Pool(p, dstRaw.(*v1beta1.Pool), nil) +} + +func (p *Pool) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Pool_To_v1alpha1_Pool(dstRaw.(*v1beta1.Pool), p, nil) +} diff --git a/api/v1alpha1/pool_webhook.go b/api/v1alpha1/pool_webhook.go index 2667997f..9fae201c 100644 --- a/api/v1alpha1/pool_webhook.go +++ b/api/v1alpha1/pool_webhook.go @@ -3,7 +3,6 @@ package v1alpha1 import ( - "context" "encoding/json" "fmt" "reflect" @@ -39,7 +38,6 @@ var _ webhook.Validator = &Pool{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (p *Pool) ValidateCreate() (admission.Warnings, error) { poollog.Info("validate create", "name", p.Name) - ctx := context.TODO() if err := p.validateExtraSpec(); err != nil { return nil, apierrors.NewInvalid(schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, @@ -48,23 +46,6 @@ func (p *Pool) ValidateCreate() (admission.Warnings, error) { ) } - poolImage, err := p.GetImageCR(ctx, c) - if err != nil { - poollog.Error(err, "cannot fetch Image", "error", err) - return nil, nil - } - - duplicate, duplicateName, err := p.CheckDuplicate(ctx, c, poolImage) - if err != nil { - poollog.Error(err, "error checking for duplicate", "error", err) - return nil, nil - } - - if duplicate { - err := fmt.Sprintf("pool with same image, flavor, provider and github scope already exists: %s", duplicateName) - return nil, apierrors.NewBadRequest(err) - } - return nil, nil } diff --git a/api/v1alpha1/repository_conversion.go b/api/v1alpha1/repository_conversion.go index 54501bab..9b344b84 100644 --- a/api/v1alpha1/repository_conversion.go +++ b/api/v1alpha1/repository_conversion.go @@ -4,8 +4,19 @@ import ( "github.com/mercedes-benz/garm-operator/api/v1beta1" v1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" + "sigs.k8s.io/controller-runtime/pkg/conversion" ) +var _ conversion.Convertible = &Repository{} + +func (r *Repository) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Repository_To_v1beta1_Repository(r, dstRaw.(*v1beta1.Repository), nil) +} + +func (r *Repository) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Repository_To_v1alpha1_Repository(dstRaw.(*v1beta1.Repository), r, nil) +} + func Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in *RepositorySpec, out *v1beta1.RepositorySpec, s apiconversion.Scope) error { out.CredentialsRef = v1.TypedLocalObjectReference{ Name: in.CredentialsName, diff --git a/api/v1alpha1/runner_conversion.go b/api/v1alpha1/runner_conversion.go new file mode 100644 index 00000000..57f6af2d --- /dev/null +++ b/api/v1alpha1/runner_conversion.go @@ -0,0 +1,16 @@ +package v1alpha1 + +import ( + "github.com/mercedes-benz/garm-operator/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Convertible = &Runner{} + +func (r *Runner) ConvertTo(dstRaw conversion.Hub) error { + return Convert_v1alpha1_Runner_To_v1beta1_Runner(r, dstRaw.(*v1beta1.Runner), nil) +} + +func (r *Runner) ConvertFrom(dstRaw conversion.Hub) error { + return Convert_v1beta1_Runner_To_v1alpha1_Runner(dstRaw.(*v1beta1.Runner), r, nil) +} diff --git a/api/v1alpha1/runner_webhook.go b/api/v1alpha1/runner_webhook.go new file mode 100644 index 00000000..f578531e --- /dev/null +++ b/api/v1alpha1/runner_webhook.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +package v1alpha1 + +import ( + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +// log is for logging in this package. +var runnerlog = logf.Log.WithName("runner-resource") + +func (r *Runner) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/cmd/main.go b/cmd/main.go index 2d4ef825..eb3db37e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,14 +5,13 @@ package main import ( "context" "fmt" - "log" - "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2/textlogger" + "log" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -153,18 +152,6 @@ func run() error { return fmt.Errorf("unable to create controller Pool: %w", err) } - if err = (&garmoperatorv1alpha1.Pool{}).SetupWebhookWithManager(mgr); err != nil { - return fmt.Errorf("unable to create webhook Pool: %w", err) - } - - if err = (&garmoperatorv1alpha1.Image{}).SetupWebhookWithManager(mgr); err != nil { - return fmt.Errorf("unable to create webhook Image: %w", err) - } - - if err = (&garmoperatorv1alpha1.Repository{}).SetupWebhookWithManager(mgr); err != nil { - return fmt.Errorf("unable to create webhook Repository: %w", err) - } - if err = (&garmcontroller.OrganizationReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), @@ -234,6 +221,43 @@ func run() error { }).SetupWithManager(mgr); err != nil { return fmt.Errorf("unable to create controller GitHubCredentials: %w", err) } + + // webhooks + if err = (&garmoperatorv1alpha1.Enterprise{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Enterprise: %w", err) + } + + if err = (&garmoperatorv1alpha1.Organization{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Organization: %w", err) + } + + if err = (&garmoperatorv1alpha1.Pool{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Pool: %w", err) + } + + if err = (&garmoperatorv1beta1.Pool{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Pool: %w", err) + } + + if err = (&garmoperatorv1alpha1.Image{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Image: %w", err) + } + + if err = (&garmoperatorv1beta1.Image{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Image: %w", err) + } + + if err = (&garmoperatorv1alpha1.Repository{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Repository: %w", err) + } + + if err = (&garmoperatorv1beta1.Repository{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Repository: %w", err) + } + + if err = (&garmoperatorv1alpha1.Runner{}).SetupWebhookWithManager(mgr); err != nil { + return fmt.Errorf("unable to create webhook Runner: %w", err) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { From d3c3dc46b9828cce667dce53f7477b46c5b28ccf Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Wed, 16 Oct 2024 17:28:42 +0200 Subject: [PATCH 23/30] fix linter findings and build issues Signed-off-by: Mario Constanti --- .golangci.yaml | 8 +++ api/v1alpha1/enterprise_conversion.go | 7 ++- api/v1alpha1/enterprise_types.go | 3 +- api/v1alpha1/image_conversion.go | 3 +- api/v1alpha1/organization_conversion.go | 7 ++- api/v1alpha1/pool_conversion.go | 3 +- api/v1alpha1/repository_conversion.go | 7 ++- api/v1alpha1/runner_conversion.go | 3 +- api/v1beta1/pool_helper.go | 1 + api/v1beta1/pool_types_test.go | 3 +- cmd/main.go | 3 +- .../garmserverconfig_controller_test.go | 13 +++-- .../githubendpoint_controller_test.go | 55 ++++++++++--------- pkg/pools/pools.go | 1 + pkg/secret/secret.go | 3 +- 15 files changed, 72 insertions(+), 48 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index cce8715c..71625552 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -65,3 +65,11 @@ linters-settings: gosec: excludes: - G115 # Potential integer overflow when converting between integer types + +issues: + exclude-rules: + # exclude revive warnings for generated code + - linters: + - revive + path: 'api/v1alpha1/(.+)_conversion\.go' + text: "var-naming: don't use underscores in Go names; func (.+)" diff --git a/api/v1alpha1/enterprise_conversion.go b/api/v1alpha1/enterprise_conversion.go index 05eff779..3d6048d7 100644 --- a/api/v1alpha1/enterprise_conversion.go +++ b/api/v1alpha1/enterprise_conversion.go @@ -1,10 +1,11 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/api/v1beta1" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/mercedes-benz/garm-operator/api/v1beta1" ) var _ conversion.Convertible = &Enterprise{} @@ -18,7 +19,7 @@ func (e *Enterprise) ConvertFrom(dstRaw conversion.Hub) error { } func Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in *EnterpriseSpec, out *v1beta1.EnterpriseSpec, s apiconversion.Scope) error { - out.CredentialsRef = v1.TypedLocalObjectReference{ + out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, Kind: "GitHubCredentials", APIGroup: &v1beta1.GroupVersion.Group, diff --git a/api/v1alpha1/enterprise_types.go b/api/v1alpha1/enterprise_types.go index bf597800..976e4db4 100644 --- a/api/v1alpha1/enterprise_types.go +++ b/api/v1alpha1/enterprise_types.go @@ -3,8 +3,9 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/pkg/conditions" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/mercedes-benz/garm-operator/pkg/conditions" ) // EnterpriseSpec defines the desired state of Enterprise diff --git a/api/v1alpha1/image_conversion.go b/api/v1alpha1/image_conversion.go index e0b380d9..14988dad 100644 --- a/api/v1alpha1/image_conversion.go +++ b/api/v1alpha1/image_conversion.go @@ -1,8 +1,9 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/mercedes-benz/garm-operator/api/v1beta1" ) var _ conversion.Convertible = &Image{} diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go index fd97199f..1d48104b 100644 --- a/api/v1alpha1/organization_conversion.go +++ b/api/v1alpha1/organization_conversion.go @@ -1,10 +1,11 @@ package v1alpha1 import ( - v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" + + v1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" ) func (o *Organization) ConvertTo(dstRaw conversion.Hub) error { @@ -16,7 +17,7 @@ func (o *Organization) ConvertFrom(dstRaw conversion.Hub) error { } func Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s apiconversion.Scope) error { - out.CredentialsRef = v1.TypedLocalObjectReference{ + out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, Kind: "GitHubCredentials", APIGroup: &v1beta1.GroupVersion.Group, diff --git a/api/v1alpha1/pool_conversion.go b/api/v1alpha1/pool_conversion.go index 9a115ff1..57a32d7d 100644 --- a/api/v1alpha1/pool_conversion.go +++ b/api/v1alpha1/pool_conversion.go @@ -1,8 +1,9 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/mercedes-benz/garm-operator/api/v1beta1" ) var _ conversion.Convertible = &Pool{} diff --git a/api/v1alpha1/repository_conversion.go b/api/v1alpha1/repository_conversion.go index 9b344b84..c7351538 100644 --- a/api/v1alpha1/repository_conversion.go +++ b/api/v1alpha1/repository_conversion.go @@ -1,10 +1,11 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/api/v1beta1" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" apiconversion "k8s.io/apimachinery/pkg/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/mercedes-benz/garm-operator/api/v1beta1" ) var _ conversion.Convertible = &Repository{} @@ -18,7 +19,7 @@ func (r *Repository) ConvertFrom(dstRaw conversion.Hub) error { } func Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in *RepositorySpec, out *v1beta1.RepositorySpec, s apiconversion.Scope) error { - out.CredentialsRef = v1.TypedLocalObjectReference{ + out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, Kind: "GitHubCredentials", APIGroup: &v1beta1.GroupVersion.Group, diff --git a/api/v1alpha1/runner_conversion.go b/api/v1alpha1/runner_conversion.go index 57f6af2d..cf45ca26 100644 --- a/api/v1alpha1/runner_conversion.go +++ b/api/v1alpha1/runner_conversion.go @@ -1,8 +1,9 @@ package v1alpha1 import ( - "github.com/mercedes-benz/garm-operator/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/mercedes-benz/garm-operator/api/v1beta1" ) var _ conversion.Convertible = &Runner{} diff --git a/api/v1beta1/pool_helper.go b/api/v1beta1/pool_helper.go index 28d797b5..a8fff800 100644 --- a/api/v1beta1/pool_helper.go +++ b/api/v1beta1/pool_helper.go @@ -4,6 +4,7 @@ package v1beta1 import ( "context" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/api/v1beta1/pool_types_test.go b/api/v1beta1/pool_types_test.go index 2facfd6a..72b62795 100644 --- a/api/v1beta1/pool_types_test.go +++ b/api/v1beta1/pool_types_test.go @@ -3,12 +3,13 @@ package v1beta1 import ( - "github.com/mercedes-benz/garm-operator/pkg/filter" "testing" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" + + "github.com/mercedes-benz/garm-operator/pkg/filter" ) func TestPoolList_FilterByFields(t *testing.T) { diff --git a/cmd/main.go b/cmd/main.go index eb3db37e..7bbbed05 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,13 +5,14 @@ package main import ( "context" "fmt" + "log" + "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/klog/v2/textlogger" - "log" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/controller" diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go index 049d9cc1..dd1189dc 100644 --- a/internal/controller/garmserverconfig_controller_test.go +++ b/internal/controller/garmserverconfig_controller_test.go @@ -8,18 +8,19 @@ import ( "github.com/cloudbase/garm/client/controller_info" "github.com/cloudbase/garm/params" "github.com/google/uuid" - garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" - "github.com/mercedes-benz/garm-operator/pkg/client/mock" - "github.com/mercedes-benz/garm-operator/pkg/conditions" "go.uber.org/mock/gomock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client/fake" + + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" + "github.com/mercedes-benz/garm-operator/pkg/client/mock" + "github.com/mercedes-benz/garm-operator/pkg/conditions" ) -var controllerId = uuid.New() +var controllerID = uuid.New() func TestGarmServerConfig_reconcile(t *testing.T) { mockCtrl := gomock.NewController(t) @@ -57,7 +58,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { WebhookURL: "http://garm-server.garm-server.svc:9997/api/v1/webhook", }, Status: garmoperatorv1beta1.GarmServerConfigStatus{ - ControllerID: controllerId.String(), + ControllerID: controllerID.String(), Hostname: "garm.server.com", MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", @@ -71,7 +72,7 @@ func TestGarmServerConfig_reconcile(t *testing.T) { wantErr: false, expectGarmRequest: func(m *mock.MockControllerClientMockRecorder) { m.GetControllerInfo().Return(&controller_info.ControllerInfoOK{Payload: params.ControllerInfo{ - ControllerID: controllerId, + ControllerID: controllerID, Hostname: "garm.server.com", MetadataURL: "http://garm-server.garm-server.svc:9997/api/v1/metadata", CallbackURL: "http://garm-server.garm-server.svc:9997/api/v1/callbacks", diff --git a/internal/controller/githubendpoint_controller_test.go b/internal/controller/githubendpoint_controller_test.go index 26892b31..4e75244f 100644 --- a/internal/controller/githubendpoint_controller_test.go +++ b/internal/controller/githubendpoint_controller_test.go @@ -4,12 +4,11 @@ package controller import ( "context" - "github.com/cloudbase/garm/client/endpoints" - "github.com/mercedes-benz/garm-operator/pkg/util" "reflect" "testing" "time" + "github.com/cloudbase/garm/client/endpoints" "github.com/cloudbase/garm/params" "go.uber.org/mock/gomock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -23,6 +22,7 @@ import ( "github.com/mercedes-benz/garm-operator/pkg/client/key" "github.com/mercedes-benz/garm-operator/pkg/client/mock" "github.com/mercedes-benz/garm-operator/pkg/conditions" + "github.com/mercedes-benz/garm-operator/pkg/util" ) func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { @@ -84,14 +84,15 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { }, }, expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { - m.GetEndpoint(endpoints.NewGetGithubEndpointParams().WithName("existing-github-endpoint")).Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ - Name: "existing-github-endpoint", - Description: "existing-github-endpoint", - APIBaseURL: "https://api.github.com", - UploadBaseURL: "https://uploads.github.com", - BaseURL: "https://github.com", - CACertBundle: nil, - }, + m.GetEndpoint(endpoints.NewGetGithubEndpointParams().WithName("existing-github-endpoint")).Return(&endpoints.GetGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, }, nil) m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). WithName("existing-github-endpoint"). @@ -174,14 +175,15 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { m.GetEndpoint(endpoints.NewGetGithubEndpointParams(). WithName("existing-github-endpoint")). - Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ - Name: "existing-github-endpoint", - Description: "existing-github-endpoint", - APIBaseURL: "https://api.github.com", - UploadBaseURL: "https://uploads.github.com", - BaseURL: "https://github.com", - CACertBundle: nil, - }, + Return(&endpoints.GetGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, }, nil) m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). WithName("existing-github-endpoint"). @@ -330,14 +332,15 @@ func TestGitHubEndpointReconciler_reconcileNormal(t *testing.T) { expectGarmRequest: func(m *mock.MockEndpointClientMockRecorder) { m.GetEndpoint(endpoints.NewGetGithubEndpointParams(). WithName("existing-github-endpoint")). - Return(&endpoints.GetGithubEndpointOK{Payload: params.GithubEndpoint{ - Name: "existing-github-endpoint", - Description: "existing-github-endpoint", - APIBaseURL: "https://api.github.com", - UploadBaseURL: "https://uploads.github.com", - BaseURL: "https://github.com", - CACertBundle: nil, - }, + Return(&endpoints.GetGithubEndpointOK{ + Payload: params.GithubEndpoint{ + Name: "existing-github-endpoint", + Description: "existing-github-endpoint", + APIBaseURL: "https://api.github.com", + UploadBaseURL: "https://uploads.github.com", + BaseURL: "https://github.com", + CACertBundle: nil, + }, }, nil) m.UpdateEndpoint(endpoints.NewUpdateGithubEndpointParams(). WithName("existing-github-endpoint"). diff --git a/pkg/pools/pools.go b/pkg/pools/pools.go index 69e9f40a..76484c54 100644 --- a/pkg/pools/pools.go +++ b/pkg/pools/pools.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/cloudbase/garm/client/enterprises" "github.com/cloudbase/garm/client/organizations" "github.com/cloudbase/garm/client/pools" diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index 32b6b100..9c24f973 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -5,11 +5,12 @@ package secret import ( "context" "fmt" - garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" + + garmoperatorv1beta1 "github.com/mercedes-benz/garm-operator/api/v1beta1" ) // FetchRef fetches a secret for a given garmoperatorv1alpha1.SecretRef and namespace From e76d57dffda80672e76cf9c07ec186dab5937f2f Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 07:11:16 +0200 Subject: [PATCH 24/30] chore: add license header Signed-off-by: Mario Constanti --- api/v1alpha1/doc.go | 2 ++ api/v1alpha1/enterprise_conversion.go | 1 + api/v1alpha1/image_conversion.go | 1 + api/v1alpha1/organization_conversion.go | 1 + api/v1alpha1/pool_conversion.go | 1 + api/v1alpha1/repository_conversion.go | 1 + api/v1alpha1/runner_conversion.go | 1 + api/v1beta1/conversion.go | 1 + hack/verify-license.sh | 2 +- internal/controller/garmserverconfig_controller_test.go | 1 + pkg/client/controller.go | 1 + pkg/client/credentials.go | 1 + pkg/client/endpoint.go | 1 + pkg/util/util.go | 1 + 14 files changed, 15 insertions(+), 1 deletion(-) diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go index 4d89826d..4d472081 100644 --- a/api/v1alpha1/doc.go +++ b/api/v1alpha1/doc.go @@ -1,2 +1,4 @@ +// SPDX-License-Identifier: MIT + // +k8s:conversion-gen=github.com/mercedes-benz/garm-operator/api/v1beta1 package v1alpha1 diff --git a/api/v1alpha1/enterprise_conversion.go b/api/v1alpha1/enterprise_conversion.go index 3d6048d7..d4208d1d 100644 --- a/api/v1alpha1/enterprise_conversion.go +++ b/api/v1alpha1/enterprise_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1alpha1/image_conversion.go b/api/v1alpha1/image_conversion.go index 14988dad..3c42aef4 100644 --- a/api/v1alpha1/image_conversion.go +++ b/api/v1alpha1/image_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go index 1d48104b..ebde5a57 100644 --- a/api/v1alpha1/organization_conversion.go +++ b/api/v1alpha1/organization_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1alpha1/pool_conversion.go b/api/v1alpha1/pool_conversion.go index 57a32d7d..2996486a 100644 --- a/api/v1alpha1/pool_conversion.go +++ b/api/v1alpha1/pool_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1alpha1/repository_conversion.go b/api/v1alpha1/repository_conversion.go index c7351538..51eba50a 100644 --- a/api/v1alpha1/repository_conversion.go +++ b/api/v1alpha1/repository_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1alpha1/runner_conversion.go b/api/v1alpha1/runner_conversion.go index cf45ca26..3809d8b4 100644 --- a/api/v1alpha1/runner_conversion.go +++ b/api/v1alpha1/runner_conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1alpha1 import ( diff --git a/api/v1beta1/conversion.go b/api/v1beta1/conversion.go index 5928d54f..8d39b03c 100644 --- a/api/v1beta1/conversion.go +++ b/api/v1beta1/conversion.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package v1beta1 // Hub marks this type as a conversion hub. diff --git a/hack/verify-license.sh b/hack/verify-license.sh index 2e369415..d1b20322 100755 --- a/hack/verify-license.sh +++ b/hack/verify-license.sh @@ -19,7 +19,7 @@ HEADER="SPDX-License-Identifier: MIT" all_files=() export IFS=$'\n' -while IFS='' read -r line; do all_error_files+=("$line"); done < <(git ls-files | grep -v -E '\.excalidraw$|\.jpeg$|\.jpg$|\.gif$|\.png$|\.yaml$|^(go.sum|LICENSE|hack/boilerplate.go.txt)$|.*zz_generated.deepcopy.go$') +while IFS='' read -r line; do all_error_files+=("$line"); done < <(git ls-files | grep -v -E '\.excalidraw$|\.jpeg$|\.jpg$|\.gif$|\.png$|\.yaml$|^(go.sum|LICENSE|PROJECT|hack/boilerplate.go.txt)$|.*zz_generated.deepcopy.go$|.*zz_generated.conversion.go$') unset IFS errors=() diff --git a/internal/controller/garmserverconfig_controller_test.go b/internal/controller/garmserverconfig_controller_test.go index dd1189dc..428f5504 100644 --- a/internal/controller/garmserverconfig_controller_test.go +++ b/internal/controller/garmserverconfig_controller_test.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package controller import ( diff --git a/pkg/client/controller.go b/pkg/client/controller.go index 99b47eea..ba493810 100644 --- a/pkg/client/controller.go +++ b/pkg/client/controller.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package client import ( diff --git a/pkg/client/credentials.go b/pkg/client/credentials.go index ea6cd362..6118fc14 100644 --- a/pkg/client/credentials.go +++ b/pkg/client/credentials.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package client import ( diff --git a/pkg/client/endpoint.go b/pkg/client/endpoint.go index 975c698b..29fe1962 100644 --- a/pkg/client/endpoint.go +++ b/pkg/client/endpoint.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package client import ( diff --git a/pkg/util/util.go b/pkg/util/util.go index a7000633..0960a729 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package util func StringPtr(s string) *string { From 528e8252c60061e2237b06de24dc8027d85cb036 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 07:34:45 +0200 Subject: [PATCH 25/30] fix: remove unused logger --- api/v1alpha1/enterprise_webhook.go | 4 ---- api/v1alpha1/organization_webhook.go | 4 ---- api/v1alpha1/runner_webhook.go | 4 ---- 3 files changed, 12 deletions(-) diff --git a/api/v1alpha1/enterprise_webhook.go b/api/v1alpha1/enterprise_webhook.go index f9092da6..28bb2cd9 100644 --- a/api/v1alpha1/enterprise_webhook.go +++ b/api/v1alpha1/enterprise_webhook.go @@ -4,12 +4,8 @@ package v1alpha1 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var enterpriselog = logf.Log.WithName("enterprise-resource") - func (r *Enterprise) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/api/v1alpha1/organization_webhook.go b/api/v1alpha1/organization_webhook.go index 4172b759..612f5213 100644 --- a/api/v1alpha1/organization_webhook.go +++ b/api/v1alpha1/organization_webhook.go @@ -4,12 +4,8 @@ package v1alpha1 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var organizationlog = logf.Log.WithName("organization-resource") - func (r *Organization) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/api/v1alpha1/runner_webhook.go b/api/v1alpha1/runner_webhook.go index f578531e..f417ba93 100644 --- a/api/v1alpha1/runner_webhook.go +++ b/api/v1alpha1/runner_webhook.go @@ -4,12 +4,8 @@ package v1alpha1 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var runnerlog = logf.Log.WithName("runner-resource") - func (r *Runner) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). From 00bc1106020e89f8a55bf3a41556fa2b1d3103a6 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 07:38:24 +0200 Subject: [PATCH 26/30] fix: remove nonexisting api resources Signed-off-by: Mario Constanti --- PROJECT | 327 ++++++++---------- ...rm-operator_v1alpha1_garmserverconfig.yaml | 14 - ...m-operator_v1alpha1_githubcredentials.yaml | 32 -- ...garm-operator_v1alpha1_githubendpoint.yaml | 16 - .../samples/garm-operator_v1beta1_runner.yaml | 12 - config/samples/kustomization.yaml | 23 +- 6 files changed, 159 insertions(+), 265 deletions(-) delete mode 100644 config/samples/garm-operator_v1alpha1_garmserverconfig.yaml delete mode 100644 config/samples/garm-operator_v1alpha1_githubcredentials.yaml delete mode 100644 config/samples/garm-operator_v1alpha1_githubendpoint.yaml delete mode 100644 config/samples/garm-operator_v1beta1_runner.yaml diff --git a/PROJECT b/PROJECT index 24b97084..f9c10730 100644 --- a/PROJECT +++ b/PROJECT @@ -4,184 +4,157 @@ # More info: https://book.kubebuilder.io/reference/project-config.html domain: mercedes-benz.com layout: -- go.kubebuilder.io/v4 + - go.kubebuilder.io/v4 projectName: garm-operator repo: github.com/mercedes-benz/garm-operator resources: -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: Enterprise - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: Pool - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - defaulting: true - validation: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: Organization - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Image - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - defaulting: true - validation: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: Repository - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - defaulting: true - validation: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: Runner - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 - webhooks: - conversion: true - webhookVersion: v1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: GarmServerConfig - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: GitHubEndpoint - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: mercedes-benz.com - group: garm-operator - kind: GitHubCredentials - path: github.com/mercedes-benz/garm-operator/api/v1alpha1 - version: v1alpha1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Enterprise - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Organization - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Repository - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Pool - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Runner - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: Image - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: GitHubEndpoint - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: GitHubCredentials - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 -- api: - crdVersion: v1 - namespaced: true - domain: mercedes-benz.com - group: garm-operator - kind: GarmServerConfig - path: github.com/mercedes-benz/garm-operator/api/v1beta1 - version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Enterprise + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Pool + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Organization + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Image + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Repository + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercedes-benz.com + group: garm-operator + kind: Runner + path: github.com/mercedes-benz/garm-operator/api/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Enterprise + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Organization + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Repository + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Pool + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Runner + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: Image + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GitHubEndpoint + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GitHubCredentials + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 + - api: + crdVersion: v1 + namespaced: true + domain: mercedes-benz.com + group: garm-operator + kind: GarmServerConfig + path: github.com/mercedes-benz/garm-operator/api/v1beta1 + version: v1beta1 version: "3" diff --git a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml b/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml deleted file mode 100644 index 4a29d517..00000000 --- a/config/samples/garm-operator_v1alpha1_garmserverconfig.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: garm-operator.mercedes-benz.com/v1alpha1 -kind: GarmServerConfig -metadata: - labels: - app.kubernetes.io/name: garmserverconfig - app.kubernetes.io/instance: garmserverconfig-sample - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: garm-operator - name: garmserverconfig-sample -spec: - callbackURL: http://garm-server.garm-server.svc:9997/api/v1/callbacks - metadataURL: http://garm-server.garm-server.svc:9997/api/v1/metadata - webhookURL: http://garm-server.garm-server.svc:9997/api/v1/webhook diff --git a/config/samples/garm-operator_v1alpha1_githubcredentials.yaml b/config/samples/garm-operator_v1alpha1_githubcredentials.yaml deleted file mode 100644 index b5e4e514..00000000 --- a/config/samples/garm-operator_v1alpha1_githubcredentials.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: garm-operator.mercedes-benz.com/v1alpha1 -kind: GitHubCredentials -metadata: - labels: - app.kubernetes.io/name: githubcredentials - app.kubernetes.io/instance: githubcredentials-sample - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: garm-operator - name: github-pat -spec: - description: credentials for mercedes-benz github - endpointRef: - apiGroup: garm-operator.mercedes-benz.com - kind: Endpoint - name: github-enterprise - authType: pat - secretRef: - name: github-pat - key: token ---- -apiVersion: v1 -kind: Secret -metadata: - name: github-pat - namespace: garm-operator-system -data: - # just a base64 encoded string for demonstration purposes, use your own github pat. - # Make sure there is no \n at the end of the string, use: echo -n "gh_mysecrettoken" | base64 - token: Z2hfbXlzZWNyZXR0b2tlbg== - - diff --git a/config/samples/garm-operator_v1alpha1_githubendpoint.yaml b/config/samples/garm-operator_v1alpha1_githubendpoint.yaml deleted file mode 100644 index 63178345..00000000 --- a/config/samples/garm-operator_v1alpha1_githubendpoint.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: garm-operator.mercedes-benz.com/v1alpha1 -kind: Endpoint -metadata: - labels: - app.kubernetes.io/name: endpoint - app.kubernetes.io/instance: endpoint-sample - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: garm-operator - name: github-enterprise -spec: - description: "GitHub Enterprise endpoint" - apiBaseURL: "https://github.enterprise.com" - uploadBaseURL: "https://github.enterprise.com" - baseURL: "https://github.enterprise.com" - caCertBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFb3pDQ0JFbWdBd0lCQWdJUVRpajNoclpzR2p1VUxOTEVEcmRDcFRBS0JnZ3Foa2pPUFFRREFqQ0JqekVMDQpNQWtHQTFVRUJoTUNSMEl4R3pBWkJnTlZCQWdURWtkeVpXRjBaWElnVFdGdVkyaGxjM1JsY2pFUU1BNEdBMVVFDQpCeE1IVTJGc1ptOXlaREVZTUJZR0ExVUVDaE1QVTJWamRHbG5ieUJNYVcxcGRHVmtNVGN3TlFZRFZRUURFeTVUDQpaV04wYVdkdklFVkRReUJFYjIxaGFXNGdWbUZzYVdSaGRHbHZiaUJUWldOMWNtVWdVMlZ5ZG1WeUlFTkJNQjRYDQpEVEkwTURNd056QXdNREF3TUZvWERUSTFNRE13TnpJek5UazFPVm93RlRFVE1CRUdBMVVFQXhNS1oybDBhSFZpDQpMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkFSTy9IbzlYZGtZMXFoOW1BZ2pPVWtXDQptWFRiMDVqZ1J1bEtjaU1WQnVLQjNaSGV4dkNkeW9pQ1JIRU1CZkZYb1poV2tRVk1vZ05Mby9sVzIxNVgzcEdqDQpnZ0wrTUlJQytqQWZCZ05WSFNNRUdEQVdnQlQyaFFvN0VZYmhCSDBPcWdzczB1N01aSHQ3cmpBZEJnTlZIUTRFDQpGZ1FVTzJnL05EcjFSelRLNzZaT1BacTlYbTU2eko4d0RnWURWUjBQQVFIL0JBUURBZ2VBTUF3R0ExVWRFd0VCDQovd1FDTUFBd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNRWtHQTFVZElBUkNNRUF3DQpOQVlMS3dZQkJBR3lNUUVDQWdjd0pUQWpCZ2dyQmdFRkJRY0NBUllYYUhSMGNITTZMeTl6WldOMGFXZHZMbU52DQpiUzlEVUZNd0NBWUdaNEVNQVFJQk1JR0VCZ2dyQmdFRkJRY0JBUVI0TUhZd1R3WUlLd1lCQlFVSE1BS0dRMmgwDQpkSEE2THk5amNuUXVjMlZqZEdsbmJ5NWpiMjB2VTJWamRHbG5iMFZEUTBSdmJXRnBibFpoYkdsa1lYUnBiMjVUDQpaV04xY21WVFpYSjJaWEpEUVM1amNuUXdJd1lJS3dZQkJRVUhNQUdHRjJoMGRIQTZMeTl2WTNOd0xuTmxZM1JwDQpaMjh1WTI5dE1JSUJnQVlLS3dZQkJBSFdlUUlFQWdTQ0FYQUVnZ0ZzQVdvQWR3RFBFVmJ1MVM1OHIvT0hXOWxwDQpMcHZwR25GblNyQVg3S3dCMGx0M3pzdzdDQUFBQVk0V092QVpBQUFFQXdCSU1FWUNJUUQ3b056LzJvTzhWR2FXDQpXcnFyc0JRQnpRSDBoUmhNTG0xMW9lTXBnMWZOYXdJaEFLV2MwcTdaK214RFZZVi82b3Y3Zi9pMEgvYUFjSFNDDQpJaS9RSmNFQ3JhT3BBSFlBb3VNSzVFWHZ2YTJiZmpqdFIyZDNVOWVDVzRTVTF5dGVHeXpFdVZDa1IrY0FBQUdPDQpGanJ2K0FBQUJBTUFSekJGQWlFQXl1cEVJVkFNazBjOEJWVnBGMFFiaXNmb0V3eTV4SlFLUU9lOEV2TVU0VzhDDQpJR0FJSXV6anhCRmxIcGtxY3NhN1VaeTI0eS9CNnhabmt0VXcvTmU1cTVoQ0FIY0FUbldqSjF5YUVNTTRXMnpVDQozejlTNngzdzRJNGJqV25Bc2Zwa3NXS2FPZDhBQUFHT0ZqcnY5d0FBQkFNQVNEQkdBaUVBKzhPdlF6cGdSZjMxDQp1TEJzQ0U4a3RDVWZ2c2lSVDd6V1NxZVhsaUEwOVRVQ0lRRGNCN1huOTdhRURNQktYSWJkbTVLWjlHanZSeW9GDQo5c2tENS80R25lb01XekFsQmdOVkhSRUVIakFjZ2dwbmFYUm9kV0l1WTI5dGdnNTNkM2N1WjJsMGFIVmlMbU52DQpiVEFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBcnUyTWNQcjBlTndjV051REVZMGEvckd6WFJmUnJtKzZYZlplDQpTemhZWmV3Q0lCcTRUVUVCQ2dhcHY3eHZBdFJLZFZkaS9iNG0zNlV5ZWoxZ2d5SnNpZXNBDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo= diff --git a/config/samples/garm-operator_v1beta1_runner.yaml b/config/samples/garm-operator_v1beta1_runner.yaml deleted file mode 100644 index c36ad6ee..00000000 --- a/config/samples/garm-operator_v1beta1_runner.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: garm-operator.mercedes-benz.com/v1beta1 -kind: Runner -metadata: - labels: - app.kubernetes.io/name: runner - app.kubernetes.io/instance: runner-sample - app.kubernetes.io/part-of: garm-operator - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: garm-operator - name: runner-sample -spec: - # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index f455d0f4..d47ce1a4 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -5,17 +5,12 @@ resources: - garm-operator_v1alpha1_organization.yaml - garm-operator_v1alpha1_image.yaml - garm-operator_v1alpha1_repository.yaml - - garm-operator_v1alpha1_runner.yaml - - garm-operator_v1alpha1_garmserverconfig.yaml - - garm-operator_v1alpha1_githubendpoint.yaml - - garm-operator_v1alpha1_githubcredentials.yaml -- garm-operator_v1beta1_enterprise.yaml -- garm-operator_v1beta1_organization.yaml -- garm-operator_v1beta1_repository.yaml -- garm-operator_v1beta1_pool.yaml -- garm-operator_v1beta1_runner.yaml -- garm-operator_v1beta1_image.yaml -- garm-operator_v1beta1_githubendpoint.yaml -- garm-operator_v1beta1_githubcredentials.yaml -- garm-operator_v1beta1_garmserverconfig.yaml -#+kubebuilder:scaffold:manifestskustomizesamples + - garm-operator_v1beta1_enterprise.yaml + - garm-operator_v1beta1_organization.yaml + - garm-operator_v1beta1_repository.yaml + - garm-operator_v1beta1_pool.yaml + - garm-operator_v1beta1_image.yaml + - garm-operator_v1beta1_githubendpoint.yaml + - garm-operator_v1beta1_githubcredentials.yaml + - garm-operator_v1beta1_garmserverconfig.yaml + #+kubebuilder:scaffold:manifestskustomizesamples From aa15df6ac0d2564e8e859bca7669ac7952f9b81a Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 13:05:36 +0200 Subject: [PATCH 27/30] remove pool adoption test as we do not do pool adoption anymore we can get rid of the test case as well --- internal/controller/pool_controller_test.go | 196 -------------------- 1 file changed, 196 deletions(-) diff --git a/internal/controller/pool_controller_test.go b/internal/controller/pool_controller_test.go index fe8597bb..376e8c60 100644 --- a/internal/controller/pool_controller_test.go +++ b/internal/controller/pool_controller_test.go @@ -37,7 +37,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - outdatedPoolID := "a9f48897-77c3-4293-8462-732a22a908f1" poolID := "fb2bceeb-f74d-435d-9648-626c75cb23ce" enterpriseID := "93068607-2d0d-4b76-a950-0e40d31955b8" enterpriseName := "test-enterprise" @@ -199,8 +198,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, }, expectGarmRequest: func(poolClient *mock.MockPoolClientMockRecorder, _ *mock.MockInstanceClientMockRecorder) { - poolClient.ListAllPools(pools.NewListPoolsParams()).Return(&pools.ListPoolsOK{Payload: params.Pools{}}, nil) - extraSpecs := json.RawMessage([]byte{}) poolClient.CreateEnterprisePool( enterprises.NewCreateEnterprisePoolParams().WithEnterpriseID(enterpriseID).WithBody( @@ -264,199 +261,6 @@ func TestPoolController_ReconcileCreate(t *testing.T) { }, nil) }, }, - { - name: "pool with matching specs exists in garm, outdated garmId in pool.Status - sync ids", - object: &garmoperatorv1beta1.Pool{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pool", - APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "my-enterprise-pool", - Namespace: namespaceName, - }, - Spec: garmoperatorv1beta1.PoolSpec{ - GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: string(garmoperatorv1beta1.EnterpriseScope), - Name: enterpriseName, - }, - ProviderName: "kubernetes_external", - MaxRunners: 5, - MinIdleRunners: 3, - ImageName: "ubuntu-image", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []string{"kubernetes", "linux", "arm64", "ubuntu"}, - Enabled: true, - RunnerBootstrapTimeout: 20, - ExtraSpecs: "", - GitHubRunnerGroup: "", - }, - Status: garmoperatorv1beta1.PoolStatus{ - ID: outdatedPoolID, - }, - }, - expectedObject: &garmoperatorv1beta1.Pool{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pool", - APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "my-enterprise-pool", - Namespace: namespaceName, - Finalizers: []string{ - key.PoolFinalizerName, - }, - }, - Spec: garmoperatorv1beta1.PoolSpec{ - GitHubScopeRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: string(garmoperatorv1beta1.EnterpriseScope), - Name: enterpriseName, - }, - ProviderName: "kubernetes_external", - MaxRunners: 5, - MinIdleRunners: 3, - ImageName: "ubuntu-image", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []string{"kubernetes", "linux", "arm64", "ubuntu"}, - Enabled: true, - RunnerBootstrapTimeout: 20, - ExtraSpecs: "", - GitHubRunnerGroup: "", - }, - Status: garmoperatorv1beta1.PoolStatus{ - ID: poolID, - LongRunningIdleRunners: 3, - Selector: "", - Conditions: []metav1.Condition{ - { - Type: string(conditions.ReadyCondition), - Status: metav1.ConditionTrue, - LastTransitionTime: metav1.NewTime(time.Now()), - Reason: string(conditions.SuccessfulReconcileReason), - Message: "", - }, - { - Type: string(conditions.ImageReference), - Status: metav1.ConditionTrue, - Message: "Successfully fetched Image CR Ref", - Reason: string(conditions.FetchingImageRefSuccessReason), - LastTransitionTime: metav1.NewTime(time.Now()), - }, - }, - }, - }, - runtimeObjects: []runtime.Object{ - &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespaceName, - Name: "my-webhook-secret", - }, - Data: map[string][]byte{ - "webhookSecret": []byte("supersecretvalue"), - }, - }, - &garmoperatorv1beta1.Image{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ubuntu-image", - Namespace: namespaceName, - }, - Spec: garmoperatorv1beta1.ImageSpec{ - Tag: "linux-ubuntu-22.04-arm64", - }, - }, - &garmoperatorv1beta1.Enterprise{ - TypeMeta: metav1.TypeMeta{ - Kind: "Enterprise", - APIVersion: garmoperatorv1beta1.GroupVersion.Group + "/" + garmoperatorv1beta1.GroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: enterpriseName, - Namespace: namespaceName, - }, - Spec: garmoperatorv1beta1.EnterpriseSpec{ - CredentialsRef: corev1.TypedLocalObjectReference{ - APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", - Name: "github-creds", - }, - WebhookSecretRef: garmoperatorv1beta1.SecretRef{ - Name: "my-webhook-secret", - Key: "webhookSecret", - }, - }, - Status: garmoperatorv1beta1.EnterpriseStatus{ - ID: enterpriseID, - Conditions: []metav1.Condition{ - { - Type: string(conditions.ReadyCondition), - Reason: string(conditions.SuccessfulReconcileReason), - Status: metav1.ConditionTrue, - Message: "", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - { - Type: string(conditions.PoolManager), - Reason: string(conditions.PoolManagerFailureReason), - Status: metav1.ConditionFalse, - Message: "no resources available", - LastTransitionTime: metav1.NewTime(time.Now()), - }, - }, - }, - }, - }, - expectGarmRequest: func(poolClient *mock.MockPoolClientMockRecorder, _ *mock.MockInstanceClientMockRecorder) { - poolClient.GetPool(pools.NewGetPoolParams().WithPoolID(outdatedPoolID)).Return(&pools.GetPoolOK{Payload: params.Pool{}}, nil) - - poolClient.ListAllPools(pools.NewListPoolsParams()).Return(&pools.ListPoolsOK{Payload: params.Pools{ - { - RunnerPrefix: params.RunnerPrefix{ - Prefix: "", - }, - ID: poolID, - ProviderName: "kubernetes_external", - MaxRunners: 5, - MinIdleRunners: 3, - Image: "linux-ubuntu-22.04-arm64", - Flavor: "medium", - OSType: "linux", - OSArch: "arm64", - Tags: []params.Tag{ - { - ID: "b3ea9882-a25c-4eb1-94ba-6c70b9abb6da", - Name: "kubernetes", - }, - { - ID: "b3ea9882-a25c-4eb1-94ba-6c70b9abb6db", - Name: "linux", - }, - { - ID: "b3ea9882-a25c-4eb1-94ba-6c70b9abb6dc", - Name: "arm64", - }, - { - ID: "b3ea9882-a25c-4eb1-94ba-6c70b9abb6dd", - Name: "ubuntu", - }, - }, - Enabled: true, - Instances: []params.Instance{}, - RepoID: "", - RepoName: "", - OrgID: "", - OrgName: "", - EnterpriseID: enterpriseID, - EnterpriseName: enterpriseName, - }, - }}, nil) - }, - }, { name: "pool.Status has matching id in garm database, pool.Specs changed - update pool in garm", object: &garmoperatorv1beta1.Pool{ From 99827da60d8057c82d936f59d7e3a83ed8893780 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 13:08:34 +0200 Subject: [PATCH 28/30] set current todo to nolint --- api/v1beta1/githubendpoint_types.go | 4 +++- .../garm-operator.mercedes-benz.com_githubendpoints.yaml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/api/v1beta1/githubendpoint_types.go b/api/v1beta1/githubendpoint_types.go index 21d1fd55..64fbb56b 100644 --- a/api/v1beta1/githubendpoint_types.go +++ b/api/v1beta1/githubendpoint_types.go @@ -12,7 +12,9 @@ type GitHubEndpointSpec struct { APIBaseURL string `json:"apiBaseUrl,omitempty"` UploadBaseURL string `json:"uploadBaseUrl,omitempty"` BaseURL string `json:"baseUrl,omitempty"` - CACertBundle []byte `json:"caCertBundle,omitempty"` // TODO: This should be a secret reference + //nolint:godox + // TODO: This should be a secret reference + CACertBundle []byte `json:"caCertBundle,omitempty"` } // GitHubEndpointStatus defines the observed state of GitHubEndpoint diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml index 28c3d4ae..bf26a54d 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubendpoints.yaml @@ -64,6 +64,7 @@ spec: baseUrl: type: string caCertBundle: + description: 'TODO: This should be a secret reference' format: byte type: string description: From e239cf6af942eb00ea8d9480d9ff8105a4d48834 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Thu, 17 Oct 2024 15:51:23 +0200 Subject: [PATCH 29/30] log webhook with values --- api/v1beta1/image_webhook.go | 6 +++--- api/v1beta1/pool_webhook.go | 4 ++-- api/v1beta1/repository_webhook.go | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/v1beta1/image_webhook.go b/api/v1beta1/image_webhook.go index 2b2642f5..17a22940 100644 --- a/api/v1beta1/image_webhook.go +++ b/api/v1beta1/image_webhook.go @@ -30,19 +30,19 @@ var _ webhook.Validator = &Image{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (i *Image) ValidateCreate() (admission.Warnings, error) { - imagelog.Info("validate create", "name", i.Name) + imagelog.Info("validate create", "name", i.Name, "namespace", i.Namespace) return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (i *Image) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { - imagelog.Info("validate update", "name", i.Name) + imagelog.Info("validate update", "name", i.Name, "namespace", i.Namespace) return nil, nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (i *Image) ValidateDelete() (admission.Warnings, error) { - imagelog.Info("validate delete", "name", i.Name) + imagelog.Info("validate delete", "name", i.Name, "namespace", i.Namespace) var msg string pools, err := i.attachedPools(context.Background()) diff --git a/api/v1beta1/pool_webhook.go b/api/v1beta1/pool_webhook.go index a47e8648..fc7972d4 100644 --- a/api/v1beta1/pool_webhook.go +++ b/api/v1beta1/pool_webhook.go @@ -37,7 +37,7 @@ var _ webhook.Validator = &Pool{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (r *Pool) ValidateCreate() (admission.Warnings, error) { - poollog.Info("validate create", "name", r.Name) + poollog.Info("validate create request", "name", r.Name, "namespace", r.Namespace) if err := r.validateExtraSpec(); err != nil { return nil, apierrors.NewInvalid(schema.GroupKind{Group: GroupVersion.Group, Kind: "Pool"}, @@ -134,6 +134,6 @@ func (r *Pool) validateGitHubScope(old *Pool) *field.Error { // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (r *Pool) ValidateDelete() (admission.Warnings, error) { - poollog.Info("validate delete", "name", r.Name) + poollog.Info("validate delete", "name", r.Name, "namespace", r.Namespace) return nil, nil } diff --git a/api/v1beta1/repository_webhook.go b/api/v1beta1/repository_webhook.go index ab645959..81646005 100644 --- a/api/v1beta1/repository_webhook.go +++ b/api/v1beta1/repository_webhook.go @@ -30,13 +30,13 @@ var _ webhook.Validator = &Repository{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (r *Repository) ValidateCreate() (admission.Warnings, error) { - repositorylog.Info("validate create", "name", r.Name) + repositorylog.Info("validate create", "name", r.Name, "namespace", r.Namespace) return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (r *Repository) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - repositorylog.Info("validate update", "name", r.Name) + repositorylog.Info("validate update", "name", r.Name, "namespace", r.Namespace) oldCRD, ok := old.(*Repository) if !ok { @@ -70,6 +70,6 @@ func (r *Repository) validateRepoOwnerName(old *Repository) *field.Error { // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (r *Repository) ValidateDelete() (admission.Warnings, error) { - repositorylog.Info("validate delete", "name", r.Name) + repositorylog.Info("validate delete", "name", r.Name, "namespace", r.Namespace) return nil, nil } From c153b89cb6647a9989e1944d07bf50cfb3607ecd Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Mon, 21 Oct 2024 14:28:01 +0200 Subject: [PATCH 30/30] change githubcredential CRD to singular Signed-off-by: Mario Constanti --- PROJECT | 2 +- Tiltfile | 2 +- api/v1alpha1/enterprise_conversion.go | 2 +- api/v1alpha1/organization_conversion.go | 2 +- api/v1alpha1/repository_conversion.go | 2 +- api/v1beta1/githubcredentials_types.go | 32 +- api/v1beta1/zz_generated.deepcopy.go | 38 +- cmd/main.go | 4 +- ...or.mercedes-benz.com_githubcredential.yaml | 214 ++++++++++ ...r.mercedes-benz.com_githubcredentials.yaml | 386 +++++++++--------- config/crd/kustomization.yaml | 66 +-- .../cainjection_in_githubcredentials.yaml | 2 +- .../patches/webhook_in_githubcredentials.yaml | 4 +- .../rbac/githubcredentials_editor_role.yaml | 42 +- .../rbac/githubcredentials_viewer_role.yaml | 34 +- config/rbac/role.yaml | 6 +- ...rm-operator_v1beta1_githubcredentials.yaml | 6 +- config/samples/kustomization.yaml | 2 +- internal/controller/enterprise_controller.go | 8 +- .../controller/enterprise_controller_test.go | 58 +-- .../githubcredentials_controller.go | 42 +- .../controller/organization_controller.go | 8 +- .../organization_controller_test.go | 58 +-- internal/controller/pool_controller_test.go | 14 +- internal/controller/repository_controller.go | 8 +- .../controller/repository_controller_test.go | 58 +-- 26 files changed, 658 insertions(+), 442 deletions(-) create mode 100644 config/crd/bases/garm-operator.mercedes-benz.com_githubcredential.yaml diff --git a/PROJECT b/PROJECT index f9c10730..a60f7b0f 100644 --- a/PROJECT +++ b/PROJECT @@ -146,7 +146,7 @@ resources: namespaced: true domain: mercedes-benz.com group: garm-operator - kind: GitHubCredentials + kind: GitHubCredential path: github.com/mercedes-benz/garm-operator/api/v1beta1 version: v1beta1 - api: diff --git a/Tiltfile b/Tiltfile index 26193ba2..c5577507 100644 --- a/Tiltfile +++ b/Tiltfile @@ -37,7 +37,7 @@ k8s_resource( 'runners.garm-operator.mercedes-benz.com:customresourcedefinition', 'repositories.garm-operator.mercedes-benz.com:customresourcedefinition', 'garmserverconfigs.garm-operator.mercedes-benz.com:customresourcedefinition', - 'githubcredentials.garm-operator.mercedes-benz.com:customresourcedefinition', + 'githubcredential.garm-operator.mercedes-benz.com:customresourcedefinition', 'githubendpoints.garm-operator.mercedes-benz.com:customresourcedefinition', 'garm-operator-controller-manager:serviceaccount', 'garm-operator-leader-election-role:role', diff --git a/api/v1alpha1/enterprise_conversion.go b/api/v1alpha1/enterprise_conversion.go index d4208d1d..92183636 100644 --- a/api/v1alpha1/enterprise_conversion.go +++ b/api/v1alpha1/enterprise_conversion.go @@ -22,7 +22,7 @@ func (e *Enterprise) ConvertFrom(dstRaw conversion.Hub) error { func Convert_v1alpha1_EnterpriseSpec_To_v1beta1_EnterpriseSpec(in *EnterpriseSpec, out *v1beta1.EnterpriseSpec, s apiconversion.Scope) error { out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", APIGroup: &v1beta1.GroupVersion.Group, } diff --git a/api/v1alpha1/organization_conversion.go b/api/v1alpha1/organization_conversion.go index ebde5a57..de505619 100644 --- a/api/v1alpha1/organization_conversion.go +++ b/api/v1alpha1/organization_conversion.go @@ -20,7 +20,7 @@ func (o *Organization) ConvertFrom(dstRaw conversion.Hub) error { func Convert_v1alpha1_OrganizationSpec_To_v1beta1_OrganizationSpec(in *OrganizationSpec, out *v1beta1.OrganizationSpec, s apiconversion.Scope) error { out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", APIGroup: &v1beta1.GroupVersion.Group, } diff --git a/api/v1alpha1/repository_conversion.go b/api/v1alpha1/repository_conversion.go index 51eba50a..e737c884 100644 --- a/api/v1alpha1/repository_conversion.go +++ b/api/v1alpha1/repository_conversion.go @@ -22,7 +22,7 @@ func (r *Repository) ConvertFrom(dstRaw conversion.Hub) error { func Convert_v1alpha1_RepositorySpec_To_v1beta1_RepositorySpec(in *RepositorySpec, out *v1beta1.RepositorySpec, s apiconversion.Scope) error { out.CredentialsRef = corev1.TypedLocalObjectReference{ Name: in.CredentialsName, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", APIGroup: &v1beta1.GroupVersion.Group, } diff --git a/api/v1beta1/githubcredentials_types.go b/api/v1beta1/githubcredentials_types.go index d0053315..ae5a2441 100644 --- a/api/v1beta1/githubcredentials_types.go +++ b/api/v1beta1/githubcredentials_types.go @@ -8,8 +8,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// GitHubCredentialsSpec defines the desired state of GitHubCredentials -type GitHubCredentialsSpec struct { +// GitHubCredentialSpec defines the desired state of GitHubCredential +type GitHubCredentialSpec struct { Description string `json:"description"` EndpointRef corev1.TypedLocalObjectReference `json:"endpointRef"` @@ -24,8 +24,8 @@ type GitHubCredentialsSpec struct { SecretRef SecretRef `json:"secretRef,omitempty"` } -// GitHubCredentialsStatus defines the observed state of GitHubCredentials -type GitHubCredentialsStatus struct { +// GitHubCredentialStatus defines the observed state of GitHubCredential +type GitHubCredentialStatus struct { ID int64 `json:"id"` APIBaseURL string `json:"apiBaseUrl"` UploadBaseURL string `json:"uploadBaseUrl"` @@ -35,7 +35,7 @@ type GitHubCredentialsStatus struct { } //+kubebuilder:object:root=true -//+kubebuilder:resource:path=githubcredentials,scope=Namespaced,categories=garm,shortName=creds +//+kubebuilder:resource:path=githubcredential,scope=Namespaced,categories=garm,shortName=creds //+kubebuilder:subresource:status //+kubebuilder:storageversion //+kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.id",description="Credentials ID" @@ -43,34 +43,34 @@ type GitHubCredentialsStatus struct { //+kubebuilder:printcolumn:name="Error",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].message",priority=1 //+kubebuilder:printcolumn:name="AuthType",type="string",JSONPath=`.spec.authType`,description="Authentication type" //+kubebuilder:printcolumn:name="GitHubEndpoint",type="string",JSONPath=`.spec.endpointRef.name`,description="GitHubEndpoint name these credentials are tied to" -//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GitHubCredentials" +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of GitHubCredential" -// GitHubCredentials is the Schema for the githubcredentials API -type GitHubCredentials struct { +// GitHubCredential is the Schema for the githubcredential API +type GitHubCredential struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec GitHubCredentialsSpec `json:"spec,omitempty"` - Status GitHubCredentialsStatus `json:"status,omitempty"` + Spec GitHubCredentialSpec `json:"spec,omitempty"` + Status GitHubCredentialStatus `json:"status,omitempty"` } -func (g *GitHubCredentials) SetConditions(conditions []metav1.Condition) { +func (g *GitHubCredential) SetConditions(conditions []metav1.Condition) { g.Status.Conditions = conditions } -func (g *GitHubCredentials) GetConditions() []metav1.Condition { +func (g *GitHubCredential) GetConditions() []metav1.Condition { return g.Status.Conditions } //+kubebuilder:object:root=true -// GitHubCredentialsList contains a list of GitHubCredentials -type GitHubCredentialsList struct { +// GitHubCredentialList contains a list of GitHubCredential +type GitHubCredentialList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []GitHubCredentials `json:"items"` + Items []GitHubCredential `json:"items"` } func init() { - SchemeBuilder.Register(&GitHubCredentials{}, &GitHubCredentialsList{}) + SchemeBuilder.Register(&GitHubCredential{}, &GitHubCredentialList{}) } diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 5ef29fb1..d78c7430 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -207,7 +207,7 @@ func (in *GarmServerConfigStatus) DeepCopy() *GarmServerConfigStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { +func (in *GitHubCredential) DeepCopyInto(out *GitHubCredential) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -215,18 +215,18 @@ func (in *GitHubCredentials) DeepCopyInto(out *GitHubCredentials) { in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentials. -func (in *GitHubCredentials) DeepCopy() *GitHubCredentials { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredential. +func (in *GitHubCredential) DeepCopy() *GitHubCredential { if in == nil { return nil } - out := new(GitHubCredentials) + out := new(GitHubCredential) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentials) DeepCopyObject() runtime.Object { +func (in *GitHubCredential) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -234,31 +234,31 @@ func (in *GitHubCredentials) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsList) DeepCopyInto(out *GitHubCredentialsList) { +func (in *GitHubCredentialList) DeepCopyInto(out *GitHubCredentialList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items - *out = make([]GitHubCredentials, len(*in)) + *out = make([]GitHubCredential, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsList. -func (in *GitHubCredentialsList) DeepCopy() *GitHubCredentialsList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialList. +func (in *GitHubCredentialList) DeepCopy() *GitHubCredentialList { if in == nil { return nil } - out := new(GitHubCredentialsList) + out := new(GitHubCredentialList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { +func (in *GitHubCredentialList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -266,24 +266,24 @@ func (in *GitHubCredentialsList) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsSpec) DeepCopyInto(out *GitHubCredentialsSpec) { +func (in *GitHubCredentialSpec) DeepCopyInto(out *GitHubCredentialSpec) { *out = *in in.EndpointRef.DeepCopyInto(&out.EndpointRef) out.SecretRef = in.SecretRef } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsSpec. -func (in *GitHubCredentialsSpec) DeepCopy() *GitHubCredentialsSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialSpec. +func (in *GitHubCredentialSpec) DeepCopy() *GitHubCredentialSpec { if in == nil { return nil } - out := new(GitHubCredentialsSpec) + out := new(GitHubCredentialSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { +func (in *GitHubCredentialStatus) DeepCopyInto(out *GitHubCredentialStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -294,12 +294,12 @@ func (in *GitHubCredentialsStatus) DeepCopyInto(out *GitHubCredentialsStatus) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialsStatus. -func (in *GitHubCredentialsStatus) DeepCopy() *GitHubCredentialsStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubCredentialStatus. +func (in *GitHubCredentialStatus) DeepCopy() *GitHubCredentialStatus { if in == nil { return nil } - out := new(GitHubCredentialsStatus) + out := new(GitHubCredentialStatus) in.DeepCopyInto(out) return out } diff --git a/cmd/main.go b/cmd/main.go index 7bbbed05..f7821a9f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -215,12 +215,12 @@ func run() error { return fmt.Errorf("unable to create controller GitHubEndpoint: %w", err) } - if err = (&garmcontroller.GitHubCredentialsReconciler{ + if err = (&garmcontroller.GitHubCredentialReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("github-credentials-controller"), }).SetupWithManager(mgr); err != nil { - return fmt.Errorf("unable to create controller GitHubCredentials: %w", err) + return fmt.Errorf("unable to create controller GitHubCredential: %w", err) } // webhooks diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredential.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredential.yaml new file mode 100644 index 00000000..81ee9818 --- /dev/null +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredential.yaml @@ -0,0 +1,214 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: githubcredential.garm-operator.mercedes-benz.com +spec: + group: garm-operator.mercedes-benz.com + names: + categories: + - garm + kind: GitHubCredential + listKind: GitHubCredentialList + plural: githubcredential + shortNames: + - creds + singular: githubcredential + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Credentials ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - description: Authentication type + jsonPath: .spec.authType + name: AuthType + type: string + - description: GitHubEndpoint name these credentials are tied to + jsonPath: .spec.endpointRef.name + name: GitHubEndpoint + type: string + - description: Time duration since creation of GitHubCredential + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: GitHubCredential is the Schema for the githubcredential API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GitHubCredentialSpec defines the desired state of GitHubCredential + properties: + appId: + description: if AuthType is app + format: int64 + type: integer + authType: + description: either pat or app + type: string + description: + type: string + endpointRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + installationId: + format: int64 + type: integer + secretRef: + description: containing either privateKey or pat token + properties: + key: + description: Key is the key in the secret's data map for this + value + type: string + name: + description: Name of the kubernetes secret to use + type: string + required: + - key + - name + type: object + required: + - authType + - description + - endpointRef + type: object + status: + description: GitHubCredentialStatus defines the observed state of GitHubCredential + properties: + apiBaseUrl: + type: string + baseUrl: + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + format: int64 + type: integer + uploadBaseUrl: + type: string + required: + - apiBaseUrl + - baseUrl + - id + - uploadBaseUrl + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml index cb7f1246..a154795e 100644 --- a/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml +++ b/config/crd/bases/garm-operator.mercedes-benz.com_githubcredentials.yaml @@ -4,211 +4,213 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.15.0 - name: githubcredentials.garm-operator.mercedes-benz.com + name: githubcredential.garm-operator.mercedes-benz.com spec: group: garm-operator.mercedes-benz.com names: categories: - - garm - kind: GitHubCredentials - listKind: GitHubCredentialsList - plural: githubcredentials + - garm + kind: GitHubCredential + listKind: GitHubCredentialList + plural: githubcredential shortNames: - - creds - singular: githubcredentials + - creds + singular: githubcredential scope: Namespaced versions: - - additionalPrinterColumns: - - description: Credentials ID - jsonPath: .status.id - name: ID - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].message - name: Error - priority: 1 - type: string - - description: Authentication type - jsonPath: .spec.authType - name: AuthType - type: string - - description: GitHubEndpoint name these credentials are tied to - jsonPath: .spec.endpointRef.name - name: GitHubEndpoint - type: string - - description: Time duration since creation of GitHubCredentials - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: GitHubCredentials is the Schema for the githubcredentials API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: GitHubCredentialsSpec defines the desired state of GitHubCredentials - properties: - appId: - description: if AuthType is app - format: int64 - type: integer - authType: - description: either pat or app - type: string - description: - type: string - endpointRef: - description: |- - TypedLocalObjectReference contains enough information to let you locate the - typed referenced object inside the same namespace. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - installationId: - format: int64 - type: integer - secretRef: - description: containing either privateKey or pat token - properties: - key: - description: Key is the key in the secret's data map for this - value - type: string - name: - description: Name of the kubernetes secret to use - type: string - required: - - key - - name - type: object - required: - - authType - - description - - endpointRef - type: object - status: - description: GitHubCredentialsStatus defines the observed state of GitHubCredentials - properties: - apiBaseUrl: - type: string - baseUrl: - type: string - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + - additionalPrinterColumns: + - description: Credentials ID + jsonPath: .status.id + name: ID + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].message + name: Error + priority: 1 + type: string + - description: Authentication type + jsonPath: .spec.authType + name: AuthType + type: string + - description: GitHubEndpoint name these credentials are tied to + jsonPath: .spec.endpointRef.name + name: GitHubEndpoint + type: string + - description: Time duration since creation of GitHubCredential + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: GitHubCredential is the Schema for the githubcredential API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GitHubCredentialSpec defines the desired state of GitHubCredential + properties: + appId: + description: if AuthType is app + format: int64 + type: integer + authType: + description: either pat or app + type: string + description: + type: string + endpointRef: + description: |- + TypedLocalObjectReference contains enough information to let you locate the + typed referenced object inside the same namespace. properties: - lastTransitionTime: + apiGroup: description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 + kind: + description: Kind is the type of resource being referenced type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + name: + description: Name is the name of resource being referenced type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + installationId: + format: int64 + type: integer + secretRef: + description: containing either privateKey or pat token + properties: + key: + description: + Key is the key in the secret's data map for this + value type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + name: + description: Name of the kubernetes secret to use type: string required: - - lastTransitionTime - - message - - reason - - status - - type + - key + - name type: object - type: array - id: - format: int64 - type: integer - uploadBaseUrl: - type: string - required: - - apiBaseUrl - - baseUrl - - id - - uploadBaseUrl - type: object - type: object - served: true - storage: true - subresources: - status: {} + required: + - authType + - description + - endpointRef + type: object + status: + description: GitHubCredentialStatus defines the observed state of GitHubCredential + properties: + apiBaseUrl: + type: string + baseUrl: + type: string + conditions: + items: + description: + "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + id: + format: int64 + type: integer + uploadBaseUrl: + type: string + required: + - apiBaseUrl + - baseUrl + - id + - uploadBaseUrl + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 64837e5b..d86c9289 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,42 +2,42 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: -- bases/garm-operator.mercedes-benz.com_enterprises.yaml -- bases/garm-operator.mercedes-benz.com_pools.yaml -- bases/garm-operator.mercedes-benz.com_organizations.yaml -- bases/garm-operator.mercedes-benz.com_images.yaml -- bases/garm-operator.mercedes-benz.com_repositories.yaml -- bases/garm-operator.mercedes-benz.com_runners.yaml -- bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml -- bases/garm-operator.mercedes-benz.com_githubendpoints.yaml -- bases/garm-operator.mercedes-benz.com_githubcredentials.yaml + - bases/garm-operator.mercedes-benz.com_enterprises.yaml + - bases/garm-operator.mercedes-benz.com_pools.yaml + - bases/garm-operator.mercedes-benz.com_organizations.yaml + - bases/garm-operator.mercedes-benz.com_images.yaml + - bases/garm-operator.mercedes-benz.com_repositories.yaml + - bases/garm-operator.mercedes-benz.com_runners.yaml + - bases/garm-operator.mercedes-benz.com_garmserverconfigs.yaml + - bases/garm-operator.mercedes-benz.com_githubendpoints.yaml + - bases/garm-operator.mercedes-benz.com_githubcredentials.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. -# patches here are for enabling the conversion webhook for each CRD -- path: patches/webhook_in_enterprises.yaml -- path: patches/webhook_in_pools.yaml -- path: patches/webhook_in_organizations.yaml -- path: patches/webhook_in_repositories.yaml -#- path: patches/webhook_in_runners.yaml -#- path: patches/webhook_in_garmserverconfigs.yaml -#- path: patches/webhook_in_githubendpoints.yaml -#- path: patches/webhook_in_githubcredentials.yaml -#- path: patches/webhook_in_enterprises.yaml -#- path: patches/webhook_in_organizations.yaml -#- path: patches/webhook_in_repositories.yaml -#- path: patches/webhook_in_pools.yaml -#- path: patches/webhook_in_images.yaml -#+kubebuilder:scaffold:crdkustomizewebhookpatch + # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. + # patches here are for enabling the conversion webhook for each CRD + - path: patches/webhook_in_enterprises.yaml + - path: patches/webhook_in_pools.yaml + - path: patches/webhook_in_organizations.yaml + - path: patches/webhook_in_repositories.yaml + #- path: patches/webhook_in_runners.yaml + #- path: patches/webhook_in_garmserverconfigs.yaml + #- path: patches/webhook_in_githubendpoints.yaml + #- path: patches/webhook_in_githubcredentials.yaml + #- path: patches/webhook_in_enterprises.yaml + #- path: patches/webhook_in_organizations.yaml + #- path: patches/webhook_in_repositories.yaml + #- path: patches/webhook_in_pools.yaml + #- path: patches/webhook_in_images.yaml + #+kubebuilder:scaffold:crdkustomizewebhookpatch -# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -- path: patches/cainjection_in_enterprises.yaml -- path: patches/cainjection_in_pools.yaml -- path: patches/cainjection_in_organizations.yaml -#- path: patches/cainjection_in_images.yaml -- path: patches/cainjection_in_repositories.yaml + # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. + # patches here are for enabling the CA injection for each CRD + - path: patches/cainjection_in_enterprises.yaml + - path: patches/cainjection_in_pools.yaml + - path: patches/cainjection_in_organizations.yaml + #- path: patches/cainjection_in_images.yaml + - path: patches/cainjection_in_repositories.yaml #- path: patches/cainjection_in_runners.yaml #- path: patches/cainjection_in_garmserverconfigs.yaml #- path: patches/cainjection_in_githubendpoints.yaml @@ -50,4 +50,4 @@ patches: # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: -- kustomizeconfig.yaml + - kustomizeconfig.yaml diff --git a/config/crd/patches/cainjection_in_githubcredentials.yaml b/config/crd/patches/cainjection_in_githubcredentials.yaml index 95397d02..1443d50c 100644 --- a/config/crd/patches/cainjection_in_githubcredentials.yaml +++ b/config/crd/patches/cainjection_in_githubcredentials.yaml @@ -4,4 +4,4 @@ kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME - name: githubcredentials.garm-operator.mercedes-benz.com + name: githubcredential.garm-operator.mercedes-benz.com diff --git a/config/crd/patches/webhook_in_githubcredentials.yaml b/config/crd/patches/webhook_in_githubcredentials.yaml index 93bd0f14..2d15f685 100644 --- a/config/crd/patches/webhook_in_githubcredentials.yaml +++ b/config/crd/patches/webhook_in_githubcredentials.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: githubcredentials.garm-operator.mercedes-benz.com + name: githubcredential.garm-operator.mercedes-benz.com spec: conversion: strategy: Webhook @@ -13,4 +13,4 @@ spec: name: webhook-service path: /convert conversionReviewVersions: - - v1 + - v1 diff --git a/config/rbac/githubcredentials_editor_role.yaml b/config/rbac/githubcredentials_editor_role.yaml index 040f2fb0..a3371d07 100644 --- a/config/rbac/githubcredentials_editor_role.yaml +++ b/config/rbac/githubcredentials_editor_role.yaml @@ -1,31 +1,31 @@ -# permissions for end users to edit githubcredentials. +# permissions for end users to edit githubcredential. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: githubcredentials-editor-role + app.kubernetes.io/instance: githubcredential-editor-role app.kubernetes.io/component: rbac app.kubernetes.io/created-by: garm-operator app.kubernetes.io/part-of: garm-operator app.kubernetes.io/managed-by: kustomize - name: githubcredentials-editor-role + name: githubcredential-editor-role rules: -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - githubcredentials - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - githubcredentials/status - verbs: - - get + - apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredential + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredential/status + verbs: + - get diff --git a/config/rbac/githubcredentials_viewer_role.yaml b/config/rbac/githubcredentials_viewer_role.yaml index 7bbc6fca..dbb5e4f0 100644 --- a/config/rbac/githubcredentials_viewer_role.yaml +++ b/config/rbac/githubcredentials_viewer_role.yaml @@ -1,27 +1,27 @@ -# permissions for end users to view githubcredentials. +# permissions for end users to view githubcredential. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: githubcredentials-viewer-role + app.kubernetes.io/instance: githubcredential-viewer-role app.kubernetes.io/component: rbac app.kubernetes.io/created-by: garm-operator app.kubernetes.io/part-of: garm-operator app.kubernetes.io/managed-by: kustomize - name: githubcredentials-viewer-role + name: githubcredential-viewer-role rules: -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - githubcredentials - verbs: - - get - - list - - watch -- apiGroups: - - garm-operator.mercedes-benz.com - resources: - - githubcredentials/status - verbs: - - get + - apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredential + verbs: + - get + - list + - watch + - apiGroups: + - garm-operator.mercedes-benz.com + resources: + - githubcredential/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 78deb244..b390bd2d 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -81,7 +81,7 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials + - githubcredential verbs: - create - delete @@ -93,13 +93,13 @@ rules: - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials/finalizers + - githubcredential/finalizers verbs: - update - apiGroups: - garm-operator.mercedes-benz.com resources: - - githubcredentials/status + - githubcredential/status verbs: - get - patch diff --git a/config/samples/garm-operator_v1beta1_githubcredentials.yaml b/config/samples/garm-operator_v1beta1_githubcredentials.yaml index f9431ed4..a588bda9 100644 --- a/config/samples/garm-operator_v1beta1_githubcredentials.yaml +++ b/config/samples/garm-operator_v1beta1_githubcredentials.yaml @@ -2,11 +2,11 @@ apiVersion: garm-operator.mercedes-benz.com/v1beta1 kind: GitHubCredentials metadata: labels: - app.kubernetes.io/name: githubcredentials - app.kubernetes.io/instance: githubcredentials-sample + app.kubernetes.io/name: githubcredential + app.kubernetes.io/instance: githubcredential-sample app.kubernetes.io/part-of: garm-operator app.kubernetes.io/managed-by: kustomize app.kubernetes.io/created-by: garm-operator - name: githubcredentials-sample + name: githubcredential-sample spec: # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index d47ce1a4..0fef6a75 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -11,6 +11,6 @@ resources: - garm-operator_v1beta1_pool.yaml - garm-operator_v1beta1_image.yaml - garm-operator_v1beta1_githubendpoint.yaml - - garm-operator_v1beta1_githubcredentials.yaml + - garm-operator_v1beta1_githubcredential.yaml - garm-operator_v1beta1_garmserverconfig.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/internal/controller/enterprise_controller.go b/internal/controller/enterprise_controller.go index c17501b9..37ab0ad0 100644 --- a/internal/controller/enterprise_controller.go +++ b/internal/controller/enterprise_controller.go @@ -274,8 +274,8 @@ func (r *EnterpriseReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise *garmoperatorv1beta1.Enterprise) (*garmoperatorv1beta1.GitHubCredentials, error) { - creds := &garmoperatorv1beta1.GitHubCredentials{} +func (r *EnterpriseReconciler) getCredentialsRef(ctx context.Context, enterprise *garmoperatorv1beta1.Enterprise) (*garmoperatorv1beta1.GitHubCredential, error) { + creds := &garmoperatorv1beta1.GitHubCredential{} err := r.Get(ctx, types.NamespacedName{ Namespace: enterprise.Namespace, Name: enterprise.Spec.CredentialsRef.Name, @@ -295,7 +295,7 @@ func (r *EnterpriseReconciler) ensureFinalizer(ctx context.Context, enterprise * } func (r *EnterpriseReconciler) findEnterprisesForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredential) if !ok { return nil } @@ -325,7 +325,7 @@ func (r *EnterpriseReconciler) SetupWithManager(mgr ctrl.Manager, options contro return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1beta1.Enterprise{}). Watches( - &garmoperatorv1beta1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredential{}, handler.EnqueueRequestsFromMapFunc(r.findEnterprisesForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/enterprise_controller_test.go b/internal/controller/enterprise_controller_test.go index d991908d..d77225b8 100644 --- a/internal/controller/enterprise_controller_test.go +++ b/internal/controller/enterprise_controller_test.go @@ -50,7 +50,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -72,12 +72,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -99,7 +99,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -178,7 +178,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -200,12 +200,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -227,7 +227,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -306,7 +306,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -329,7 +329,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -381,12 +381,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -435,7 +435,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -455,7 +455,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -507,12 +507,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -570,7 +570,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -590,7 +590,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -642,12 +642,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -694,7 +694,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -716,12 +716,12 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -743,7 +743,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -830,7 +830,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -852,7 +852,7 @@ func TestEnterpriseReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -970,7 +970,7 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -992,12 +992,12 @@ func TestEnterpriseReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", diff --git a/internal/controller/githubcredentials_controller.go b/internal/controller/githubcredentials_controller.go index 7ebcf651..eb8ee25d 100644 --- a/internal/controller/githubcredentials_controller.go +++ b/internal/controller/githubcredentials_controller.go @@ -34,26 +34,26 @@ import ( "github.com/mercedes-benz/garm-operator/pkg/util" ) -// GitHubCredentialsReconciler reconciles a GitHubCredentials object -type GitHubCredentialsReconciler struct { +// GitHubCredentialReconciler reconciles a GitHubCredential object +type GitHubCredentialReconciler struct { client.Client Scheme *runtime.Scheme Recorder record.EventRecorder } //+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredentials/finalizers,verbs=update +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredential,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredential/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=garm-operator.mercedes-benz.com,namespace=xxxxx,resources=githubcredential/finalizers,verbs=update //+kubebuilder:rbac:groups="",namespace=xxxxx,resources=secrets,verbs=get;list;watch; -func (r *GitHubCredentialsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *GitHubCredentialReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - credentials := &garmoperatorv1beta1.GitHubCredentials{} + credentials := &garmoperatorv1beta1.GitHubCredential{} if err := r.Get(ctx, req.NamespacedName, credentials); err != nil { if apierrors.IsNotFound(err) { - log.Info("GitHubCredentials resource not found.") + log.Info("GitHubCredential resource not found.") return ctrl.Result{}, nil } return ctrl.Result{}, err @@ -75,11 +75,11 @@ func (r *GitHubCredentialsReconciler) Reconcile(ctx context.Context, req ctrl.Re return r.reconcileNormal(ctx, credentialsClient, credentials) } -func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials) (ctrl.Result, error) { +func (r *GitHubCredentialReconciler) reconcileNormal(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredential) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) - // If the GitHubCredentials doesn't have our finalizer, add it. + // If the GitHubCredential doesn't have our finalizer, add it. if err := r.ensureFinalizer(ctx, credentials); err != nil { return ctrl.Result{}, err } @@ -157,7 +157,7 @@ func (r *GitHubCredentialsReconciler) reconcileNormal(ctx context.Context, clien return ctrl.Result{}, nil } -func (r *GitHubCredentialsReconciler) getExistingCredentials(client garmClient.CredentialsClient, name string) (params.GithubCredentials, error) { +func (r *GitHubCredentialReconciler) getExistingCredentials(client garmClient.CredentialsClient, name string) (params.GithubCredentials, error) { credentials, err := client.ListCredentials(garmcredentials.NewListCredentialsParams()) if err != nil { return params.GithubCredentials{}, err @@ -172,11 +172,11 @@ func (r *GitHubCredentialsReconciler) getExistingCredentials(client garmClient.C return params.GithubCredentials{}, nil } -func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials, endpoint, githubSecret string) (params.GithubCredentials, error) { +func (r *GitHubCredentialReconciler) createCredentials(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredential, endpoint, githubSecret string) (params.GithubCredentials, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) - log.Info("GitHubCredentials doesn't exist on garm side. Creating new credentials in garm.") + log.Info("GitHubCredential doesn't exist on garm side. Creating new credentials in garm.") event.Creating(r.Recorder, credentials, "credentials doesn't exist on garm side") req := params.CreateGithubCredentialsParams{ @@ -211,7 +211,7 @@ func (r *GitHubCredentialsReconciler) createCredentials(ctx context.Context, cli return garmCredentials.Payload, nil } -func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, client garmClient.CredentialsClient, credentialsID int64, credentials *garmoperatorv1beta1.GitHubCredentials, githubSecret string) (params.GithubCredentials, error) { +func (r *GitHubCredentialReconciler) updateCredentials(ctx context.Context, client garmClient.CredentialsClient, credentialsID int64, credentials *garmoperatorv1beta1.GitHubCredential, githubSecret string) (params.GithubCredentials, error) { log := log.FromContext(ctx) log.V(1).Info("update credentials") @@ -245,7 +245,7 @@ func (r *GitHubCredentialsReconciler) updateCredentials(ctx context.Context, cli return retValue.Payload, nil } -func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredentials) (ctrl.Result, error) { +func (r *GitHubCredentialReconciler) reconcileDelete(ctx context.Context, client garmClient.CredentialsClient, credentials *garmoperatorv1beta1.GitHubCredential) (ctrl.Result, error) { log := log.FromContext(ctx) log.WithValues("credentials", credentials.Name) @@ -281,7 +281,7 @@ func (r *GitHubCredentialsReconciler) reconcileDelete(ctx context.Context, clien return ctrl.Result{}, nil } -func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredentials) (*garmoperatorv1beta1.GitHubEndpoint, error) { +func (r *GitHubCredentialReconciler) getEndpointRef(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredential) (*garmoperatorv1beta1.GitHubEndpoint, error) { endpoint := &garmoperatorv1beta1.GitHubEndpoint{} err := r.Get(ctx, types.NamespacedName{ Namespace: credentials.Namespace, @@ -293,7 +293,7 @@ func (r *GitHubCredentialsReconciler) getEndpointRef(ctx context.Context, creden return endpoint, nil } -func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredentials) error { +func (r *GitHubCredentialReconciler) ensureFinalizer(ctx context.Context, credentials *garmoperatorv1beta1.GitHubCredential) error { if !controllerutil.ContainsFinalizer(credentials, key.CredentialsFinalizerName) { controllerutil.AddFinalizer(credentials, key.CredentialsFinalizerName) return r.Update(ctx, credentials) @@ -301,13 +301,13 @@ func (r *GitHubCredentialsReconciler) ensureFinalizer(ctx context.Context, crede return nil } -func (r *GitHubCredentialsReconciler) findCredentialsForSecret(ctx context.Context, obj client.Object) []reconcile.Request { +func (r *GitHubCredentialReconciler) findCredentialsForSecret(ctx context.Context, obj client.Object) []reconcile.Request { secret, ok := obj.(*corev1.Secret) if !ok { return nil } - var creds garmoperatorv1beta1.GitHubCredentialsList + var creds garmoperatorv1beta1.GitHubCredentialList if err := r.List(ctx, &creds); err != nil { return nil } @@ -328,9 +328,9 @@ func (r *GitHubCredentialsReconciler) findCredentialsForSecret(ctx context.Conte } // SetupWithManager sets up the controller with the Manager. -func (r *GitHubCredentialsReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *GitHubCredentialReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&garmoperatorv1beta1.GitHubCredentials{}). + For(&garmoperatorv1beta1.GitHubCredential{}). Watches( &corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.findCredentialsForSecret), diff --git a/internal/controller/organization_controller.go b/internal/controller/organization_controller.go index ef03f272..aa4d37d4 100644 --- a/internal/controller/organization_controller.go +++ b/internal/controller/organization_controller.go @@ -272,8 +272,8 @@ func (r *OrganizationReconciler) reconcileDelete(ctx context.Context, client gar return ctrl.Result{}, nil } -func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *garmoperatorv1beta1.Organization) (*garmoperatorv1beta1.GitHubCredentials, error) { - creds := &garmoperatorv1beta1.GitHubCredentials{} +func (r *OrganizationReconciler) getCredentialsRef(ctx context.Context, org *garmoperatorv1beta1.Organization) (*garmoperatorv1beta1.GitHubCredential, error) { + creds := &garmoperatorv1beta1.GitHubCredential{} err := r.Get(ctx, types.NamespacedName{ Namespace: org.Namespace, Name: org.Spec.CredentialsRef.Name, @@ -293,7 +293,7 @@ func (r *OrganizationReconciler) ensureFinalizer(ctx context.Context, org *garmo } func (r *OrganizationReconciler) findOrgsForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredential) if !ok { return nil } @@ -323,7 +323,7 @@ func (r *OrganizationReconciler) SetupWithManager(mgr ctrl.Manager, options cont return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1beta1.Organization{}). Watches( - &garmoperatorv1beta1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredential{}, handler.EnqueueRequestsFromMapFunc(r.findOrgsForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/organization_controller_test.go b/internal/controller/organization_controller_test.go index 9c1435df..09a8ea4f 100644 --- a/internal/controller/organization_controller_test.go +++ b/internal/controller/organization_controller_test.go @@ -50,7 +50,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -72,12 +72,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -99,7 +99,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -178,7 +178,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -200,12 +200,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -227,7 +227,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -306,7 +306,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -328,12 +328,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -355,7 +355,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -435,7 +435,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -454,12 +454,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -481,7 +481,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -570,7 +570,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -589,12 +589,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -616,7 +616,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -694,7 +694,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -716,12 +716,12 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -743,7 +743,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -830,7 +830,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -852,7 +852,7 @@ func TestOrganizationReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -970,7 +970,7 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { Spec: garmoperatorv1beta1.OrganizationSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -992,12 +992,12 @@ func TestOrganizationReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", diff --git a/internal/controller/pool_controller_test.go b/internal/controller/pool_controller_test.go index 376e8c60..d7558e31 100644 --- a/internal/controller/pool_controller_test.go +++ b/internal/controller/pool_controller_test.go @@ -168,7 +168,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -377,7 +377,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -667,7 +667,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -1055,7 +1055,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -1204,7 +1204,7 @@ func TestPoolController_ReconcileCreate(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -1463,7 +1463,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -1679,7 +1679,7 @@ func TestPoolController_ReconcileDelete(t *testing.T) { Spec: garmoperatorv1beta1.EnterpriseSpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ diff --git a/internal/controller/repository_controller.go b/internal/controller/repository_controller.go index 89fae5da..cf8c92ce 100644 --- a/internal/controller/repository_controller.go +++ b/internal/controller/repository_controller.go @@ -273,8 +273,8 @@ func (r *RepositoryReconciler) reconcileDelete(ctx context.Context, client garmC return ctrl.Result{}, nil } -func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository *garmoperatorv1beta1.Repository) (*garmoperatorv1beta1.GitHubCredentials, error) { - creds := &garmoperatorv1beta1.GitHubCredentials{} +func (r *RepositoryReconciler) getCredentialsRef(ctx context.Context, repository *garmoperatorv1beta1.Repository) (*garmoperatorv1beta1.GitHubCredential, error) { + creds := &garmoperatorv1beta1.GitHubCredential{} err := r.Get(ctx, types.NamespacedName{ Namespace: repository.Namespace, Name: repository.Spec.CredentialsRef.Name, @@ -294,7 +294,7 @@ func (r *RepositoryReconciler) ensureFinalizer(ctx context.Context, pool *garmop } func (r *RepositoryReconciler) findReposForCredentials(ctx context.Context, obj client.Object) []reconcile.Request { - credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredentials) + credentials, ok := obj.(*garmoperatorv1beta1.GitHubCredential) if !ok { return nil } @@ -324,7 +324,7 @@ func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager, options contro return ctrl.NewControllerManagedBy(mgr). For(&garmoperatorv1beta1.Repository{}). Watches( - &garmoperatorv1beta1.GitHubCredentials{}, + &garmoperatorv1beta1.GitHubCredential{}, handler.EnqueueRequestsFromMapFunc(r.findReposForCredentials), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). diff --git a/internal/controller/repository_controller_test.go b/internal/controller/repository_controller_test.go index b169ac71..2c421c39 100644 --- a/internal/controller/repository_controller_test.go +++ b/internal/controller/repository_controller_test.go @@ -50,7 +50,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -73,12 +73,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -100,7 +100,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -182,7 +182,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, Owner: "test-repo", @@ -205,12 +205,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("has-changed"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "has-changed", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -232,7 +232,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "has-changed", }, Owner: "test-repo", @@ -314,7 +314,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -337,12 +337,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -364,7 +364,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -447,7 +447,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -467,12 +467,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -494,7 +494,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -588,7 +588,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -608,12 +608,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -635,7 +635,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -716,7 +716,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -739,12 +739,12 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat", @@ -766,7 +766,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, Owner: "test-repo", @@ -857,7 +857,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -879,7 +879,7 @@ func TestRepositoryReconciler_reconcileNormal(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -997,7 +997,7 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { Spec: garmoperatorv1beta1.RepositorySpec{ CredentialsRef: corev1.TypedLocalObjectReference{ APIGroup: &garmoperatorv1beta1.GroupVersion.Group, - Kind: "GitHubCredentials", + Kind: "GitHubCredential", Name: "github-creds", }, WebhookSecretRef: garmoperatorv1beta1.SecretRef{ @@ -1019,12 +1019,12 @@ func TestRepositoryReconciler_reconcileDelete(t *testing.T) { "webhookSecret": []byte("foobar"), }, }, - &garmoperatorv1beta1.GitHubCredentials{ + &garmoperatorv1beta1.GitHubCredential{ ObjectMeta: metav1.ObjectMeta{ Name: "github-creds", Namespace: "default", }, - Spec: garmoperatorv1beta1.GitHubCredentialsSpec{ + Spec: garmoperatorv1beta1.GitHubCredentialSpec{ Description: "github-creds", EndpointRef: corev1.TypedLocalObjectReference{}, AuthType: "pat",