Skip to content

Commit 936cfd6

Browse files
authored
Merge pull request #1243 from fluxcd/helmrepo-oci-static
Static HelmRepository OCI
2 parents f54a59c + 1a7adeb commit 936cfd6

16 files changed

+472
-1115
lines changed

api/v1beta2/helmrepository_types.go

+18-5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const (
4444
type HelmRepositorySpec struct {
4545
// URL of the Helm repository, a valid URL contains at least a protocol and
4646
// host.
47+
// +kubebuilder:validation:Pattern="^(http|https|oci)://.*$"
4748
// +required
4849
URL string `json:"url"`
4950

@@ -88,13 +89,13 @@ type HelmRepositorySpec struct {
8889
// efficient use of resources.
8990
// +kubebuilder:validation:Type=string
9091
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
91-
// +required
92-
Interval metav1.Duration `json:"interval"`
92+
// +optional
93+
Interval metav1.Duration `json:"interval,omitempty"`
9394

9495
// Timeout is used for the index fetch operation for an HTTPS helm repository,
95-
// and for remote OCI Repository operations like pulling for an OCI helm repository.
96+
// and for remote OCI Repository operations like pulling for an OCI helm
97+
// chart by the associated HelmChart.
9698
// Its default value is 60s.
97-
// +kubebuilder:default:="60s"
9899
// +kubebuilder:validation:Type=string
99100
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m))+$"
100101
// +optional
@@ -169,7 +170,19 @@ func (in *HelmRepository) SetConditions(conditions []metav1.Condition) {
169170
// GetRequeueAfter returns the duration after which the source must be
170171
// reconciled again.
171172
func (in HelmRepository) GetRequeueAfter() time.Duration {
172-
return in.Spec.Interval.Duration
173+
if in.Spec.Interval.Duration != 0 {
174+
return in.Spec.Interval.Duration
175+
}
176+
return time.Minute
177+
}
178+
179+
// GetTimeout returns the timeout duration used for various operations related
180+
// to this HelmRepository.
181+
func (in HelmRepository) GetTimeout() time.Duration {
182+
if in.Spec.Timeout != nil {
183+
return in.Spec.Timeout.Duration
184+
}
185+
return time.Minute
173186
}
174187

175188
// GetArtifact returns the latest artifact from the source if present in the

config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,10 @@ spec:
357357
of this HelmRepository.
358358
type: boolean
359359
timeout:
360-
default: 60s
361360
description: Timeout is used for the index fetch operation for an
362361
HTTPS helm repository, and for remote OCI Repository operations
363-
like pulling for an OCI helm repository. Its default value is 60s.
362+
like pulling for an OCI helm chart by the associated HelmChart.
363+
Its default value is 60s.
364364
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$
365365
type: string
366366
type:
@@ -373,9 +373,9 @@ spec:
373373
url:
374374
description: URL of the Helm repository, a valid URL contains at least
375375
a protocol and host.
376+
pattern: ^(http|https|oci)://.*$
376377
type: string
377378
required:
378-
- interval
379379
- url
380380
type: object
381381
status:

docs/api/v1beta2/source.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@ Kubernetes meta/v1.Duration
866866
</em>
867867
</td>
868868
<td>
869+
<em>(Optional)</em>
869870
<p>Interval at which the HelmRepository URL is checked for updates.
870871
This interval is approximate and may be subject to jitter to ensure
871872
efficient use of resources.</p>
@@ -883,7 +884,8 @@ Kubernetes meta/v1.Duration
883884
<td>
884885
<em>(Optional)</em>
885886
<p>Timeout is used for the index fetch operation for an HTTPS helm repository,
886-
and for remote OCI Repository operations like pulling for an OCI helm repository.
887+
and for remote OCI Repository operations like pulling for an OCI helm
888+
chart by the associated HelmChart.
887889
Its default value is 60s.</p>
888890
</td>
889891
</tr>
@@ -2583,6 +2585,7 @@ Kubernetes meta/v1.Duration
25832585
</em>
25842586
</td>
25852587
<td>
2588+
<em>(Optional)</em>
25862589
<p>Interval at which the HelmRepository URL is checked for updates.
25872590
This interval is approximate and may be subject to jitter to ensure
25882591
efficient use of resources.</p>
@@ -2600,7 +2603,8 @@ Kubernetes meta/v1.Duration
26002603
<td>
26012604
<em>(Optional)</em>
26022605
<p>Timeout is used for the index fetch operation for an HTTPS helm repository,
2603-
and for remote OCI Repository operations like pulling for an OCI helm repository.
2606+
and for remote OCI Repository operations like pulling for an OCI helm
2607+
chart by the associated HelmChart.
26042608
Its default value is 60s.</p>
26052609
</td>
26062610
</tr>

docs/spec/v1beta2/helmrepositories.md

+38-32
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
There are 2 [Helm repository types](#type) defined by the `HelmRepository` API:
66
- Helm HTTP/S repository, which defines a Source to produce an Artifact for a Helm
77
repository index YAML (`index.yaml`).
8-
- OCI Helm repository, which defines a source that does not produce an Artifact.
9-
Instead a validation of the Helm repository is performed and the outcome is reported in the
10-
`.status.conditions` field.
8+
- OCI Helm repository, which defines a source that does not produce an Artifact.
9+
It's a data container to store the information about the OCI repository that
10+
can be used by [HelmChart](helmcharts.md) to access OCI Helm charts.
1111

1212
## Examples
1313

@@ -113,9 +113,11 @@ In the above example:
113113

114114
- A HelmRepository named `podinfo` is created, indicated by the
115115
`.metadata.name` field.
116-
- The source-controller performs the Helm repository url validation i.e. the url
117-
is a valid OCI registry url, every five minutes with the information indicated by the
118-
`.spec.interval` and `.spec.url` fields.
116+
- A HelmChart that refers to this HelmRepository uses the URL in the `.spec.url`
117+
field to access the OCI Helm chart.
118+
119+
**NOTE:** The `.spec.interval` field is only used by the `default` Helm
120+
repository and is ignored for any value in `oci` Helm repository.
119121

120122
You can run this example by saving the manifest into `helmrepository.yaml`.
121123

@@ -129,25 +131,12 @@ You can run this example by saving the manifest into `helmrepository.yaml`.
129131

130132
```console
131133
NAME URL AGE READY STATUS
132-
podinfo oci://ghcr.io/stefanprodan/charts 3m22s True Helm repository "podinfo" is ready
134+
podinfo oci://ghcr.io/stefanprodan/charts 3m22s
133135
```
134136

135-
3. Run `kubectl describe helmrepository podinfo` to see the [Conditions](#conditions)
136-
in the HelmRepository's Status:
137-
138-
```console
139-
...
140-
Status:
141-
Conditions:
142-
Last Transition Time: 2022-05-12T14:02:12Z
143-
Message: Helm repository "podinfo" is ready
144-
Observed Generation: 1
145-
Reason: Succeeded
146-
Status: True
147-
Type: Ready
148-
Observed Generation: 1
149-
Events: <none>
150-
```
137+
Because the OCI Helm repository is a data container, there's nothing to report
138+
for `READY` and `STATUS` columns above. The existence of the object can be
139+
considered to be ready for use.
151140

152141
## Writing a HelmRepository spec
153142

@@ -360,8 +349,12 @@ for more information about setting up GKE Workload Identity.
360349

361350
### Interval
362351

363-
`.spec.interval` is a required field that specifies the interval which the
364-
Helm repository index must be consulted at.
352+
**Note:** This field is ineffectual for [OCI Helm
353+
Repositories](#helm-oci-repository).
354+
355+
`.spec.interval` is a an optional field that specifies the interval which the
356+
Helm repository index must be consulted at. When not set, the default value is
357+
`1m`.
365358

366359
After successfully reconciling a HelmRepository object, the source-controller
367360
requeues the object for inspection after the specified interval. The value
@@ -387,11 +380,14 @@ For Helm repositories which require authentication, see [Secret reference](#secr
387380

388381
### Timeout
389382

383+
**Note:** This field is not applicable to [OCI Helm
384+
Repositories](#helm-oci-repository).
385+
390386
`.spec.timeout` is an optional field to specify a timeout for the fetch
391387
operation. The value must be in a
392388
[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
393-
e.g. `1m30s` for a timeout of one minute and thirty seconds. The default value
394-
is `60s`.
389+
e.g. `1m30s` for a timeout of one minute and thirty seconds. When not set, the
390+
default value is `1m`.
395391

396392
### Secret reference
397393

@@ -537,6 +533,9 @@ to HTTP/S Helm repositories.
537533

538534
### Suspend
539535

536+
**Note:** This field is not applicable to [OCI Helm
537+
Repositories](#helm-oci-repository).
538+
540539
`.spec.suspend` is an optional field to suspend the reconciliation of a
541540
HelmRepository. When set to `true`, the controller will stop reconciling the
542541
HelmRepository, and changes to the resource or the Helm repository index will
@@ -547,6 +546,10 @@ For practical information, see
547546
[suspending and resuming](#suspending-and-resuming).
548547

549548
## Working with HelmRepositories
549+
550+
**Note:** This section does not apply to [OCI Helm
551+
Repositories](#helm-oci-repository), being a data container, once created, they
552+
are ready to used by [HelmCharts](helmcharts.md).
550553

551554
### Triggering a reconcile
552555

@@ -648,6 +651,10 @@ flux resume source helm <repository-name>
648651

649652
### Debugging a HelmRepository
650653

654+
**Note:** This section does not apply to [OCI Helm
655+
Repositories](#helm-oci-repository), being a data container, they are static
656+
objects that don't require debugging if valid.
657+
651658
There are several ways to gather information about a HelmRepository for debugging
652659
purposes.
653660

@@ -713,9 +720,11 @@ specific HelmRepository, e.g. `flux logs --level=error --kind=HelmRepository --n
713720

714721
## HelmRepository Status
715722

716-
### Artifact
723+
**Note:** This section does not apply to [OCI Helm
724+
Repositories](#helm-oci-repository), they do not contain any information in the
725+
status.
717726

718-
**Note:** This section does not apply to [OCI Helm Repositories](#helm-oci-repository), they do not emit artifacts.
727+
### Artifact
719728

720729
The HelmRepository reports the last fetched repository index as an Artifact
721730
object in the `.status.artifact` of the resource.
@@ -757,9 +766,6 @@ and reports `Reconciling` and `Stalled` conditions where applicable to
757766
provide better (timeout) support to solutions polling the HelmRepository to become
758767
`Ready`.
759768

760-
OCI Helm repositories use only `Reconciling`, `Ready`, `FetchFailed`, and `Stalled`
761-
condition types.
762-
763769
#### Reconciling HelmRepository
764770

765771
The source-controller marks a HelmRepository as _reconciling_ when one of the following

hack/ci/e2e.sh

-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ kubectl -n source-system rollout status deploy/source-controller --timeout=1m
7575
kubectl -n source-system wait gitrepository/gitrepository-sample --for=condition=ready --timeout=1m
7676
kubectl -n source-system wait ocirepository/ocirepository-sample --for=condition=ready --timeout=1m
7777
kubectl -n source-system wait helmrepository/helmrepository-sample --for=condition=ready --timeout=1m
78-
kubectl -n source-system wait helmrepository/helmrepository-sample-oci --for=condition=ready --timeout=1m
7978
kubectl -n source-system wait helmchart/helmchart-sample --for=condition=ready --timeout=1m
8079
kubectl -n source-system wait helmchart/helmchart-sample-oci --for=condition=ready --timeout=1m
8180
kubectl -n source-system delete -f "${ROOT_DIR}/config/samples"
@@ -145,7 +144,6 @@ kubectl -n source-system wait gitrepository/large-repo --for=condition=ready --t
145144

146145
echo "Run HelmChart from OCI registry tests"
147146
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oci/source.yaml"
148-
kubectl -n source-system wait helmrepository/podinfo --for=condition=ready --timeout=1m
149147
kubectl -n source-system wait helmchart/podinfo --for=condition=ready --timeout=1m
150148
kubectl -n source-system wait helmchart/podinfo-keyless --for=condition=ready --timeout=1m
151149

internal/controller/helmchart_controller.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package controller
1818

1919
import (
2020
"context"
21+
"crypto/tls"
2122
"errors"
2223
"fmt"
2324
"net/url"
@@ -139,6 +140,12 @@ type HelmChartReconciler struct {
139140
patchOptions []patch.Option
140141
}
141142

143+
// RegistryClientGeneratorFunc is a function that returns a registry client
144+
// and an optional file name.
145+
// The file is used to store the registry client credentials.
146+
// The caller is responsible for deleting the file.
147+
type RegistryClientGeneratorFunc func(tlsConfig *tls.Config, isLogin bool) (*helmreg.Client, string, error)
148+
142149
func (r *HelmChartReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
143150
return r.SetupWithManagerAndOptions(ctx, mgr, HelmChartReconcilerOptions{})
144151
}
@@ -507,7 +514,7 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.Ser
507514
func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *helmv1.HelmChart,
508515
repo *helmv1.HelmRepository, b *chart.Build) (sreconcile.Result, error) {
509516
// Used to login with the repository declared provider
510-
ctxTimeout, cancel := context.WithTimeout(ctx, repo.Spec.Timeout.Duration)
517+
ctxTimeout, cancel := context.WithTimeout(ctx, repo.GetTimeout())
511518
defer cancel()
512519

513520
normalizedURL, err := repository.NormalizeURL(repo.Spec.URL)
@@ -992,7 +999,7 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
992999
}
9931000

9941001
// Used to login with the repository declared provider
995-
ctxTimeout, cancel := context.WithTimeout(ctx, obj.Spec.Timeout.Duration)
1002+
ctxTimeout, cancel := context.WithTimeout(ctx, obj.GetTimeout())
9961003
defer cancel()
9971004

9981005
clientOpts, certsTmpDir, err := getter.GetClientOpts(ctxTimeout, r.Client, obj, normalizedURL)

internal/controller/helmchart_controller_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func TestHelmChartReconciler_Reconcile(t *testing.T) {
197197
{
198198
name: "Stalling on invalid repository URL",
199199
beforeFunc: func(repository *helmv1.HelmRepository) {
200-
repository.Spec.URL = "://unsupported" // Invalid URL
200+
repository.Spec.URL = "https://unsupported/foo://" // Invalid URL
201201
},
202202
assertFunc: func(g *WithT, obj *helmv1.HelmChart, _ *helmv1.HelmRepository) {
203203
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
@@ -293,6 +293,7 @@ func TestHelmChartReconciler_Reconcile(t *testing.T) {
293293
}
294294

295295
g.Expect(testEnv.CreateAndWait(ctx, &repository)).To(Succeed())
296+
defer func() { g.Expect(testEnv.Delete(ctx, &repository)).To(Succeed()) }()
296297

297298
obj := helmv1.HelmChart{
298299
ObjectMeta: metav1.ObjectMeta{

0 commit comments

Comments
 (0)