diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index 784a694c5..99d190b58 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -192,7 +192,7 @@ metadata: ] capabilities: Seamless Upgrades containerImage: registry.redhat.io/rhtas/rhtas-rhel9-operator@sha256:a21f7128694a64989bf0d84a7a7da4c1ffc89edf62d594dc8bea7bcfe9ac08d3 - createdAt: "2024-06-12T14:09:20Z" + createdAt: "2024-06-14T12:17:18Z" features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" features.operators.openshift.io/csi: "false" diff --git a/internal/controller/common/action/base_action.go b/internal/controller/common/action/base_action.go index 84c5687fd..18b395731 100644 --- a/internal/controller/common/action/base_action.go +++ b/internal/controller/common/action/base_action.go @@ -70,8 +70,9 @@ func (action *BaseAction) FailedWithStatusUpdate(ctx context.Context, err error, } err = errors.Join(e, err) } - // Requeue will be caused by update - return &Result{Result: reconcile.Result{Requeue: false}, Err: err} + // Requeue is disabled for Failed objects + // wait for 30 second and invoke error-handler + return &Result{Result: reconcile.Result{RequeueAfter: 30 * time.Second}} } func (action *BaseAction) Return() *Result { diff --git a/internal/controller/constants/config.go b/internal/controller/constants/config.go index bc8dcf3df..761d45f7e 100644 --- a/internal/controller/constants/config.go +++ b/internal/controller/constants/config.go @@ -1,5 +1,5 @@ package constants var ( - CreateTreeDeadline int64 = 1200 + CreateTreeDeadline int64 = 30 ) diff --git a/internal/controller/rekor/actions/error.go b/internal/controller/rekor/actions/error.go new file mode 100644 index 000000000..e4512ca6f --- /dev/null +++ b/internal/controller/rekor/actions/error.go @@ -0,0 +1,62 @@ +package actions + +import ( + "context" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/common/action" + "github.com/securesign/operator/internal/controller/constants" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func NewHandleErrorAction() action.Action[rhtasv1alpha1.Rekor] { + return &handleErrorAction{} +} + +type handleErrorAction struct { + action.BaseAction +} + +func (i handleErrorAction) Name() string { + return "error handler" +} + +func (i handleErrorAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } + return c.Reason == constants.Failure +} + +func (i handleErrorAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { + i.Recorder.Event(instance, v1.EventTypeWarning, constants.Failure, "Restarted by error handler") + + newStatus := rhtasv1alpha1.RekorStatus{} + + // - keep the status.treeId if not nil + newStatus.TreeID = instance.Status.TreeID + // - keep the status.pvcName if not nil + newStatus.PvcName = instance.Status.PvcName + + if meta.IsStatusConditionTrue(instance.Status.Conditions, SignerCondition) { + instance.Status.Signer.DeepCopyInto(&newStatus.Signer) + newStatus.Conditions = append(newStatus.Conditions, *meta.FindStatusCondition(instance.Status.Conditions, SignerCondition)) + } + + if meta.IsStatusConditionTrue(instance.Status.Conditions, ServerCondition) { + instance.Status.ServerConfigRef.DeepCopyInto(newStatus.ServerConfigRef) + // do not append server condition - let controller to redeploy + } + + meta.SetStatusCondition(&newStatus.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Pending, + Message: "Restarted by error handler", + }) + instance.Status = newStatus + return i.StatusUpdate(ctx, instance) +} diff --git a/internal/controller/rekor/actions/pending.go b/internal/controller/rekor/actions/pending.go index b952efa23..9cda6d34c 100644 --- a/internal/controller/rekor/actions/pending.go +++ b/internal/controller/rekor/actions/pending.go @@ -26,6 +26,9 @@ func (i pendingAction) Name() string { func (i pendingAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Pending } diff --git a/internal/controller/rekor/actions/rbac.go b/internal/controller/rekor/actions/rbac.go index 835bd875b..ef1dd9c06 100644 --- a/internal/controller/rekor/actions/rbac.go +++ b/internal/controller/rekor/actions/rbac.go @@ -29,6 +29,9 @@ func (i rbacAction) Name() string { func (i rbacAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating || c.Reason == constants.Ready } diff --git a/internal/controller/rekor/actions/server/createTree.go b/internal/controller/rekor/actions/server/createTree.go index 393cac6de..56522ed3d 100644 --- a/internal/controller/rekor/actions/server/createTree.go +++ b/internal/controller/rekor/actions/server/createTree.go @@ -30,6 +30,9 @@ func (i createTrillianTreeAction) Name() string { func (i createTrillianTreeAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating && instance.Status.TreeID == nil } diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 68abfac70..ac7cb745a 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -29,6 +29,9 @@ func (i deployAction) Name() string { func (i deployAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating || c.Reason == constants.Ready } diff --git a/internal/controller/rekor/actions/server/generate_signer.go b/internal/controller/rekor/actions/server/generate_signer.go index 1098bb84d..be26836a6 100644 --- a/internal/controller/rekor/actions/server/generate_signer.go +++ b/internal/controller/rekor/actions/server/generate_signer.go @@ -43,6 +43,9 @@ func (g generateSigner) Name() string { func (g generateSigner) CanHandle(_ context.Context, instance *v1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } if c.Reason != constants.Pending && c.Reason != constants.Ready { return false } @@ -165,12 +168,6 @@ func (g generateSigner) Handle(ctx context.Context, instance *v1alpha1.Rekor) *a } else { instance.Status.Signer.PasswordRef = instance.Spec.Signer.PasswordRef } - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Creating, - Message: "Signer resolved", - }) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, Status: metav1.ConditionFalse, diff --git a/internal/controller/rekor/actions/server/ingress.go b/internal/controller/rekor/actions/server/ingress.go index 0c52ebbe8..c9a00c7a6 100644 --- a/internal/controller/rekor/actions/server/ingress.go +++ b/internal/controller/rekor/actions/server/ingress.go @@ -30,6 +30,9 @@ func (i ingressAction) Name() string { func (i ingressAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return (c.Reason == constants.Creating || c.Reason == constants.Ready) && instance.Spec.ExternalAccess.Enabled } diff --git a/internal/controller/rekor/actions/server/initialize.go b/internal/controller/rekor/actions/server/initialize.go index 24dd56ea8..225f69ceb 100644 --- a/internal/controller/rekor/actions/server/initialize.go +++ b/internal/controller/rekor/actions/server/initialize.go @@ -26,6 +26,9 @@ func (i initializeAction) Name() string { func (i initializeAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Initialize && !meta.IsStatusConditionTrue(instance.Status.Conditions, actions.ServerCondition) } diff --git a/internal/controller/rekor/actions/server/monitoring.go b/internal/controller/rekor/actions/server/monitoring.go index 6919431cd..0529c514a 100644 --- a/internal/controller/rekor/actions/server/monitoring.go +++ b/internal/controller/rekor/actions/server/monitoring.go @@ -30,6 +30,9 @@ func (i monitoringAction) Name() string { func (i monitoringAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return (c.Reason == constants.Creating || c.Reason == constants.Ready) && instance.Spec.Monitoring.Enabled } diff --git a/internal/controller/rekor/actions/server/pvc.go b/internal/controller/rekor/actions/server/pvc.go index f0e33cef3..93d0cf03b 100644 --- a/internal/controller/rekor/actions/server/pvc.go +++ b/internal/controller/rekor/actions/server/pvc.go @@ -34,6 +34,9 @@ func (i createPvcAction) Name() string { func (i createPvcAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating && instance.Status.PvcName == "" } diff --git a/internal/controller/rekor/actions/server/resolve_pub_key.go b/internal/controller/rekor/actions/server/resolve_pub_key.go index a958bb303..6ceb4b863 100644 --- a/internal/controller/rekor/actions/server/resolve_pub_key.go +++ b/internal/controller/rekor/actions/server/resolve_pub_key.go @@ -37,6 +37,9 @@ func (i resolvePubKeyAction) Name() string { func (i resolvePubKeyAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } if (c.Reason != constants.Initialize && c.Reason != constants.Ready) || !meta.IsStatusConditionTrue(instance.Status.Conditions, actions.ServerCondition) { return false } diff --git a/internal/controller/rekor/actions/server/servrConfig.go b/internal/controller/rekor/actions/server/servrConfig.go index 4880598ad..12f7f0b45 100644 --- a/internal/controller/rekor/actions/server/servrConfig.go +++ b/internal/controller/rekor/actions/server/servrConfig.go @@ -32,6 +32,9 @@ func (i serverConfig) Name() string { func (i serverConfig) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating && instance.Status.ServerConfigRef == nil } diff --git a/internal/controller/rekor/actions/server/status_url.go b/internal/controller/rekor/actions/server/status_url.go index 846b74712..a03e66b37 100644 --- a/internal/controller/rekor/actions/server/status_url.go +++ b/internal/controller/rekor/actions/server/status_url.go @@ -28,6 +28,9 @@ func (i statusUrlAction) Name() string { func (i statusUrlAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating || c.Reason == constants.Ready } diff --git a/internal/controller/rekor/actions/server/svc.go b/internal/controller/rekor/actions/server/svc.go index 1514eeef1..1847402a0 100644 --- a/internal/controller/rekor/actions/server/svc.go +++ b/internal/controller/rekor/actions/server/svc.go @@ -31,6 +31,9 @@ func (i createServiceAction) Name() string { func (i createServiceAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating || c.Reason == constants.Ready } diff --git a/internal/controller/rekor/actions/transitions/to_create_phase.go b/internal/controller/rekor/actions/transitions/to_create_phase.go new file mode 100644 index 000000000..ef1b64677 --- /dev/null +++ b/internal/controller/rekor/actions/transitions/to_create_phase.go @@ -0,0 +1,39 @@ +package transitions + +import ( + "context" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/common/action" + "github.com/securesign/operator/internal/controller/constants" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func NewToCreateAction() action.Action[rhtasv1alpha1.Rekor] { + return &toCreateAction{} +} + +type toCreateAction struct { + action.BaseAction +} + +func (i toCreateAction) Name() string { + return "move to create phase" +} + +func (i toCreateAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } + return c.Reason == constants.Pending +} + +func (i toCreateAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { + + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + Status: metav1.ConditionFalse, Reason: constants.Creating}) + + return i.StatusUpdate(ctx, instance) +} diff --git a/internal/controller/rekor/actions/to_initialize_phase.go b/internal/controller/rekor/actions/transitions/to_initialize_phase.go similarity index 95% rename from internal/controller/rekor/actions/to_initialize_phase.go rename to internal/controller/rekor/actions/transitions/to_initialize_phase.go index a467763e4..4d88981d0 100644 --- a/internal/controller/rekor/actions/to_initialize_phase.go +++ b/internal/controller/rekor/actions/transitions/to_initialize_phase.go @@ -1,4 +1,4 @@ -package actions +package transitions import ( "context" @@ -24,6 +24,9 @@ func (i toInitializeAction) Name() string { func (i toInitializeAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + if c == nil { + return false + } return c.Reason == constants.Creating } diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index e452e23a8..bc1f48b6f 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -21,15 +21,20 @@ import ( olpredicate "github.com/operator-framework/operator-lib/predicate" "github.com/securesign/operator/internal/controller/annotations" - + "github.com/securesign/operator/internal/controller/constants" actions2 "github.com/securesign/operator/internal/controller/rekor/actions" backfillredis "github.com/securesign/operator/internal/controller/rekor/actions/backfillRedis" "github.com/securesign/operator/internal/controller/rekor/actions/redis" "github.com/securesign/operator/internal/controller/rekor/actions/server" + "github.com/securesign/operator/internal/controller/rekor/actions/transitions" "github.com/securesign/operator/internal/controller/rekor/actions/ui" v13 "k8s.io/api/core/v1" v1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" "github.com/securesign/operator/internal/controller/common/action" v12 "k8s.io/api/apps/v1" @@ -88,6 +93,9 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl } target := instance.DeepCopy() actions := []action.Action[rhtasv1alpha1.Rekor]{ + // register error handler + actions2.NewHandleErrorAction(), + // NONE -> PENDING actions2.NewInitializeConditions(), @@ -96,6 +104,7 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl // PENDING -> CREATE server.NewGenerateSignerAction(), + transitions.NewToCreateAction(), // CREATE actions2.NewRBACAction(), server.NewServerConfigAction(), @@ -117,7 +126,7 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl backfillredis.NewBackfillRedisCronJobAction(), // CREATE -> INITIALIZE - actions2.NewToInitializeAction(), + transitions.NewToInitializeAction(), // INITIALIZE server.NewInitializeAction(), server.NewResolvePubKeyAction(), @@ -155,7 +164,17 @@ func (r *RekorReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). WithEventFilter(pause). - For(&rhtasv1alpha1.Rekor{}). + For(&rhtasv1alpha1.Rekor{}, builder.WithPredicates(predicate.Funcs{UpdateFunc: func(event event.UpdateEvent) bool { + // do not requeue failed object updates + rekor, ok := event.ObjectNew.(*rhtasv1alpha1.Rekor) + if !ok { + return false + } + if c := meta.FindStatusCondition(rekor.Status.Conditions, constants.Ready); c != nil { + return c.Reason != constants.Failure + } + return true + }})). Owns(&v12.Deployment{}). Owns(&v13.Service{}). Owns(&v1.Ingress{}). diff --git a/internal/controller/rekor/rekor_error_handler_test.go b/internal/controller/rekor/rekor_error_handler_test.go new file mode 100644 index 000000000..45caf07ea --- /dev/null +++ b/internal/controller/rekor/rekor_error_handler_test.go @@ -0,0 +1,178 @@ +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rekor + +import ( + "context" + "time" + + "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + trillian "github.com/securesign/operator/internal/controller/trillian/actions" + appsv1 "k8s.io/api/apps/v1" + runtimeClient "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/constants" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Rekor ErrorHandler", func() { + Context("Rekor ErrorHandler test", func() { + + const ( + Name = "test" + Namespace = "default" + ) + + ctx := context.Background() + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: Name, + Namespace: Namespace, + }, + } + + typeNamespaceName := types.NamespacedName{Name: Name, Namespace: Namespace} + instance := &v1alpha1.Rekor{} + + BeforeEach(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterEach(func() { + By("removing the custom resource for the Kind Rekor") + found := &v1alpha1.Rekor{} + err := k8sClient.Get(ctx, typeNamespaceName, found) + Expect(err).To(Not(HaveOccurred())) + + Eventually(func() error { + return k8sClient.Delete(context.TODO(), found) + }, 2*time.Minute, time.Second).Should(Succeed()) + + // TODO(user): Attention if you improve this code by adding other context test you MUST + // be aware of the current delete namespace limitations. + // More info: https://book.kubebuilder.io/reference/envtest.html#testing-considerations + By("Deleting the Namespace to perform the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + It("should successfully reconcile a custom resource for Rekor", func() { + By("creating the custom resource for the Kind Rekor") + err := k8sClient.Get(ctx, typeNamespaceName, instance) + if err != nil && errors.IsNotFound(err) { + // Let's mock our custom resource at the same way that we would + // apply on the cluster the manifest under config/samples + instance := &v1alpha1.Rekor{ + ObjectMeta: metav1.ObjectMeta{ + Name: Name, + Namespace: Namespace, + }, + Spec: v1alpha1.RekorSpec{ + ExternalAccess: v1alpha1.ExternalAccess{ + Enabled: true, + Host: "rekor.local", + }, + RekorSearchUI: v1alpha1.RekorSearchUI{ + Enabled: utils.Pointer(true), + }, + BackFillRedis: v1alpha1.BackFillRedis{ + Enabled: utils.Pointer(true), + Schedule: "0 0 * * *", + }, + }, + } + err = k8sClient.Create(ctx, instance) + Expect(err).To(Not(HaveOccurred())) + } + err = k8sClient.Create(ctx, kubernetes.CreateService(Namespace, trillian.LogserverDeploymentName, 8090, instance.Labels)) + Expect(err).To(Not(HaveOccurred())) + + found := &v1alpha1.Rekor{} + + By("Deployment should fail") + Eventually(func() string { + + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + condition := meta.FindStatusCondition(found.Status.Conditions, constants.Ready) + if condition == nil { + return "" + } + return condition.Reason + }).Should(Equal(constants.Failure)) + + // persist signer name + signerName := found.Status.Signer.KeyRef.Name + Expect(signerName).To(Not(BeEmpty())) + + By("Periodically trying to restart deployment") + Eventually(func() string { + found := &v1alpha1.Rekor{} + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + return meta.FindStatusCondition(found.Status.Conditions, constants.Ready).Reason + }).Should(Not(Equal(constants.Failure))) + Eventually(func() string { + found := &v1alpha1.Rekor{} + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + return meta.FindStatusCondition(found.Status.Conditions, constants.Ready).Reason + }).Should(Equal(constants.Failure)) + + By("After fixing the problem the Rekor instance is Ready") + Eventually(func() error { + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + found.Spec.TreeID = utils.Pointer(int64(1)) + return k8sClient.Update(ctx, found) + }).Should(Succeed()) + + By("Waiting until Rekor instance is Initialization") + Eventually(func() string { + found := &v1alpha1.Rekor{} + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + return meta.FindStatusCondition(found.Status.Conditions, constants.Ready).Reason + }).Should(Equal(constants.Initialize)) + + deployments := &appsv1.DeploymentList{} + Expect(k8sClient.List(ctx, deployments, runtimeClient.InNamespace(Namespace))).To(Succeed()) + By("Move to Ready phase") + for _, d := range deployments.Items { + d.Status.Conditions = []appsv1.DeploymentCondition{ + {Status: corev1.ConditionTrue, Type: appsv1.DeploymentAvailable, Reason: constants.Ready}} + Expect(k8sClient.Status().Update(ctx, &d)).Should(Succeed()) + } + // Workaround to succeed condition for Ready phase + + Eventually(func() bool { + found := &v1alpha1.Rekor{} + Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) + return meta.IsStatusConditionTrue(found.Status.Conditions, constants.Ready) + }).Should(BeTrue()) + + By("Pregenerated resources are reused") + Expect(signerName).To(Equal(found.Status.Signer.KeyRef.Name)) + }) + }) +})