github.com/redhat-appstudio/release-service@v0.0.0-20240507045911-a8558ef3422a/controllers/releaseplan/adapter.go (about) 1 /* 2 Copyright 2022. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package releaseplan 18 19 import ( 20 "context" 21 "reflect" 22 "time" 23 24 "github.com/go-logr/logr" 25 "github.com/konflux-ci/operator-toolkit/controller" 26 "github.com/redhat-appstudio/release-service/api/v1alpha1" 27 "github.com/redhat-appstudio/release-service/loader" 28 "github.com/redhat-appstudio/release-service/syncer" 29 "k8s.io/apimachinery/pkg/api/errors" 30 "k8s.io/apimachinery/pkg/api/meta" 31 ctrl "sigs.k8s.io/controller-runtime" 32 "sigs.k8s.io/controller-runtime/pkg/client" 33 ) 34 35 // adapter holds the objects needed to reconcile a ReleasePlan. 36 type adapter struct { 37 client client.Client 38 ctx context.Context 39 loader loader.ObjectLoader 40 logger *logr.Logger 41 releasePlan *v1alpha1.ReleasePlan 42 syncer *syncer.Syncer 43 } 44 45 // newAdapter creates and returns an adapter instance. 46 func newAdapter(ctx context.Context, client client.Client, releasePlan *v1alpha1.ReleasePlan, loader loader.ObjectLoader, logger *logr.Logger) *adapter { 47 return &adapter{ 48 client: client, 49 ctx: ctx, 50 loader: loader, 51 logger: logger, 52 releasePlan: releasePlan, 53 syncer: syncer.NewSyncerWithContext(client, logger, ctx), 54 } 55 } 56 57 // EnsureOwnerReferenceIsSet is an operation that will ensure that the owner reference is set. 58 // If the Application who owns the ReleasePlan is not found, the error will be ignored and the 59 // ReleasePlan will be reconciled again after a minute. 60 func (a *adapter) EnsureOwnerReferenceIsSet() (controller.OperationResult, error) { 61 if len(a.releasePlan.OwnerReferences) > 0 { 62 return controller.ContinueProcessing() 63 } 64 65 application, err := a.loader.GetApplication(a.ctx, a.client, a.releasePlan) 66 if err != nil { 67 if errors.IsNotFound(err) { 68 return controller.RequeueAfter(time.Minute, nil) 69 } 70 return controller.RequeueWithError(err) 71 } 72 73 patch := client.MergeFrom(a.releasePlan.DeepCopy()) 74 err = ctrl.SetControllerReference(application, a.releasePlan, a.client.Scheme()) 75 if err != nil { 76 return controller.RequeueWithError(err) 77 } 78 79 err = a.client.Patch(a.ctx, a.releasePlan, patch) 80 if err != nil && !errors.IsNotFound(err) { 81 return controller.RequeueWithError(err) 82 } 83 84 return controller.ContinueProcessing() 85 } 86 87 // EnsureMatchingInformationIsSet is an operation that will ensure that the ReleasePlan has updated matching 88 // information in its status. 89 func (a *adapter) EnsureMatchingInformationIsSet() (controller.OperationResult, error) { 90 // If an error occurs getting the ReleasePlanAdmission, mark the ReleasePlan as unmatched 91 releasePlanAdmission, _ := a.loader.GetMatchingReleasePlanAdmission(a.ctx, a.client, a.releasePlan) 92 93 copiedReleasePlan := a.releasePlan.DeepCopy() 94 patch := client.MergeFrom(a.releasePlan.DeepCopy()) 95 96 if releasePlanAdmission == nil { 97 a.releasePlan.MarkUnmatched() 98 } else { 99 a.releasePlan.MarkMatched(releasePlanAdmission) 100 } 101 102 // If there is no change in the matched ReleasePlanAdmission and the Matched condition is present 103 // (in case it is a new ReleasePlan going from matched to nil -> matched to nil), do not patch 104 if reflect.DeepEqual(copiedReleasePlan.Status.ReleasePlanAdmission, a.releasePlan.Status.ReleasePlanAdmission) && 105 meta.FindStatusCondition(copiedReleasePlan.Status.Conditions, v1alpha1.MatchedConditionType.String()) != nil { 106 return controller.ContinueProcessing() 107 } 108 109 return controller.RequeueOnErrorOrContinue(a.client.Status().Patch(a.ctx, a.releasePlan, patch)) 110 }