From c8ac4d4ec2cf340aebea1e9b45943d2376b119ce Mon Sep 17 00:00:00 2001 From: pritidesai Date: Tue, 7 Mar 2023 14:13:00 -0800 Subject: [PATCH] simplifying matrix combinations Matrix combinations is created in [][]Param format which is very hard to process with matrix.Include. The parameters value can change in a combination or a new combination can be added based on matrix.Include.Params. Its easy to compare and work with map[string]string instead of []Param. Signed-off-by: pritidesai --- docs/pipeline-api.md | 87 ++------ go.mod | 25 +-- go.sum | 2 + pkg/apis/pipeline/v1/matrix_types.go | 81 +++++-- pkg/apis/pipeline/v1/matrix_types_test.go | 115 ++++++---- pkg/apis/pipeline/v1/zz_generated.deepcopy.go | 50 +++++ pkg/apis/pipeline/v1beta1/matrix_types.go | 81 +++++-- .../pipeline/v1beta1/matrix_types_test.go | 114 ++++++---- .../pipeline/v1beta1/zz_generated.deepcopy.go | 50 +++++ pkg/reconciler/pipelinerun/pipelinerun.go | 4 +- .../pipelinerun/pipelinerun_test.go | 108 +++++----- third_party/github.com/LICENSE | 202 ------------------ vendor/golang.org/x/exp/LICENSE | 27 +++ vendor/golang.org/x/exp/PATENTS | 22 ++ vendor/golang.org/x/exp/maps/maps.go | 94 ++++++++ vendor/modules.txt | 3 + 16 files changed, 615 insertions(+), 450 deletions(-) delete mode 100644 third_party/github.com/LICENSE create mode 100644 vendor/golang.org/x/exp/LICENSE create mode 100644 vendor/golang.org/x/exp/PATENTS create mode 100644 vendor/golang.org/x/exp/maps/maps.go diff --git a/docs/pipeline-api.md b/docs/pipeline-api.md index 6ed65c4a126..9f003a59f47 100644 --- a/docs/pipeline-api.md +++ b/docs/pipeline-api.md @@ -1320,6 +1320,16 @@ string +

Combination +(map[string]string alias)

+
+

Combination holds a single combination from a Matrix with key as param.Name and value as param.Value

+
+

Combinations +([]github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.Combination alias)

+
+

Combinations holds a list of combination for a given Matrix

+

ConfigSource

@@ -8176,6 +8186,16 @@ int32 +

Combination +(map[string]string alias)

+
+

Combination holds a single combination from a Matrix with key as param.Name and value as param.Value

+
+

Combinations +([]github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.Combination alias)

+
+

Combinations holds a list of combination for a given Matrix

+

ConfigSource

@@ -8658,11 +8678,7 @@ The names of the params must match the names of the paramsParam

-<<<<<<< HEAD -(Appears on:RunSpec, CustomRunSpec, PipelineRunSpec, ResolverRef, TaskRunInputs, TaskRunSpec, ResolutionRequestSpec) -======= -(Appears on:RunSpec, CustomRunSpec, Matrix, MatrixInclude, PipelineRunSpec, PipelineTask, ResolverRef, TaskRunSpec, ResolutionRequestSpec) ->>>>>>> 88e27b27f (Remove Git, Storage and Generic PipelineResources) +(Appears on:RunSpec, CustomRunSpec, PipelineRunSpec, ResolverRef, TaskRunSpec, ResolutionRequestSpec)

Param declares an ParamValues to use for the parameter called name.

@@ -8863,7 +8879,6 @@ map[string]string -<<<<<<< HEAD

Params ([]github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1.Param alias)

@@ -8872,66 +8887,6 @@ map[string]string

Params is a list of Param

-

PipelineDeclaredResource -

-

-(Appears on:PipelineSpec) -

-
-

PipelineDeclaredResource is used by a Pipeline to declare the types of the -PipelineResources that it will required to run and names which can be used to -refer to these PipelineResources in PipelineTaskResourceBindings.

-
- - - - - - - - - - - - - - - - - - - - - -
FieldDescription
-name
- -string - -
-

Name is the name that will be used by the Pipeline to refer to this resource. -It does not directly correspond to the name of any PipelineResources Task -inputs or outputs, and it does not correspond to the actual names of the -PipelineResources that will be bound in the PipelineRun.

