diff --git a/pkg/resolution/resolver/bundle/config.go b/pkg/resolution/resolver/bundle/config.go index e46a3151334..da672db62e8 100644 --- a/pkg/resolution/resolver/bundle/config.go +++ b/pkg/resolution/resolver/bundle/config.go @@ -14,12 +14,13 @@ limitations under the License. package bundle const ( - // ConfigMapName is the bundle resolver's config map - ConfigMapName = "bundleresolver-config" // ConfigServiceAccount is the configuration field name for controlling // the Service Account name to use for bundle requests. ConfigServiceAccount = "default-service-account" // ConfigKind is the configuration field name for controlling // what the layer name in the bundle image is. ConfigKind = "default-kind" + // DefaultTimeoutKey is the configuration field name for controlling + // the maximum duration of a resolution request for a file from registry. + ConfigTimeoutKey = "fetch-timeout" ) diff --git a/pkg/resolution/resolver/bundle/resolver.go b/pkg/resolution/resolver/bundle/resolver.go index 95c18f21963..2d0e37b670d 100644 --- a/pkg/resolution/resolver/bundle/resolver.go +++ b/pkg/resolution/resolver/bundle/resolver.go @@ -19,6 +19,7 @@ package bundle import ( "context" "errors" + "fmt" "time" "github.com/google/go-containerregistry/pkg/authn/k8schain" @@ -34,18 +35,26 @@ import ( const ( disabledError = "cannot handle resolution request, enable-bundles-resolver feature flag not true" - // TODO(sbwsg): This should be exposed as a configurable option for - // admins (e.g. via ConfigMap) - timeoutDuration = time.Minute - // LabelValueBundleResolverType is the value to use for the // resolution.tekton.dev/type label on resource requests LabelValueBundleResolverType string = "bundles" // BundleResolverName is the name that the bundle resolver should be associated with. BundleResolverName = "bundleresolver" + + // ConfigMapName is the bundle resolver's config map + ConfigMapName = "bundleresolver-config" ) +var _ framework.ConfigWatcher = &Resolver{} + +// GetConfigName returns the name of the git resolver's configmap. +func (r *Resolver) GetConfigName(context.Context) string { + return ConfigMapName +} + +var _ framework.TimedResolution = &Resolver{} + // Resolver implements a framework.Resolver that can fetch files from OCI bundles. // // Deprecated: Use [github.com/tektoncd/pipeline/pkg/remoteresolution/resolver/bundle.Resolver] instead. @@ -64,11 +73,6 @@ func (r *Resolver) GetName(context.Context) string { return BundleResolverName } -// GetConfigName returns the name of the bundle resolver's configmap. -func (r *Resolver) GetConfigName(context.Context) string { - return ConfigMapName -} - // GetSelector returns a map of labels to match requests to this Resolver. func (r *Resolver) GetSelector(context.Context) map[string]string { return map[string]string{ @@ -108,8 +112,6 @@ func ResolveRequest(ctx context.Context, kubeClientSet kubernetes.Interface, req if err != nil { return nil, err } - ctx, cancelFn := context.WithTimeout(ctx, timeoutDuration) - defer cancelFn() return GetEntry(ctx, kc, opts) } @@ -127,3 +129,21 @@ func isDisabled(ctx context.Context) bool { cfg := resolverconfig.FromContextOrDefaults(ctx) return !cfg.FeatureFlags.EnableBundleResolver } + +// GetResolutionTimeout returns a time.Duration for the amount of time a +// single bundle fetch may take. This can be configured with the +// fetch-timeout field in the bundle-resolver-config ConfigMap. +func (r *Resolver) GetResolutionTimeout(ctx context.Context, defaultTimeout time.Duration, params map[string]string) (time.Duration, error) { + conf := framework.GetResolverConfigFromContext(ctx) + + timeout := defaultTimeout + if v, ok := conf[ConfigTimeoutKey]; ok { + var err error + timeout, err = time.ParseDuration(v) + if err != nil { + return time.Duration(0), fmt.Errorf("error parsing bundle timeout value %s: %w", v, err) + } + } + + return timeout, nil +} diff --git a/pkg/resolution/resolver/bundle/resolver_test.go b/pkg/resolution/resolver/bundle/resolver_test.go index d5e1ce4f84d..0ee6b9847a9 100644 --- a/pkg/resolution/resolver/bundle/resolver_test.go +++ b/pkg/resolution/resolver/bundle/resolver_test.go @@ -711,3 +711,32 @@ func pushToRegistry(t *testing.T, registry, imageName string, data []runtime.Obj hex: hex, } } + +func TestGetResolutionTimeoutDefault(t *testing.T) { + resolver := Resolver{} + defaultTimeout := 30 * time.Minute + timeout, err := resolver.GetResolutionTimeout(context.Background(), defaultTimeout, map[string]string{}) + if err != nil { + t.Fatalf("couldn't get default-timeout: %v", err) + } + if timeout != defaultTimeout { + t.Fatalf("expected default timeout to be returned") + } +} + +func TestGetResolutionTimeoutCustom(t *testing.T) { + resolver := Resolver{} + defaultTimeout := 30 * time.Minute + configTimeout := 5 * time.Second + config := map[string]string{ + ConfigTimeoutKey: configTimeout.String(), + } + ctx := framework.InjectResolverConfigToContext(context.Background(), config) + timeout, err := resolver.GetResolutionTimeout(ctx, defaultTimeout, map[string]string{}) + if err != nil { + t.Fatalf("couldn't get default-timeout: %v", err) + } + if timeout != configTimeout { + t.Fatalf("expected timeout from config to be returned") + } +}