Skip to content

Commit 23cba41

Browse files
waveywavesbrianwcooktwoGiantsclaude
committed
feat: implement shared cache for bundle, git, and cluster resolvers
Implements a shared, thread-safe LRU cache with TTL expiration for Tekton resolvers (bundle, git, cluster). All resolvers share a single cache instance configured via ConfigMap with hot-reload support. Features: - Shared singleton cache across all resolver types - ConfigMap-based configuration (max-size, ttl) - Three cache modes: always, never, auto (immutability detection) - Thread-safe concurrent access with proper locking - Content-addressable keys using SHA-256 hashing - Observability via annotations (cache hit/miss, timestamps) - Clock interface for testable timestamp generation Testing: - Unit tests for cache operations, TTL, LRU eviction - Race detector tests for concurrent access - E2E tests for end-to-end cache behavior - High-load concurrency tests (1000 goroutines) Implementation uses k8s.io/apimachinery LRUExpireCache with ConfigMap watching for dynamic reconfiguration without restart. Co-authored-by: Brian Cook <[email protected]> Co-authored-by: Stanislav Jakuschevskij <[email protected]> Co-authored-by: Vibhav Bobade <[email protected]> Co-authored-by: AI Assistant <[email protected]>
1 parent d8f7b93 commit 23cba41

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+4789
-321
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,6 @@ docs/pipeline-api.md.backup
6666

6767
# Ignore generated kind.yaml
6868
kind.yaml
69+
70+
# Profiling
71+
cpu.prof

config/resolvers/bundleresolver-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ data:
2626
default-service-account: "default"
2727
# The default layer kind in the bundle image.
2828
default-kind: "task"
29+
# Optional: Default cache mode for this resolver. Valid values: "always", "never", "auto" (default: "auto")
30+
# "always" - Always cache resolved resources
31+
# "never" - Never cache resolved resources
32+
# "auto" - Only cache bundles with digest references (@sha256:...)
33+
# default-cache-mode: "auto"

config/resolvers/cluster-resolver-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ data:
3030
allowed-namespaces: ""
3131
# An optional comma-separated list of namespaces which the resolver is blocked from accessing. Defaults to empty, meaning all namespaces are allowed.
3232
blocked-namespaces: ""
33+
# Optional: Default cache mode for this resolver. Valid values: "always", "never", "auto" (default: "auto")
34+
# "always" - Always cache resolved resources
35+
# "never" - Never cache resolved resources (recommended for cluster resolver since resources are mutable)
36+
# "auto" - Never cache for cluster resolver (same as "never")
37+
# default-cache-mode: "auto"

config/resolvers/git-resolver-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ data:
4141
# The default organization to look for repositories under when using the authenticated API,
4242
# if not specified in the resolver parameters. Optional.
4343
default-org: ""
44+
# Optional: Default cache mode for this resolver. Valid values: "always", "never", "auto" (default: "auto")
45+
# "always" - Always cache resolved resources
46+
# "never" - Never cache resolved resources
47+
# "auto" - Only cache when revision is a commit hash
48+
# default-cache-mode: "auto"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2025 The Tekton Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: v1
16+
kind: ConfigMap
17+
metadata:
18+
name: resolver-cache-config
19+
namespace: tekton-pipelines-resolvers
20+
labels:
21+
app.kubernetes.io/component: resolvers
22+
app.kubernetes.io/instance: default
23+
app.kubernetes.io/part-of: tekton-pipelines
24+
data:
25+
# Maximum number of entries in the resolver cache
26+
max-size: "1000"
27+
# Time-to-live for cache entries (examples: 5m, 10m, 1h)
28+
ttl: "5m"

docs/bundle-resolver.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This Resolver responds to type `bundles`.
1919
| `bundle` | The bundle url pointing at the image to fetch | `gcr.io/tekton-releases/catalog/upstream/golang-build:0.1` |
2020
| `name` | The name of the resource to pull out of the bundle | `golang-build` |
2121
| `kind` | The resource kind to pull out of the bundle | `task` |
22+
| `cache` | Controls caching behavior for the resolved resource | `always`, `never`, `auto` |
2223

2324
## Requirements
2425

@@ -45,6 +46,44 @@ for the name, namespace and defaults that the resolver ships with.
4546
| `backoff-cap` | The maxumum backoff duration. If reached, remaining steps are zeroed.| `10s`, `20s` |
4647
| `default-kind` | The default layer kind in the bundle image. | `task`, `pipeline` |
4748