-
-type
- -string - -
-

Type is the type of the PipelineResource.

-
-optional
- -bool - -
-

Optional declares the resource as optional. -optional: true - the resource is considered optional -optional: false - the resource is considered required (default/equivalent of not specifying it)

-
-======= ->>>>>>> 88e27b27f (Remove Git, Storage and Generic PipelineResources)

PipelineObject

diff --git a/go.mod b/go.mod index c77536319f1..acc24733462 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/tektoncd/plumbing v0.0.0-20220817140952-3da8ce01aeeb go.opencensus.io v0.24.0 go.uber.org/zap v1.24.0 + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 golang.org/x/oauth2 v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 gopkg.in/square/go-jose.v2 v2.6.0 @@ -41,9 +42,19 @@ require github.com/benbjohnson/clock v1.1.0 // indirect require ( code.gitea.io/sdk/gitea v0.15.1 + github.com/cenkalti/backoff/v3 v3.2.2 github.com/goccy/kpoward v0.1.0 github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20221030203717-1711cefd7eec + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-retryablehttp v0.7.2 + github.com/hashicorp/go-rootcerts v1.0.2 + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 + github.com/hashicorp/go-sockaddr v1.0.2 + github.com/hashicorp/hcl v1.0.0 github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf + github.com/mitchellh/mapstructure v1.5.0 + github.com/ryanuber/go-glob v1.0.0 github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 go.opentelemetry.io/otel v1.14.0 go.opentelemetry.io/otel/exporters/jaeger v1.14.0 @@ -73,7 +84,6 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/aws/aws-sdk-go-v2/service/kms v1.20.5 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.4 // indirect - github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/cloudflare/circl v1.1.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/fatih/color v1.13.0 // indirect @@ -83,21 +93,12 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.2 // indirect - github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect - github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/vault/api v1.9.0 // indirect github.com/jellydator/ttlcache/v2 v2.11.1 // indirect github.com/kr/pretty v0.3.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/rogpeppe/go-internal v1.8.0 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect github.com/skeema/knownhosts v1.1.0 // indirect github.com/theupdateframework/go-tuf v0.5.2 // indirect github.com/zeebo/errs v1.3.0 // indirect @@ -193,12 +194,12 @@ require ( go.uber.org/multierr v1.8.0 // indirect golang.org/x/crypto v0.6.0 golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/net v0.8.0 golang.org/x/sync v0.1.0 golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/time v0.3.0 golang.org/x/tools v0.6.0 // indirect google.golang.org/api v0.110.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 15b229f6fb6..078b9f3e1c6 100644 --- a/go.sum +++ b/go.sum @@ -1199,6 +1199,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/pkg/apis/pipeline/v1/matrix_types.go b/pkg/apis/pipeline/v1/matrix_types.go index 2ca66c10f1f..446bab576fd 100644 --- a/pkg/apis/pipeline/v1/matrix_types.go +++ b/pkg/apis/pipeline/v1/matrix_types.go @@ -16,8 +16,10 @@ package v1 import ( "context" "fmt" + "sort" "github.com/tektoncd/pipeline/pkg/apis/config" + "golang.org/x/exp/maps" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/strings/slices" "knative.dev/pkg/apis" @@ -51,49 +53,86 @@ type MatrixInclude struct { Params Params `json:"params,omitempty"` } -// FanOut produces combinations of Parameters of type String from a slice of Parameters of type Array. -func (m *Matrix) FanOut() []Params { - var combinations []Params - for _, parameter := range m.Params { - combinations = fanOut(parameter, combinations) +// Combination is a map, mainly defined to hold a single combination from a Matrix with key as param.Name and value as param.Value +type Combination map[string]string + +// Combinations is a list of combinations +type Combinations []Combination + +// ToParams transforms Combinations from a slice of map[string]string to a slice of Params +// such that, these combinations can be directly consumed in creating taskRun/run object +func (cs Combinations) ToParams() []Params { + listOfParams := make([]Params, len(cs)) + for i := range cs { + var params Params + combination := cs[i] + order, _ := combination.sortCombination() + for _, key := range order { + params = append(params, Param{ + Name: key, + Value: ParamValue{Type: ParamTypeString, StringVal: combination[key]}, + }) + } + listOfParams[i] = params } - return combinations + return listOfParams } // fanOut generates a new combination based on a given Parameter in the Matrix. -func fanOut(param Param, combinations []Params) []Params { - if len(combinations) == 0 { +func (cs Combinations) fanOut(param Param) Combinations { + if len(cs) == 0 { return initializeCombinations(param) } - return distribute(param, combinations) + return cs.distribute(param) } // distribute generates a new combination of Parameters by adding a new Parameter to an existing list of Combinations. -func distribute(param Param, combinations []Params) []Params { - var expandedCombinations []Params +func (cs Combinations) distribute(param Param) Combinations { + var expandedCombinations Combinations for _, value := range param.Value.ArrayVal { - for _, combination := range combinations { - expandedCombinations = append(expandedCombinations, createCombination(param.Name, value, combination)) + for _, combination := range cs { + newCombination := make(Combination) + maps.Copy(newCombination, combination) + newCombination[param.Name] = value + _, orderedCombination := newCombination.sortCombination() + expandedCombinations = append(expandedCombinations, orderedCombination) } } return expandedCombinations } // initializeCombinations generates a new combination based on the first Parameter in the Matrix. -func initializeCombinations(param Param) []Params { - var combinations []Params +func initializeCombinations(param Param) Combinations { + var combinations Combinations for _, value := range param.Value.ArrayVal { - combinations = append(combinations, createCombination(param.Name, value, []Param{})) + combinations = append(combinations, Combination{param.Name: value}) } return combinations } -func createCombination(name string, value string, combination Params) Params { - combination = append(combination, Param{ - Name: name, - Value: ParamValue{Type: ParamTypeString, StringVal: value}, +// sortCombination sorts the given Combination based on the param names to produce a deterministic ordering +func (c Combination) sortCombination() ([]string, Combination) { + sortedCombination := make(Combination, len(c)) + order := make([]string, 0, len(c)) + for key := range c { + order = append(order, key) + } + sort.Slice(order, func(i, j int) bool { + return order[i] <= order[j] }) - return combination + for _, key := range order { + sortedCombination[key] = c[key] + } + return order, sortedCombination +} + +// FanOut produces combinations of Parameters of type String from a slice of Parameters of type Array. +func (m *Matrix) FanOut() Combinations { + var combinations Combinations + for _, parameter := range m.Params { + combinations = combinations.fanOut(parameter) + } + return combinations } // CountCombinations returns the count of combinations of Parameters generated from the Matrix in PipelineTask. diff --git a/pkg/apis/pipeline/v1/matrix_types_test.go b/pkg/apis/pipeline/v1/matrix_types_test.go index db0e027803a..7c3a87ff66d 100644 --- a/pkg/apis/pipeline/v1/matrix_types_test.go +++ b/pkg/apis/pipeline/v1/matrix_types_test.go @@ -20,17 +20,19 @@ import ( "github.com/tektoncd/pipeline/test/diff" ) -func TestMatrix_FanOut(t *testing.T) { +func TestMatrix_FanOut_ToParams(t *testing.T) { tests := []struct { - name string - matrix Matrix - want []Params + name string + matrix Matrix + want Combinations + expectedParams []Params }{{ name: "matrix with no params", matrix: Matrix{ Params: Params{}, }, - want: nil, + want: nil, + expectedParams: nil, }, { name: "single array in matrix", matrix: Matrix{ @@ -39,7 +41,14 @@ func TestMatrix_FanOut(t *testing.T) { Value: ParamValue{Type: ParamTypeArray, ArrayVal: []string{"linux", "mac", "windows"}}, }}, }, - want: []Params{{ + want: Combinations{{ + "platform": "linux", + }, { + "platform": "mac", + }, { + "platform": "windows", + }}, + expectedParams: []Params{{ { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, @@ -65,84 +74,118 @@ func TestMatrix_FanOut(t *testing.T) { Name: "browser", Value: ParamValue{Type: ParamTypeArray, ArrayVal: []string{"chrome", "safari", "firefox"}}, }}}, - want: []Params{{ + want: Combinations{{ + "browser": "chrome", + "platform": "linux", + }, { + "browser": "chrome", + "platform": "mac", + }, { + "browser": "chrome", + "platform": "windows", + }, { + "browser": "safari", + "platform": "linux", + }, { + "browser": "safari", + "platform": "mac", + }, { + "browser": "safari", + "platform": "windows", + }, { + "browser": "firefox", + "platform": "linux", + }, { + "browser": "firefox", + "platform": "mac", + }, { + "browser": "firefox", + "platform": "windows", + }}, + expectedParams: []Params{{ { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }, { { + Name: "browser", + Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, + }, { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { + }}, { + { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, - }, - }, { - { + }, { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { - Name: "browser", - Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.matrix.FanOut() if d := cmp.Diff(tt.want, tt.matrix.FanOut()); d != "" { - t.Errorf("Combinations of Parameters did not match the expected Params: %s", d) + t.Errorf("Combinations of Parameters did not match the expected Params: %s", diff.PrintWantGot(d)) + } + c := tt.matrix.FanOut().ToParams() + for i := range c { + if d := cmp.Diff(tt.expectedParams[i], c[i]); d != "" { + t.Errorf("The formatted Combinations of Parameters did not match the expected Params: %s", diff.PrintWantGot(d)) + } } }) } diff --git a/pkg/apis/pipeline/v1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1/zz_generated.deepcopy.go index b50cea80046..f08cf537027 100644 --- a/pkg/apis/pipeline/v1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1/zz_generated.deepcopy.go @@ -54,6 +54,56 @@ func (in *ChildStatusReference) DeepCopy() *ChildStatusReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Combination) DeepCopyInto(out *Combination) { + { + in := &in + *out = make(Combination, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Combination. +func (in Combination) DeepCopy() Combination { + if in == nil { + return nil + } + out := new(Combination) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Combinations) DeepCopyInto(out *Combinations) { + { + in := &in + *out = make(Combinations, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = make(Combination, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Combinations. +func (in Combinations) DeepCopy() Combinations { + if in == nil { + return nil + } + out := new(Combinations) + in.DeepCopyInto(out) + return *out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigSource) DeepCopyInto(out *ConfigSource) { *out = *in diff --git a/pkg/apis/pipeline/v1beta1/matrix_types.go b/pkg/apis/pipeline/v1beta1/matrix_types.go index 6e64485ae47..204a178fddc 100644 --- a/pkg/apis/pipeline/v1beta1/matrix_types.go +++ b/pkg/apis/pipeline/v1beta1/matrix_types.go @@ -16,8 +16,10 @@ package v1beta1 import ( "context" "fmt" + "sort" "github.com/tektoncd/pipeline/pkg/apis/config" + "golang.org/x/exp/maps" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/strings/slices" "knative.dev/pkg/apis" @@ -51,49 +53,86 @@ type MatrixInclude struct { Params Params `json:"params,omitempty"` } -// FanOut produces combinations of Parameters of type String from a slice of Parameters of type Array. -func (m *Matrix) FanOut() []Params { - var combinations []Params - for _, parameter := range m.Params { - combinations = fanOut(parameter, combinations) +// Combination is a map, mainly defined to hold a single combination from a Matrix with key as param.Name and value as param.Value +type Combination map[string]string + +// Combinations is a list of combination +type Combinations []Combination + +// ToParams transforms Combinations from a slice of map[string]string to a slice of Params +// such that, the combinations can be directly consumed in creating taskRun/run object +func (cs Combinations) ToParams() []Params { + listOfParams := make([]Params, len(cs)) + for i := range cs { + var params Params + combination := cs[i] + order, sortedCombination := combination.sortCombination() + for _, key := range order { + params = append(params, Param{ + Name: key, + Value: ParamValue{Type: ParamTypeString, StringVal: sortedCombination[key]}, + }) + } + listOfParams[i] = params } - return combinations + return listOfParams } // fanOut generates a new combination based on a given Parameter in the Matrix. -func fanOut(param Param, combinations []Params) []Params { - if len(combinations) == 0 { +func (cs Combinations) fanOut(param Param) Combinations { + if len(cs) == 0 { return initializeCombinations(param) } - return distribute(param, combinations) + return cs.distribute(param) } // distribute generates a new combination of Parameters by adding a new Parameter to an existing list of Combinations. -func distribute(param Param, combinations []Params) []Params { - var expandedCombinations []Params +func (cs Combinations) distribute(param Param) Combinations { + var expandedCombinations Combinations for _, value := range param.Value.ArrayVal { - for _, combination := range combinations { - expandedCombinations = append(expandedCombinations, createCombination(param.Name, value, combination)) + for _, combination := range cs { + newCombination := make(Combination) + maps.Copy(newCombination, combination) + newCombination[param.Name] = value + _, orderedCombination := newCombination.sortCombination() + expandedCombinations = append(expandedCombinations, orderedCombination) } } return expandedCombinations } // initializeCombinations generates a new combination based on the first Parameter in the Matrix. -func initializeCombinations(param Param) []Params { - var combinations []Params +func initializeCombinations(param Param) Combinations { + var combinations Combinations for _, value := range param.Value.ArrayVal { - combinations = append(combinations, createCombination(param.Name, value, []Param{})) + combinations = append(combinations, Combination{param.Name: value}) } return combinations } -func createCombination(name string, value string, combination Params) Params { - combination = append(combination, Param{ - Name: name, - Value: ParamValue{Type: ParamTypeString, StringVal: value}, +// sortCombination sorts the given Combination based on the param names to produce a deterministic ordering +func (c Combination) sortCombination() ([]string, Combination) { + sortedCombination := make(Combination, len(c)) + order := make([]string, 0, len(c)) + for key := range c { + order = append(order, key) + } + sort.Slice(order, func(i, j int) bool { + return order[i] <= order[j] }) - return combination + for _, key := range order { + sortedCombination[key] = c[key] + } + return order, sortedCombination +} + +// FanOut produces combinations of Parameters of type String from a slice of Parameters of type Array. +func (m *Matrix) FanOut() Combinations { + var combinations Combinations + for _, parameter := range m.Params { + combinations = combinations.fanOut(parameter) + } + return combinations } // CountCombinations returns the count of combinations of Parameters generated from the Matrix in PipelineTask. diff --git a/pkg/apis/pipeline/v1beta1/matrix_types_test.go b/pkg/apis/pipeline/v1beta1/matrix_types_test.go index 86c404c7c6e..be058a74a34 100644 --- a/pkg/apis/pipeline/v1beta1/matrix_types_test.go +++ b/pkg/apis/pipeline/v1beta1/matrix_types_test.go @@ -20,17 +20,19 @@ import ( "github.com/tektoncd/pipeline/test/diff" ) -func TestMatrix_FanOut(t *testing.T) { +func TestMatrix_FanOut_ToParams(t *testing.T) { tests := []struct { - name string - matrix Matrix - want []Params + name string + matrix Matrix + want Combinations + expectedParams []Params }{{ name: "matrix with no params", matrix: Matrix{ Params: Params{}, }, - want: nil, + want: nil, + expectedParams: nil, }, { name: "single array in matrix", matrix: Matrix{ @@ -39,7 +41,14 @@ func TestMatrix_FanOut(t *testing.T) { Value: ParamValue{Type: ParamTypeArray, ArrayVal: []string{"linux", "mac", "windows"}}, }}, }, - want: []Params{{ + want: Combinations{{ + "platform": "linux", + }, { + "platform": "mac", + }, { + "platform": "windows", + }}, + expectedParams: []Params{{ { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, @@ -65,84 +74,117 @@ func TestMatrix_FanOut(t *testing.T) { Name: "browser", Value: ParamValue{Type: ParamTypeArray, ArrayVal: []string{"chrome", "safari", "firefox"}}, }}}, - want: []Params{{ + want: Combinations{{ + "browser": "chrome", + "platform": "linux", + }, { + "browser": "chrome", + "platform": "mac", + }, { + "browser": "chrome", + "platform": "windows", + }, { + "browser": "safari", + "platform": "linux", + }, { + "browser": "safari", + "platform": "mac", + }, { + "browser": "safari", + "platform": "windows", + }, { + "browser": "firefox", + "platform": "linux", + }, { + "browser": "firefox", + "platform": "mac", + }, { + "browser": "firefox", + "platform": "windows", + }}, + expectedParams: []Params{{ { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "chrome"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }, { { + Name: "browser", + Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, + }, { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { + }}, { + { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, - }, - }, { - { + }, { Name: "platform", Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { - Name: "browser", - Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "safari"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "mac"}, }, }, { { - Name: "platform", - Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, - }, { Name: "browser", Value: ParamValue{Type: ParamTypeString, StringVal: "firefox"}, + }, { + Name: "platform", + Value: ParamValue{Type: ParamTypeString, StringVal: "windows"}, }, }}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if d := cmp.Diff(tt.want, tt.matrix.FanOut()); d != "" { - t.Errorf("Combinations of Parameters did not match the expected Params: %s", d) + t.Errorf("Combinations of Parameters did not match the expected Params: %s", diff.PrintWantGot(d)) + } + c := tt.matrix.FanOut().ToParams() + for i := range c { + if d := cmp.Diff(tt.expectedParams[i], c[i]); d != "" { + t.Errorf("The formatted Combinations of Parameters did not match the expected Params: %s", diff.PrintWantGot(d)) + } } }) } diff --git a/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go index c521b8f9bf1..8f54536d032 100644 --- a/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1beta1/zz_generated.deepcopy.go @@ -151,6 +151,56 @@ func (in *ClusterTaskList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Combination) DeepCopyInto(out *Combination) { + { + in := &in + *out = make(Combination, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Combination. +func (in Combination) DeepCopy() Combination { + if in == nil { + return nil + } + out := new(Combination) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Combinations) DeepCopyInto(out *Combinations) { + { + in := &in + *out = make(Combinations, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = make(Combination, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Combinations. +func (in Combinations) DeepCopy() Combinations { + if in == nil { + return nil + } + out := new(Combinations) + in.DeepCopyInto(out) + return *out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigSource) DeepCopyInto(out *ConfigSource) { *out = *in diff --git a/pkg/reconciler/pipelinerun/pipelinerun.go b/pkg/reconciler/pipelinerun/pipelinerun.go index 92e1b6e1c94..cb01cb3dab9 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/pipelinerun/pipelinerun.go @@ -798,7 +798,7 @@ func (c *Reconciler) createTaskRuns(ctx context.Context, rpt *resources.Resolved ctx, span := c.tracerProvider.Tracer(TracerName).Start(ctx, "createTaskRuns") defer span.End() var taskRuns []*v1beta1.TaskRun - matrixCombinations := rpt.PipelineTask.Matrix.FanOut() + matrixCombinations := rpt.PipelineTask.Matrix.FanOut().ToParams() for i, taskRunName := range rpt.TaskRunNames { params := matrixCombinations[i] taskRun, err := c.createTaskRun(ctx, taskRunName, params, rpt, pr) @@ -872,7 +872,7 @@ func (c *Reconciler) createRunObjects(ctx context.Context, rpt *resources.Resolv var runObjects []v1beta1.RunObject ctx, span := c.tracerProvider.Tracer(TracerName).Start(ctx, "createRunObjects") defer span.End() - matrixCombinations := rpt.PipelineTask.Matrix.FanOut() + matrixCombinations := rpt.PipelineTask.Matrix.FanOut().ToParams() for i, runObjectName := range rpt.RunObjectNames { params := matrixCombinations[i] runObject, err := c.createRunObject(ctx, runObjectName, params, rpt, pr) diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index d9c20499d1c..e95835b4fde 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -7479,10 +7479,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: chrome + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7496,10 +7496,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: chrome + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7513,10 +7513,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: chrome + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7530,10 +7530,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: safari + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7547,10 +7547,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: safari + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7564,10 +7564,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: safari + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7581,10 +7581,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: firefox + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7598,10 +7598,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: firefox + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -7615,10 +7615,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: firefox + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8003,10 +8003,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: chrome + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8020,10 +8020,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: chrome + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8037,10 +8037,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: chrome + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8054,10 +8054,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: safari + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8071,10 +8071,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: safari + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8088,10 +8088,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: safari + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8105,10 +8105,10 @@ spec: ` spec: params: - - name: platform - value: linux - name: browser value: firefox + - name: platform + value: linux - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8122,10 +8122,10 @@ spec: ` spec: params: - - name: platform - value: mac - name: browser value: firefox + - name: platform + value: mac - name: version value: v0.33.0 serviceAccountName: test-sa @@ -8139,10 +8139,10 @@ spec: ` spec: params: - - name: platform - value: windows - name: browser value: firefox + - name: platform + value: windows - name: version value: v0.33.0 serviceAccountName: test-sa @@ -9020,10 +9020,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: linux - name: browser value: chrome + - name: platform + value: linux - name: version value: v0.1 serviceAccountName: test-sa @@ -9039,10 +9039,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: mac - name: browser value: chrome + - name: platform + value: mac - name: version value: v0.1 serviceAccountName: test-sa @@ -9058,10 +9058,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: windows - name: browser value: chrome + - name: platform + value: windows - name: version value: v0.1 serviceAccountName: test-sa @@ -9077,10 +9077,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: linux - name: browser value: safari + - name: platform + value: linux - name: version value: v0.1 serviceAccountName: test-sa @@ -9096,10 +9096,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: mac - name: browser value: safari + - name: platform + value: mac - name: version value: v0.1 serviceAccountName: test-sa @@ -9115,10 +9115,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: windows - name: browser value: safari + - name: platform + value: windows - name: version value: v0.1 serviceAccountName: test-sa @@ -9134,10 +9134,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: linux - name: browser value: firefox + - name: platform + value: linux - name: version value: v0.1 serviceAccountName: test-sa @@ -9153,10 +9153,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: mac - name: browser value: firefox + - name: platform + value: mac - name: version value: v0.1 serviceAccountName: test-sa @@ -9172,10 +9172,10 @@ spec: apiVersion: example.dev/v0 kind: Example params: - - name: platform - value: windows - name: browser value: firefox + - name: platform + value: windows - name: version value: v0.1 serviceAccountName: test-sa diff --git a/third_party/github.com/LICENSE b/third_party/github.com/LICENSE deleted file mode 100644 index d6456956733..00000000000 --- a/third_party/github.com/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/vendor/golang.org/x/exp/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/PATENTS b/vendor/golang.org/x/exp/PATENTS new file mode 100644 index 00000000000..733099041f8 --- /dev/null +++ b/vendor/golang.org/x/exp/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/exp/maps/maps.go b/vendor/golang.org/x/exp/maps/maps.go new file mode 100644 index 00000000000..ecc0dabb74d --- /dev/null +++ b/vendor/golang.org/x/exp/maps/maps.go @@ -0,0 +1,94 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package maps defines various functions useful with maps of any type. +package maps + +// Keys returns the keys of the map m. +// The keys will be in an indeterminate order. +func Keys[M ~map[K]V, K comparable, V any](m M) []K { + r := make([]K, 0, len(m)) + for k := range m { + r = append(r, k) + } + return r +} + +// Values returns the values of the map m. +// The values will be in an indeterminate order. +func Values[M ~map[K]V, K comparable, V any](m M) []V { + r := make([]V, 0, len(m)) + for _, v := range m { + r = append(r, v) + } + return r +} + +// Equal reports whether two maps contain the same key/value pairs. +// Values are compared using ==. +func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool { + if len(m1) != len(m2) { + return false + } + for k, v1 := range m1 { + if v2, ok := m2[k]; !ok || v1 != v2 { + return false + } + } + return true +} + +// EqualFunc is like Equal, but compares values using eq. +// Keys are still compared with ==. +func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool { + if len(m1) != len(m2) { + return false + } + for k, v1 := range m1 { + if v2, ok := m2[k]; !ok || !eq(v1, v2) { + return false + } + } + return true +} + +// Clear removes all entries from m, leaving it empty. +func Clear[M ~map[K]V, K comparable, V any](m M) { + for k := range m { + delete(m, k) + } +} + +// Clone returns a copy of m. This is a shallow clone: +// the new keys and values are set using ordinary assignment. +func Clone[M ~map[K]V, K comparable, V any](m M) M { + // Preserve nil in case it matters. + if m == nil { + return nil + } + r := make(M, len(m)) + for k, v := range m { + r[k] = v + } + return r +} + +// Copy copies all key/value pairs in src adding them to dst. +// When a key in src is already present in dst, +// the value in dst will be overwritten by the value associated +// with the key in src. +func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) { + for k, v := range src { + dst[k] = v + } +} + +// DeleteFunc deletes any key/value pairs from m for which del returns true. +func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) { + for k, v := range m { + if del(k, v) { + delete(m, k) + } + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 22a8dee39bd..81ea764a42f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -863,6 +863,9 @@ golang.org/x/crypto/ssh golang.org/x/crypto/ssh/agent golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/knownhosts +# golang.org/x/exp v0.0.0-20230307190834-24139beb5833 +## explicit; go 1.18 +golang.org/x/exp/maps # golang.org/x/mod v0.8.0 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp