Skip to content

Commit

Permalink
fix(STONEINTG-709): add support missing info of build PLR error
Browse files Browse the repository at this point in the history
Signed-off-by: Kasem Alem <kasem.alem@gmail.com>
  • Loading branch information
kasemAlem committed Jan 18, 2024
1 parent dbb4090 commit cb0b172
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 14 deletions.
10 changes: 10 additions & 0 deletions controllers/buildpipeline/buildpipeline_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ func (a *Adapter) EnsureSnapshotExists() (controller.OperationResult, error) {

expectedSnapshot, err := a.prepareSnapshotForPipelineRun(a.pipelineRun, a.component, a.application)
if err != nil {
// If PipelineRun result returns cusomized error update PLR annotation and exit
if h.IsMissingInfoInPipelineRunError(err) {
// update the build PLR annotation with the error cusomized Reason and Value
if annotateErr := a.annotateBuildPipelineRunWithCreateSnapshotAnnotation(err); annotateErr != nil {
a.logger.Error(annotateErr, "Could not add create snapshot annotation to build pipelineRun", h.CreateSnapshotAnnotationName, a.pipelineRun)
}
a.logger.Error(err, "Build PipelineRun %s failed with error, should be fixed and re-run manually", a.pipelineRun)
return a.removeFinalizerAndContinueProcessing()
}

return controller.RequeueWithError(err)
}

Expand Down
49 changes: 49 additions & 0 deletions controllers/buildpipeline/buildpipeline_adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,55 @@ var _ = Describe("Pipeline Adapter", Ordered, func() {
Expect(err).ToNot(BeNil())
})

It("ensure err is returned when pipelinerun doesn't have Result for customized error and build pipelineRun annotated ", func() {
// We don't need to update the underlying resource on the control plane,
// so we create a copy and modify its status. This prevents update conflicts in other tests.
buildPipelineRunNoSource := buildPipelineRun.DeepCopy()
buildPipelineRunNoSource.Status = tektonv1.PipelineRunStatus{
PipelineRunStatusFields: tektonv1.PipelineRunStatusFields{
ChildReferences: []tektonv1.ChildStatusReference{
{
Name: successfulTaskRun.Name,
PipelineTaskName: "task1",
},
},
Results: []tektonv1.PipelineRunResult{
{
Name: "CHAINS-GIT_URL",
Value: *tektonv1.NewStructuredValues(SampleRepoLink),
},
{
Name: "IMAGE_URL",
Value: *tektonv1.NewStructuredValues(SampleImageWithoutDigest),
},
},
},
Status: v1.Status{
Conditions: v1.Conditions{
apis.Condition{
Reason: "Completed",
Status: "True",
Type: apis.ConditionSucceeded,
},
},
},
}

messageError := "Missing info IMAGE_DIGEST from pipelinerun pipelinerun-build-sample"
var info map[string]string
expectedSnap, err := adapter.prepareSnapshotForPipelineRun(buildPipelineRunNoSource, hasComp, hasApp)
Expect(expectedSnap).To(BeNil())
Expect(err).To(HaveOccurred())
err = adapter.annotateBuildPipelineRunWithCreateSnapshotAnnotation(err)
Expect(err).NotTo(HaveOccurred())
Expect(adapter.pipelineRun.GetAnnotations()[helpers.CreateSnapshotAnnotationName]).ToNot(BeNil())
err = json.Unmarshal([]byte(adapter.pipelineRun.GetAnnotations()[helpers.CreateSnapshotAnnotationName]), &info)
Expect(err).NotTo(HaveOccurred())
Expect(info["status"]).To(Equal("failed"))
Expect(info["message"]).To(Equal(messageError))

})

It("ensures pipelines as code labels and annotations are propagated to the snapshot", func() {
snapshot, err := adapter.prepareSnapshotForPipelineRun(buildPipelineRun, hasComp, hasApp)
Expect(err).To(BeNil())
Expand Down
16 changes: 14 additions & 2 deletions helpers/errorhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import (
)

const (
ReasonEnvironmentNotInNamespace = "EnvironmentNotInNamespace"
ReasonUnknownError = "UnknownError"
ReasonEnvironmentNotInNamespace = "EnvironmentNotInNamespace"
ReasonMissingInfoInPipelineRunError = "MissingInfoInPipelineRunError"
ReasonUnknownError = "UnknownError"
)

type IntegrationError struct {
Expand Down Expand Up @@ -53,6 +54,17 @@ func IsEnvironmentNotInNamespaceError(err error) bool {
return getReason(err) == ReasonEnvironmentNotInNamespace
}

func MissingInfoInPipelineRunError(pipelineRunName, paramName string) error {
return &IntegrationError{
Reason: ReasonMissingInfoInPipelineRunError,
Message: fmt.Sprintf("Missing info %s from pipelinerun %s", paramName, pipelineRunName),
}
}

func IsMissingInfoInPipelineRunError(err error) bool {
return getReason(err) == ReasonMissingInfoInPipelineRunError
}

func HandleLoaderError(logger IntegrationLogger, err error, resource, from string) (ctrl.Result, error) {
if errors.IsNotFound(err) {
logger.Info(fmt.Sprintf("Could not get %[1]s from %[2]s. %[1]s may have been removed. Declining to proceed with reconciliation", resource, from))
Expand Down
12 changes: 12 additions & 0 deletions helpers/errorhandlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,17 @@ var _ = Describe("Helpers for error handlers", Ordered, func() {
err := fmt.Errorf("failed")
Expect(helpers.IsEnvironmentNotInNamespaceError(err)).To(BeFalse())
})

It("Can define MissingInfoInPipelineRunError", func() {
err := helpers.MissingInfoInPipelineRunError("pipelineRunName", "revision")
Expect(helpers.IsMissingInfoInPipelineRunError(err)).To(BeTrue())
Expect(err.Error()).To(Equal("Missing info revision from pipelinerun pipelineRunName"))
})

It("Can handle non integration error", func() {
err := fmt.Errorf("failed")
Expect(helpers.IsMissingInfoInPipelineRunError(err)).To(BeFalse())
})

})
})
42 changes: 30 additions & 12 deletions tekton/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package tekton
import (
"fmt"

h "github.com/redhat-appstudio/integration-service/helpers"
"github.com/redhat-appstudio/operator-toolkit/metadata"
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
"knative.dev/pkg/apis"
Expand All @@ -43,6 +44,18 @@ const (

// PipelineRunChainsSignedAnnotation is the label added by Tekton Chains to signed PipelineRuns
PipelineRunChainsSignedAnnotation = "chains.tekton.dev/signed"

// PipelineRunImageUrlParamName name of image url output param
PipelineRunImageUrlParamName = "IMAGE_URL"

// PipelineRunImageDigestParamName name of image digest in PipelineRun result param
PipelineRunImageDigestParamName = "IMAGE_DIGEST"

// PipelineRunChainsGitUrlParamName name of param chains repo url
PipelineRunChainsGitUrlParamName = "CHAINS-GIT_URL"

// PipelineRunChainsGitCommitParamName name of param repo chains commit
PipelineRunChainsGitCommitParamName = "CHAINS-GIT_COMMIT"
)

// IsBuildPipelineRun returns a boolean indicating whether the object passed is a PipelineRun from
Expand Down Expand Up @@ -136,48 +149,53 @@ func GetTypeFromPipelineRun(object client.Object) (string, error) {

// GetOutputImage returns a string containing the output-image parameter value from a given PipelineRun.
func GetOutputImage(object client.Object) (string, error) {
if pipelineRun, ok := object.(*tektonv1.PipelineRun); ok {
pipelineRun, ok := object.(*tektonv1.PipelineRun)
if ok {
for _, pipelineResult := range pipelineRun.Status.Results {
if pipelineResult.Name == "IMAGE_URL" {
if pipelineResult.Name == PipelineRunImageUrlParamName {
return pipelineResult.Value.StringVal, nil
}
}
}
return "", fmt.Errorf("couldn't find the output-image PipelineRun param")

return "", h.MissingInfoInPipelineRunError(pipelineRun.Name, PipelineRunImageUrlParamName)
}

// GetOutputImageDigest returns a string containing the IMAGE_DIGEST result value from a given PipelineRun.
func GetOutputImageDigest(object client.Object) (string, error) {
if pipelineRun, ok := object.(*tektonv1.PipelineRun); ok {
pipelineRun, ok := object.(*tektonv1.PipelineRun)
if ok {
for _, pipelineResult := range pipelineRun.Status.Results {
if pipelineResult.Name == "IMAGE_DIGEST" {
if pipelineResult.Name == PipelineRunImageDigestParamName {
return pipelineResult.Value.StringVal, nil
}
}
}
return "", fmt.Errorf("couldn't find the IMAGE_DIGEST TaskRun result")
return "", h.MissingInfoInPipelineRunError(pipelineRun.Name, PipelineRunImageDigestParamName)
}

// GetComponentSourceGitUrl returns a string containing the CHAINS-GIT_URL result value from a given PipelineRun.
func GetComponentSourceGitUrl(object client.Object) (string, error) {
if pipelineRun, ok := object.(*tektonv1.PipelineRun); ok {
pipelineRun, ok := object.(*tektonv1.PipelineRun)
if ok {
for _, pipelineResult := range pipelineRun.Status.Results {
if pipelineResult.Name == "CHAINS-GIT_URL" {
if pipelineResult.Name == PipelineRunChainsGitUrlParamName {
return pipelineResult.Value.StringVal, nil
}
}
}
return "", fmt.Errorf("couldn't find the CHAINS-GIT_URL PipelineRun result")
return "", h.MissingInfoInPipelineRunError(pipelineRun.Name, PipelineRunChainsGitUrlParamName)
}

// GetComponentSourceGitCommit returns a string containing the CHAINS-GIT_COMMIT result value from a given PipelineRun.
func GetComponentSourceGitCommit(object client.Object) (string, error) {
if pipelineRun, ok := object.(*tektonv1.PipelineRun); ok {
pipelineRun, ok := object.(*tektonv1.PipelineRun)
if ok {
for _, pipelineResult := range pipelineRun.Status.Results {
if pipelineResult.Name == "CHAINS-GIT_COMMIT" {
if pipelineResult.Name == PipelineRunChainsGitCommitParamName {
return pipelineResult.Value.StringVal, nil
}
}
}
return "", fmt.Errorf("couldn't find the CHAINS-GIT_COMMIT PipelineRun result")
return "", h.MissingInfoInPipelineRunError(pipelineRun.Name, PipelineRunChainsGitCommitParamName)
}

0 comments on commit cb0b172

Please sign in to comment.