github.com/redhat-appstudio/release-service@v0.0.0-20240507045911-a8558ef3422a/controllers/release/adapter_test.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 release
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"os"
    23  	"reflect"
    24  	"strings"
    25  	"time"
    26  	"unicode"
    27  
    28  	tektonutils "github.com/redhat-appstudio/release-service/tekton/utils"
    29  
    30  	"github.com/konflux-ci/operator-toolkit/controller"
    31  	toolkit "github.com/konflux-ci/operator-toolkit/loader"
    32  	. "github.com/onsi/ginkgo/v2"
    33  	. "github.com/onsi/gomega"
    34  	"github.com/operator-framework/operator-lib/handler"
    35  	"github.com/redhat-appstudio/release-service/api/v1alpha1"
    36  	"github.com/redhat-appstudio/release-service/loader"
    37  	"github.com/redhat-appstudio/release-service/metadata"
    38  	tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
    39  	corev1 "k8s.io/api/core/v1"
    40  	rbac "k8s.io/api/rbac/v1"
    41  	"k8s.io/apimachinery/pkg/runtime/schema"
    42  	"k8s.io/apimachinery/pkg/types"
    43  
    44  	ecapiv1alpha1 "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
    45  	applicationapiv1alpha1 "github.com/redhat-appstudio/application-api/api/v1alpha1"
    46  
    47  	"k8s.io/apimachinery/pkg/api/errors"
    48  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    49  	ctrl "sigs.k8s.io/controller-runtime"
    50  )
    51  
    52  var _ = Describe("Release adapter", Ordered, func() {
    53  	var (
    54  		createReleaseAndAdapter func() *adapter
    55  		createResources         func()
    56  		deleteResources         func()
    57  
    58  		application                 *applicationapiv1alpha1.Application
    59  		component                   *applicationapiv1alpha1.Component
    60  		enterpriseContractConfigMap *corev1.ConfigMap
    61  		enterpriseContractPolicy    *ecapiv1alpha1.EnterpriseContractPolicy
    62  		releasePlan                 *v1alpha1.ReleasePlan
    63  		releasePlanAdmission        *v1alpha1.ReleasePlanAdmission
    64  		releaseServiceConfig        *v1alpha1.ReleaseServiceConfig
    65  		roleBinding                 *rbac.RoleBinding
    66  		snapshot                    *applicationapiv1alpha1.Snapshot
    67  	)
    68  
    69  	AfterAll(func() {
    70  		deleteResources()
    71  	})
    72  
    73  	BeforeAll(func() {
    74  		Expect(os.Setenv("DEFAULT_RELEASE_WORKSPACE_NAME", "release-workspace")).To(Succeed())
    75  		Expect(os.Setenv("DEFAULT_RELEASE_WORKSPACE_SIZE", "1Gi")).To(Succeed())
    76  
    77  		createResources()
    78  	})
    79  
    80  	When("newAdapter is called", func() {
    81  		It("creates and return a new adapter", func() {
    82  			Expect(reflect.TypeOf(newAdapter(ctx, k8sClient, nil, loader.NewLoader(), &ctrl.Log))).To(Equal(reflect.TypeOf(&adapter{})))
    83  		})
    84  	})
    85  
    86  	Context("When calling EnsureConfigIsLoaded", func() {
    87  		var adapter *adapter
    88  
    89  		AfterEach(func() {
    90  			_ = adapter.client.Delete(ctx, adapter.release)
    91  		})
    92  
    93  		BeforeEach(func() {
    94  			adapter = createReleaseAndAdapter()
    95  		})
    96  
    97  		It("returns an error if SERVICE_NAMESPACE is not set", func() {
    98  			adapter.release.MarkReleasing("")
    99  			result, err := adapter.EnsureConfigIsLoaded()
   100  			Expect(!result.RequeueRequest && result.CancelRequest).To(BeTrue())
   101  			Expect(err).NotTo(HaveOccurred())
   102  			Expect(adapter.release.IsValid()).To(BeFalse())
   103  			Expect(adapter.release.HasReleaseFinished()).To(BeTrue())
   104  			Expect(adapter.releaseServiceConfig).To(BeNil())
   105  		})
   106  
   107  		It("loads the ReleaseServiceConfig and assigns it to the adapter", func() {
   108  			os.Setenv("SERVICE_NAMESPACE", "default")
   109  			result, err := adapter.EnsureConfigIsLoaded()
   110  			Expect(!result.CancelRequest && !result.RequeueRequest).To(BeTrue())
   111  			Expect(err).To(BeNil())
   112  			Expect(adapter.releaseServiceConfig).NotTo(BeNil())
   113  			Expect(adapter.releaseServiceConfig.Namespace).To(Equal("default"))
   114  		})
   115  
   116  		It("creates and assigns an empty ReleaseServiceConfig if none is found", func() {
   117  			os.Setenv("SERVICE_NAMESPACE", "test")
   118  			result, err := adapter.EnsureConfigIsLoaded()
   119  			Expect(!result.CancelRequest && !result.RequeueRequest).To(BeTrue())
   120  			Expect(err).To(BeNil())
   121  			Expect(adapter.releaseServiceConfig).NotTo(BeNil())
   122  			Expect(adapter.releaseServiceConfig.Namespace).To(Equal("test"))
   123  		})
   124  	})
   125  
   126  	When("EnsureFinalizersAreCalled is called", func() {
   127  		var adapter *adapter
   128  
   129  		AfterEach(func() {
   130  			_ = adapter.client.Delete(ctx, adapter.release)
   131  		})
   132  
   133  		BeforeEach(func() {
   134  			adapter = createReleaseAndAdapter()
   135  			adapter.releaseServiceConfig = releaseServiceConfig
   136  		})
   137  
   138  		It("should do nothing if the Release is not set to be deleted", func() {
   139  			result, err := adapter.EnsureFinalizersAreCalled()
   140  			Expect(err).NotTo(HaveOccurred())
   141  			Expect(!result.CancelRequest && !result.RequeueRequest).To(BeTrue())
   142  		})
   143  
   144  		It("should finalize the Release if it's set to be deleted and it has a finalizer", func() {
   145  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   146  				{
   147  					ContextKey: loader.ProcessingResourcesContextKey,
   148  					Resource: &loader.ProcessingResources{
   149  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   150  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   151  						ReleasePlan:                 releasePlan,
   152  						ReleasePlanAdmission:        releasePlanAdmission,
   153  						Snapshot:                    snapshot,
   154  					},
   155  				},
   156  				{
   157  					ContextKey: loader.RoleBindingContextKey,
   158  					Resource:   roleBinding,
   159  				},
   160  			})
   161  			result, err := adapter.EnsureFinalizerIsAdded()
   162  			Expect(!result.RequeueRequest && result.CancelRequest).To(BeFalse())
   163  			Expect(err).NotTo(HaveOccurred())
   164  			Expect(adapter.release.Finalizers).To(HaveLen(1))
   165  
   166  			result, err = adapter.EnsureReleaseIsProcessed()
   167  			Expect(!result.RequeueRequest && result.CancelRequest).To(BeFalse())
   168  			Expect(err).NotTo(HaveOccurred())
   169  
   170  			Expect(adapter.client.Delete(adapter.ctx, adapter.release)).To(Succeed())
   171  			adapter.release, err = adapter.loader.GetRelease(adapter.ctx, adapter.client, adapter.release.Name, adapter.release.Namespace)
   172  			Expect(adapter.release).NotTo(BeNil())
   173  			Expect(err).NotTo(HaveOccurred())
   174  			Expect(adapter.release.DeletionTimestamp).NotTo(BeNil())
   175  
   176  			result, err = adapter.EnsureFinalizersAreCalled()
   177  			Expect(result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   178  			Expect(err).NotTo(HaveOccurred())
   179  
   180  			pipelineRun, err := adapter.loader.GetManagedReleasePipelineRun(adapter.ctx, adapter.client, adapter.release)
   181  			Expect(pipelineRun).To(Or(BeNil(), HaveField("DeletionTimestamp", Not(BeNil()))))
   182  			Expect(err).NotTo(HaveOccurred())
   183  
   184  			_, err = adapter.loader.GetRelease(adapter.ctx, adapter.client, adapter.release.Name, adapter.release.Namespace)
   185  			Expect(err).To(HaveOccurred())
   186  			Expect(errors.IsNotFound(err)).To(BeTrue())
   187  		})
   188  	})
   189  
   190  	When("EnsureFinalizerIsAdded is called", func() {
   191  		var adapter *adapter
   192  
   193  		AfterEach(func() {
   194  			_ = adapter.client.Delete(ctx, adapter.release)
   195  		})
   196  
   197  		BeforeEach(func() {
   198  			adapter = createReleaseAndAdapter()
   199  		})
   200  
   201  		It("should add a finalizer to the Release", func() {
   202  			result, err := adapter.EnsureFinalizerIsAdded()
   203  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   204  			Expect(err).NotTo(HaveOccurred())
   205  			Expect(adapter.release.Finalizers).To(ContainElement(metadata.ReleaseFinalizer))
   206  		})
   207  
   208  		It("shouldn't fail if the Release already has the finalizer added", func() {
   209  			result, err := adapter.EnsureFinalizerIsAdded()
   210  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   211  			Expect(err).NotTo(HaveOccurred())
   212  			Expect(adapter.release.Finalizers).To(ContainElement(metadata.ReleaseFinalizer))
   213  
   214  			result, err = adapter.EnsureFinalizerIsAdded()
   215  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   216  			Expect(err).NotTo(HaveOccurred())
   217  		})
   218  	})
   219  
   220  	When("EnsureReleaseIsCompleted is called", func() {
   221  		var adapter *adapter
   222  
   223  		AfterEach(func() {
   224  			_ = adapter.client.Delete(ctx, adapter.release)
   225  		})
   226  
   227  		BeforeEach(func() {
   228  			adapter = createReleaseAndAdapter()
   229  			adapter.release.MarkReleasing("")
   230  		})
   231  
   232  		It("should not change the release status if it's set already", func() {
   233  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   234  				{
   235  					ContextKey: loader.ReleasePlanAdmissionContextKey,
   236  					Resource:   releasePlanAdmission,
   237  				},
   238  			})
   239  			adapter.release.MarkProcessing("")
   240  			adapter.release.MarkProcessed()
   241  			adapter.release.MarkReleaseFailed("")
   242  			result, err := adapter.EnsureReleaseIsCompleted()
   243  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   244  			Expect(err).NotTo(HaveOccurred())
   245  			Expect(adapter.release.HasReleaseFinished()).To(BeTrue())
   246  			Expect(adapter.release.IsReleased()).To(BeFalse())
   247  		})
   248  
   249  		It("should do nothing if the processing has not completed", func() {
   250  			result, err := adapter.EnsureReleaseIsCompleted()
   251  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   252  			Expect(err).NotTo(HaveOccurred())
   253  			Expect(adapter.release.HasReleaseFinished()).To(BeFalse())
   254  		})
   255  
   256  		It("should complete the release if all the required phases have completed", func() {
   257  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   258  				{
   259  					ContextKey: loader.ReleasePlanAdmissionContextKey,
   260  					Resource:   releasePlanAdmission,
   261  				},
   262  			})
   263  			adapter.release.MarkProcessing("")
   264  			adapter.release.MarkProcessed()
   265  			result, err := adapter.EnsureReleaseIsCompleted()
   266  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   267  			Expect(err).NotTo(HaveOccurred())
   268  			Expect(adapter.release.HasReleaseFinished()).To(BeTrue())
   269  		})
   270  	})
   271  
   272  	When("EnsureReleaseIsRunning is called", func() {
   273  		var adapter *adapter
   274  
   275  		AfterEach(func() {
   276  			_ = adapter.client.Delete(ctx, adapter.release)
   277  		})
   278  
   279  		BeforeEach(func() {
   280  			adapter = createReleaseAndAdapter()
   281  		})
   282  
   283  		It("should stop processing if the release has finished", func() {
   284  			adapter.release.MarkReleasing("")
   285  			adapter.release.MarkReleased()
   286  
   287  			result, err := adapter.EnsureReleaseIsRunning()
   288  			Expect(!result.RequeueRequest && result.CancelRequest).To(BeTrue())
   289  			Expect(err).NotTo(HaveOccurred())
   290  		})
   291  
   292  		It("should mark the Release as releasing if it is missing the status", func() {
   293  			result, err := adapter.EnsureReleaseIsRunning()
   294  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   295  			Expect(err).NotTo(HaveOccurred())
   296  			Expect(adapter.release.IsReleasing()).To(BeTrue())
   297  		})
   298  
   299  		It("should do nothing if the release is already running", func() {
   300  			adapter.release.MarkReleasing("")
   301  
   302  			result, err := adapter.EnsureReleaseIsRunning()
   303  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   304  			Expect(err).NotTo(HaveOccurred())
   305  			Expect(adapter.release.IsReleasing()).To(BeTrue())
   306  		})
   307  	})
   308  
   309  	When("EnsureReleaseIsProcessed is called", func() {
   310  		var adapter *adapter
   311  
   312  		AfterEach(func() {
   313  			_ = adapter.client.Delete(ctx, adapter.release)
   314  		})
   315  
   316  		BeforeEach(func() {
   317  			adapter = createReleaseAndAdapter()
   318  			adapter.releaseServiceConfig = releaseServiceConfig
   319  		})
   320  
   321  		It("should do nothing if the Release is already processed", func() {
   322  			adapter.release.MarkProcessing("")
   323  			adapter.release.MarkProcessed()
   324  
   325  			result, err := adapter.EnsureReleaseIsProcessed()
   326  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   327  			Expect(err).NotTo(HaveOccurred())
   328  			Expect(adapter.release.IsProcessing()).To(BeFalse())
   329  		})
   330  
   331  		It("should continue if the PipelineRun exists and the release processing has started", func() {
   332  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   333  				{
   334  					ContextKey: loader.ReleasePipelineRunContextKey,
   335  					Resource: &tektonv1.PipelineRun{
   336  						ObjectMeta: metav1.ObjectMeta{
   337  							Name:      "pipeline-run",
   338  							Namespace: "default",
   339  						},
   340  					},
   341  				},
   342  				{
   343  					ContextKey: loader.RoleBindingContextKey,
   344  					Resource:   roleBinding,
   345  				},
   346  			})
   347  			adapter.release.MarkProcessing("")
   348  
   349  			result, err := adapter.EnsureReleaseIsProcessed()
   350  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   351  			Expect(err).NotTo(HaveOccurred())
   352  		})
   353  
   354  		It("should register the processing data if the PipelineRun already exists", func() {
   355  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   356  				{
   357  					ContextKey: loader.ReleasePipelineRunContextKey,
   358  					Resource: &tektonv1.PipelineRun{
   359  						ObjectMeta: metav1.ObjectMeta{
   360  							Name:      "pipeline-run",
   361  							Namespace: "default",
   362  						},
   363  					},
   364  				},
   365  				{
   366  					ContextKey: loader.RoleBindingContextKey,
   367  					Resource:   roleBinding,
   368  				},
   369  				{
   370  					ContextKey: loader.ProcessingResourcesContextKey,
   371  					Resource: &loader.ProcessingResources{
   372  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   373  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   374  						ReleasePlanAdmission:        releasePlanAdmission,
   375  						Snapshot:                    snapshot,
   376  					},
   377  				},
   378  			})
   379  
   380  			result, err := adapter.EnsureReleaseIsProcessed()
   381  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   382  			Expect(err).NotTo(HaveOccurred())
   383  			Expect(adapter.release.IsProcessing()).To(BeTrue())
   384  		})
   385  
   386  		It("should requeue the Release if any of the resources is not found", func() {
   387  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   388  				{
   389  					ContextKey: loader.ProcessingResourcesContextKey,
   390  					Err:        fmt.Errorf("not found"),
   391  				},
   392  			})
   393  
   394  			result, err := adapter.EnsureReleaseIsProcessed()
   395  			Expect(result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   396  			Expect(err).To(HaveOccurred())
   397  		})
   398  
   399  		It("should create a RoleBinding if all the required resources are present and none exists in the Release Status", func() {
   400  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   401  				{
   402  					ContextKey: loader.ProcessingResourcesContextKey,
   403  					Resource: &loader.ProcessingResources{
   404  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   405  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   406  						ReleasePlan:                 releasePlan,
   407  						ReleasePlanAdmission:        releasePlanAdmission,
   408  						Snapshot:                    snapshot,
   409  					},
   410  				},
   411  				{
   412  					ContextKey: loader.RoleBindingContextKey,
   413  					Resource:   nil,
   414  				},
   415  			})
   416  
   417  			Expect(adapter.release.Status.Processing.RoleBinding).To(BeEmpty())
   418  			result, err := adapter.EnsureReleaseIsProcessed()
   419  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   420  			Expect(err).NotTo(HaveOccurred())
   421  
   422  			// Reset MockedContext so that the RoleBinding that was just created can be fetched
   423  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   424  				{
   425  					ContextKey: loader.ProcessingResourcesContextKey,
   426  					Resource: &loader.ProcessingResources{
   427  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   428  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   429  						ReleasePlan:                 releasePlan,
   430  						ReleasePlanAdmission:        releasePlanAdmission,
   431  						Snapshot:                    snapshot,
   432  					},
   433  				},
   434  			})
   435  
   436  			roleBinding, err := adapter.loader.GetRoleBindingFromReleaseStatus(adapter.ctx, adapter.client, adapter.release)
   437  			Expect(roleBinding).NotTo(BeNil())
   438  			Expect(err).NotTo(HaveOccurred())
   439  			Expect(adapter.client.Delete(adapter.ctx, roleBinding)).To(Succeed())
   440  			// Still need to cleanup the PipelineRun
   441  			pipelineRun, err := adapter.loader.GetManagedReleasePipelineRun(adapter.ctx, adapter.client, adapter.release)
   442  			Expect(pipelineRun).NotTo(BeNil())
   443  			Expect(err).NotTo(HaveOccurred())
   444  			Expect(adapter.client.Delete(adapter.ctx, pipelineRun)).To(Succeed())
   445  		})
   446  
   447  		It("should not create a RoleBinding if the ReleasePlanAdmission has no ServiceAccount set", func() {
   448  			newReleasePlanAdmission := &v1alpha1.ReleasePlanAdmission{
   449  				ObjectMeta: metav1.ObjectMeta{
   450  					Name:      "release-plan-admission",
   451  					Namespace: "default",
   452  				},
   453  				Spec: v1alpha1.ReleasePlanAdmissionSpec{
   454  					Applications: []string{application.Name},
   455  					Origin:       "default",
   456  					Pipeline: &tektonutils.Pipeline{
   457  						PipelineRef: tektonutils.PipelineRef{
   458  							Resolver: "git",
   459  							Params: []tektonutils.Param{
   460  								{Name: "url", Value: "my-url"},
   461  								{Name: "revision", Value: "my-revision"},
   462  								{Name: "pathInRepo", Value: "my-path"},
   463  							},
   464  						},
   465  					},
   466  					Policy: enterpriseContractPolicy.Name,
   467  				},
   468  			}
   469  			newReleasePlanAdmission.Kind = "ReleasePlanAdmission"
   470  
   471  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   472  				{
   473  					ContextKey: loader.ProcessingResourcesContextKey,
   474  					Resource: &loader.ProcessingResources{
   475  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   476  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   477  						ReleasePlan:                 releasePlan,
   478  						ReleasePlanAdmission:        newReleasePlanAdmission,
   479  						Snapshot:                    snapshot,
   480  					},
   481  				},
   482  				{
   483  					ContextKey: loader.RoleBindingContextKey,
   484  					Resource:   nil,
   485  				},
   486  			})
   487  
   488  			Expect(adapter.release.Status.Processing.RoleBinding).To(BeEmpty())
   489  			result, err := adapter.EnsureReleaseIsProcessed()
   490  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   491  			Expect(err).NotTo(HaveOccurred())
   492  
   493  			// Reset MockedContext so that the RoleBinding can be fetched if it exists
   494  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   495  				{
   496  					ContextKey: loader.ProcessingResourcesContextKey,
   497  					Resource: &loader.ProcessingResources{
   498  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   499  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   500  						ReleasePlan:                 releasePlan,
   501  						ReleasePlanAdmission:        newReleasePlanAdmission,
   502  						Snapshot:                    snapshot,
   503  					},
   504  				},
   505  			})
   506  
   507  			roleBinding, err := adapter.loader.GetRoleBindingFromReleaseStatus(adapter.ctx, adapter.client, adapter.release)
   508  			Expect(roleBinding).To(BeNil())
   509  			Expect(err).To(HaveOccurred())
   510  			// Still need to cleanup the PipelineRun
   511  			pipelineRun, err := adapter.loader.GetManagedReleasePipelineRun(adapter.ctx, adapter.client, adapter.release)
   512  			Expect(pipelineRun).NotTo(BeNil())
   513  			Expect(err).NotTo(HaveOccurred())
   514  			Expect(adapter.client.Delete(adapter.ctx, pipelineRun)).To(Succeed())
   515  		})
   516  
   517  		It("should create a pipelineRun and register the processing data if all the required resources are present", func() {
   518  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   519  				{
   520  					ContextKey: loader.ProcessingResourcesContextKey,
   521  					Resource: &loader.ProcessingResources{
   522  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
   523  						EnterpriseContractPolicy:    enterpriseContractPolicy,
   524  						ReleasePlan:                 releasePlan,
   525  						ReleasePlanAdmission:        releasePlanAdmission,
   526  						Snapshot:                    snapshot,
   527  					},
   528  				},
   529  				{
   530  					ContextKey: loader.RoleBindingContextKey,
   531  					Resource:   roleBinding,
   532  				},
   533  			})
   534  
   535  			result, err := adapter.EnsureReleaseIsProcessed()
   536  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   537  			Expect(err).NotTo(HaveOccurred())
   538  			Expect(adapter.release.IsProcessing()).To(BeTrue())
   539  
   540  			pipelineRun, err := adapter.loader.GetManagedReleasePipelineRun(adapter.ctx, adapter.client, adapter.release)
   541  			Expect(pipelineRun).NotTo(BeNil())
   542  			Expect(err).NotTo(HaveOccurred())
   543  			Expect(adapter.client.Delete(adapter.ctx, pipelineRun)).To(Succeed())
   544  		})
   545  	})
   546  
   547  	When("EnsureReleaseIsValid is called", func() {
   548  		var adapter *adapter
   549  
   550  		AfterEach(func() {
   551  			_ = adapter.client.Delete(ctx, adapter.release)
   552  		})
   553  
   554  		BeforeEach(func() {
   555  			adapter = createReleaseAndAdapter()
   556  			adapter.release.MarkReleasing("")
   557  			Expect(adapter.client.Status().Update(adapter.ctx, adapter.release)).To(Succeed())
   558  		})
   559  
   560  		It("should mark the release as validated if all checks pass", func() {
   561  			adapter.validations = []controller.ValidationFunction{}
   562  
   563  			result, err := adapter.EnsureReleaseIsValid()
   564  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   565  			Expect(err).NotTo(HaveOccurred())
   566  			Expect(adapter.release.IsValid()).To(BeTrue())
   567  			Expect(adapter.release.HasReleaseFinished()).To(BeFalse())
   568  		})
   569  
   570  		It("should mark the release as failed if a validation fails", func() {
   571  			adapter.validations = []controller.ValidationFunction{
   572  				func() *controller.ValidationResult {
   573  					return &controller.ValidationResult{Valid: false}
   574  				},
   575  			}
   576  
   577  			result, err := adapter.EnsureReleaseIsValid()
   578  			Expect(!result.RequeueRequest && result.CancelRequest).To(BeTrue())
   579  			Expect(err).NotTo(HaveOccurred())
   580  			Expect(adapter.release.IsValid()).To(BeFalse())
   581  			Expect(adapter.release.HasReleaseFinished()).To(BeTrue())
   582  		})
   583  
   584  		It("should requeue the release if a validation fails with an error", func() {
   585  			adapter.validations = []controller.ValidationFunction{
   586  				func() *controller.ValidationResult {
   587  					return &controller.ValidationResult{Err: fmt.Errorf("internal error")}
   588  				},
   589  			}
   590  
   591  			result, err := adapter.EnsureReleaseIsValid()
   592  			Expect(result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   593  			Expect(err).To(HaveOccurred())
   594  			Expect(adapter.release.HasReleaseFinished()).To(BeFalse())
   595  		})
   596  
   597  		It("does not clear the release status", func() {
   598  			adapter.validations = []controller.ValidationFunction{}
   599  
   600  			result, err := adapter.EnsureReleaseIsValid()
   601  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   602  			Expect(err).NotTo(HaveOccurred())
   603  			Expect(adapter.release.Status.StartTime).NotTo(BeNil())
   604  		})
   605  	})
   606  
   607  	When("EnsureReleaseProcessingIsTracked is called", func() {
   608  		var adapter *adapter
   609  
   610  		AfterEach(func() {
   611  			_ = adapter.client.Delete(ctx, adapter.release)
   612  		})
   613  
   614  		BeforeEach(func() {
   615  			adapter = createReleaseAndAdapter()
   616  		})
   617  
   618  		It("should continue if the Release processing has not started", func() {
   619  			result, err := adapter.EnsureReleaseProcessingIsTracked()
   620  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   621  			Expect(err).NotTo(HaveOccurred())
   622  		})
   623  
   624  		It("should continue if the Release processing has finished", func() {
   625  			adapter.release.MarkProcessing("")
   626  			adapter.release.MarkProcessed()
   627  
   628  			result, err := adapter.EnsureReleaseProcessingIsTracked()
   629  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   630  			Expect(err).NotTo(HaveOccurred())
   631  		})
   632  
   633  		It("should track the status if the PipelineRun exists", func() {
   634  			adapter.release.MarkProcessing("")
   635  
   636  			pipelineRun := &tektonv1.PipelineRun{
   637  				ObjectMeta: metav1.ObjectMeta{
   638  					Name:      "pipeline-run",
   639  					Namespace: "default",
   640  				},
   641  			}
   642  			pipelineRun.Status.MarkSucceeded("", "")
   643  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   644  				{
   645  					ContextKey: loader.ReleasePipelineRunContextKey,
   646  					Resource:   pipelineRun,
   647  				},
   648  				{
   649  					ContextKey: loader.RoleBindingContextKey,
   650  				},
   651  			})
   652  
   653  			result, err := adapter.EnsureReleaseProcessingIsTracked()
   654  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   655  			Expect(err).NotTo(HaveOccurred())
   656  			Expect(adapter.release.HasProcessingFinished()).To(BeTrue())
   657  		})
   658  
   659  		It("should continue if the PipelineRun doesn't exist", func() {
   660  			adapter.release.MarkProcessing("")
   661  
   662  			result, err := adapter.EnsureReleaseProcessingIsTracked()
   663  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   664  			Expect(err).NotTo(HaveOccurred())
   665  		})
   666  	})
   667  
   668  	When("EnsureReleaseExpirationTimeIsAdded is called", func() {
   669  		var adapter *adapter
   670  		var newReleasePlan *v1alpha1.ReleasePlan
   671  
   672  		AfterEach(func() {
   673  			_ = adapter.client.Delete(ctx, adapter.release)
   674  		})
   675  
   676  		BeforeEach(func() {
   677  			adapter = createReleaseAndAdapter()
   678  			newReleasePlan = &v1alpha1.ReleasePlan{
   679  				ObjectMeta: metav1.ObjectMeta{
   680  					Name:      "release-plan",
   681  					Namespace: "default",
   682  				},
   683  				Spec: v1alpha1.ReleasePlanSpec{
   684  					Application:            application.Name,
   685  					Target:                 "default",
   686  					ReleaseGracePeriodDays: 6,
   687  				},
   688  			}
   689  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   690  				{
   691  					ContextKey: loader.ReleasePlanContextKey,
   692  					Resource:   newReleasePlan,
   693  				},
   694  			})
   695  		})
   696  
   697  		It("should set the ExpirationTime with the value of Release's GracePeriodDays and then continue", func() {
   698  			expireDays := time.Duration(3)
   699  			adapter.release.Spec.GracePeriodDays = 3
   700  			creationTime := adapter.release.CreationTimestamp
   701  			expectedExpirationTime := &metav1.Time{Time: creationTime.Add(time.Hour * 24 * expireDays)}
   702  
   703  			result, err := adapter.EnsureReleaseExpirationTimeIsAdded()
   704  			Expect(adapter.release.Status.ExpirationTime).To(Equal(expectedExpirationTime))
   705  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   706  			Expect(err).NotTo(HaveOccurred())
   707  		})
   708  
   709  		It("should set the ExpirationTime with the value of ReleasePlan's ReleaseGracePeriodDays and then continue", func() {
   710  			expireDays := time.Duration(newReleasePlan.Spec.ReleaseGracePeriodDays)
   711  			creationTime := adapter.release.CreationTimestamp
   712  			expectedExpirationTime := &metav1.Time{Time: creationTime.Add(time.Hour * 24 * expireDays)}
   713  
   714  			result, err := adapter.EnsureReleaseExpirationTimeIsAdded()
   715  			Expect(adapter.release.Status.ExpirationTime).To(Equal(expectedExpirationTime))
   716  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   717  			Expect(err).NotTo(HaveOccurred())
   718  		})
   719  
   720  		It("should not change the ExpirationTime if it is already set", func() {
   721  			expireDays := time.Duration(5)
   722  			creationTime := adapter.release.CreationTimestamp
   723  			expectedExpirationTime := &metav1.Time{Time: creationTime.Add(time.Hour * 24 * expireDays)}
   724  
   725  			adapter.release.Status.ExpirationTime = expectedExpirationTime
   726  			result, err := adapter.EnsureReleaseExpirationTimeIsAdded()
   727  			Expect(adapter.release.Status.ExpirationTime).To(Equal(expectedExpirationTime))
   728  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   729  			Expect(err).NotTo(HaveOccurred())
   730  		})
   731  	})
   732  
   733  	When("EnsureReleaseProcessingResourcesAreCleanedUp is called", func() {
   734  		var adapter *adapter
   735  
   736  		AfterEach(func() {
   737  			_ = adapter.client.Delete(ctx, adapter.release)
   738  		})
   739  
   740  		BeforeEach(func() {
   741  			adapter = createReleaseAndAdapter()
   742  		})
   743  
   744  		It("should continue if the Release processing has not finished", func() {
   745  			result, err := adapter.EnsureReleaseProcessingResourcesAreCleanedUp()
   746  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   747  			Expect(err).NotTo(HaveOccurred())
   748  		})
   749  
   750  		It("should requeue the release if an error occurs fetching the managed pipelineRun", func() {
   751  			adapter.release.MarkProcessing("")
   752  			adapter.release.MarkProcessed()
   753  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   754  				{
   755  					ContextKey: loader.ReleasePipelineRunContextKey,
   756  					Err:        fmt.Errorf("error"),
   757  				},
   758  			})
   759  			result, err := adapter.EnsureReleaseProcessingResourcesAreCleanedUp()
   760  			Expect(result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   761  			Expect(err).To(HaveOccurred())
   762  		})
   763  
   764  		It("should requeue the release if an error occurs fetching the roleBinding", func() {
   765  			adapter.release.MarkProcessing("")
   766  			adapter.release.MarkProcessed()
   767  			pipelineRun := &tektonv1.PipelineRun{
   768  				ObjectMeta: metav1.ObjectMeta{
   769  					Name:      "pipeline-run",
   770  					Namespace: "default",
   771  				},
   772  			}
   773  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   774  				{
   775  					ContextKey: loader.ReleasePipelineRunContextKey,
   776  					Resource:   pipelineRun,
   777  				},
   778  				{
   779  					ContextKey: loader.RoleBindingContextKey,
   780  					Err:        fmt.Errorf("error"),
   781  				},
   782  			})
   783  			adapter.release.Status.Processing.RoleBinding = "one/two"
   784  			result, err := adapter.EnsureReleaseProcessingResourcesAreCleanedUp()
   785  			Expect(result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   786  			Expect(err).To(HaveOccurred())
   787  		})
   788  
   789  		It("should call cleanupManagedPipelineRunResources if all the resources are present", func() {
   790  			adapter.release.MarkProcessing("")
   791  			adapter.release.MarkProcessed()
   792  			pipelineRun := &tektonv1.PipelineRun{
   793  				ObjectMeta: metav1.ObjectMeta{
   794  					Name:      "pipeline-run",
   795  					Namespace: "default",
   796  				},
   797  			}
   798  			newRoleBinding := roleBinding.DeepCopy()
   799  
   800  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
   801  				{
   802  					ContextKey: loader.ReleasePipelineRunContextKey,
   803  					Resource:   pipelineRun,
   804  				},
   805  				{
   806  					ContextKey: loader.RoleBindingContextKey,
   807  					Resource:   newRoleBinding,
   808  				},
   809  			})
   810  			adapter.release.Status.Processing.RoleBinding = fmt.Sprintf("%s%c%s",
   811  				newRoleBinding.Namespace, types.Separator, newRoleBinding.Name)
   812  
   813  			result, err := adapter.EnsureReleaseProcessingResourcesAreCleanedUp()
   814  			Expect(!result.RequeueRequest && !result.CancelRequest).To(BeTrue())
   815  			Expect(err).NotTo(HaveOccurred())
   816  		})
   817  	})
   818  
   819  	When("cleanupProcessingResources is called", func() {
   820  		var adapter *adapter
   821  
   822  		AfterEach(func() {
   823  			_ = adapter.client.Delete(ctx, adapter.release)
   824  		})
   825  
   826  		BeforeEach(func() {
   827  			adapter = createReleaseAndAdapter()
   828  		})
   829  
   830  		It("removes the roleBinding if present", func() {
   831  			newRoleBinding := &rbac.RoleBinding{
   832  				ObjectMeta: metav1.ObjectMeta{
   833  					Name:      "new-role-binding",
   834  					Namespace: "default",
   835  				},
   836  				RoleRef: rbac.RoleRef{
   837  					APIGroup: rbac.GroupName,
   838  					Kind:     "ClusterRole",
   839  					Name:     "clusterrole",
   840  				},
   841  			}
   842  			// The resource needs to be created as it will get patched
   843  			Expect(adapter.client.Create(adapter.ctx, newRoleBinding)).To(Succeed())
   844  
   845  			err := adapter.cleanupProcessingResources(nil, newRoleBinding)
   846  			Expect(err).NotTo(HaveOccurred())
   847  
   848  			checkRoleBinding := &rbac.RoleBinding{}
   849  			err = toolkit.GetObject(newRoleBinding.Name, newRoleBinding.Namespace, adapter.client, adapter.ctx, checkRoleBinding)
   850  			Expect(checkRoleBinding).To(Equal(&rbac.RoleBinding{}))
   851  			Expect(errors.IsNotFound(err)).To(BeTrue())
   852  		})
   853  
   854  		It("removes the pipelineRun finalizer if present", func() {
   855  			pipelineRun := &tektonv1.PipelineRun{
   856  				ObjectMeta: metav1.ObjectMeta{
   857  					Name:       "pipeline-run",
   858  					Namespace:  "default",
   859  					Finalizers: []string{metadata.ReleaseFinalizer},
   860  				},
   861  			}
   862  			// The resource needs to be created as it will get patched
   863  			Expect(adapter.client.Create(adapter.ctx, pipelineRun)).To(Succeed())
   864  
   865  			err := adapter.cleanupProcessingResources(pipelineRun, nil)
   866  			Expect(err).NotTo(HaveOccurred())
   867  			Expect(pipelineRun.Finalizers).To(BeEmpty())
   868  
   869  			// Clean up at the end
   870  			Expect(adapter.client.Delete(adapter.ctx, pipelineRun)).To(Succeed())
   871  		})
   872  
   873  		It("should not error if either resource is nil", func() {
   874  			err := adapter.cleanupProcessingResources(nil, nil)
   875  			Expect(err).NotTo(HaveOccurred())
   876  		})
   877  	})
   878  
   879  	When("createManagedPipelineRun is called", func() {
   880  		var (
   881  			adapter     *adapter
   882  			pipelineRun *tektonv1.PipelineRun
   883  		)
   884  
   885  		AfterEach(func() {
   886  			_ = adapter.client.Delete(ctx, adapter.release)
   887  
   888  			Expect(k8sClient.Delete(ctx, pipelineRun)).To(Succeed())
   889  		})
   890  
   891  		BeforeEach(func() {
   892  			adapter = createReleaseAndAdapter()
   893  			adapter.releaseServiceConfig = releaseServiceConfig
   894  			resources := &loader.ProcessingResources{
   895  				ReleasePlan:                 releasePlan,
   896  				ReleasePlanAdmission:        releasePlanAdmission,
   897  				EnterpriseContractConfigMap: enterpriseContractConfigMap,
   898  				EnterpriseContractPolicy:    enterpriseContractPolicy,
   899  				Snapshot:                    snapshot,
   900  			}
   901  
   902  			var err error
   903  			pipelineRun, err = adapter.createManagedPipelineRun(resources)
   904  			Expect(pipelineRun).NotTo(BeNil())
   905  			Expect(err).NotTo(HaveOccurred())
   906  		})
   907  
   908  		It("returns a PipelineRun with the right prefix", func() {
   909  			Expect(reflect.TypeOf(pipelineRun)).To(Equal(reflect.TypeOf(&tektonv1.PipelineRun{})))
   910  			Expect(pipelineRun.Name).To(HavePrefix("managed"))
   911  		})
   912  
   913  		It("has the release reference", func() {
   914  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", strings.ToLower(adapter.release.Kind))))
   915  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal",
   916  				fmt.Sprintf("%s%c%s", adapter.release.Namespace, types.Separator, adapter.release.Name))))
   917  		})
   918  
   919  		It("has the releasePlan reference", func() {
   920  			name := []rune(releasePlan.Kind)
   921  			name[0] = unicode.ToLower(name[0])
   922  
   923  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", string(name))))
   924  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal",
   925  				fmt.Sprintf("%s%c%s", releasePlan.Namespace, types.Separator, releasePlan.Name))))
   926  		})
   927  
   928  		It("has the releasePlanAdmission reference", func() {
   929  			name := []rune(releasePlanAdmission.Kind)
   930  			name[0] = unicode.ToLower(name[0])
   931  
   932  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", string(name))))
   933  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal",
   934  				fmt.Sprintf("%s%c%s", releasePlanAdmission.Namespace, types.Separator, releasePlanAdmission.Name))))
   935  		})
   936  
   937  		It("has the releaseServiceConfig reference", func() {
   938  			name := []rune(releaseServiceConfig.Kind)
   939  			name[0] = unicode.ToLower(name[0])
   940  
   941  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", string(name))))
   942  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal",
   943  				fmt.Sprintf("%s%c%s", releaseServiceConfig.Namespace, types.Separator, releaseServiceConfig.Name))))
   944  		})
   945  
   946  		It("has the snapshot reference", func() {
   947  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", strings.ToLower(snapshot.Kind))))
   948  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal",
   949  				fmt.Sprintf("%s%c%s", snapshot.Namespace, types.Separator, snapshot.Name))))
   950  		})
   951  
   952  		It("has owner annotations", func() {
   953  			Expect(pipelineRun.GetAnnotations()[handler.NamespacedNameAnnotation]).To(ContainSubstring(adapter.release.Name))
   954  			Expect(pipelineRun.GetAnnotations()[handler.TypeAnnotation]).To(ContainSubstring("Release"))
   955  		})
   956  
   957  		It("has release labels", func() {
   958  			Expect(pipelineRun.GetLabels()[metadata.PipelinesTypeLabel]).To(Equal(metadata.ManagedPipelineType))
   959  			Expect(pipelineRun.GetLabels()[metadata.ReleaseNameLabel]).To(Equal(adapter.release.Name))
   960  			Expect(pipelineRun.GetLabels()[metadata.ReleaseNamespaceLabel]).To(Equal(testNamespace))
   961  			Expect(pipelineRun.GetLabels()[metadata.ReleaseSnapshotLabel]).To(Equal(adapter.release.Spec.Snapshot))
   962  		})
   963  
   964  		It("references the pipeline specified in the ReleasePlanAdmission", func() {
   965  			var pipelineUrl string
   966  			resolverParams := pipelineRun.Spec.PipelineRef.ResolverRef.Params
   967  			for i := range resolverParams {
   968  				if resolverParams[i].Name == "url" {
   969  					pipelineUrl = resolverParams[i].Value.StringVal
   970  				}
   971  			}
   972  			Expect(pipelineUrl).To(Equal(releasePlanAdmission.Spec.Pipeline.PipelineRef.Params[0].Value))
   973  		})
   974  
   975  		It("contains a parameter with the taskGitUrl", func() {
   976  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", "taskGitUrl")))
   977  			var url string
   978  			resolverParams := pipelineRun.Spec.PipelineRef.ResolverRef.Params
   979  			for i := range resolverParams {
   980  				if resolverParams[i].Name == "url" {
   981  					url = resolverParams[i].Value.StringVal
   982  				}
   983  			}
   984  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal", url)))
   985  		})
   986  
   987  		It("contains a parameter with the taskGitRevision", func() {
   988  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Name", "taskGitRevision")))
   989  			var revision string
   990  			resolverParams := pipelineRun.Spec.PipelineRef.ResolverRef.Params
   991  			for i := range resolverParams {
   992  				if resolverParams[i].Name == "revision" {
   993  					revision = resolverParams[i].Value.StringVal
   994  				}
   995  			}
   996  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal", revision)))
   997  		})
   998  
   999  		It("contains the proper timeout value", func() {
  1000  			Expect(pipelineRun.Spec.Timeouts.Pipeline).To(Equal(releasePlanAdmission.Spec.Pipeline.Timeouts.Pipeline))
  1001  		})
  1002  
  1003  		It("contains a parameter with the verify ec task bundle", func() {
  1004  			bundle := enterpriseContractConfigMap.Data["verify_ec_task_bundle"]
  1005  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal", Equal(string(bundle)))))
  1006  		})
  1007  
  1008  		It("contains a parameter with the json representation of the EnterpriseContractPolicy", func() {
  1009  			jsonSpec, _ := json.Marshal(enterpriseContractPolicy.Spec)
  1010  			Expect(pipelineRun.Spec.Params).Should(ContainElement(HaveField("Value.StringVal", Equal(string(jsonSpec)))))
  1011  		})
  1012  	})
  1013  
  1014  	When("createRoleBindingForClusterRole is called", func() {
  1015  		var adapter *adapter
  1016  
  1017  		AfterEach(func() {
  1018  			_ = adapter.client.Delete(ctx, adapter.release)
  1019  		})
  1020  
  1021  		BeforeEach(func() {
  1022  			adapter = createReleaseAndAdapter()
  1023  		})
  1024  
  1025  		It("fails when the releasePlanAdmission has no serviceAccount", func() {
  1026  			newReleasePlanAdmission := &v1alpha1.ReleasePlanAdmission{
  1027  				ObjectMeta: metav1.ObjectMeta{
  1028  					Name:      "release-plan-admission",
  1029  					Namespace: "default",
  1030  				},
  1031  				Spec: v1alpha1.ReleasePlanAdmissionSpec{
  1032  					Applications: []string{application.Name},
  1033  					Origin:       "default",
  1034  					Pipeline: &tektonutils.Pipeline{
  1035  						PipelineRef: tektonutils.PipelineRef{
  1036  							Resolver: "git",
  1037  							Params: []tektonutils.Param{
  1038  								{Name: "url", Value: "my-url"},
  1039  								{Name: "revision", Value: "my-revision"},
  1040  								{Name: "pathInRepo", Value: "my-path"},
  1041  							},
  1042  						},
  1043  					},
  1044  					Policy: enterpriseContractPolicy.Name,
  1045  				},
  1046  			}
  1047  			roleBinding, err := adapter.createRoleBindingForClusterRole("foo", newReleasePlanAdmission)
  1048  			Expect(err).To(HaveOccurred())
  1049  			Expect(roleBinding).To(BeNil())
  1050  			Expect(err.Error()).To(ContainSubstring("is invalid"))
  1051  		})
  1052  
  1053  		It("creates a new roleBinding", func() {
  1054  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1055  				{
  1056  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1057  					Resource:   releasePlanAdmission,
  1058  				},
  1059  			})
  1060  
  1061  			roleBinding, err := adapter.createRoleBindingForClusterRole("foo", releasePlanAdmission)
  1062  			Expect(err).NotTo(HaveOccurred())
  1063  			Expect(roleBinding).NotTo(BeNil())
  1064  			Expect(roleBinding.RoleRef.Name).To(Equal("foo"))
  1065  
  1066  			Expect(k8sClient.Delete(ctx, roleBinding)).Should(Succeed())
  1067  		})
  1068  	})
  1069  
  1070  	When("finalizeRelease is called", func() {
  1071  		var adapter *adapter
  1072  
  1073  		AfterEach(func() {
  1074  			_ = adapter.client.Delete(ctx, adapter.release)
  1075  		})
  1076  
  1077  		BeforeEach(func() {
  1078  			adapter = createReleaseAndAdapter()
  1079  		})
  1080  
  1081  		It("finalizes the Release successfully", func() {
  1082  			Expect(adapter.finalizeRelease()).To(Succeed())
  1083  		})
  1084  
  1085  		It("finalizes the Release and deletes the PipelineRun", func() {
  1086  			adapter.releaseServiceConfig = releaseServiceConfig
  1087  			resources := &loader.ProcessingResources{
  1088  				ReleasePlan:                 releasePlan,
  1089  				ReleasePlanAdmission:        releasePlanAdmission,
  1090  				EnterpriseContractConfigMap: enterpriseContractConfigMap,
  1091  				EnterpriseContractPolicy:    enterpriseContractPolicy,
  1092  				Snapshot:                    snapshot,
  1093  			}
  1094  			pipelineRun, err := adapter.createManagedPipelineRun(resources)
  1095  			Expect(pipelineRun).NotTo(BeNil())
  1096  			Expect(err).NotTo(HaveOccurred())
  1097  
  1098  			Expect(adapter.finalizeRelease()).To(Succeed())
  1099  			pipelineRun, err = adapter.loader.GetManagedReleasePipelineRun(adapter.ctx, adapter.client, adapter.release)
  1100  			Expect(err).NotTo(HaveOccurred())
  1101  			Expect(pipelineRun).To(BeNil())
  1102  		})
  1103  	})
  1104  
  1105  	When("getEmptyReleaseServiceConfig is called", func() {
  1106  		var adapter *adapter
  1107  
  1108  		AfterEach(func() {
  1109  			_ = adapter.client.Delete(ctx, adapter.release)
  1110  		})
  1111  
  1112  		BeforeEach(func() {
  1113  			adapter = createReleaseAndAdapter()
  1114  		})
  1115  
  1116  		It("should return a ReleaseServiceConfig without Spec and with the right ObjectMeta and Kind set", func() {
  1117  			releaseServiceConfig := adapter.getEmptyReleaseServiceConfig("namespace")
  1118  			Expect(releaseServiceConfig).NotTo(BeNil())
  1119  			Expect(releaseServiceConfig.Name).To(Equal(v1alpha1.ReleaseServiceConfigResourceName))
  1120  			Expect(releaseServiceConfig.Namespace).To(Equal("namespace"))
  1121  			Expect(releaseServiceConfig.Kind).To(Equal("ReleaseServiceConfig"))
  1122  		})
  1123  	})
  1124  
  1125  	When("registerProcessingData is called", func() {
  1126  		var adapter *adapter
  1127  
  1128  		AfterEach(func() {
  1129  			_ = adapter.client.Delete(ctx, adapter.release)
  1130  		})
  1131  
  1132  		BeforeEach(func() {
  1133  			adapter = createReleaseAndAdapter()
  1134  		})
  1135  
  1136  		It("does nothing if there is no PipelineRun", func() {
  1137  			Expect(adapter.registerProcessingData(nil, nil)).To(Succeed())
  1138  			Expect(adapter.release.Status.Processing.PipelineRun).To(BeEmpty())
  1139  		})
  1140  
  1141  		It("registers the Release processing data", func() {
  1142  			pipelineRun := &tektonv1.PipelineRun{
  1143  				ObjectMeta: metav1.ObjectMeta{
  1144  					Name:      "pipeline-run",
  1145  					Namespace: "default",
  1146  				},
  1147  			}
  1148  			roleBinding := &rbac.RoleBinding{
  1149  				ObjectMeta: metav1.ObjectMeta{
  1150  					Name:      "role-binding",
  1151  					Namespace: "default",
  1152  				},
  1153  			}
  1154  			Expect(adapter.registerProcessingData(pipelineRun, roleBinding)).To(Succeed())
  1155  			Expect(adapter.release.Status.Processing.PipelineRun).To(Equal(fmt.Sprintf("%s%c%s",
  1156  				pipelineRun.Namespace, types.Separator, pipelineRun.Name)))
  1157  			Expect(adapter.release.Status.Processing.RoleBinding).To(Equal(fmt.Sprintf("%s%c%s",
  1158  				roleBinding.Namespace, types.Separator, roleBinding.Name)))
  1159  			Expect(adapter.release.Status.Target).To(Equal(pipelineRun.Namespace))
  1160  			Expect(adapter.release.IsProcessing()).To(BeTrue())
  1161  		})
  1162  
  1163  		It("does not set RoleBinding when no RoleBinding is passed", func() {
  1164  			pipelineRun := &tektonv1.PipelineRun{
  1165  				ObjectMeta: metav1.ObjectMeta{
  1166  					Name:      "pipeline-run",
  1167  					Namespace: "default",
  1168  				},
  1169  			}
  1170  
  1171  			Expect(adapter.registerProcessingData(pipelineRun, nil)).To(Succeed())
  1172  			Expect(adapter.release.Status.Processing.RoleBinding).To(BeEmpty())
  1173  			Expect(adapter.release.IsProcessing()).To(BeTrue())
  1174  		})
  1175  	})
  1176  
  1177  	When("registerProcessingStatus is called", func() {
  1178  		var adapter *adapter
  1179  
  1180  		AfterEach(func() {
  1181  			_ = adapter.client.Delete(ctx, adapter.release)
  1182  		})
  1183  
  1184  		BeforeEach(func() {
  1185  			adapter = createReleaseAndAdapter()
  1186  		})
  1187  
  1188  		It("does nothing if there is no PipelineRun", func() {
  1189  			Expect(adapter.registerProcessingStatus(nil)).To(Succeed())
  1190  			Expect(adapter.release.Status.Processing.CompletionTime).To(BeNil())
  1191  		})
  1192  
  1193  		It("does nothing if the PipelineRun is not done", func() {
  1194  			pipelineRun := &tektonv1.PipelineRun{}
  1195  			Expect(adapter.registerProcessingStatus(pipelineRun)).To(Succeed())
  1196  			Expect(adapter.release.Status.Processing.CompletionTime).To(BeNil())
  1197  		})
  1198  
  1199  		It("sets the Release as succeeded if the PipelineRun succeeded", func() {
  1200  			pipelineRun := &tektonv1.PipelineRun{}
  1201  			pipelineRun.Status.MarkSucceeded("", "")
  1202  			adapter.release.MarkProcessing("")
  1203  
  1204  			Expect(adapter.registerProcessingStatus(pipelineRun)).To(Succeed())
  1205  			Expect(adapter.release.IsProcessed()).To(BeTrue())
  1206  		})
  1207  
  1208  		It("sets the Release as failed if the PipelineRun didn't succeed", func() {
  1209  			pipelineRun := &tektonv1.PipelineRun{}
  1210  			pipelineRun.Status.MarkFailed("", "")
  1211  			adapter.release.MarkProcessing("")
  1212  
  1213  			Expect(adapter.registerProcessingStatus(pipelineRun)).To(Succeed())
  1214  			Expect(adapter.release.HasProcessingFinished()).To(BeTrue())
  1215  			Expect(adapter.release.IsProcessed()).To(BeFalse())
  1216  		})
  1217  	})
  1218  
  1219  	When("calling syncResources", func() {
  1220  		var adapter *adapter
  1221  
  1222  		AfterEach(func() {
  1223  			_ = adapter.client.Delete(ctx, adapter.release)
  1224  		})
  1225  
  1226  		BeforeEach(func() {
  1227  			adapter = createReleaseAndAdapter()
  1228  		})
  1229  
  1230  		It("fails if there's no active ReleasePlanAdmission", func() {
  1231  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1232  				{
  1233  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1234  					Err:        fmt.Errorf("not found"),
  1235  				},
  1236  			})
  1237  
  1238  			Expect(adapter.syncResources()).NotTo(Succeed())
  1239  		})
  1240  
  1241  		It("fails if there's no Snapshot", func() {
  1242  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1243  				{
  1244  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1245  				},
  1246  				{
  1247  					ContextKey: loader.SnapshotContextKey,
  1248  					Err:        fmt.Errorf("not found"),
  1249  				},
  1250  			})
  1251  
  1252  			Expect(adapter.syncResources()).NotTo(Succeed())
  1253  		})
  1254  
  1255  		It("should sync resources properly", func() {
  1256  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1257  				{
  1258  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1259  					Resource:   releasePlanAdmission,
  1260  				},
  1261  			})
  1262  
  1263  			Expect(adapter.syncResources()).To(Succeed())
  1264  		})
  1265  	})
  1266  
  1267  	When("calling validateAuthor", func() {
  1268  		var adapter *adapter
  1269  		var conditionMsg string
  1270  
  1271  		AfterEach(func() {
  1272  			_ = adapter.client.Delete(ctx, adapter.release)
  1273  		})
  1274  
  1275  		BeforeEach(func() {
  1276  			adapter = createReleaseAndAdapter()
  1277  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1278  				{
  1279  					ContextKey: loader.ReleasePlanContextKey,
  1280  					Resource:   releasePlan,
  1281  				},
  1282  			})
  1283  		})
  1284  
  1285  		It("returns valid and no error if the release is already attributed", func() {
  1286  			adapter.release.Status.Attribution.Author = "user"
  1287  			result := adapter.validateAuthor()
  1288  			Expect(result.Valid).To(BeTrue())
  1289  			Expect(result.Err).NotTo(HaveOccurred())
  1290  		})
  1291  
  1292  		It("should return invalid and no error if the ReleasePlan is not found", func() {
  1293  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1294  				{
  1295  					ContextKey: loader.ReleasePlanContextKey,
  1296  					Err:        errors.NewNotFound(schema.GroupResource{}, ""),
  1297  				},
  1298  			})
  1299  
  1300  			result := adapter.validateAuthor()
  1301  			Expect(result.Valid).To(BeFalse())
  1302  			Expect(result.Err).NotTo(HaveOccurred())
  1303  			Expect(adapter.release.IsValid()).To(BeFalse())
  1304  		})
  1305  
  1306  		When("the release has the automated label", func() {
  1307  			AfterEach(func() {
  1308  				_ = adapter.client.Delete(ctx, adapter.release)
  1309  			})
  1310  
  1311  			BeforeEach(func() {
  1312  				adapter = createReleaseAndAdapter()
  1313  				adapter.release.Labels = map[string]string{
  1314  					metadata.AutomatedLabel: "true",
  1315  				}
  1316  				adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1317  					{
  1318  						ContextKey: loader.ReleasePlanContextKey,
  1319  						Resource:   releasePlan,
  1320  					},
  1321  				})
  1322  			})
  1323  
  1324  			It("returns invalid and an error if automated label is present but is not set in release status", func() {
  1325  				result := adapter.validateAuthor()
  1326  				Expect(result.Valid).To(BeFalse())
  1327  				Expect(result.Err).To(HaveOccurred())
  1328  				for i := range adapter.release.Status.Conditions {
  1329  					if adapter.release.Status.Conditions[i].Type == "Validated" {
  1330  						conditionMsg = adapter.release.Status.Conditions[i].Message
  1331  					}
  1332  				}
  1333  				Expect(conditionMsg).To(Equal("automated not set in status for automated release"))
  1334  			})
  1335  
  1336  			It("returns invalid if the error appears after 5 minutes of being created", func() {
  1337  				adapter.release.SetCreationTimestamp(metav1.Time{Time: time.Now().Add(-7 * time.Minute)})
  1338  				result := adapter.validateAuthor()
  1339  				Expect(result.Valid).To(BeFalse())
  1340  				Expect(result.Err).NotTo(HaveOccurred())
  1341  				for i := range adapter.release.Status.Conditions {
  1342  					if adapter.release.Status.Conditions[i].Type == "Validated" {
  1343  						conditionMsg = adapter.release.Status.Conditions[i].Message
  1344  					}
  1345  				}
  1346  				Expect(conditionMsg).To(Equal("automated not set in status for automated release"))
  1347  			})
  1348  
  1349  			It("returns invalid and an error if the ReleasePlan has no author", func() {
  1350  				adapter.release.Status.Automated = true
  1351  				result := adapter.validateAuthor()
  1352  				Expect(result.Valid).To(BeFalse())
  1353  				Expect(result.Err).NotTo(HaveOccurred())
  1354  				for i := range adapter.release.Status.Conditions {
  1355  					if adapter.release.Status.Conditions[i].Type == "Validated" {
  1356  						conditionMsg = adapter.release.Status.Conditions[i].Message
  1357  					}
  1358  				}
  1359  				Expect(conditionMsg).To(Equal("no author in the ReleasePlan found for automated release"))
  1360  			})
  1361  
  1362  			It("properly sets the Attribution data in the release status", func() {
  1363  				adapter.release.Status.Automated = true
  1364  				releasePlan.Labels = map[string]string{
  1365  					metadata.AuthorLabel: "user",
  1366  				}
  1367  				result := adapter.validateAuthor()
  1368  				Expect(result.Valid).To(BeTrue())
  1369  				Expect(result.Err).NotTo(HaveOccurred())
  1370  				Expect(adapter.release.Status.Attribution.StandingAuthorization).To(BeTrue())
  1371  				Expect(adapter.release.Status.Attribution.Author).To(Equal("user"))
  1372  			})
  1373  		})
  1374  
  1375  		It("returns invalid and an error if the Release has the automated label and no author", func() {
  1376  			adapter.release.Labels = map[string]string{
  1377  				metadata.AutomatedLabel: "false",
  1378  				metadata.AuthorLabel:    "",
  1379  			}
  1380  			result := adapter.validateAuthor()
  1381  			Expect(result.Valid).To(BeFalse())
  1382  			Expect(result.Err).NotTo(HaveOccurred())
  1383  			for i := range adapter.release.Status.Conditions {
  1384  				if adapter.release.Status.Conditions[i].Type == "Validated" {
  1385  					conditionMsg = adapter.release.Status.Conditions[i].Message
  1386  				}
  1387  			}
  1388  			Expect(conditionMsg).To(Equal("no author found for manual release"))
  1389  		})
  1390  
  1391  		It("properly sets the Attribution author in the manual release status", func() {
  1392  			adapter.release.Labels = map[string]string{
  1393  				metadata.AuthorLabel: "user",
  1394  			}
  1395  			result := adapter.validateAuthor()
  1396  			Expect(result.Valid).To(BeTrue())
  1397  			Expect(result.Err).NotTo(HaveOccurred())
  1398  			Expect(adapter.release.Status.Attribution.StandingAuthorization).To(BeFalse())
  1399  			Expect(adapter.release.Status.Attribution.Author).To(Equal("user"))
  1400  		})
  1401  	})
  1402  
  1403  	When("validateProcessingResources is called", func() {
  1404  		var adapter *adapter
  1405  
  1406  		AfterEach(func() {
  1407  			_ = adapter.client.Delete(ctx, adapter.release)
  1408  		})
  1409  
  1410  		BeforeEach(func() {
  1411  			adapter = createReleaseAndAdapter()
  1412  			adapter.release.MarkReleasing("")
  1413  		})
  1414  
  1415  		It("should return valid and no error if all the resources are found", func() {
  1416  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1417  				{
  1418  					ContextKey: loader.ProcessingResourcesContextKey,
  1419  					Resource: &loader.ProcessingResources{
  1420  						EnterpriseContractConfigMap: enterpriseContractConfigMap,
  1421  						EnterpriseContractPolicy:    enterpriseContractPolicy,
  1422  						ReleasePlanAdmission:        releasePlanAdmission,
  1423  						Snapshot:                    snapshot,
  1424  					},
  1425  				},
  1426  			})
  1427  
  1428  			result := adapter.validateProcessingResources()
  1429  			Expect(result.Valid).To(BeTrue())
  1430  			Expect(result.Err).NotTo(HaveOccurred())
  1431  		})
  1432  
  1433  		It("should return invalid and no error if any of the resources are not found", func() {
  1434  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1435  				{
  1436  					ContextKey: loader.ProcessingResourcesContextKey,
  1437  					Err:        errors.NewNotFound(schema.GroupResource{}, ""),
  1438  				},
  1439  			})
  1440  
  1441  			result := adapter.validateProcessingResources()
  1442  			Expect(result.Valid).To(BeFalse())
  1443  			Expect(result.Err).NotTo(HaveOccurred())
  1444  			Expect(adapter.release.IsValid()).To(BeFalse())
  1445  		})
  1446  
  1447  		It("should return invalid and no error if the ReleasePlanAdmission is found to be disabled", func() {
  1448  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1449  				{
  1450  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1451  					Err:        fmt.Errorf("auto-release label set to false"),
  1452  				},
  1453  			})
  1454  
  1455  			result := adapter.validateProcessingResources()
  1456  			Expect(result.Valid).To(BeFalse())
  1457  			Expect(result.Err).NotTo(HaveOccurred())
  1458  			Expect(adapter.release.IsValid()).To(BeFalse())
  1459  		})
  1460  
  1461  		It("should return invalid and no error if multiple ReleasePlanAdmissions exist", func() {
  1462  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1463  				{
  1464  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1465  					Err:        fmt.Errorf("multiple ReleasePlanAdmissions found"),
  1466  				},
  1467  			})
  1468  
  1469  			result := adapter.validateProcessingResources()
  1470  			Expect(result.Valid).To(BeFalse())
  1471  			Expect(result.Err).NotTo(HaveOccurred())
  1472  			Expect(adapter.release.IsValid()).To(BeFalse())
  1473  		})
  1474  
  1475  		It("should return invalid and an error if some other type of error occurs", func() {
  1476  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1477  				{
  1478  					ContextKey: loader.ProcessingResourcesContextKey,
  1479  					Err:        fmt.Errorf("internal error"),
  1480  					Resource: &loader.ProcessingResources{
  1481  						ReleasePlanAdmission: releasePlanAdmission,
  1482  					},
  1483  				},
  1484  			})
  1485  
  1486  			result := adapter.validateProcessingResources()
  1487  			Expect(result.Valid).To(BeFalse())
  1488  			Expect(result.Err).To(HaveOccurred())
  1489  			Expect(adapter.release.IsValid()).To(BeFalse())
  1490  		})
  1491  	})
  1492  
  1493  	When("validatePipelineRef is called", func() {
  1494  		var adapter *adapter
  1495  
  1496  		AfterEach(func() {
  1497  			_ = adapter.client.Delete(ctx, adapter.release)
  1498  		})
  1499  
  1500  		BeforeEach(func() {
  1501  			adapter = createReleaseAndAdapter()
  1502  			releaseServiceConfig.Spec = v1alpha1.ReleaseServiceConfigSpec{}
  1503  			adapter.releaseServiceConfig = releaseServiceConfig
  1504  		})
  1505  
  1506  		It("should return invalid and no error if the ReleasePlanAdmission is not found", func() {
  1507  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1508  				{
  1509  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1510  					Err:        errors.NewNotFound(schema.GroupResource{}, ""),
  1511  				},
  1512  			})
  1513  
  1514  			result := adapter.validatePipelineRef()
  1515  			Expect(result.Valid).To(BeFalse())
  1516  			Expect(result.Err).NotTo(HaveOccurred())
  1517  			Expect(adapter.release.IsValid()).To(BeFalse())
  1518  		})
  1519  
  1520  		It("should return invalid and an error if some other type of error occurs when retrieving the ReleasePlanAdmission", func() {
  1521  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1522  				{
  1523  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1524  					Err:        fmt.Errorf("internal error"),
  1525  					Resource:   releasePlanAdmission,
  1526  				},
  1527  			})
  1528  
  1529  			result := adapter.validatePipelineRef()
  1530  			Expect(result.Valid).To(BeFalse())
  1531  			Expect(result.Err).To(HaveOccurred())
  1532  			Expect(adapter.release.IsValid()).To(BeFalse())
  1533  		})
  1534  
  1535  		It("returns invalid and no error if debug is false and the PipelineRef uses a cluster resolver", func() {
  1536  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1537  				{
  1538  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1539  					Resource: &v1alpha1.ReleasePlanAdmission{
  1540  						ObjectMeta: metav1.ObjectMeta{
  1541  							Name:      "release-plan-admission",
  1542  							Namespace: "default",
  1543  							Labels: map[string]string{
  1544  								metadata.AutoReleaseLabel: "true",
  1545  							},
  1546  						},
  1547  						Spec: v1alpha1.ReleasePlanAdmissionSpec{
  1548  							Applications: []string{application.Name},
  1549  							Origin:       "default",
  1550  							Pipeline: &tektonutils.Pipeline{
  1551  								PipelineRef: tektonutils.PipelineRef{
  1552  									Resolver: "cluster",
  1553  									Params: []tektonutils.Param{
  1554  										{Name: "name", Value: "release-pipeline"},
  1555  										{Name: "namespace", Value: "default"},
  1556  										{Name: "kind", Value: "pipeline"},
  1557  									},
  1558  								},
  1559  							},
  1560  							Policy: enterpriseContractPolicy.Name,
  1561  						},
  1562  					},
  1563  				},
  1564  			})
  1565  			adapter.releaseServiceConfig.Spec.Debug = false
  1566  
  1567  			result := adapter.validatePipelineRef()
  1568  			Expect(result.Valid).To(BeFalse())
  1569  			Expect(result.Err).To(BeNil())
  1570  			Expect(adapter.release.IsValid()).To(BeFalse())
  1571  		})
  1572  
  1573  		It("returns valid and no error if debug mode is enabled in the ReleaseServiceConfig", func() {
  1574  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1575  				{
  1576  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1577  					Resource:   releasePlanAdmission,
  1578  				},
  1579  			})
  1580  			adapter.releaseServiceConfig.Spec.Debug = true
  1581  
  1582  			result := adapter.validatePipelineRef()
  1583  			Expect(result.Valid).To(BeTrue())
  1584  			Expect(result.Err).To(BeNil())
  1585  		})
  1586  
  1587  		It("returns valid and no error if debug mode is disabled and the PipelineRef uses a bundle resolver", func() {
  1588  			adapter.ctx = toolkit.GetMockedContext(ctx, []toolkit.MockData{
  1589  				{
  1590  					ContextKey: loader.ReleasePlanAdmissionContextKey,
  1591  					Resource:   releasePlanAdmission,
  1592  				},
  1593  			})
  1594  			result := adapter.validatePipelineRef()
  1595  			Expect(result.Valid).To(BeTrue())
  1596  			Expect(result.Err).To(BeNil())
  1597  		})
  1598  	})
  1599  
  1600  	createReleaseAndAdapter = func() *adapter {
  1601  		release := &v1alpha1.Release{
  1602  			ObjectMeta: metav1.ObjectMeta{
  1603  				GenerateName: "release-",
  1604  				Namespace:    "default",
  1605  			},
  1606  			Spec: v1alpha1.ReleaseSpec{
  1607  				Snapshot:    snapshot.Name,
  1608  				ReleasePlan: releasePlan.Name,
  1609  			},
  1610  		}
  1611  		Expect(k8sClient.Create(ctx, release)).To(Succeed())
  1612  		release.Kind = "Release"
  1613  
  1614  		return newAdapter(ctx, k8sClient, release, loader.NewMockLoader(), &ctrl.Log)
  1615  	}
  1616  
  1617  	createResources = func() {
  1618  		application = &applicationapiv1alpha1.Application{
  1619  			ObjectMeta: metav1.ObjectMeta{
  1620  				Name:      "application",
  1621  				Namespace: "default",
  1622  			},
  1623  			Spec: applicationapiv1alpha1.ApplicationSpec{
  1624  				DisplayName: "application",
  1625  			},
  1626  		}
  1627  		Expect(k8sClient.Create(ctx, application)).To(Succeed())
  1628  
  1629  		component = &applicationapiv1alpha1.Component{
  1630  			ObjectMeta: metav1.ObjectMeta{
  1631  				Name:      "component",
  1632  				Namespace: "default",
  1633  			},
  1634  			Spec: applicationapiv1alpha1.ComponentSpec{
  1635  				Application:   application.Name,
  1636  				ComponentName: "component",
  1637  			},
  1638  		}
  1639  		Expect(k8sClient.Create(ctx, component)).Should(Succeed())
  1640  
  1641  		enterpriseContractConfigMap = &corev1.ConfigMap{
  1642  			ObjectMeta: metav1.ObjectMeta{
  1643  				Name:      "enterprise-contract-cm",
  1644  				Namespace: "default",
  1645  			},
  1646  			Data: map[string]string{
  1647  				"verify_ec_task_bundle": "test-bundle",
  1648  			},
  1649  		}
  1650  		Expect(k8sClient.Create(ctx, enterpriseContractConfigMap)).Should(Succeed())
  1651  
  1652  		enterpriseContractPolicy = &ecapiv1alpha1.EnterpriseContractPolicy{
  1653  			ObjectMeta: metav1.ObjectMeta{
  1654  				Name:      "enterprise-contract-policy",
  1655  				Namespace: "default",
  1656  			},
  1657  			Spec: ecapiv1alpha1.EnterpriseContractPolicySpec{
  1658  				Sources: []ecapiv1alpha1.Source{
  1659  					{
  1660  						Name: "foo",
  1661  					},
  1662  				},
  1663  			},
  1664  		}
  1665  		Expect(k8sClient.Create(ctx, enterpriseContractPolicy)).Should(Succeed())
  1666  		enterpriseContractPolicy.Kind = "EnterpriseContractPolicy"
  1667  
  1668  		releasePlan = &v1alpha1.ReleasePlan{
  1669  			ObjectMeta: metav1.ObjectMeta{
  1670  				Name:      "release-plan",
  1671  				Namespace: "default",
  1672  			},
  1673  			Spec: v1alpha1.ReleasePlanSpec{
  1674  				Application: application.Name,
  1675  				Target:      "default",
  1676  			},
  1677  		}
  1678  		Expect(k8sClient.Create(ctx, releasePlan)).To(Succeed())
  1679  		releasePlan.Kind = "ReleasePlan"
  1680  
  1681  		releaseServiceConfig = &v1alpha1.ReleaseServiceConfig{
  1682  			ObjectMeta: metav1.ObjectMeta{
  1683  				Name:      v1alpha1.ReleaseServiceConfigResourceName,
  1684  				Namespace: "default",
  1685  			},
  1686  		}
  1687  		Expect(k8sClient.Create(ctx, releaseServiceConfig)).To(Succeed())
  1688  		releaseServiceConfig.Kind = "ReleaseServiceConfig"
  1689  
  1690  		releasePlanAdmission = &v1alpha1.ReleasePlanAdmission{
  1691  			ObjectMeta: metav1.ObjectMeta{
  1692  				Name:      "release-plan-admission",
  1693  				Namespace: "default",
  1694  				Labels: map[string]string{
  1695  					metadata.AutoReleaseLabel: "true",
  1696  				},
  1697  			},
  1698  			Spec: v1alpha1.ReleasePlanAdmissionSpec{
  1699  				Applications: []string{application.Name},
  1700  				Origin:       "default",
  1701  				Pipeline: &tektonutils.Pipeline{
  1702  					PipelineRef: tektonutils.PipelineRef{
  1703  						Resolver: "git",
  1704  						Params: []tektonutils.Param{
  1705  							{Name: "url", Value: "my-url"},
  1706  							{Name: "revision", Value: "my-revision"},
  1707  							{Name: "pathInRepo", Value: "my-path"},
  1708  						},
  1709  					},
  1710  					ServiceAccount: "service-account",
  1711  					Timeouts: tektonv1.TimeoutFields{
  1712  						Pipeline: &metav1.Duration{Duration: 1 * time.Hour},
  1713  					},
  1714  				},
  1715  				Policy: enterpriseContractPolicy.Name,
  1716  			},
  1717  		}
  1718  		Expect(k8sClient.Create(ctx, releasePlanAdmission)).Should(Succeed())
  1719  		releasePlanAdmission.Kind = "ReleasePlanAdmission"
  1720  
  1721  		roleBinding = &rbac.RoleBinding{
  1722  			ObjectMeta: metav1.ObjectMeta{
  1723  				Name:      "rolebinding",
  1724  				Namespace: "default",
  1725  			},
  1726  			RoleRef: rbac.RoleRef{
  1727  				APIGroup: rbac.GroupName,
  1728  				Kind:     "ClusterRole",
  1729  				Name:     "clusterrole",
  1730  			},
  1731  		}
  1732  		Expect(k8sClient.Create(ctx, roleBinding)).To(Succeed())
  1733  
  1734  		snapshot = &applicationapiv1alpha1.Snapshot{
  1735  			ObjectMeta: metav1.ObjectMeta{
  1736  				Name:      "snapshot",
  1737  				Namespace: "default",
  1738  			},
  1739  			Spec: applicationapiv1alpha1.SnapshotSpec{
  1740  				Application: application.Name,
  1741  			},
  1742  		}
  1743  		Expect(k8sClient.Create(ctx, snapshot)).To(Succeed())
  1744  		snapshot.Kind = "Snapshot"
  1745  	}
  1746  
  1747  	deleteResources = func() {
  1748  		Expect(k8sClient.Delete(ctx, application)).To(Succeed())
  1749  		Expect(k8sClient.Delete(ctx, component)).Should(Succeed())
  1750  		Expect(k8sClient.Delete(ctx, enterpriseContractConfigMap)).Should(Succeed())
  1751  		Expect(k8sClient.Delete(ctx, enterpriseContractPolicy)).Should(Succeed())
  1752  		Expect(k8sClient.Delete(ctx, releasePlan)).To(Succeed())
  1753  		Expect(k8sClient.Delete(ctx, releasePlanAdmission)).Should(Succeed())
  1754  		Expect(k8sClient.Delete(ctx, releaseServiceConfig)).Should(Succeed())
  1755  		Expect(k8sClient.Delete(ctx, snapshot)).To(Succeed())
  1756  	}
  1757  
  1758  })