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  }