github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/pkg/utils/build/task_results.go (about)

     1  package build
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  
     8  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
     9  	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
    10  	"k8s.io/apimachinery/pkg/types"
    11  
    12  	crclient "sigs.k8s.io/controller-runtime/pkg/client"
    13  )
    14  
    15  var taskNames = []string{"clair-scan", "clamav-scan", "deprecated-base-image-check", "inspect-image", "label-check", "sbom-json-check"}
    16  
    17  type TestOutput struct {
    18  	Result    string `json:"result"`
    19  	Timestamp string `json:"timestamp"`
    20  	Note      string `json:"note"`
    21  	Namespace string `json:"namespace"`
    22  	Successes int    `json:"successes"`
    23  	Failures  int    `json:"failures"`
    24  	Warnings  int    `json:"warnings"`
    25  }
    26  
    27  type ClairScanResult struct {
    28  	Vulnerabilities Vulnerabilities `json:"vulnerabilities"`
    29  }
    30  
    31  type Vulnerabilities struct {
    32  	Critical int `json:"critical"`
    33  	High     int `json:"high"`
    34  	Medium   int `json:"medium"`
    35  	Low      int `json:"low"`
    36  }
    37  
    38  func ValidateBuildPipelineTestResults(pipelineRun *v1beta1.PipelineRun, c crclient.Client) error {
    39  	for _, taskName := range taskNames {
    40  		results, err := fetchTaskRunResults(c, pipelineRun, taskName)
    41  		if err != nil {
    42  			return err
    43  		}
    44  
    45  		resultsToValidate := []string{constants.TektonTaskTestOutputName}
    46  
    47  		switch taskName {
    48  		case "clair-scan":
    49  			resultsToValidate = append(resultsToValidate, "CLAIR_SCAN_RESULT")
    50  		case "deprecated-image-check":
    51  			resultsToValidate = append(resultsToValidate, "PYXIS_HTTP_CODE")
    52  		case "inspect-image":
    53  			resultsToValidate = append(resultsToValidate, "BASE_IMAGE", "BASE_IMAGE_REPOSITORY")
    54  		}
    55  
    56  		if err := validateTaskRunResult(results, resultsToValidate, taskName); err != nil {
    57  			return err
    58  		}
    59  
    60  	}
    61  	return nil
    62  }
    63  
    64  func fetchTaskRunResults(c crclient.Client, pr *v1beta1.PipelineRun, pipelineTaskName string) ([]v1beta1.TaskRunResult, error) {
    65  	for _, chr := range pr.Status.ChildReferences {
    66  		if chr.PipelineTaskName != pipelineTaskName {
    67  			continue
    68  		}
    69  		taskRun := &v1beta1.TaskRun{}
    70  		taskRunKey := types.NamespacedName{Namespace: pr.Namespace, Name: chr.Name}
    71  		if err := c.Get(context.TODO(), taskRunKey, taskRun); err != nil {
    72  			return nil, err
    73  		}
    74  		return taskRun.Status.TaskRunResults, nil
    75  	}
    76  	return nil, fmt.Errorf(
    77  		"pipelineTaskName %q not found in PipelineRun %s/%s", pipelineTaskName, pr.GetName(), pr.GetNamespace())
    78  }
    79  
    80  func validateTaskRunResult(trResults []v1beta1.TaskRunResult, expectedResultNames []string, taskName string) error {
    81  	for _, rn := range expectedResultNames {
    82  		found := false
    83  		for _, r := range trResults {
    84  			if rn == r.Name {
    85  				found = true
    86  				switch r.Name {
    87  				case constants.TektonTaskTestOutputName:
    88  					var testOutput = &TestOutput{}
    89  					err := json.Unmarshal([]byte(r.Value.StringVal), &testOutput)
    90  					if err != nil {
    91  						return fmt.Errorf("cannot parse %q result: %+v", constants.TektonTaskTestOutputName, err)
    92  					}
    93  					// If the test result isn't SUCCESS, the overall outcome is a failure
    94  					if taskName == "sbom-json-check" {
    95  						if testOutput.Result == "FAILURE" {
    96  							return fmt.Errorf("expected Result for Task name %q to be SUCCESS: %+v", taskName, testOutput)
    97  						}
    98  					}
    99  				case "CLAIR_SCAN_RESULT":
   100  					var testOutput = &ClairScanResult{}
   101  					err := json.Unmarshal([]byte(r.Value.StringVal), &testOutput)
   102  					if err != nil {
   103  						return fmt.Errorf("cannot parse CLAIR_SCAN_RESULT result: %+v", err)
   104  					}
   105  				case "PYXIS_HTTP_CODE", "BASE_IMAGE", "BASE_IMAGE_REPOSITORY":
   106  					if len(r.Value.StringVal) < 1 {
   107  						return fmt.Errorf("value of %q result is empty", r.Name)
   108  					}
   109  				}
   110  			}
   111  		}
   112  		if !found {
   113  			return fmt.Errorf("expected result name %q not found in Task %q result", rn, taskName)
   114  		}
   115  	}
   116  	return nil
   117  }