-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
734f35a
commit 912271b
Showing
82 changed files
with
3,363 additions
and
2,707 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
Copyright 2024 The Tekton Authors | ||
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. | ||
*/ | ||
|
||
package resolution | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"fmt" | ||
|
||
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" | ||
"github.com/tektoncd/pipeline/pkg/apis/resolution/v1beta1" | ||
"github.com/tektoncd/pipeline/pkg/resolution/common" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
func CreateResolutionRequest(ctx context.Context, resolver common.ResolverName, name, namespace string, params []v1.Param, ownerRef metav1.OwnerReference) *v1beta1.ResolutionRequest { | ||
rr := &v1beta1.ResolutionRequest{ | ||
TypeMeta: metav1.TypeMeta{ | ||
APIVersion: "resolution.tekton.dev/v1beta1", | ||
Kind: "ResolutionRequest", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
Labels: map[string]string{ | ||
common.LabelKeyResolverType: string(resolver), | ||
}, | ||
}, | ||
Spec: v1beta1.ResolutionRequestSpec{ | ||
Params: params, | ||
}, | ||
} | ||
appendOwnerReference(rr, ownerRef) | ||
return rr | ||
} | ||
|
||
func appendOwnerReference(rr *v1beta1.ResolutionRequest, ownerRef metav1.OwnerReference) { | ||
isOwner := false | ||
for _, ref := range rr.ObjectMeta.OwnerReferences { | ||
if ownerRefsAreEqual(ref, ownerRef) { | ||
isOwner = true | ||
} | ||
} | ||
if !isOwner { | ||
rr.ObjectMeta.OwnerReferences = append(rr.ObjectMeta.OwnerReferences, ownerRef) | ||
} | ||
} | ||
|
||
func ownerRefsAreEqual(a, b metav1.OwnerReference) bool { | ||
// pointers values cannot be directly compared. | ||
if (a.Controller == nil && b.Controller != nil) || | ||
(a.Controller != nil && b.Controller == nil) || | ||
(*a.Controller != *b.Controller) { | ||
return false | ||
} | ||
return a.APIVersion == b.APIVersion && a.Kind == b.Kind && a.Name == b.Name && a.UID == b.UID | ||
} | ||
|
||
// ReadOnlyResolutionRequest is an opaque wrapper around ResolutionRequest | ||
// that provides the methods needed to read data from it using the | ||
// Resource interface without exposing the underlying API | ||
// object. | ||
type ReadOnlyResolutionRequest struct { | ||
req *v1beta1.ResolutionRequest | ||
} | ||
|
||
var _ common.ResolvedResource = ReadOnlyResolutionRequest{} | ||
|
||
func CrdIntoResource(rr *v1beta1.ResolutionRequest) ReadOnlyResolutionRequest { | ||
return ReadOnlyResolutionRequest{req: rr} | ||
} | ||
|
||
func (r ReadOnlyResolutionRequest) Annotations() map[string]string { | ||
status := r.req.GetStatus() | ||
if status != nil && status.Annotations != nil { | ||
annotationsCopy := map[string]string{} | ||
for key, val := range status.Annotations { | ||
annotationsCopy[key] = val | ||
} | ||
return annotationsCopy | ||
} | ||
return nil | ||
} | ||
|
||
func (r ReadOnlyResolutionRequest) Data() ([]byte, error) { | ||
encodedData := r.req.Status.ResolutionRequestStatusFields.Data | ||
decodedBytes, err := base64.StdEncoding.Strict().DecodeString(encodedData) | ||
if err != nil { | ||
return nil, fmt.Errorf("error decoding data from base64: %w", err) | ||
} | ||
return decodedBytes, nil | ||
} | ||
|
||
func (r ReadOnlyResolutionRequest) RefSource() *v1.RefSource { | ||
return r.req.Status.RefSource | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
Copyright 2024 The Tekton Authors | ||
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. | ||
*/ | ||
package resolution | ||
|
||
import ( | ||
"fmt" | ||
"hash" | ||
"hash/fnv" | ||
"sort" | ||
|
||
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" | ||
"github.com/tektoncd/pipeline/pkg/apis/resolution/v1beta1" | ||
"knative.dev/pkg/kmeta" | ||
) | ||
|
||
func GetNameNamespace(resolverName string, owner kmeta.OwnerRefable, name string, namespace string, params v1.Params) (string, string, error) { | ||
if name == "" { | ||
name = owner.GetObjectMeta().GetName() | ||
namespace = owner.GetObjectMeta().GetNamespace() | ||
} | ||
if namespace == "" { | ||
namespace = "default" | ||
} | ||
// Generating a deterministic name for the resource request | ||
// prevents multiple requests being issued for the same | ||
// pipelinerun's pipelineRef or taskrun's taskRef. | ||
remoteResourceBaseName := namespace + "/" + name | ||
name, err := GenerateDeterministicName(resolverName, remoteResourceBaseName, &v1beta1.ResolutionRequestSpec{Params: params}) | ||
if err != nil { | ||
return "", "", fmt.Errorf("error generating name for taskrun %s/%s: %w", namespace, name, err) | ||
} | ||
return name, namespace, nil | ||
} | ||
|
||
// nameHasher returns the hash.Hash to use when generating names. | ||
func nameHasher() hash.Hash { | ||
return fnv.New128a() | ||
} | ||
|
||
// GenerateDeterministicName makes a best-effort attempt to create a | ||
// unique but reproducible name for use in a Request. The returned value | ||
// will have the format {prefix}-{hash} where {prefix} is | ||
// given and {hash} is nameHasher(base) + nameHasher(param1) + | ||
// nameHasher(param2) + ... | ||
func GenerateDeterministicName(prefix, base string, resolutionSpec *v1beta1.ResolutionRequestSpec) (string, error) { | ||
hasher := nameHasher() | ||
if _, err := hasher.Write([]byte(base)); err != nil { | ||
return "", err | ||
} | ||
|
||
if resolutionSpec == nil { | ||
return fmt.Sprintf("%s-%x", prefix, hasher.Sum(nil)), nil | ||
} | ||
params := resolutionSpec.Params | ||
sortedParams := make(v1.Params, len(params)) | ||
for i := range params { | ||
sortedParams[i] = *params[i].DeepCopy() | ||
} | ||
sort.SliceStable(sortedParams, func(i, j int) bool { | ||
return sortedParams[i].Name < sortedParams[j].Name | ||
}) | ||
for _, p := range sortedParams { | ||
if _, err := hasher.Write([]byte(p.Name)); err != nil { | ||
return "", err | ||
} | ||
switch p.Value.Type { | ||
case v1.ParamTypeString: | ||
if _, err := hasher.Write([]byte(p.Value.StringVal)); err != nil { | ||
return "", err | ||
} | ||
case v1.ParamTypeArray, v1.ParamTypeObject: | ||
asJSON, err := p.Value.MarshalJSON() | ||
if err != nil { | ||
return "", err | ||
} | ||
if _, err := hasher.Write(asJSON); err != nil { | ||
return "", err | ||
} | ||
} | ||
} | ||
return fmt.Sprintf("%s-%x", prefix, hasher.Sum(nil)), nil | ||
} |
Oops, something went wrong.