diff --git a/docs/cluster-resolver.md b/docs/cluster-resolver.md index fc545420ce8..1a43f579449 100644 --- a/docs/cluster-resolver.md +++ b/docs/cluster-resolver.md @@ -13,11 +13,11 @@ This Resolver responds to type `cluster`. ## Parameters -| Param Name | Description | Example Value | -|-------------|-------------------------------------------------------|------------------------------| -| `kind` | The kind of resource to fetch. | `task`, `pipeline` | -| `name` | The name of the resource to fetch. | `some-pipeline`, `some-task` | -| `namespace` | The namespace in the cluster containing the resource. | `default`, `other-namespace` | +| Param Name | Description | Example Value | +|-------------|-------------------------------------------------------|----------------------------------| +| `kind` | The kind of resource to fetch. | `task`, `pipeline`, `stepaction` | +| `name` | The name of the resource to fetch. | `some-pipeline`, `some-task` | +| `namespace` | The namespace in the cluster containing the resource. | `default`, `other-namespace` | ## Requirements @@ -37,7 +37,7 @@ for the name, namespace and defaults that the resolver ships with. | Option Name | Description | Example Values | |----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------| -| `default-kind` | The default resource kind to fetch if not specified in parameters. | `task`, `pipeline` | +| `default-kind` | The default resource kind to fetch if not specified in parameters. | `task`, `pipeline`, `stepaction` | | `default-namespace` | The default namespace to fetch resources from if not specified in parameters. | `default`, `some-namespace` | | `allowed-namespaces` | An optional comma-separated list of namespaces which the resolver is allowed to access. Defaults to empty, meaning all namespaces are allowed. | `default,some-namespace`, (empty) | | `blocked-namespaces` | An optional comma-separated list of namespaces which the resolver is blocked from accessing. If the value is a `*` all namespaces will be disallowed and allowed namespace will need to be explicitely listed in `allowed-namespaces`. Defaults to empty, meaning all namespaces are allowed. | `default,other-namespace`, `*`, (empty) | @@ -63,6 +63,27 @@ spec: value: namespace-containing-task ``` +### StepAction Resolution + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: remote-stepaction-reference +spec: + steps: + - name: step-action-example + ref + resolver: cluster + params: + - name: kind + value: stepaction + - name: name + value: some-stepaction + - name: namespace + value: namespace-containing-stepaction +``` + ### Pipeline resolution ```yaml diff --git a/pkg/resolution/resolver/cluster/resolver.go b/pkg/resolution/resolver/cluster/resolver.go index bc53d51ab8d..bc9d5cd3e30 100644 --- a/pkg/resolution/resolver/cluster/resolver.go +++ b/pkg/resolution/resolver/cluster/resolver.go @@ -21,6 +21,7 @@ import ( "encoding/hex" "errors" "fmt" + "slices" "strings" resolverconfig "github.com/tektoncd/pipeline/pkg/apis/config/resolver" @@ -51,6 +52,8 @@ const ( var _ framework.Resolver = &Resolver{} +var supportedKinds = []string{"task", "pipeline", "stepaction"} + // Resolver implements a framework.Resolver that can fetch resources from other namespaces. // // Deprecated: Use [github.com/tektoncd/pipeline/pkg/remoteresolution/resolver/cluster.Resolver] instead. @@ -229,7 +232,7 @@ func populateParamsWithDefaults(ctx context.Context, origParams []pipelinev1.Par } else { params[KindParam] = pKind.StringVal } - if kindVal, ok := params[KindParam]; ok && kindVal != "task" && kindVal != "pipeline" { + if kindVal, ok := params[KindParam]; ok && !isSupportedKind(kindVal) { return nil, fmt.Errorf("unknown or unsupported resource kind '%s'", kindVal) } @@ -364,3 +367,7 @@ func fetchPipeline(ctx context.Context, groupVersion string, pipeline *pipelinev } return uid, data, sha256Checksum, spec, nil } + +func isSupportedKind(kindValue string) bool { + return slices.Contains[[]string, string](supportedKinds, kindValue) +} diff --git a/pkg/resolution/resolver/cluster/resolver_test.go b/pkg/resolution/resolver/cluster/resolver_test.go index 6cfdf36ac70..dd24ae7846b 100644 --- a/pkg/resolution/resolver/cluster/resolver_test.go +++ b/pkg/resolution/resolver/cluster/resolver_test.go @@ -279,6 +279,28 @@ func TestResolve(t *testing.T) { t.Fatalf("couldn't marshal pipeline: %v", err) } + exampleStepAction := &pipelinev1beta1.StepAction{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example-stepaction", + Namespace: "stepaction-ns", + ResourceVersion: "00003", + UID: "c123", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "StepAction", + APIVersion: "tekton.dev/v1beta1", + }, + Spec: pipelinev1beta1.StepActionSpec{}, + } + stepActionChecksum, err := exampleStepAction.Checksum() + if err != nil { + t.Fatalf("couldn't checksum stepaction: %v", err) + } + stepActionAsYAML, err := yaml.Marshal(exampleStepAction) + if err != nil { + t.Fatalf("couldn't marshal stepaction: %v", err) + } + testCases := []struct { name string kind string @@ -323,6 +345,23 @@ func TestResolve(t *testing.T) { }, }, }, + }, { + name: "successful stepaction", + kind: "stepaction", + resourceName: exampleStepAction.Name, + namespace: exampleStepAction.Namespace, + expectedStatus: &v1beta1.ResolutionRequestStatus{ + Status: duckv1.Status{}, + ResolutionRequestStatusFields: v1beta1.ResolutionRequestStatusFields{ + Data: base64.StdEncoding.Strict().EncodeToString(stepActionAsYAML), + RefSource: &pipelinev1.RefSource{ + URI: "/apis/tekton.dev/v1/namespaces/stepaction-ns/stepaction/example-stepaction@c123", + Digest: map[string]string{ + "sha256": hex.EncodeToString(stepActionChecksum), + }, + }, + }, + }, }, { name: "default namespace", kind: "pipeline", @@ -427,6 +466,7 @@ func TestResolve(t *testing.T) { Pipelines: []*pipelinev1.Pipeline{examplePipeline}, ResolutionRequests: []*v1beta1.ResolutionRequest{request}, Tasks: []*pipelinev1.Task{exampleTask}, + StepActions: []*pipelinev1beta1.StepAction{exampleStepAction}, } resolver := &cluster.Resolver{}