49+
### Caching Options
50+
51+
The bundle resolver supports caching of resolved resources to improve performance. The caching behavior can be configured using the `cache` option:
52+
53+
| Cache Value | Description |
54+
|-------------|-------------|
55+
| `always` | Always cache resolved resources. This is the most aggressive caching strategy and will cache all resolved resources regardless of their source. |
56+
| `never` | Never cache resolved resources. This disables caching completely. |
57+
| `auto` | Caching will only occur for bundles pulled by digest. (default) |
58+
59+
### Cache Configuration
60+
61+
The resolver cache can be configured globally using the `resolver-cache-config` ConfigMap. This ConfigMap controls the cache size and TTL (time-to-live) for all resolvers.
62+
63+
| Option Name | Description | Default Value | Example Values |
64+
|-------------|-------------|---------------|----------------|
65+
| `max-size` | Maximum number of entries in the cache | `1000` | `500`, `2000` |
66+
| `ttl` | Time-to-live for cache entries | `5m` | `10m`, `1h` |
67+
68+
The ConfigMap name can be customized using the `RESOLVER_CACHE_CONFIG_MAP_NAME` environment variable. If not set, it defaults to `resolver-cache-config`.
69+
70+
Additionally, you can set a default cache mode for the bundle resolver by adding the `default-cache-mode` option to the `bundleresolver-config` ConfigMap. This overrides the system default (`auto`) for this resolver:
71+
72+
| Option Name | Description | Valid Values | Default |
73+
|-------------|-------------|--------------|---------|
74+
| `default-cache-mode` | Default caching behavior when `cache` parameter is not specified | `always`, `never`, `auto` | `auto` |
75+
76+
Example:
77+
```yaml
78+
apiVersion: v1
79+
kind: ConfigMap
80+
metadata:
81+
name: bundleresolver-config
82+
namespace: tekton-pipelines-resolvers
83+
data:
84+
default-cache-mode: "always" # Always cache unless task/pipeline specifies otherwise
85+
```
86+
4887
## Usage
4988
5089
### Task Resolution

docs/cluster-resolver.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,48 @@ This Resolver responds to type `cluster`.
1818
| `kind` | The kind of resource to fetch. | `task`, `pipeline`, `stepaction` |
1919
| `name` | The name of the resource to fetch. | `some-pipeline`, `some-task` |
2020
| `namespace` | The namespace in the cluster containing the resource. | `default`, `other-namespace` |
21+
| `cache` | Optional cache mode for the resolver. | `always`, `never`, `auto` |
22+
23+
### Cache Parameter
24+
25+
The `cache` parameter controls whether the cluster resolver caches resolved resources:
26+
27+
| Cache Mode | Description |
28+
|------------|-------------|
29+
| `always` | Always cache the resolved resource, regardless of whether it has an immutable reference. |
30+
| `never` | Never cache the resolved resource. |
31+
| `auto` | **Cluster resolver behavior**: Never cache (cluster resources lack immutable references). |
32+
| (not specified) | **Default behavior**: Never cache (same as `auto` for cluster resolver). |
33+
34+
**Note**: The cluster resolver only caches when `cache: always` is explicitly specified. This is because cluster resources (Tasks, Pipelines, etc.) do not have immutable references like Git commit hashes or bundle digests, making automatic caching unreliable.
35+
36+
### Cache Configuration
37+
38+
The resolver cache can be configured globally using the `resolver-cache-config` ConfigMap. This ConfigMap controls the cache size and TTL (time-to-live) for all resolvers.
39+
40+
| Option Name | Description | Default Value | Example Values |
41+
|-------------|-------------|---------------|----------------|
42+
| `max-size` | Maximum number of entries in the cache | `1000` | `500`, `2000` |
43+
| `ttl` | Time-to-live for cache entries | `5m` | `10m`, `1h` |
44+
45+
The ConfigMap name can be customized using the `RESOLVER_CACHE_CONFIG_MAP_NAME` environment variable. If not set, it defaults to `resolver-cache-config`.
46+
47+
Additionally, you can set a default cache mode for the cluster resolver by adding the `default-cache-mode` option to the `cluster-resolver-config` ConfigMap. This overrides the system default (`auto`) for this resolver:
48+
49+
| Option Name | Description | Valid Values | Default |
50+
|-------------|-------------|--------------|---------|
51+
| `default-cache-mode` | Default caching behavior when `cache` parameter is not specified | `always`, `never`, `auto` | `auto` |
52+
53+
Example:
54+
```yaml
55+
apiVersion: v1
56+
kind: ConfigMap
57+
metadata:
58+
name: cluster-resolver-config
59+
namespace: tekton-pipelines-resolvers
60+
data:
61+
default-cache-mode: "never" # Never cache by default (since cluster resources are mutable)
62+
```
2163
2264
## Requirements
2365
@@ -63,6 +105,48 @@ spec:
63105
value: namespace-containing-task
64106
```
65107

108+
### Task Resolution with Caching
109+
110+
```yaml
111+
apiVersion: tekton.dev/v1beta1
112+
kind: TaskRun
113+
metadata:
114+
name: remote-task-reference-cached
115+
spec:
116+
taskRef:
117+
resolver: cluster
118+
params:
119+
- name: kind
120+
value: task
121+
- name: name
122+
value: some-task
123+
- name: namespace
124+
value: namespace-containing-task
125+
- name: cache
126+
value: always
127+
```
128+
129+
### Task Resolution without Caching
130+
131+
```yaml
132+
apiVersion: tekton.dev/v1beta1
133+
kind: TaskRun
134+
metadata:
135+
name: remote-task-reference-no-cache
136+
spec:
137+
taskRef:
138+
resolver: cluster
139+
params:
140+
- name: kind
141+
value: task
142+
- name: name
143+
value: some-task
144+
- name: namespace
145+
value: namespace-containing-task
146+
- name: cache
147+
value: never
148+
```
149+
66150
### StepAction Resolution
67151

68152
```yaml

