Skip to content

Commit

Permalink
feat: update chain's controllers to support both v1beta1 and v1 Tekto…
Browse files Browse the repository at this point in the history
…n APIs via ConfigMap
  • Loading branch information
aaron-prindle committed Dec 4, 2023
1 parent 16a7f80 commit 5dc235e
Show file tree
Hide file tree
Showing 85 changed files with 4,176 additions and 1,732 deletions.
3 changes: 2 additions & 1 deletion cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ func main() {
flag.Parse()
ctx := injection.WithNamespaceScope(signals.NewContext(), *namespace)

sharedmain.MainWithContext(ctx, "watcher", taskrun.NewController, pipelinerun.NewController)
sharedmain.MainWithContext(ctx, "watcher", taskrun.NewControllerV1, pipelinerun.NewControllerV1)
sharedmain.MainWithContext(ctx, "watcher", taskrun.NewControllerV1Beta1, pipelinerun.NewControllerV1Beta1)
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/tektoncd/chains

go 1.20
go 1.21

require (
cloud.google.com/go/compute/metadata v0.2.3
Expand All @@ -15,6 +15,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/in-toto/in-toto-golang v0.9.0
github.com/opencontainers/go-digest v1.0.0
github.com/opentracing/opentracing-go v1.2.0
github.com/pkg/errors v0.9.1
github.com/secure-systems-lab/go-securesystemslib v0.7.0
github.com/sigstore/cosign/v2 v2.2.1
Expand Down Expand Up @@ -335,7 +336,6 @@ require (
github.com/oleiade/reflections v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openzipkin/zipkin-go v0.3.0 // indirect
github.com/outcaste-io/ristretto v0.2.3 // indirect
github.com/pborman/uuid v1.2.1 // indirect
Expand Down
75 changes: 75 additions & 0 deletions go.sum

Large diffs are not rendered by default.

111 changes: 58 additions & 53 deletions pkg/artifacts/signable.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ import (
"context"
_ "crypto/sha256" // Recommended by go-digest.
_ "crypto/sha512" // Recommended by go-digest.
"encoding/json"
"fmt"
"regexp"
"strings"

"github.com/google/go-containerregistry/pkg/name"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
"github.com/opencontainers/go-digest"
"github.com/opentracing/opentracing-go/log"
"github.com/tektoncd/chains/internal/backport"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/config"
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/logging"
Expand Down Expand Up @@ -65,12 +68,12 @@ type TaskRunArtifact struct{}
var _ Signable = &TaskRunArtifact{}

func (ta *TaskRunArtifact) ShortKey(obj interface{}) string {
tro := obj.(*objects.TaskRunObject)
tro := obj.(*objects.TaskRunObjectV1)
return "taskrun-" + string(tro.UID)
}

func (ta *TaskRunArtifact) FullKey(obj interface{}) string {
tro := obj.(*objects.TaskRunObject)
tro := obj.(*objects.TaskRunObjectV1)
gvk := tro.GetGroupVersionKind()
return fmt.Sprintf("%s-%s-%s-%s", gvk.Group, gvk.Version, gvk.Kind, tro.UID)
}
Expand Down Expand Up @@ -104,12 +107,12 @@ type PipelineRunArtifact struct{}
var _ Signable = &PipelineRunArtifact{}

func (pa *PipelineRunArtifact) ShortKey(obj interface{}) string {
pro := obj.(*objects.PipelineRunObject)
pro := obj.(*objects.PipelineRunObjectV1)
return "pipelinerun-" + string(pro.UID)
}

func (pa *PipelineRunArtifact) FullKey(obj interface{}) string {
pro := obj.(*objects.PipelineRunObject)
pro := obj.(*objects.PipelineRunObjectV1)
gvk := pro.GetGroupVersionKind()
return fmt.Sprintf("%s-%s-%s-%s", gvk.Group, gvk.Version, gvk.Kind, pro.UID)
}
Expand Down Expand Up @@ -149,40 +152,50 @@ type image struct {
}

func (oa *OCIArtifact) ExtractObjects(ctx context.Context, obj objects.TektonObject) []interface{} {
log := logging.FromContext(ctx)
objs := []interface{}{}
if trV1, ok := obj.GetObject().(*v1.TaskRun); ok {
serializedResources := trV1.Annotations["tekton.dev/v1beta1-status-taskrunstatusfields-taskspec-resources"]
var resources v1beta1.TaskResources //nolint:staticcheck
shouldReplace := false
if err := json.Unmarshal([]byte(serializedResources), &resources); err == nil {
shouldReplace = true

// TODO: Not applicable to PipelineRuns, should look into a better way to separate this out
if tr, ok := obj.GetObject().(*v1beta1.TaskRun); ok {
imageResourceNames := map[string]*image{}
if tr.Status.TaskSpec != nil && tr.Status.TaskSpec.Resources != nil {
for _, output := range tr.Status.TaskSpec.Resources.Outputs {
if output.Type == backport.PipelineResourceTypeImage {
imageResourceNames[output.Name] = &image{}
}
trV1Beta1 := &v1beta1.TaskRun{} //nolint:staticcheck
if err := trV1Beta1.ConvertFrom(ctx, trV1); err == nil {
if shouldReplace {
trV1Beta1.Status.TaskSpec.Resources = &resources //nolint:staticcheck
}
imageResourceNames := map[string]*image{}
if trV1Beta1.Status.TaskSpec != nil && trV1Beta1.Status.TaskSpec.Resources != nil { //nolint:staticcheck
for _, output := range trV1Beta1.Status.TaskSpec.Resources.Outputs { //nolint:staticcheck
if output.Type == backport.PipelineResourceTypeImage {
imageResourceNames[output.Name] = &image{}
}
}
}
}

for _, rr := range tr.Status.ResourcesResult {
img, ok := imageResourceNames[rr.ResourceName]
if !ok {
continue
}
// We have a result for an image!
if rr.Key == "url" {
img.url = rr.Value
} else if rr.Key == "digest" {
img.digest = rr.Value
for _, rr := range trV1Beta1.Status.ResourcesResult {
img, ok := imageResourceNames[rr.ResourceName]
if !ok {
continue
}
// We have a result for an image!
if rr.Key == "url" {
img.url = rr.Value
} else if rr.Key == "digest" {
img.digest = rr.Value
}
}
}

for _, image := range imageResourceNames {
dgst, err := name.NewDigest(fmt.Sprintf("%s@%s", image.url, image.digest))
if err != nil {
log.Error(err)
continue
for _, image := range imageResourceNames {
dgst, err := name.NewDigest(fmt.Sprintf("%s@%s", image.url, image.digest))
if err != nil {
log.Error(err)
continue
}
objs = append(objs, dgst)
}
objs = append(objs, dgst)
}
}

Expand All @@ -208,16 +221,15 @@ func ExtractOCIImagesFromResults(ctx context.Context, obj objects.TektonObject)
logger.Errorf("error getting digest: %v", err)
continue
}

objs = append(objs, dgst)
}

// look for a comma separated list of images
for _, key := range obj.GetResults() {
if key.Name != "IMAGES" {
if key.GetName() != "IMAGES" {
continue
}
imgs := strings.FieldsFunc(key.Value.StringVal, split)
imgs := strings.FieldsFunc(key.GetStringValue(), split)

for _, img := range imgs {
trimmed := strings.TrimSpace(img)
Expand Down Expand Up @@ -291,43 +303,36 @@ func ExtractStructuredTargetFromResults(ctx context.Context, obj objects.TektonO
}

// TODO(#592): support structured results using Run
results := []objects.Result{}
for _, res := range obj.GetResults() {
results = append(results, objects.Result{
Name: res.Name,
Value: res.Value,
})
}
for _, res := range results {
if strings.HasSuffix(res.Name, categoryMarker) {
if strings.HasSuffix(res.GetName(), categoryMarker) {
valid, err := isStructuredResult(res, categoryMarker)
if err != nil {
logger.Debugf("ExtractStructuredTargetFromResults: %v", err)
}
if valid {
logger.Debugf("Extracted Structured data from Result %s, %s", res.Value.ObjectVal["uri"], res.Value.ObjectVal["digest"])
objs = append(objs, &StructuredSignable{URI: res.Value.ObjectVal["uri"], Digest: res.Value.ObjectVal["digest"]})
logger.Debugf("Extracted Structured data from Result %v", res)
objs = append(objs, &StructuredSignable{URI: res.GetObjectValue("uri"), Digest: res.GetObjectValue("digest")})
}
}
}
return objs
}

func isStructuredResult(res objects.Result, categoryMarker string) (bool, error) {
if !strings.HasSuffix(res.Name, categoryMarker) {
func isStructuredResult(res objects.GenericResult, categoryMarker string) (bool, error) {
if !strings.HasSuffix(res.GetName(), categoryMarker) {
return false, nil
}
if res.Value.ObjectVal == nil {
return false, fmt.Errorf("%s should be an object: %v", res.Name, res.Value.ObjectVal)
if res.ObjectValueIsNil() {
return false, fmt.Errorf("%s should be an object: %v", res.GetName(), res)
}
if res.Value.ObjectVal["uri"] == "" {
return false, fmt.Errorf("%s should have uri field: %v", res.Name, res.Value.ObjectVal)
if res.GetObjectValue("uri") == "" {
return false, fmt.Errorf("%s should have uri field: %v", res.GetName(), res)
}
if res.Value.ObjectVal["digest"] == "" {
return false, fmt.Errorf("%s should have digest field: %v", res.Name, res.Value.ObjectVal)
if res.GetObjectValue("digest") == "" {
return false, fmt.Errorf("%s should have digest field: %v", res.GetName(), res)
}
if _, _, err := ParseDigest(res.Value.ObjectVal["digest"]); err != nil {
return false, fmt.Errorf("error getting digest %s: %v", res.Value.ObjectVal["digest"], err)
if _, _, err := ParseDigest(res.GetObjectValue("digest")); err != nil {
return false, fmt.Errorf("error getting digest %s: %v", res.GetObjectValue("digest"), err)
}
return true, nil
}
Expand Down
Loading

0 comments on commit 5dc235e

Please sign in to comment.