docs/git-resolver.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ This Resolver responds to type `git`.
2626
| `pathInRepo` | Where to find the file in the repo. | `task/golang-build/0.3/golang-build.yaml` |
2727
| `serverURL` | An optional server URL (that includes the https:// prefix) to connect for API operations | `https:/github.mycompany.com` |
2828
| `scmType` | An optional SCM type to use for API operations | `github`, `gitlab`, `gitea` |
29+
| `cache` | Controls caching behavior for the resolved resource | `always`, `never`, `auto` |
2930

3031
## Requirements
3132

@@ -55,6 +56,44 @@ for the name, namespace and defaults that the resolver ships with.
5556
| `api-token-secret-namespace` | The namespace containing the token secret, if not `default`. | `other-namespace` |
5657
| `default-org` | The default organization to look for repositories under when using the authenticated API, if not specified in the resolver parameters. Optional. | `tektoncd`, `kubernetes` |
5758

59+
### Caching Options
60+
61+
The git resolver supports caching of resolved resources to improve performance. The caching behavior can be configured using the `cache` option:
62+
63+
| Cache Value | Description |
64+
|-------------|-------------|
65+
| `always` | Always cache resolved resources. This is the most aggressive caching strategy and will cache all resolved resources regardless of their source. |
66+
| `never` | Never cache resolved resources. This disables caching completely. |
67+
| `auto` | Caching will only occur when revision is a commit hash. (default) |
68+
69+
### Cache Configuration
70+
71+
The resolver cache can be configured globally using the `resolver-cache-config` ConfigMap. This ConfigMap controls the cache size and TTL (time-to-live) for all resolvers.
72+
73+
| Option Name | Description | Default Value | Example Values |
74+
|-------------|-------------|---------------|----------------|
75+
| `max-size` | Maximum number of entries in the cache | `1000` | `500`, `2000` |
76+
| `ttl` | Time-to-live for cache entries | `5m` | `10m`, `1h` |
77+
78+
The ConfigMap name can be customized using the `RESOLVER_CACHE_CONFIG_MAP_NAME` environment variable. If not set, it defaults to `resolver-cache-config`.
79+
80+
Additionally, you can set a default cache mode for the git resolver by adding the `default-cache-mode` option to the `git-resolver-config` ConfigMap. This overrides the system default (`auto`) for this resolver:
81+
82+
| Option Name | Description | Valid Values | Default |
83+
|-------------|-------------|--------------|---------|
84+
| `default-cache-mode` | Default caching behavior when `cache` parameter is not specified | `always`, `never`, `auto` | `auto` |
85+
86+
Example:
87+
```yaml
88+
apiVersion: v1
89+
kind: ConfigMap
90+
metadata:
91+
name: git-resolver-config
92+
namespace: tekton-pipelines-resolvers
93+
data:
94+
default-cache-mode: "always" # Always cache unless task/pipeline specifies otherwise
95+
```
96+
5897
## Usage
5998
6099
The `git` resolver has two modes: cloning a repository with `git clone` (with

docs/hub-resolver.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ for the name, namespace and defaults that the resolver ships with.
4545
| `default-kind` | The default object kind for references. | `task`, `pipeline` |
4646
| `default-type` | The default hub from where to pull the resource. | `artifact`, `tekton` |
4747

48-
4948
### Configuring the Hub API endpoint
5049

5150
The Hub Resolver supports to resolve resources from the [Artifact Hub](https://artifacthub.io/) and the [Tekton Hub](https://hub.tekton.dev/),

docs/resolution.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ accompanying [resolver-template](./resolver-template).
3434
For a table of the interfaces and methods a resolver must implement
3535
along with those that are optional, see [resolver-reference.md](./resolver-reference.md).
3636

37+
## Resolver Cache Configuration
38+
39+
The resolver cache is used to improve performance by caching resolved resources for bundle and git resolver. By default, the cache uses:
40+
- 5 minutes ("5m") as the time-to-live (TTL) for cache entries
41+
- 1000 entries as the maximum cache size
42+
43+
You can override these defaults by editing the `resolver-cache-config.yaml` ConfigMap in the `tekton-pipelines-resolvers` namespace. Set the following keys:
44+
- `max-size`: Set the maximum number of cache entries (e.g., "500")
45+
- `default-ttl`: Set the default TTL for cache entries (e.g., "10m", "30s")
46+
47+
If these values are missing or invalid, the defaults will be used.
48+
3749
---
3850

3951
Except as otherwise noted, the content of this page is licensed under the

0 commit comments

Comments
 (0)