Merge pull request #1428 from fluxcd/helm-ga
Promote Helm APIs to `source.toolkit.fluxcd.io/v1` (GA)
This commit is contained in:
commit
cf750b57cb
6
PROJECT
6
PROJECT
|
|
@ -7,9 +7,15 @@ resources:
|
|||
- group: source
|
||||
kind: GitRepository
|
||||
version: v1beta2
|
||||
- group: source
|
||||
kind: HelmRepository
|
||||
version: v1
|
||||
- group: source
|
||||
kind: HelmRepository
|
||||
version: v1beta2
|
||||
- group: source
|
||||
kind: HelmChart
|
||||
version: v1
|
||||
- group: source
|
||||
kind: HelmChart
|
||||
version: v1beta2
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ and is a core component of the [GitOps toolkit](https://fluxcd.io/flux/component
|
|||
## APIs
|
||||
|
||||
| Kind | API Version |
|
||||
|---------------------------------------------------------|------------------------------------|
|
||||
|-------------------------------------------------------|------------------------------------|
|
||||
| [GitRepository](docs/spec/v1/gitrepositories.md) | `source.toolkit.fluxcd.io/v1` |
|
||||
| [OCIRepository](docs/spec/v1beta2/ocirepositories.md) | `source.toolkit.fluxcd.io/v1beta2` |
|
||||
| [HelmRepository](docs/spec/v1beta2/helmrepositories.md) | `source.toolkit.fluxcd.io/v1beta2` |
|
||||
| [HelmChart](docs/spec/v1beta2/helmcharts.md) | `source.toolkit.fluxcd.io/v1beta2` |
|
||||
| [HelmRepository](docs/spec/v1/helmrepositories.md) | `source.toolkit.fluxcd.io/v1` |
|
||||
| [HelmChart](docs/spec/v1/helmcharts.md) | `source.toolkit.fluxcd.io/v1` |
|
||||
| [Bucket](docs/spec/v1beta2/buckets.md) | `source.toolkit.fluxcd.io/v1beta2` |
|
||||
|
||||
## Features
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require (
|
|||
github.com/fluxcd/pkg/apis/acl v0.3.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.5.0
|
||||
k8s.io/apimachinery v0.30.0
|
||||
sigs.k8s.io/controller-runtime v0.18.0
|
||||
sigs.k8s.io/controller-runtime v0.18.1
|
||||
)
|
||||
|
||||
// Fix CVE-2022-28948
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
|||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.18.0 h1:Z7jKuX784TQSUL1TIyeuF7j8KXZ4RtSX0YgtjKcSTME=
|
||||
sigs.k8s.io/controller-runtime v0.18.0/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
|
||||
sigs.k8s.io/controller-runtime v0.18.1 h1:RpWbigmuiylbxOCLy0tGnq1cU1qWPwNIQzoJk+QeJx4=
|
||||
sigs.k8s.io/controller-runtime v0.18.1/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
|
|
|
|||
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
Copyright 2024 The Flux 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 v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
// HelmChartKind is the string representation of a HelmChart.
|
||||
const HelmChartKind = "HelmChart"
|
||||
|
||||
// HelmChartSpec specifies the desired state of a Helm chart.
|
||||
type HelmChartSpec struct {
|
||||
// Chart is the name or path the Helm chart is available at in the
|
||||
// SourceRef.
|
||||
// +required
|
||||
Chart string `json:"chart"`
|
||||
|
||||
// Version is the chart version semver expression, ignored for charts from
|
||||
// GitRepository and Bucket sources. Defaults to latest when omitted.
|
||||
// +kubebuilder:default:=*
|
||||
// +optional
|
||||
Version string `json:"version,omitempty"`
|
||||
|
||||
// SourceRef is the reference to the Source the chart is available at.
|
||||
// +required
|
||||
SourceRef LocalHelmChartSourceReference `json:"sourceRef"`
|
||||
|
||||
// Interval at which the HelmChart SourceRef is checked for updates.
|
||||
// This interval is approximate and may be subject to jitter to ensure
|
||||
// efficient use of resources.
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
|
||||
// +required
|
||||
Interval metav1.Duration `json:"interval"`
|
||||
|
||||
// ReconcileStrategy determines what enables the creation of a new artifact.
|
||||
// Valid values are ('ChartVersion', 'Revision').
|
||||
// See the documentation of the values for an explanation on their behavior.
|
||||
// Defaults to ChartVersion when omitted.
|
||||
// +kubebuilder:validation:Enum=ChartVersion;Revision
|
||||
// +kubebuilder:default:=ChartVersion
|
||||
// +optional
|
||||
ReconcileStrategy string `json:"reconcileStrategy,omitempty"`
|
||||
|
||||
// ValuesFiles is an alternative list of values files to use as the chart
|
||||
// values (values.yaml is not included by default), expected to be a
|
||||
// relative path in the SourceRef.
|
||||
// Values files are merged in the order of this list with the last file
|
||||
// overriding the first. Ignored when omitted.
|
||||
// +optional
|
||||
ValuesFiles []string `json:"valuesFiles,omitempty"`
|
||||
|
||||
// IgnoreMissingValuesFiles controls whether to silently ignore missing values
|
||||
// files rather than failing.
|
||||
// +optional
|
||||
IgnoreMissingValuesFiles bool `json:"ignoreMissingValuesFiles,omitempty"`
|
||||
|
||||
// Suspend tells the controller to suspend the reconciliation of this
|
||||
// source.
|
||||
// +optional
|
||||
Suspend bool `json:"suspend,omitempty"`
|
||||
|
||||
// Verify contains the secret name containing the trusted public keys
|
||||
// used to verify the signature and specifies which provider to use to check
|
||||
// whether OCI image is authentic.
|
||||
// This field is only supported when using HelmRepository source with spec.type 'oci'.
|
||||
// Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified.
|
||||
// +optional
|
||||
Verify *OCIRepositoryVerification `json:"verify,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
// ReconcileStrategyChartVersion reconciles when the version of the Helm chart is different.
|
||||
ReconcileStrategyChartVersion string = "ChartVersion"
|
||||
|
||||
// ReconcileStrategyRevision reconciles when the Revision of the source is different.
|
||||
ReconcileStrategyRevision string = "Revision"
|
||||
)
|
||||
|
||||
// LocalHelmChartSourceReference contains enough information to let you locate
|
||||
// the typed referenced object at namespace level.
|
||||
type LocalHelmChartSourceReference struct {
|
||||
// APIVersion of the referent.
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
|
||||
// Kind of the referent, valid values are ('HelmRepository', 'GitRepository',
|
||||
// 'Bucket').
|
||||
// +kubebuilder:validation:Enum=HelmRepository;GitRepository;Bucket
|
||||
// +required
|
||||
Kind string `json:"kind"`
|
||||
|
||||
// Name of the referent.
|
||||
// +required
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// HelmChartStatus records the observed state of the HelmChart.
|
||||
type HelmChartStatus struct {
|
||||
// ObservedGeneration is the last observed generation of the HelmChart
|
||||
// object.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// ObservedSourceArtifactRevision is the last observed Artifact.Revision
|
||||
// of the HelmChartSpec.SourceRef.
|
||||
// +optional
|
||||
ObservedSourceArtifactRevision string `json:"observedSourceArtifactRevision,omitempty"`
|
||||
|
||||
// ObservedChartName is the last observed chart name as specified by the
|
||||
// resolved chart reference.
|
||||
// +optional
|
||||
ObservedChartName string `json:"observedChartName,omitempty"`
|
||||
|
||||
// ObservedValuesFiles are the observed value files of the last successful
|
||||
// reconciliation.
|
||||
// It matches the chart in the last successfully reconciled artifact.
|
||||
// +optional
|
||||
ObservedValuesFiles []string `json:"observedValuesFiles,omitempty"`
|
||||
|
||||
// Conditions holds the conditions for the HelmChart.
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
|
||||
// URL is the dynamic fetch link for the latest Artifact.
|
||||
// It is provided on a "best effort" basis, and using the precise
|
||||
// BucketStatus.Artifact data is recommended.
|
||||
// +optional
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Artifact represents the output of the last successful reconciliation.
|
||||
// +optional
|
||||
Artifact *Artifact `json:"artifact,omitempty"`
|
||||
|
||||
meta.ReconcileRequestStatus `json:",inline"`
|
||||
}
|
||||
|
||||
const (
|
||||
// ChartPullSucceededReason signals that the pull of the Helm chart
|
||||
// succeeded.
|
||||
ChartPullSucceededReason string = "ChartPullSucceeded"
|
||||
|
||||
// ChartPackageSucceededReason signals that the package of the Helm
|
||||
// chart succeeded.
|
||||
ChartPackageSucceededReason string = "ChartPackageSucceeded"
|
||||
)
|
||||
|
||||
// GetConditions returns the status conditions of the object.
|
||||
func (in HelmChart) GetConditions() []metav1.Condition {
|
||||
return in.Status.Conditions
|
||||
}
|
||||
|
||||
// SetConditions sets the status conditions on the object.
|
||||
func (in *HelmChart) SetConditions(conditions []metav1.Condition) {
|
||||
in.Status.Conditions = conditions
|
||||
}
|
||||
|
||||
// GetRequeueAfter returns the duration after which the source must be
|
||||
// reconciled again.
|
||||
func (in HelmChart) GetRequeueAfter() time.Duration {
|
||||
return in.Spec.Interval.Duration
|
||||
}
|
||||
|
||||
// GetArtifact returns the latest artifact from the source if present in the
|
||||
// status sub-resource.
|
||||
func (in *HelmChart) GetArtifact() *Artifact {
|
||||
return in.Status.Artifact
|
||||
}
|
||||
|
||||
// GetValuesFiles returns a merged list of HelmChartSpec.ValuesFiles.
|
||||
func (in *HelmChart) GetValuesFiles() []string {
|
||||
return in.Spec.ValuesFiles
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=hc
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Chart",type=string,JSONPath=`.spec.chart`
|
||||
// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version`
|
||||
// +kubebuilder:printcolumn:name="Source Kind",type=string,JSONPath=`.spec.sourceRef.kind`
|
||||
// +kubebuilder:printcolumn:name="Source Name",type=string,JSONPath=`.spec.sourceRef.name`
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
|
||||
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
|
||||
|
||||
// HelmChart is the Schema for the helmcharts API.
|
||||
type HelmChart struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec HelmChartSpec `json:"spec,omitempty"`
|
||||
// +kubebuilder:default={"observedGeneration":-1}
|
||||
Status HelmChartStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// HelmChartList contains a list of HelmChart objects.
|
||||
// +kubebuilder:object:root=true
|
||||
type HelmChartList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []HelmChart `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&HelmChart{}, &HelmChartList{})
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
Copyright 2024 The Flux 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 v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/acl"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
const (
|
||||
// HelmRepositoryKind is the string representation of a HelmRepository.
|
||||
HelmRepositoryKind = "HelmRepository"
|
||||
// HelmRepositoryURLIndexKey is the key used for indexing HelmRepository
|
||||
// objects by their HelmRepositorySpec.URL.
|
||||
HelmRepositoryURLIndexKey = ".metadata.helmRepositoryURL"
|
||||
// HelmRepositoryTypeDefault is the default HelmRepository type.
|
||||
// It is used when no type is specified and corresponds to a Helm repository.
|
||||
HelmRepositoryTypeDefault = "default"
|
||||
// HelmRepositoryTypeOCI is the type for an OCI repository.
|
||||
HelmRepositoryTypeOCI = "oci"
|
||||
)
|
||||
|
||||
// HelmRepositorySpec specifies the required configuration to produce an
|
||||
// Artifact for a Helm repository index YAML.
|
||||
type HelmRepositorySpec struct {
|
||||
// URL of the Helm repository, a valid URL contains at least a protocol and
|
||||
// host.
|
||||
// +kubebuilder:validation:Pattern="^(http|https|oci)://.*$"
|
||||
// +required
|
||||
URL string `json:"url"`
|
||||
|
||||
// SecretRef specifies the Secret containing authentication credentials
|
||||
// for the HelmRepository.
|
||||
// For HTTP/S basic auth the secret must contain 'username' and 'password'
|
||||
// fields.
|
||||
// Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile'
|
||||
// keys is deprecated. Please use `.spec.certSecretRef` instead.
|
||||
// +optional
|
||||
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
|
||||
|
||||
// CertSecretRef can be given the name of a Secret containing
|
||||
// either or both of
|
||||
//
|
||||
// - a PEM-encoded client certificate (`tls.crt`) and private
|
||||
// key (`tls.key`);
|
||||
// - a PEM-encoded CA certificate (`ca.crt`)
|
||||
//
|
||||
// and whichever are supplied, will be used for connecting to the
|
||||
// registry. The client cert and key are useful if you are
|
||||
// authenticating with a certificate; the CA cert is useful if
|
||||
// you are using a self-signed server certificate. The Secret must
|
||||
// be of type `Opaque` or `kubernetes.io/tls`.
|
||||
//
|
||||
// It takes precedence over the values specified in the Secret referred
|
||||
// to by `.spec.secretRef`.
|
||||
// +optional
|
||||
CertSecretRef *meta.LocalObjectReference `json:"certSecretRef,omitempty"`
|
||||
|
||||
// PassCredentials allows the credentials from the SecretRef to be passed
|
||||
// on to a host that does not match the host as defined in URL.
|
||||
// This may be required if the host of the advertised chart URLs in the
|
||||
// index differ from the defined URL.
|
||||
// Enabling this should be done with caution, as it can potentially result
|
||||
// in credentials getting stolen in a MITM-attack.
|
||||
// +optional
|
||||
PassCredentials bool `json:"passCredentials,omitempty"`
|
||||
|
||||
// Interval at which the HelmRepository URL is checked for updates.
|
||||
// This interval is approximate and may be subject to jitter to ensure
|
||||
// efficient use of resources.
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
|
||||
// +optional
|
||||
Interval metav1.Duration `json:"interval,omitempty"`
|
||||
|
||||
// Insecure allows connecting to a non-TLS HTTP container registry.
|
||||
// This field is only taken into account if the .spec.type field is set to 'oci'.
|
||||
// +optional
|
||||
Insecure bool `json:"insecure,omitempty"`
|
||||
|
||||
// Timeout is used for the index fetch operation for an HTTPS helm repository,
|
||||
// and for remote OCI Repository operations like pulling for an OCI helm
|
||||
// chart by the associated HelmChart.
|
||||
// Its default value is 60s.
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m))+$"
|
||||
// +optional
|
||||
Timeout *metav1.Duration `json:"timeout,omitempty"`
|
||||
|
||||
// Suspend tells the controller to suspend the reconciliation of this
|
||||
// HelmRepository.
|
||||
// +optional
|
||||
Suspend bool `json:"suspend,omitempty"`
|
||||
|
||||
// AccessFrom specifies an Access Control List for allowing cross-namespace
|
||||
// references to this object.
|
||||
// NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092
|
||||
// +optional
|
||||
AccessFrom *acl.AccessFrom `json:"accessFrom,omitempty"`
|
||||
|
||||
// Type of the HelmRepository.
|
||||
// When this field is set to "oci", the URL field value must be prefixed with "oci://".
|
||||
// +kubebuilder:validation:Enum=default;oci
|
||||
// +optional
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'.
|
||||
// This field is optional, and only taken into account if the .spec.type field is set to 'oci'.
|
||||
// When not specified, defaults to 'generic'.
|
||||
// +kubebuilder:validation:Enum=generic;aws;azure;gcp
|
||||
// +kubebuilder:default:=generic
|
||||
// +optional
|
||||
Provider string `json:"provider,omitempty"`
|
||||
}
|
||||
|
||||
// HelmRepositoryStatus records the observed state of the HelmRepository.
|
||||
type HelmRepositoryStatus struct {
|
||||
// ObservedGeneration is the last observed generation of the HelmRepository
|
||||
// object.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// Conditions holds the conditions for the HelmRepository.
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
|
||||
// URL is the dynamic fetch link for the latest Artifact.
|
||||
// It is provided on a "best effort" basis, and using the precise
|
||||
// HelmRepositoryStatus.Artifact data is recommended.
|
||||
// +optional
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Artifact represents the last successful HelmRepository reconciliation.
|
||||
// +optional
|
||||
Artifact *Artifact `json:"artifact,omitempty"`
|
||||
|
||||
meta.ReconcileRequestStatus `json:",inline"`
|
||||
}
|
||||
|
||||
const (
|
||||
// IndexationFailedReason signals that the HelmRepository index fetch
|
||||
// failed.
|
||||
IndexationFailedReason string = "IndexationFailed"
|
||||
)
|
||||
|
||||
// GetConditions returns the status conditions of the object.
|
||||
func (in HelmRepository) GetConditions() []metav1.Condition {
|
||||
return in.Status.Conditions
|
||||
}
|
||||
|
||||
// SetConditions sets the status conditions on the object.
|
||||
func (in *HelmRepository) SetConditions(conditions []metav1.Condition) {
|
||||
in.Status.Conditions = conditions
|
||||
}
|
||||
|
||||
// GetRequeueAfter returns the duration after which the source must be
|
||||
// reconciled again.
|
||||
func (in HelmRepository) GetRequeueAfter() time.Duration {
|
||||
if in.Spec.Interval.Duration != 0 {
|
||||
return in.Spec.Interval.Duration
|
||||
}
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
// GetTimeout returns the timeout duration used for various operations related
|
||||
// to this HelmRepository.
|
||||
func (in HelmRepository) GetTimeout() time.Duration {
|
||||
if in.Spec.Timeout != nil {
|
||||
return in.Spec.Timeout.Duration
|
||||
}
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
// GetArtifact returns the latest artifact from the source if present in the
|
||||
// status sub-resource.
|
||||
func (in *HelmRepository) GetArtifact() *Artifact {
|
||||
return in.Status.Artifact
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=helmrepo
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.spec.url`
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
|
||||
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
|
||||
|
||||
// HelmRepository is the Schema for the helmrepositories API.
|
||||
type HelmRepository struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec HelmRepositorySpec `json:"spec,omitempty"`
|
||||
// +kubebuilder:default={"observedGeneration":-1}
|
||||
Status HelmRepositoryStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// HelmRepositoryList contains a list of HelmRepository objects.
|
||||
// +kubebuilder:object:root=true
|
||||
type HelmRepositoryList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []HelmRepository `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&HelmRepository{}, &HelmRepositoryList{})
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2024 The Flux 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 v1
|
||||
|
||||
import (
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
// OCIRepositoryVerification verifies the authenticity of an OCI Artifact
|
||||
type OCIRepositoryVerification struct {
|
||||
// Provider specifies the technology used to sign the OCI Artifact.
|
||||
// +kubebuilder:validation:Enum=cosign;notation
|
||||
// +kubebuilder:default:=cosign
|
||||
Provider string `json:"provider"`
|
||||
|
||||
// SecretRef specifies the Kubernetes Secret containing the
|
||||
// trusted public keys.
|
||||
// +optional
|
||||
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
|
||||
|
||||
// MatchOIDCIdentity specifies the identity matching criteria to use
|
||||
// while verifying an OCI artifact which was signed using Cosign keyless
|
||||
// signing. The artifact's identity is deemed to be verified if any of the
|
||||
// specified matchers match against the identity.
|
||||
// +optional
|
||||
MatchOIDCIdentity []OIDCIdentityMatch `json:"matchOIDCIdentity,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCIdentityMatch specifies options for verifying the certificate identity,
|
||||
// i.e. the issuer and the subject of the certificate.
|
||||
type OIDCIdentityMatch struct {
|
||||
// Issuer specifies the regex pattern to match against to verify
|
||||
// the OIDC issuer in the Fulcio certificate. The pattern must be a
|
||||
// valid Go regular expression.
|
||||
// +required
|
||||
Issuer string `json:"issuer"`
|
||||
// Subject specifies the regex pattern to match against to verify
|
||||
// the identity subject in the Fulcio certificate. The pattern must
|
||||
// be a valid Go regular expression.
|
||||
// +required
|
||||
Subject string `json:"subject"`
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
//go:build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
Copyright 2024 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
@ -21,6 +21,7 @@ limitations under the License.
|
|||
package v1
|
||||
|
||||
import (
|
||||
"github.com/fluxcd/pkg/apis/acl"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
|
@ -264,3 +265,300 @@ func (in *GitRepositoryVerification) DeepCopy() *GitRepositoryVerification {
|
|||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmChart) DeepCopyInto(out *HelmChart) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChart.
|
||||
func (in *HelmChart) DeepCopy() *HelmChart {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmChart)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *HelmChart) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmChartList) DeepCopyInto(out *HelmChartList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]HelmChart, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartList.
|
||||
func (in *HelmChartList) DeepCopy() *HelmChartList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmChartList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *HelmChartList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) {
|
||||
*out = *in
|
||||
out.SourceRef = in.SourceRef
|
||||
out.Interval = in.Interval
|
||||
if in.ValuesFiles != nil {
|
||||
in, out := &in.ValuesFiles, &out.ValuesFiles
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Verify != nil {
|
||||
in, out := &in.Verify, &out.Verify
|
||||
*out = new(OCIRepositoryVerification)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartSpec.
|
||||
func (in *HelmChartSpec) DeepCopy() *HelmChartSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmChartSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmChartStatus) DeepCopyInto(out *HelmChartStatus) {
|
||||
*out = *in
|
||||
if in.ObservedValuesFiles != nil {
|
||||
in, out := &in.ObservedValuesFiles, &out.ObservedValuesFiles
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]metav1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Artifact != nil {
|
||||
in, out := &in.Artifact, &out.Artifact
|
||||
*out = new(Artifact)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.ReconcileRequestStatus = in.ReconcileRequestStatus
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartStatus.
|
||||
func (in *HelmChartStatus) DeepCopy() *HelmChartStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmChartStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmRepository) DeepCopyInto(out *HelmRepository) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmRepository.
|
||||
func (in *HelmRepository) DeepCopy() *HelmRepository {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmRepository)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *HelmRepository) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmRepositoryList) DeepCopyInto(out *HelmRepositoryList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]HelmRepository, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmRepositoryList.
|
||||
func (in *HelmRepositoryList) DeepCopy() *HelmRepositoryList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmRepositoryList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *HelmRepositoryList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmRepositorySpec) DeepCopyInto(out *HelmRepositorySpec) {
|
||||
*out = *in
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.CertSecretRef != nil {
|
||||
in, out := &in.CertSecretRef, &out.CertSecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
out.Interval = in.Interval
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(metav1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.AccessFrom != nil {
|
||||
in, out := &in.AccessFrom, &out.AccessFrom
|
||||
*out = new(acl.AccessFrom)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmRepositorySpec.
|
||||
func (in *HelmRepositorySpec) DeepCopy() *HelmRepositorySpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmRepositorySpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmRepositoryStatus) DeepCopyInto(out *HelmRepositoryStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]metav1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Artifact != nil {
|
||||
in, out := &in.Artifact, &out.Artifact
|
||||
*out = new(Artifact)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.ReconcileRequestStatus = in.ReconcileRequestStatus
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmRepositoryStatus.
|
||||
func (in *HelmRepositoryStatus) DeepCopy() *HelmRepositoryStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmRepositoryStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LocalHelmChartSourceReference) DeepCopyInto(out *LocalHelmChartSourceReference) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalHelmChartSourceReference.
|
||||
func (in *LocalHelmChartSourceReference) DeepCopy() *LocalHelmChartSourceReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LocalHelmChartSourceReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OCIRepositoryVerification) DeepCopyInto(out *OCIRepositoryVerification) {
|
||||
*out = *in
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.MatchOIDCIdentity != nil {
|
||||
in, out := &in.MatchOIDCIdentity, &out.MatchOIDCIdentity
|
||||
*out = make([]OIDCIdentityMatch, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OCIRepositoryVerification.
|
||||
func (in *OCIRepositoryVerification) DeepCopy() *OCIRepositoryVerification {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OCIRepositoryVerification)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCIdentityMatch) DeepCopyInto(out *OIDCIdentityMatch) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCIdentityMatch.
|
||||
func (in *OIDCIdentityMatch) DeepCopy() *OIDCIdentityMatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityMatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ func (in *Bucket) GetInterval() metav1.Duration {
|
|||
// +genclient
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:deprecatedversion:warning="v1beta1 Bucket is deprecated, upgrade to v1beta2"
|
||||
// +kubebuilder:printcolumn:name="Endpoint",type=string,JSONPath=`.spec.endpoint`
|
||||
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ func (in *HelmChart) GetValuesFiles() []string {
|
|||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=hc
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:deprecatedversion:warning="v1beta1 HelmChart is deprecated, upgrade to v1"
|
||||
// +kubebuilder:printcolumn:name="Chart",type=string,JSONPath=`.spec.chart`
|
||||
// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version`
|
||||
// +kubebuilder:printcolumn:name="Source Kind",type=string,JSONPath=`.spec.sourceRef.kind`
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ func (in *HelmRepository) GetInterval() metav1.Duration {
|
|||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=helmrepo
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:deprecatedversion:warning="v1beta1 HelmRepository is deprecated, upgrade to v1"
|
||||
// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.spec.url`
|
||||
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//go:build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
Copyright 2024 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"github.com/fluxcd/pkg/apis/acl"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
apiv1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
|
|
@ -101,7 +102,7 @@ type HelmChartSpec struct {
|
|||
// This field is only supported when using HelmRepository source with spec.type 'oci'.
|
||||
// Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified.
|
||||
// +optional
|
||||
Verify *OCIRepositoryVerification `json:"verify,omitempty"`
|
||||
Verify *apiv1.OCIRepositoryVerification `json:"verify,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -214,10 +215,10 @@ func (in *HelmChart) GetValuesFiles() []string {
|
|||
}
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=hc
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:deprecatedversion:warning="v1beta2 HelmChart is deprecated, upgrade to v1"
|
||||
// +kubebuilder:printcolumn:name="Chart",type=string,JSONPath=`.spec.chart`
|
||||
// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version`
|
||||
// +kubebuilder:printcolumn:name="Source Kind",type=string,JSONPath=`.spec.sourceRef.kind`
|
||||
|
|
|
|||
|
|
@ -198,10 +198,10 @@ func (in *HelmRepository) GetArtifact() *apiv1.Artifact {
|
|||
}
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:shortName=helmrepo
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:deprecatedversion:warning="v1beta2 HelmRepository is deprecated, upgrade to v1"
|
||||
// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.spec.url`
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
|
||||
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
apiv1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
|
|
@ -89,7 +90,7 @@ type OCIRepositorySpec struct {
|
|||
// used to verify the signature and specifies which provider to use to check
|
||||
// whether OCI image is authentic.
|
||||
// +optional
|
||||
Verify *OCIRepositoryVerification `json:"verify,omitempty"`
|
||||
Verify *apiv1.OCIRepositoryVerification `json:"verify,omitempty"`
|
||||
|
||||
// ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate
|
||||
// the image pull if the service account has attached pull secrets. For more information:
|
||||
|
|
@ -183,41 +184,6 @@ type OCILayerSelector struct {
|
|||
Operation string `json:"operation,omitempty"`
|
||||
}
|
||||
|
||||
// OCIRepositoryVerification verifies the authenticity of an OCI Artifact
|
||||
type OCIRepositoryVerification struct {
|
||||
// Provider specifies the technology used to sign the OCI Artifact.
|
||||
// +kubebuilder:validation:Enum=cosign;notation
|
||||
// +kubebuilder:default:=cosign
|
||||
Provider string `json:"provider"`
|
||||
|
||||
// SecretRef specifies the Kubernetes Secret containing the
|
||||
// trusted public keys.
|
||||
// +optional
|
||||
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
|
||||
|
||||
// MatchOIDCIdentity specifies the identity matching criteria to use
|
||||
// while verifying an OCI artifact which was signed using Cosign keyless
|
||||
// signing. The artifact's identity is deemed to be verified if any of the
|
||||
// specified matchers match against the identity.
|
||||
// +optional
|
||||
MatchOIDCIdentity []OIDCIdentityMatch `json:"matchOIDCIdentity,omitempty"`
|
||||
}
|
||||
|
||||
// OIDCIdentityMatch specifies options for verifying the certificate identity,
|
||||
// i.e. the issuer and the subject of the certificate.
|
||||
type OIDCIdentityMatch struct {
|
||||
// Issuer specifies the regex pattern to match against to verify
|
||||
// the OIDC issuer in the Fulcio certificate. The pattern must be a
|
||||
// valid Go regular expression.
|
||||
// +required
|
||||
Issuer string `json:"issuer"`
|
||||
// Subject specifies the regex pattern to match against to verify
|
||||
// the identity subject in the Fulcio certificate. The pattern must
|
||||
// be a valid Go regular expression.
|
||||
// +required
|
||||
Subject string `json:"subject"`
|
||||
}
|
||||
|
||||
// OCIRepositoryStatus defines the observed state of OCIRepository
|
||||
type OCIRepositoryStatus struct {
|
||||
// ObservedGeneration is the last observed generation.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//go:build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
Copyright 2024 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
@ -466,7 +466,7 @@ func (in *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) {
|
|||
}
|
||||
if in.Verify != nil {
|
||||
in, out := &in.Verify, &out.Verify
|
||||
*out = new(OCIRepositoryVerification)
|
||||
*out = new(apiv1.OCIRepositoryVerification)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
|
@ -761,7 +761,7 @@ func (in *OCIRepositorySpec) DeepCopyInto(out *OCIRepositorySpec) {
|
|||
}
|
||||
if in.Verify != nil {
|
||||
in, out := &in.Verify, &out.Verify
|
||||
*out = new(OCIRepositoryVerification)
|
||||
*out = new(apiv1.OCIRepositoryVerification)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CertSecretRef != nil {
|
||||
|
|
@ -829,43 +829,3 @@ func (in *OCIRepositoryStatus) DeepCopy() *OCIRepositoryStatus {
|
|||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OCIRepositoryVerification) DeepCopyInto(out *OCIRepositoryVerification) {
|
||||
*out = *in
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.MatchOIDCIdentity != nil {
|
||||
in, out := &in.MatchOIDCIdentity, &out.MatchOIDCIdentity
|
||||
*out = make([]OIDCIdentityMatch, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OCIRepositoryVerification.
|
||||
func (in *OCIRepositoryVerification) DeepCopy() *OCIRepositoryVerification {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OCIRepositoryVerification)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OIDCIdentityMatch) DeepCopyInto(out *OIDCIdentityMatch) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OIDCIdentityMatch.
|
||||
func (in *OIDCIdentityMatch) DeepCopy() *OIDCIdentityMatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OIDCIdentityMatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ spec:
|
|||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta1 Bucket is deprecated, upgrade to v1beta2
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,351 @@ spec:
|
|||
singular: helmchart
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.chart
|
||||
name: Chart
|
||||
type: string
|
||||
- jsonPath: .spec.version
|
||||
name: Version
|
||||
type: string
|
||||
- jsonPath: .spec.sourceRef.kind
|
||||
name: Source Kind
|
||||
type: string
|
||||
- jsonPath: .spec.sourceRef.name
|
||||
name: Source Name
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||
name: Ready
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: HelmChart is the Schema for the helmcharts API.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: HelmChartSpec specifies the desired state of a Helm chart.
|
||||
properties:
|
||||
chart:
|
||||
description: |-
|
||||
Chart is the name or path the Helm chart is available at in the
|
||||
SourceRef.
|
||||
type: string
|
||||
ignoreMissingValuesFiles:
|
||||
description: |-
|
||||
IgnoreMissingValuesFiles controls whether to silently ignore missing values
|
||||
files rather than failing.
|
||||
type: boolean
|
||||
interval:
|
||||
description: |-
|
||||
Interval at which the HelmChart SourceRef is checked for updates.
|
||||
This interval is approximate and may be subject to jitter to ensure
|
||||
efficient use of resources.
|
||||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
|
||||
type: string
|
||||
reconcileStrategy:
|
||||
default: ChartVersion
|
||||
description: |-
|
||||
ReconcileStrategy determines what enables the creation of a new artifact.
|
||||
Valid values are ('ChartVersion', 'Revision').
|
||||
See the documentation of the values for an explanation on their behavior.
|
||||
Defaults to ChartVersion when omitted.
|
||||
enum:
|
||||
- ChartVersion
|
||||
- Revision
|
||||
type: string
|
||||
sourceRef:
|
||||
description: SourceRef is the reference to the Source the chart is
|
||||
available at.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion of the referent.
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind of the referent, valid values are ('HelmRepository', 'GitRepository',
|
||||
'Bucket').
|
||||
enum:
|
||||
- HelmRepository
|
||||
- GitRepository
|
||||
- Bucket
|
||||
type: string
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: |-
|
||||
Suspend tells the controller to suspend the reconciliation of this
|
||||
source.
|
||||
type: boolean
|
||||
valuesFiles:
|
||||
description: |-
|
||||
ValuesFiles is an alternative list of values files to use as the chart
|
||||
values (values.yaml is not included by default), expected to be a
|
||||
relative path in the SourceRef.
|
||||
Values files are merged in the order of this list with the last file
|
||||
overriding the first. Ignored when omitted.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
verify:
|
||||
description: |-
|
||||
Verify contains the secret name containing the trusted public keys
|
||||
used to verify the signature and specifies which provider to use to check
|
||||
whether OCI image is authentic.
|
||||
This field is only supported when using HelmRepository source with spec.type 'oci'.
|
||||
Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified.
|
||||
properties:
|
||||
matchOIDCIdentity:
|
||||
description: |-
|
||||
MatchOIDCIdentity specifies the identity matching criteria to use
|
||||
while verifying an OCI artifact which was signed using Cosign keyless
|
||||
signing. The artifact's identity is deemed to be verified if any of the
|
||||
specified matchers match against the identity.
|
||||
items:
|
||||
description: |-
|
||||
OIDCIdentityMatch specifies options for verifying the certificate identity,
|
||||
i.e. the issuer and the subject of the certificate.
|
||||
properties:
|
||||
issuer:
|
||||
description: |-
|
||||
Issuer specifies the regex pattern to match against to verify
|
||||
the OIDC issuer in the Fulcio certificate. The pattern must be a
|
||||
valid Go regular expression.
|
||||
type: string
|
||||
subject:
|
||||
description: |-
|
||||
Subject specifies the regex pattern to match against to verify
|
||||
the identity subject in the Fulcio certificate. The pattern must
|
||||
be a valid Go regular expression.
|
||||
type: string
|
||||
required:
|
||||
- issuer
|
||||
- subject
|
||||
type: object
|
||||
type: array
|
||||
provider:
|
||||
default: cosign
|
||||
description: Provider specifies the technology used to sign the
|
||||
OCI Artifact.
|
||||
enum:
|
||||
- cosign
|
||||
- notation
|
||||
type: string
|
||||
secretRef:
|
||||
description: |-
|
||||
SecretRef specifies the Kubernetes Secret containing the
|
||||
trusted public keys.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
required:
|
||||
- provider
|
||||
type: object
|
||||
version:
|
||||
default: '*'
|
||||
description: |-
|
||||
Version is the chart version semver expression, ignored for charts from
|
||||
GitRepository and Bucket sources. Defaults to latest when omitted.
|
||||
type: string
|
||||
required:
|
||||
- chart
|
||||
- interval
|
||||
- sourceRef
|
||||
type: object
|
||||
status:
|
||||
default:
|
||||
observedGeneration: -1
|
||||
description: HelmChartStatus records the observed state of the HelmChart.
|
||||
properties:
|
||||
artifact:
|
||||
description: Artifact represents the output of the last successful
|
||||
reconciliation.
|
||||
properties:
|
||||
digest:
|
||||
description: Digest is the digest of the file in the form of '<algorithm>:<checksum>'.
|
||||
pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
description: |-
|
||||
LastUpdateTime is the timestamp corresponding to the last update of the
|
||||
Artifact.
|
||||
format: date-time
|
||||
type: string
|
||||
metadata:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Metadata holds upstream information such as OCI annotations.
|
||||
type: object
|
||||
path:
|
||||
description: |-
|
||||
Path is the relative file path of the Artifact. It can be used to locate
|
||||
the file in the root of the Artifact storage on the local file system of
|
||||
the controller managing the Source.
|
||||
type: string
|
||||
revision:
|
||||
description: |-
|
||||
Revision is a human-readable identifier traceable in the origin source
|
||||
system. It can be a Git commit SHA, Git tag, a Helm chart version, etc.
|
||||
type: string
|
||||
size:
|
||||
description: Size is the number of bytes in the file.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
description: |-
|
||||
URL is the HTTP address of the Artifact as exposed by the controller
|
||||
managing the Source. It can be used to retrieve the Artifact for
|
||||
consumption, e.g. by another controller applying the Artifact contents.
|
||||
type: string
|
||||
required:
|
||||
- lastUpdateTime
|
||||
- path
|
||||
- revision
|
||||
- url
|
||||
type: object
|
||||
conditions:
|
||||
description: Conditions holds the conditions for the HelmChart.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
---
|
||||
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastHandledReconcileAt:
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
observedChartName:
|
||||
description: |-
|
||||
ObservedChartName is the last observed chart name as specified by the
|
||||
resolved chart reference.
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
ObservedGeneration is the last observed generation of the HelmChart
|
||||
object.
|
||||
format: int64
|
||||
type: integer
|
||||
observedSourceArtifactRevision:
|
||||
description: |-
|
||||
ObservedSourceArtifactRevision is the last observed Artifact.Revision
|
||||
of the HelmChartSpec.SourceRef.
|
||||
type: string
|
||||
observedValuesFiles:
|
||||
description: |-
|
||||
ObservedValuesFiles are the observed value files of the last successful
|
||||
reconciliation.
|
||||
It matches the chart in the last successfully reconciled artifact.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
url:
|
||||
description: |-
|
||||
URL is the dynamic fetch link for the latest Artifact.
|
||||
It is provided on a "best effort" basis, and using the precise
|
||||
BucketStatus.Artifact data is recommended.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.chart
|
||||
name: Chart
|
||||
|
|
@ -38,6 +383,8 @@ spec:
|
|||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta1 HelmChart is deprecated, upgrade to v1
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
|
@ -305,6 +652,8 @@ spec:
|
|||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta2 HelmChart is deprecated, upgrade to v1
|
||||
name: v1beta2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
|
@ -660,6 +1009,6 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
|
|
|
|||
|
|
@ -16,236 +16,6 @@ spec:
|
|||
singular: helmrepository
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.url
|
||||
name: URL
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||
name: Ready
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: HelmRepository is the Schema for the helmrepositories API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: HelmRepositorySpec defines the reference to a Helm repository.
|
||||
properties:
|
||||
accessFrom:
|
||||
description: AccessFrom defines an Access Control List for allowing
|
||||
cross-namespace references to this object.
|
||||
properties:
|
||||
namespaceSelectors:
|
||||
description: |-
|
||||
NamespaceSelectors is the list of namespace selectors to which this ACL applies.
|
||||
Items in this list are evaluated using a logical OR operation.
|
||||
items:
|
||||
description: |-
|
||||
NamespaceSelector selects the namespaces to which this ACL applies.
|
||||
An empty map of MatchLabels matches all namespaces in a cluster.
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||
map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||
operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- namespaceSelectors
|
||||
type: object
|
||||
interval:
|
||||
description: The interval at which to check the upstream for updates.
|
||||
type: string
|
||||
passCredentials:
|
||||
description: |-
|
||||
PassCredentials allows the credentials from the SecretRef to be passed on to
|
||||
a host that does not match the host as defined in URL.
|
||||
This may be required if the host of the advertised chart URLs in the index
|
||||
differ from the defined URL.
|
||||
Enabling this should be done with caution, as it can potentially result in
|
||||
credentials getting stolen in a MITM-attack.
|
||||
type: boolean
|
||||
secretRef:
|
||||
description: |-
|
||||
The name of the secret containing authentication credentials for the Helm
|
||||
repository.
|
||||
For HTTP/S basic auth the secret must contain username and
|
||||
password fields.
|
||||
For TLS the secret must contain a certFile and keyFile, and/or
|
||||
caFile fields.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: This flag tells the controller to suspend the reconciliation
|
||||
of this source.
|
||||
type: boolean
|
||||
timeout:
|
||||
default: 60s
|
||||
description: The timeout of index downloading, defaults to 60s.
|
||||
type: string
|
||||
url:
|
||||
description: The Helm repository URL, a valid URL contains at least
|
||||
a protocol and host.
|
||||
type: string
|
||||
required:
|
||||
- interval
|
||||
- url
|
||||
type: object
|
||||
status:
|
||||
default:
|
||||
observedGeneration: -1
|
||||
description: HelmRepositoryStatus defines the observed state of the HelmRepository.
|
||||
properties:
|
||||
artifact:
|
||||
description: Artifact represents the output of the last successful
|
||||
repository sync.
|
||||
properties:
|
||||
checksum:
|
||||
description: Checksum is the SHA256 checksum of the artifact.
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
description: |-
|
||||
LastUpdateTime is the timestamp corresponding to the last update of this
|
||||
artifact.
|
||||
format: date-time
|
||||
type: string
|
||||
path:
|
||||
description: Path is the relative file path of this artifact.
|
||||
type: string
|
||||
revision:
|
||||
description: |-
|
||||
Revision is a human readable identifier traceable in the origin source
|
||||
system. It can be a Git commit SHA, Git tag, a Helm index timestamp, a Helm
|
||||
chart version, etc.
|
||||
type: string
|
||||
url:
|
||||
description: URL is the HTTP address of this artifact.
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
- url
|
||||
type: object
|
||||
conditions:
|
||||
description: Conditions holds the conditions for the HelmRepository.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
---
|
||||
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastHandledReconcileAt:
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: ObservedGeneration is the last observed generation.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
description: URL is the download link for the last index fetched.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.url
|
||||
name: URL
|
||||
|
|
@ -259,7 +29,7 @@ spec:
|
|||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
name: v1beta2
|
||||
name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: HelmRepository is the Schema for the helmrepositories API.
|
||||
|
|
@ -564,3 +334,555 @@ spec:
|
|||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.url
|
||||
name: URL
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||
name: Ready
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta1 HelmRepository is deprecated, upgrade to v1
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: HelmRepository is the Schema for the helmrepositories API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: HelmRepositorySpec defines the reference to a Helm repository.
|
||||
properties:
|
||||
accessFrom:
|
||||
description: AccessFrom defines an Access Control List for allowing
|
||||
cross-namespace references to this object.
|
||||
properties:
|
||||
namespaceSelectors:
|
||||
description: |-
|
||||
NamespaceSelectors is the list of namespace selectors to which this ACL applies.
|
||||
Items in this list are evaluated using a logical OR operation.
|
||||
items:
|
||||
description: |-
|
||||
NamespaceSelector selects the namespaces to which this ACL applies.
|
||||
An empty map of MatchLabels matches all namespaces in a cluster.
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||
map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||
operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- namespaceSelectors
|
||||
type: object
|
||||
interval:
|
||||
description: The interval at which to check the upstream for updates.
|
||||
type: string
|
||||
passCredentials:
|
||||
description: |-
|
||||
PassCredentials allows the credentials from the SecretRef to be passed on to
|
||||
a host that does not match the host as defined in URL.
|
||||
This may be required if the host of the advertised chart URLs in the index
|
||||
differ from the defined URL.
|
||||
Enabling this should be done with caution, as it can potentially result in
|
||||
credentials getting stolen in a MITM-attack.
|
||||
type: boolean
|
||||
secretRef:
|
||||
description: |-
|
||||
The name of the secret containing authentication credentials for the Helm
|
||||
repository.
|
||||
For HTTP/S basic auth the secret must contain username and
|
||||
password fields.
|
||||
For TLS the secret must contain a certFile and keyFile, and/or
|
||||
caFile fields.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: This flag tells the controller to suspend the reconciliation
|
||||
of this source.
|
||||
type: boolean
|
||||
timeout:
|
||||
default: 60s
|
||||
description: The timeout of index downloading, defaults to 60s.
|
||||
type: string
|
||||
url:
|
||||
description: The Helm repository URL, a valid URL contains at least
|
||||
a protocol and host.
|
||||
type: string
|
||||
required:
|
||||
- interval
|
||||
- url
|
||||
type: object
|
||||
status:
|
||||
default:
|
||||
observedGeneration: -1
|
||||
description: HelmRepositoryStatus defines the observed state of the HelmRepository.
|
||||
properties:
|
||||
artifact:
|
||||
description: Artifact represents the output of the last successful
|
||||
repository sync.
|
||||
properties:
|
||||
checksum:
|
||||
description: Checksum is the SHA256 checksum of the artifact.
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
description: |-
|
||||
LastUpdateTime is the timestamp corresponding to the last update of this
|
||||
artifact.
|
||||
format: date-time
|
||||
type: string
|
||||
path:
|
||||
description: Path is the relative file path of this artifact.
|
||||
type: string
|
||||
revision:
|
||||
description: |-
|
||||
Revision is a human readable identifier traceable in the origin source
|
||||
system. It can be a Git commit SHA, Git tag, a Helm index timestamp, a Helm
|
||||
chart version, etc.
|
||||
type: string
|
||||
url:
|
||||
description: URL is the HTTP address of this artifact.
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
- url
|
||||
type: object
|
||||
conditions:
|
||||
description: Conditions holds the conditions for the HelmRepository.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
---
|
||||
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastHandledReconcileAt:
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: ObservedGeneration is the last observed generation.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
description: URL is the download link for the last index fetched.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.url
|
||||
name: URL
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||
name: Ready
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Status
|
||||
type: string
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta2 HelmRepository is deprecated, upgrade to v1
|
||||
name: v1beta2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: HelmRepository is the Schema for the helmrepositories API.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: |-
|
||||
HelmRepositorySpec specifies the required configuration to produce an
|
||||
Artifact for a Helm repository index YAML.
|
||||
properties:
|
||||
accessFrom:
|
||||
description: |-
|
||||
AccessFrom specifies an Access Control List for allowing cross-namespace
|
||||
references to this object.
|
||||
NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092
|
||||
properties:
|
||||
namespaceSelectors:
|
||||
description: |-
|
||||
NamespaceSelectors is the list of namespace selectors to which this ACL applies.
|
||||
Items in this list are evaluated using a logical OR operation.
|
||||
items:
|
||||
description: |-
|
||||
NamespaceSelector selects the namespaces to which this ACL applies.
|
||||
An empty map of MatchLabels matches all namespaces in a cluster.
|
||||
properties:
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||
map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||
operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- namespaceSelectors
|
||||
type: object
|
||||
certSecretRef:
|
||||
description: |-
|
||||
CertSecretRef can be given the name of a Secret containing
|
||||
either or both of
|
||||
|
||||
|
||||
- a PEM-encoded client certificate (`tls.crt`) and private
|
||||
key (`tls.key`);
|
||||
- a PEM-encoded CA certificate (`ca.crt`)
|
||||
|
||||
|
||||
and whichever are supplied, will be used for connecting to the
|
||||
registry. The client cert and key are useful if you are
|
||||
authenticating with a certificate; the CA cert is useful if
|
||||
you are using a self-signed server certificate. The Secret must
|
||||
be of type `Opaque` or `kubernetes.io/tls`.
|
||||
|
||||
|
||||
It takes precedence over the values specified in the Secret referred
|
||||
to by `.spec.secretRef`.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
insecure:
|
||||
description: |-
|
||||
Insecure allows connecting to a non-TLS HTTP container registry.
|
||||
This field is only taken into account if the .spec.type field is set to 'oci'.
|
||||
type: boolean
|
||||
interval:
|
||||
description: |-
|
||||
Interval at which the HelmRepository URL is checked for updates.
|
||||
This interval is approximate and may be subject to jitter to ensure
|
||||
efficient use of resources.
|
||||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
|
||||
type: string
|
||||
passCredentials:
|
||||
description: |-
|
||||
PassCredentials allows the credentials from the SecretRef to be passed
|
||||
on to a host that does not match the host as defined in URL.
|
||||
This may be required if the host of the advertised chart URLs in the
|
||||
index differ from the defined URL.
|
||||
Enabling this should be done with caution, as it can potentially result
|
||||
in credentials getting stolen in a MITM-attack.
|
||||
type: boolean
|
||||
provider:
|
||||
default: generic
|
||||
description: |-
|
||||
Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'.
|
||||
This field is optional, and only taken into account if the .spec.type field is set to 'oci'.
|
||||
When not specified, defaults to 'generic'.
|
||||
enum:
|
||||
- generic
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
type: string
|
||||
secretRef:
|
||||
description: |-
|
||||
SecretRef specifies the Secret containing authentication credentials
|
||||
for the HelmRepository.
|
||||
For HTTP/S basic auth the secret must contain 'username' and 'password'
|
||||
fields.
|
||||
Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile'
|
||||
keys is deprecated. Please use `.spec.certSecretRef` instead.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: |-
|
||||
Suspend tells the controller to suspend the reconciliation of this
|
||||
HelmRepository.
|
||||
type: boolean
|
||||
timeout:
|
||||
description: |-
|
||||
Timeout is used for the index fetch operation for an HTTPS helm repository,
|
||||
and for remote OCI Repository operations like pulling for an OCI helm
|
||||
chart by the associated HelmChart.
|
||||
Its default value is 60s.
|
||||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
Type of the HelmRepository.
|
||||
When this field is set to "oci", the URL field value must be prefixed with "oci://".
|
||||
enum:
|
||||
- default
|
||||
- oci
|
||||
type: string
|
||||
url:
|
||||
description: |-
|
||||
URL of the Helm repository, a valid URL contains at least a protocol and
|
||||
host.
|
||||
pattern: ^(http|https|oci)://.*$
|
||||
type: string
|
||||
required:
|
||||
- url
|
||||
type: object
|
||||
status:
|
||||
default:
|
||||
observedGeneration: -1
|
||||
description: HelmRepositoryStatus records the observed state of the HelmRepository.
|
||||
properties:
|
||||
artifact:
|
||||
description: Artifact represents the last successful HelmRepository
|
||||
reconciliation.
|
||||
properties:
|
||||
digest:
|
||||
description: Digest is the digest of the file in the form of '<algorithm>:<checksum>'.
|
||||
pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
description: |-
|
||||
LastUpdateTime is the timestamp corresponding to the last update of the
|
||||
Artifact.
|
||||
format: date-time
|
||||
type: string
|
||||
metadata:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Metadata holds upstream information such as OCI annotations.
|
||||
type: object
|
||||
path:
|
||||
description: |-
|
||||
Path is the relative file path of the Artifact. It can be used to locate
|
||||
the file in the root of the Artifact storage on the local file system of
|
||||
the controller managing the Source.
|
||||
type: string
|
||||
revision:
|
||||
description: |-
|
||||
Revision is a human-readable identifier traceable in the origin source
|
||||
system. It can be a Git commit SHA, Git tag, a Helm chart version, etc.
|
||||
type: string
|
||||
size:
|
||||
description: Size is the number of bytes in the file.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
description: |-
|
||||
URL is the HTTP address of the Artifact as exposed by the controller
|
||||
managing the Source. It can be used to retrieve the Artifact for
|
||||
consumption, e.g. by another controller applying the Artifact contents.
|
||||
type: string
|
||||
required:
|
||||
- lastUpdateTime
|
||||
- path
|
||||
- revision
|
||||
- url
|
||||
type: object
|
||||
conditions:
|
||||
description: Conditions holds the conditions for the HelmRepository.
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource.\n---\nThis struct is intended for
|
||||
direct use as an array at the field path .status.conditions. For
|
||||
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
|
||||
observations of a foo's current state.\n\t // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
|
||||
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
|
||||
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
|
||||
\ // other fields\n\t}"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: |-
|
||||
type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
---
|
||||
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
|
||||
useful (see .node.status.conditions), the ability to deconflict is important.
|
||||
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastHandledReconcileAt:
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
ObservedGeneration is the last observed generation of the HelmRepository
|
||||
object.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
description: |-
|
||||
URL is the dynamic fetch link for the latest Artifact.
|
||||
It is provided on a "best effort" basis, and using the precise
|
||||
HelmRepositoryStatus.Artifact data is recommended.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: helmchart-git-sample
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: helmchart-sample-oci
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: helmchart-sample
|
||||
spec:
|
||||
chart: podinfo
|
||||
version: '>=2.0.0 <3.0.0'
|
||||
version: '6.x'
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: helmrepository-sample
|
||||
interval: 1m
|
||||
ignoreMissingValuesFiles: true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: helmrepository-sample-oci
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: helmrepository-sample
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo-notation
|
||||
|
|
@ -8,7 +8,7 @@ spec:
|
|||
type: "oci"
|
||||
interval: 1m
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo-notation
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -704,8 +704,8 @@ NOTE: Not implemented, provisional as of <a href="https://github.com/fluxcd/flux
|
|||
<td>
|
||||
<code>verify</code><br>
|
||||
<em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">
|
||||
OCIRepositoryVerification
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/source-controller/api/v1#OCIRepositoryVerification">
|
||||
github.com/fluxcd/source-controller/api/v1.OCIRepositoryVerification
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
|
@ -1122,8 +1122,8 @@ The secret must be of type kubernetes.io/dockerconfigjson.</p>
|
|||
<td>
|
||||
<code>verify</code><br>
|
||||
<em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">
|
||||
OCIRepositoryVerification
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/source-controller/api/v1#OCIRepositoryVerification">
|
||||
github.com/fluxcd/source-controller/api/v1.OCIRepositoryVerification
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
|
@ -2386,8 +2386,8 @@ NOTE: Not implemented, provisional as of <a href="https://github.com/fluxcd/flux
|
|||
<td>
|
||||
<code>verify</code><br>
|
||||
<em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">
|
||||
OCIRepositoryVerification
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/source-controller/api/v1#OCIRepositoryVerification">
|
||||
github.com/fluxcd/source-controller/api/v1.OCIRepositoryVerification
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
|
@ -3096,8 +3096,8 @@ The secret must be of type kubernetes.io/dockerconfigjson.</p>
|
|||
<td>
|
||||
<code>verify</code><br>
|
||||
<em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">
|
||||
OCIRepositoryVerification
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/source-controller/api/v1#OCIRepositoryVerification">
|
||||
github.com/fluxcd/source-controller/api/v1.OCIRepositoryVerification
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
|
@ -3357,119 +3357,6 @@ github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">OCIRepositoryVerification
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.HelmChartSpec">HelmChartSpec</a>,
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositorySpec">OCIRepositorySpec</a>)
|
||||
</p>
|
||||
<p>OCIRepositoryVerification verifies the authenticity of an OCI Artifact</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>provider</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Provider specifies the technology used to sign the OCI Artifact.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>secretRef</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
|
||||
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>SecretRef specifies the Kubernetes Secret containing the
|
||||
trusted public keys.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>matchOIDCIdentity</code><br>
|
||||
<em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">
|
||||
[]OIDCIdentityMatch
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MatchOIDCIdentity specifies the identity matching criteria to use
|
||||
while verifying an OCI artifact which was signed using Cosign keyless
|
||||
signing. The artifact’s identity is deemed to be verified if any of the
|
||||
specified matchers match against the identity.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">OIDCIdentityMatch
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">OCIRepositoryVerification</a>)
|
||||
</p>
|
||||
<p>OIDCIdentityMatch specifies options for verifying the certificate identity,
|
||||
i.e. the issuer and the subject of the certificate.</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>issuer</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Issuer specifies the regex pattern to match against to verify
|
||||
the OIDC issuer in the Fulcio certificate. The pattern must be a
|
||||
valid Go regular expression.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>subject</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Subject specifies the regex pattern to match against to verify
|
||||
the identity subject in the Fulcio certificate. The pattern must
|
||||
be a valid Go regular expression.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="source.toolkit.fluxcd.io/v1beta2.Source">Source
|
||||
</h3>
|
||||
<p>Source interface must be supported by all API types.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ This is the v1 API specification for defining the desired state sources of Kuber
|
|||
|
||||
* Source kinds:
|
||||
+ [GitRepository](gitrepositories.md)
|
||||
+ [HelmRepository](helmrepositories.md)
|
||||
+ [HelmChart](helmcharts.md)
|
||||
|
||||
## Implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,865 @@
|
|||
# Helm Charts
|
||||
|
||||
<!-- menuweight:50 -->
|
||||
|
||||
The `HelmChart` API defines a Source to produce an Artifact for a Helm chart
|
||||
archive with a set of specific configurations.
|
||||
|
||||
## Example
|
||||
|
||||
The following is an example of a HelmChart. It fetches and/or packages a Helm
|
||||
chart and exposes it as a tarball (`.tgz`) Artifact for the specified
|
||||
configuration:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
chart: podinfo
|
||||
reconcileStrategy: ChartVersion
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: podinfo
|
||||
version: '5.*'
|
||||
```
|
||||
|
||||
In the above example:
|
||||
|
||||
- A HelmChart named `podinfo` is created, indicated by the `.metadata.name`
|
||||
field.
|
||||
- The source-controller fetches the Helm chart every five minutes from the
|
||||
`podinfo` HelmRepository source reference, indicated by the
|
||||
`.spec.sourceRef.kind` and `.spec.sourceRef.name` fields.
|
||||
- The fetched Helm chart version is the latest available chart
|
||||
version in the range specified in `spec.version`. This version is also used as
|
||||
Artifact revision, reported in-cluster in the `.status.artifact.revision`
|
||||
field.
|
||||
- When the current Helm Chart version differs from the latest available chart
|
||||
in the version range, it is fetched and/or packaged as a new Artifact.
|
||||
- The new Artifact is reported in the `.status.artifact` field.
|
||||
|
||||
You can run this example by saving the manifest into `helmchart.yaml`.
|
||||
|
||||
**Note:** HelmChart is usually used by the helm-controller. Based on the
|
||||
HelmRelease configuration, an associated HelmChart is created by the
|
||||
helm-controller.
|
||||
|
||||
1. Apply the resource on the cluster:
|
||||
|
||||
```sh
|
||||
kubectl apply -f helmchart.yaml
|
||||
```
|
||||
|
||||
2. Run `kubectl get helmchart` to see the HelmChart:
|
||||
|
||||
```console
|
||||
NAME CHART VERSION SOURCE KIND SOURCE NAME AGE READY STATUS
|
||||
podinfo podinfo 5.* HelmRepository podinfo 53s True pulled 'podinfo' chart with version '5.2.1'
|
||||
```
|
||||
|
||||
3. Run `kubectl describe helmchart podinfo` to see the [Artifact](#artifact) and
|
||||
[Conditions](#conditions) in the HelmChart's Status:
|
||||
|
||||
```console
|
||||
Status:
|
||||
Observed Source Artifact Revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
|
||||
Artifact:
|
||||
Digest: sha256:6c3cc3b955bce1686036ae6822ee2ca0ef6ecb994e3f2d19eaf3ec03dcba84b3
|
||||
Last Update Time: 2022-02-13T11:24:10Z
|
||||
Path: helmchart/default/podinfo/podinfo-5.2.1.tgz
|
||||
Revision: 5.2.1
|
||||
Size: 14166
|
||||
URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/podinfo-5.2.1.tgz
|
||||
Conditions:
|
||||
Last Transition Time: 2022-02-13T11:24:10Z
|
||||
Message: pulled 'podinfo' chart with version '5.2.1'
|
||||
Observed Generation: 1
|
||||
Reason: ChartPullSucceeded
|
||||
Status: True
|
||||
Type: Ready
|
||||
Last Transition Time: 2022-02-13T11:24:10Z
|
||||
Message: pulled 'podinfo' chart with version '5.2.1'
|
||||
Observed Generation: 1
|
||||
Reason: ChartPullSucceeded
|
||||
Status: True
|
||||
Type: ArtifactInStorage
|
||||
Observed Chart Name: podinfo
|
||||
Observed Generation: 1
|
||||
URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/latest.tar.gz
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Normal ChartPullSucceeded 2m51s source-controller pulled 'podinfo' chart with version '5.2.1'
|
||||
```
|
||||
|
||||
## Writing a HelmChart spec
|
||||
|
||||
As with all other Kubernetes config, a HelmChart needs `apiVersion`, `kind`, and
|
||||
`metadata` fields. The name of a HelmChart object must be a valid
|
||||
[DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
|
||||
|
||||
A HelmChart also needs a
|
||||
[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
|
||||
|
||||
### Source reference
|
||||
|
||||
`.spec.sourceRef` is a required field that specifies a reference to the Source
|
||||
the chart is available at.
|
||||
|
||||
Supported references are:
|
||||
- [`HelmRepository`](helmrepositories.md)
|
||||
- [`GitRepository`](gitrepositories.md)
|
||||
- [`Bucket`](buckets.md)
|
||||
|
||||
Although there are three kinds of source references, there are only two
|
||||
underlying implementations. The artifact building process for `GitRepository`
|
||||
and `Bucket` are the same as they are already built source artifacts. In case
|
||||
of `HelmRepository`, a chart is fetched and/or packaged based on the
|
||||
configuration of the Helm chart.
|
||||
|
||||
For a `HelmChart` to be reconciled, the associated artifact in the source
|
||||
reference must be ready. If the source artifact is not ready, the `HelmChart`
|
||||
reconciliation is retried.
|
||||
|
||||
When the `metadata.generation` of the `HelmChart` don't match with the
|
||||
`status.observedGeneration`, the chart is fetched from source and/or packaged.
|
||||
If there's no `.spec.valuesFiles` specified, the chart is only fetched from the
|
||||
source, and not packaged. If `.spec.valuesFiles` are specified, the chart is
|
||||
fetched and packaged with the values files. When the `metadata.generation`
|
||||
matches the `status.observedGeneration`, the chart is only fetched from source
|
||||
or from the cache if available, and not packaged.
|
||||
|
||||
When using a `HelmRepository` source reference, the secret reference defined in
|
||||
the Helm repository is used to fetch the chart.
|
||||
|
||||
The HelmChart reconciliation behavior varies depending on the source reference
|
||||
kind, see [reconcile strategy](#reconcile-strategy).
|
||||
|
||||
The attributes of the generated artifact also varies depending on the source
|
||||
reference kind, see [artifact](#artifact).
|
||||
|
||||
### Chart
|
||||
|
||||
`.spec.chart` is a required field that specifies the name or path the Helm chart
|
||||
is available at in the [Source reference](#source-reference).
|
||||
|
||||
For `HelmRepository` Source reference, it'll be just the name of the chart.
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
chart: podinfo
|
||||
sourceRef:
|
||||
name: podinfo
|
||||
kind: HelmRepository
|
||||
```
|
||||
|
||||
For `GitRepository` and `Bucket` Source reference, it'll be the path to the
|
||||
Helm chart directory.
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
chart: ./charts/podinfo
|
||||
sourceRef:
|
||||
name: podinfo
|
||||
kind: <GitRepository|Bucket>
|
||||
```
|
||||
|
||||
### Version
|
||||
|
||||
`.spec.version` is an optional field to specify the version of the chart in
|
||||
semver. It is applicable only when the Source reference is a `HelmRepository`.
|
||||
It is ignored for `GitRepository` and `Bucket` Source reference. It defaults to
|
||||
the latest version of the chart with value `*`.
|
||||
|
||||
Version can be a fixed semver, minor or patch semver range of a specific
|
||||
version (i.e. `4.0.x`) or any semver range (i.e. `>=4.0.0 <5.0.0`).
|
||||
|
||||
### Values files
|
||||
|
||||
`.spec.valuesFiles` is an optional field to specify an alternative list of
|
||||
values files to use as the chart values (values.yaml). The file paths are
|
||||
expected to be relative to the Source reference. Values files are merged in the
|
||||
order of the list with the last file overriding the first. It is ignored when
|
||||
omitted. When values files are specified, the chart is fetched and packaged
|
||||
with the provided values.
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: podinfo
|
||||
...
|
||||
valuesFiles:
|
||||
- values.yaml
|
||||
- values-production.yaml
|
||||
```
|
||||
|
||||
Values files also affect the generated artifact revision, see
|
||||
[artifact](#artifact).
|
||||
|
||||
### Ignore missing values files
|
||||
|
||||
`.spec.ignoreMissingValuesFiles` is an optional field to specify whether missing
|
||||
values files should be ignored rather than be considered errors. It defaults to
|
||||
`false`.
|
||||
|
||||
When `.spec.valuesFiles` and `.spec.ignoreMissingValuesFiles` are specified,
|
||||
the `.status.observedValuesFiles` field is populated with the list of values
|
||||
files that were found and actually contributed to the packaged chart.
|
||||
|
||||
### Reconcile strategy
|
||||
|
||||
`.spec.reconcileStrategy` is an optional field to specify what enables the
|
||||
creation of a new Artifact. Valid values are `ChartVersion` and `Revision`.
|
||||
`ChartVersion` is used for creating a new artifact when the chart version
|
||||
changes in a `HelmRepository`. `Revision` is used for creating a new artifact
|
||||
when the source revision changes in a `GitRepository` or a `Bucket` Source. It
|
||||
defaults to `ChartVersion`.
|
||||
|
||||
**Note:** If the reconcile strategy is `ChartVersion` and the source reference
|
||||
is a `GitRepository` or a `Bucket`, no new chart artifact is produced on updates
|
||||
to the source unless the `version` in `Chart.yaml` is incremented. To produce
|
||||
new chart artifact on change in source revision, set the reconcile strategy to
|
||||
`Revision`.
|
||||
|
||||
Reconcile strategy also affects the artifact version, see [artifact](#artifact)
|
||||
for more details.
|
||||
|
||||
### Interval
|
||||
|
||||
`.spec.interval` is a required field that specifies the interval at which the
|
||||
Helm Chart source must be checked for updates.
|
||||
|
||||
After successfully reconciling a HelmChart object, the source-controller
|
||||
requeues the object for inspection after the specified interval. The value must
|
||||
be in a [Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
|
||||
e.g. `10m0s` to look at the source for updates every 10 minutes.
|
||||
|
||||
If the `.metadata.generation` of a resource changes (due to e.g. applying a
|
||||
change to the spec), this is handled instantly outside the interval window.
|
||||
|
||||
**Note:** The controller can be configured to apply a jitter to the interval in
|
||||
order to distribute the load more evenly when multiple HelmChart objects are set
|
||||
up with the same interval. For more information, please refer to the
|
||||
[source-controller configuration options](https://fluxcd.io/flux/components/source/options/).
|
||||
|
||||
### Suspend
|
||||
|
||||
`.spec.suspend` is an optional field to suspend the reconciliation of a
|
||||
HelmChart. When set to `true`, the controller will stop reconciling the
|
||||
HelmChart, and changes to the resource or the Helm chart Source will not result
|
||||
in a new Artifact. When the field is set to `false` or removed, it will resume.
|
||||
|
||||
For practical information, see
|
||||
[suspending and resuming](#suspending-and-resuming).
|
||||
|
||||
### Verification
|
||||
|
||||
**Note:** This feature is available only for Helm charts fetched from an OCI Registry.
|
||||
|
||||
`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign) or [Notation](https://github.com/notaryproject/notation)
|
||||
signatures. The field offers three subfields:
|
||||
|
||||
- `.provider`, to specify the verification provider. The supported options are `cosign` and `notation` at present.
|
||||
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
|
||||
the HelmChart, containing the public keys of trusted authors. For Notation this Secret should also include the [trust policy](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy) in
|
||||
addition to the CA certificate.
|
||||
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers (only supported when using `cosign` as the verification provider). Please see
|
||||
[Keyless verification](#keyless-verification) for more details.
|
||||
|
||||
#### Cosign
|
||||
|
||||
The `cosign` provider can be used to verify the signature of an OCI artifact using either a known public key or via the [Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
verify:
|
||||
provider: cosign
|
||||
secretRef:
|
||||
name: cosign-public-keys
|
||||
```
|
||||
|
||||
When the verification succeeds, the controller adds a Condition with the
|
||||
following attributes to the HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: SourceVerified`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
##### Public keys verification
|
||||
|
||||
To verify the authenticity of HelmChart hosted in an OCI Registry, create a Kubernetes
|
||||
secret with the Cosign public keys:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: cosign-public-keys
|
||||
type: Opaque
|
||||
data:
|
||||
key1.pub: <BASE64>
|
||||
key2.pub: <BASE64>
|
||||
```
|
||||
|
||||
Note that the keys must have the `.pub` extension for Flux to make use of them.
|
||||
|
||||
Flux will loop over the public keys and use them to verify a HelmChart's signature.
|
||||
This allows for older HelmCharts to be valid as long as the right key is in the secret.
|
||||
|
||||
##### Keyless verification
|
||||
|
||||
For publicly available HelmCharts, which are signed using the
|
||||
[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
|
||||
you can enable the verification by omitting the `.verify.secretRef` field.
|
||||
|
||||
To verify the identity's subject and the OIDC issuer present in the Fulcio
|
||||
certificate, you can specify a list of OIDC identity matchers using
|
||||
`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:
|
||||
|
||||
- `.issuer`, to specify a regexp that matches against the OIDC issuer.
|
||||
- `.subject`, to specify a regexp that matches against the subject identity in
|
||||
the certificate.
|
||||
Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).
|
||||
|
||||
The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
|
||||
verified if any one matcher successfully matches against the identity.
|
||||
|
||||
Example of verifying HelmCharts signed by the
|
||||
[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:
|
||||
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
interval: 5m
|
||||
chart: podinfo
|
||||
reconcileStrategy: ChartVersion
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: podinfo
|
||||
version: ">=6.1.6"
|
||||
verify:
|
||||
provider: cosign
|
||||
matchOIDCIdentity:
|
||||
- issuer: "^https://token.actions.githubusercontent.com$"
|
||||
subject: "^https://github.com/stefanprodan/podinfo.*$"
|
||||
```
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
interval: 1m0s
|
||||
url: oci://ghcr.io/stefanprodan/charts
|
||||
type: "oci"
|
||||
```
|
||||
|
||||
The controller verifies the signatures using the Fulcio root CA and the Rekor
|
||||
instance hosted at [rekor.sigstore.dev](https://rekor.sigstore.dev/).
|
||||
|
||||
Note that keyless verification is an **experimental feature**, using
|
||||
custom root CAs or self-hosted Rekor instances are not currently supported.
|
||||
|
||||
#### Notation
|
||||
|
||||
The `notation` provider can be used to verify the signature of an OCI artifact using known
|
||||
trust policy and CA certificate.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
verify:
|
||||
provider: notation
|
||||
secretRef:
|
||||
name: notation-config
|
||||
```
|
||||
|
||||
When the verification succeeds, the controller adds a Condition with the
|
||||
following attributes to the HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: SourceVerified`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
To verify the authenticity of an OCI artifact, create a Kubernetes secret
|
||||
containing Certificate Authority (CA) root certificates and the a `trust policy`
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: notation-config
|
||||
type: Opaque
|
||||
data:
|
||||
certificate1.pem: <BASE64>
|
||||
certificate2.crt: <BASE64>
|
||||
trustpolicy.json: <BASE64>
|
||||
```
|
||||
|
||||
Note that the CA certificates must have either `.pem` or `.crt` extension and your trust policy must
|
||||
be named `trustpolicy.json` for Flux to make use of them.
|
||||
|
||||
For more information on the signing and verification process see [Signing and Verification Workflow](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signing-and-verification-workflow.md).
|
||||
|
||||
Flux will loop over the certificates and use them to verify an artifact's signature.
|
||||
This allows for older artifacts to be valid as long as the right certificate is in the secret.
|
||||
|
||||
## Working with HelmCharts
|
||||
|
||||
### Triggering a reconcile
|
||||
|
||||
To manually tell the source-controller to reconcile a HelmChart outside the
|
||||
[specified interval window](#interval), a HelmCHart can be annotated with
|
||||
`reconcile.fluxcd.io/requestedAt: <arbitrary value>`. Annotating the resource
|
||||
queues the object for reconciliation if the `<arbitrary-value>` differs from
|
||||
the last value the controller acted on, as reported in
|
||||
[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl annotate --field-manager=flux-client-side-apply --overwrite helmchart/<chart-name> reconcile.fluxcd.io/requestedAt="$(date +%s)"
|
||||
```
|
||||
|
||||
### Waiting for `Ready`
|
||||
|
||||
When a change is applied, it is possible to wait for the HelmChart to reach a
|
||||
[ready state](#ready-helmchart) using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl wait helmchart/<chart-name> --for=condition=ready --timeout=1m
|
||||
```
|
||||
|
||||
### Suspending and resuming
|
||||
|
||||
When you find yourself in a situation where you temporarily want to pause the
|
||||
reconciliation of a HelmChart, you can suspend it using the
|
||||
[`.spec.suspend` field](#suspend).
|
||||
|
||||
#### Suspend a HelmChart
|
||||
|
||||
In your YAML declaration:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: <chart-name>
|
||||
spec:
|
||||
suspend: true
|
||||
```
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl patch helmchart <chart-name> --field-manager=flux-client-side-apply -p '{\"spec\": {\"suspend\" : true }}'
|
||||
```
|
||||
|
||||
**Note:** When a HelmChart has an Artifact and is suspended, and this
|
||||
Artifact later disappears from the storage due to e.g. the source-controller
|
||||
Pod being evicted from a Node, this will not be reflected in the
|
||||
HelmChart's Status until it is resumed.
|
||||
|
||||
#### Resume a HelmChart
|
||||
|
||||
In your YAML declaration, comment out (or remove) the field:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: <chart-name>
|
||||
spec:
|
||||
# suspend: true
|
||||
```
|
||||
|
||||
**Note:** Setting the field value to `false` has the same effect as removing
|
||||
it, but does not allow for "hot patching" using e.g. `kubectl` while practicing
|
||||
GitOps; as the manually applied patch would be overwritten by the declared
|
||||
state in Git.
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl patch helmchart <chart-name> --field-manager=flux-client-side-apply -p '{\"spec\" : {\"suspend\" : false }}'
|
||||
```
|
||||
|
||||
### Debugging a HelmChart
|
||||
|
||||
There are several ways to gather information about a HelmChart for debugging
|
||||
purposes.
|
||||
|
||||
#### Describe the HelmChart
|
||||
|
||||
Describing a HelmChart using `kubectl describe helmchart <chart-name>` displays
|
||||
the latest recorded information for the resource in the `Status` and `Events`
|
||||
sections:
|
||||
|
||||
```console
|
||||
...
|
||||
Status:
|
||||
...
|
||||
Conditions:
|
||||
Last Transition Time: 2022-02-13T14:06:27Z
|
||||
Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
|
||||
Observed Generation: 3
|
||||
Reason: InvalidChartReference
|
||||
Status: True
|
||||
Type: Stalled
|
||||
Last Transition Time: 2022-02-13T14:06:27Z
|
||||
Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
|
||||
Observed Generation: 3
|
||||
Reason: InvalidChartReference
|
||||
Status: False
|
||||
Type: Ready
|
||||
Last Transition Time: 2022-02-13T14:06:27Z
|
||||
Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
|
||||
Observed Generation: 3
|
||||
Reason: InvalidChartReference
|
||||
Status: True
|
||||
Type: FetchFailed
|
||||
Last Handled Reconcile At: 1644759954
|
||||
Observed Chart Name: podinfo
|
||||
Observed Generation: 3
|
||||
URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/latest.tar.gz
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Warning InvalidChartReference 11s source-controller invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with ver
|
||||
sion matching '9.*' found
|
||||
```
|
||||
|
||||
#### Trace emitted Events
|
||||
|
||||
To view events for specific HelmChart(s), `kubectl events` can be used in
|
||||
combination with `--for` to list the Events for specific objects. For example,
|
||||
running
|
||||
|
||||
```sh
|
||||
kubectl events --for HelmChart/<chart-name>
|
||||
```
|
||||
|
||||
lists
|
||||
|
||||
```console
|
||||
LAST SEEN TYPE REASON OBJECT MESSAGE
|
||||
22s Warning InvalidChartReference helmchart/<chart-name> invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
|
||||
2s Normal ChartPullSucceeded helmchart/<chart-name> pulled 'podinfo' chart with version '6.0.3'
|
||||
2s Normal ArtifactUpToDate helmchart/<chart-name> artifact up-to-date with remote revision: '6.0.3'
|
||||
```
|
||||
|
||||
Besides being reported in Events, the reconciliation errors are also logged by
|
||||
the controller. The Flux CLI offer commands for filtering the logs for a
|
||||
specific HelmChart, e.g. `flux logs --level=error --kind=HelmChart --name=<chart-name>`.
|
||||
|
||||
### Improving resource consumption by enabling the cache
|
||||
|
||||
When using a `HelmRepository` as Source for a `HelmChart`, the controller loads
|
||||
the repository index in memory to find the latest version of the chart.
|
||||
|
||||
The controller can be configured to cache Helm repository indexes in memory.
|
||||
The cache is used to avoid loading repository indexes for every `HelmChart`
|
||||
reconciliation.
|
||||
|
||||
The following flags are provided to enable and configure the cache:
|
||||
- `helm-cache-max-size`: The maximum size of the cache in number of indexes.
|
||||
If `0`, then the cache is disabled.
|
||||
- `helm-cache-ttl`: The TTL of an index in the cache.
|
||||
- `helm-cache-purge-interval`: The interval at which the cache is purged of
|
||||
expired items.
|
||||
|
||||
The caching strategy is to pull a repository index from the cache if it is
|
||||
available, otherwise to load the index, retrieve and build the chart,
|
||||
then cache the index. The cached index TTL is refreshed every time the
|
||||
Helm repository index is loaded with the `helm-cache-ttl` value.
|
||||
|
||||
The cache is purged of expired items every `helm-cache-purge-interval`.
|
||||
|
||||
When the cache is full, no more items can be added to the cache, and the
|
||||
source-controller will report a warning event instead.
|
||||
|
||||
In order to use the cache, set the related flags in the source-controller
|
||||
Deployment config:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- --watch-all-namespaces
|
||||
- --log-level=info
|
||||
- --log-encoding=json
|
||||
- --enable-leader-election
|
||||
- --storage-path=/data
|
||||
- --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local.
|
||||
## Helm cache with up to 10 items, i.e. 10 indexes.
|
||||
- --helm-cache-max-size=10
|
||||
## TTL of an index is 1 hour.
|
||||
- --helm-cache-ttl=1h
|
||||
## Purge expired index every 10 minutes.
|
||||
- --helm-cache-purge-interval=10m
|
||||
```
|
||||
|
||||
## HelmChart Status
|
||||
|
||||
### Artifact
|
||||
|
||||
The HelmChart reports the last built chart as an Artifact object in the
|
||||
`.status.artifact` of the resource.
|
||||
|
||||
The Artifact file is a gzip compressed TAR archive (`<chart-name>-<chart-version>.tgz`),
|
||||
and can be retrieved in-cluster from the `.status.artifact.url` HTTP address.
|
||||
|
||||
#### Artifact example
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: <chart-name>
|
||||
status:
|
||||
artifact:
|
||||
digest: sha256:e30b95a08787de69ffdad3c232d65cfb131b5b50c6fd44295f48a078fceaa44e
|
||||
lastUpdateTime: "2022-02-10T18:53:47Z"
|
||||
path: helmchart/<source-namespace>/<chart-name>/<chart-name>-<chart-version>.tgz
|
||||
revision: 6.0.3
|
||||
size: 14166
|
||||
url: http://source-controller.flux-system.svc.cluster.local./helmchart/<source-namespace>/<chart-name>/<chart-name>-<chart-version>.tgz
|
||||
```
|
||||
|
||||
When using a `HelmRepository` as the source reference and values files are
|
||||
provided, the value of `status.artifact.revision` is the chart version combined
|
||||
with the `HelmChart` object generation. For example, if the chart version is
|
||||
`6.0.3` and the `HelmChart` object generation is `1`, the
|
||||
`status.artifact.revision` value will be `6.0.3+1`.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: <chart-name>
|
||||
status:
|
||||
artifact:
|
||||
digest: sha256:ee68224ded207ebb18a8e9730cf3313fa6bc1f31e6d8d3943ab541113559bb52
|
||||
lastUpdateTime: "2022-02-28T08:07:12Z"
|
||||
path: helmchart/<source-namespace>/<chart-name>/<chart-name>-6.0.3+1.tgz
|
||||
revision: 6.0.3+1
|
||||
size: 14166
|
||||
url: http://source-controller.flux-system.svc.cluster.local./helmchart/<source-namespace>/<chart-name>/<chart-name>-6.0.3+1.tgz
|
||||
observedGeneration: 1
|
||||
...
|
||||
```
|
||||
|
||||
When using a `GitRepository` or a `Bucket` as the source reference and
|
||||
`Revision` as the reconcile strategy, the value of `status.artifact.revision` is
|
||||
the chart version combined with the first 12 characters of the revision of the
|
||||
`GitRepository` or `Bucket`. For example if the chart version is `6.0.3` and the
|
||||
revision of the `Bucket` is `4e5cbb7b97d00a8039b8810b90b922f4256fd3bd8f78b934b4892dae13f7ca87`,
|
||||
the `status.artifact.revision` value will be `6.0.3+4e5cbb7b97d0`.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: <chart-name>
|
||||
status:
|
||||
artifact:
|
||||
digest: sha256:8d1f0ac3f4b0e8759a32180086f17ac87ca04e5d46c356e67f97e97616ef4718
|
||||
lastUpdateTime: "2022-02-28T08:07:12Z"
|
||||
path: helmchart/<source-namespace>/<chart-name>/<chart-name>-6.0.3+4e5cbb7b97d0.tgz
|
||||
revision: 6.0.3+4e5cbb7b97d0
|
||||
size: 14166
|
||||
url: http://source-controller.flux-system.svc.cluster.local./helmchart/<source-namespace>/<chart-name>/<chart-name>-6.0.3+4e5cbb7b97d0.tgz
|
||||
```
|
||||
|
||||
### Conditions
|
||||
|
||||
A HelmChart enters various states during its lifecycle, reflected as [Kubernetes
|
||||
Conditions][typical-status-properties].
|
||||
It can be [reconciling](#reconciling-helmchart) while fetching or building the
|
||||
chart, it can be [ready](#ready-helmchart), it can
|
||||
[fail during reconciliation](#failed-helmchart), or it can
|
||||
[stall](#stalled-helmchart).
|
||||
|
||||
The HelmChart API is compatible with the [kstatus
|
||||
specification][kstatus-spec],
|
||||
and reports `Reconciling` and `Stalled` conditions where applicable to
|
||||
provide better (timeout) support to solutions polling the HelmChart to become
|
||||
`Ready`.
|
||||
|
||||
#### Reconciling HelmChart
|
||||
|
||||
The source-controller marks a HelmChart as _reconciling_ when one of the
|
||||
following is true:
|
||||
|
||||
- There is no current Artifact for the HelmChart, or the reported Artifact is
|
||||
determined to have disappeared from the storage.
|
||||
- The generation of the HelmChart is newer than the [Observed
|
||||
Generation](#observed-generation).
|
||||
- The newly fetched Artifact revision differs from the current Artifact.
|
||||
|
||||
When the HelmChart is "reconciling", the `Ready` Condition status becomes
|
||||
`Unknown` when the controller detects drift, and the controller adds a Condition
|
||||
with the following attributes to the HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: Reconciling`
|
||||
- `status: "True"`
|
||||
- `reason: Progressing` | `reason: ProgressingWithRetry`
|
||||
|
||||
If the reconciling state is due to a new version, it adds an additional
|
||||
Condition with the following attributes:
|
||||
|
||||
- `type: ArtifactOutdated`
|
||||
- `status: "True"`
|
||||
- `reason: NewChart`
|
||||
|
||||
Both Conditions have a ["negative polarity"][typical-status-properties],
|
||||
and are only present on the HelmChart while their status value is `"True"`.
|
||||
|
||||
#### Ready HelmChart
|
||||
|
||||
The source-controller marks a HelmChart as _ready_ when it has the following
|
||||
characteristics:
|
||||
|
||||
- The HelmChart reports an [Artifact](#artifact).
|
||||
- The reported Artifact exists in the controller's Artifact storage.
|
||||
- The controller was able to fetch and build the Helm chart using the current
|
||||
spec.
|
||||
- The version/revision of the reported Artifact is up-to-date with the
|
||||
latest version/revision of the Helm chart.
|
||||
|
||||
When the HelmChart is "ready", the controller sets a Condition with the
|
||||
following attributes in the HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: Ready`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
This `Ready` Condition will retain a status value of `"True"` until the
|
||||
HelmChart is marked as [reconciling](#reconciling-helmchart), or e.g.
|
||||
a [transient error](#failed-helmchart) occurs due to a temporary network issue.
|
||||
|
||||
When the HelmChart Artifact is archived in the controller's Artifact
|
||||
storage, the controller sets a Condition with the following attributes in the
|
||||
HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: ArtifactInStorage`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
This `ArtifactInStorage` Condition will retain a status value of `"True"` until
|
||||
the Artifact in the storage no longer exists.
|
||||
|
||||
#### Failed HelmChart
|
||||
|
||||
The source-controller may get stuck trying to produce an Artifact for a
|
||||
HelmChart without completing. This can occur due to some of the following
|
||||
factors:
|
||||
|
||||
- The Helm chart Source is temporarily unavailable.
|
||||
- The credentials in the [Source reference](#source-reference) Secret are
|
||||
invalid.
|
||||
- The HelmChart spec contains a generic misconfiguration.
|
||||
- A storage related failure when storing the artifact.
|
||||
|
||||
When this happens, the controller sets the `Ready` Condition status to `False`,
|
||||
and adds a Condition with the following attributes to the HelmChart's
|
||||
`.status.conditions`:
|
||||
|
||||
- `type: FetchFailed` | `type: StorageOperationFailed`
|
||||
- `status: "True"`
|
||||
- `reason: AuthenticationFailed` | `reason: StorageOperationFailed` | `reason: URLInvalid` | `reason: IllegalPath` | `reason: Failed`
|
||||
|
||||
This condition has a ["negative polarity"][typical-status-properties],
|
||||
and is only present on the HelmChart while the status value is `"True"`.
|
||||
There may be more arbitrary values for the `reason` field to provide accurate
|
||||
reason for a condition.
|
||||
|
||||
While the HelmChart has this Condition, the controller will continue to
|
||||
attempt to produce an Artifact for the resource with an exponential backoff,
|
||||
until it succeeds and the HelmChart is marked as [ready](#ready-helmchart).
|
||||
|
||||
Note that a HelmChart can be [reconciling](#reconciling-helmchart)
|
||||
while failing at the same time, for example due to a newly introduced
|
||||
configuration issue in the HelmChart spec. When a reconciliation fails, the
|
||||
`Reconciling` Condition reason would be `ProgressingWithRetry`. When the
|
||||
reconciliation is performed again after the failure, the reason is updated to
|
||||
`Progressing`.
|
||||
|
||||
#### Stalled HelmChart
|
||||
|
||||
The source-controller can mark a HelmChart as _stalled_ when it determines that
|
||||
without changes to the spec, the reconciliation can not succeed.
|
||||
For example because a HelmChart Version is set to a non-existing version.
|
||||
|
||||
When this happens, the controller sets the same Conditions as when it
|
||||
[fails](#failed-helmchart), but adds another Condition with the following
|
||||
attributes to the HelmChart's `.status.conditions`:
|
||||
|
||||
- `type: Stalled`
|
||||
- `status: "True"`
|
||||
- `reason: InvalidChartReference`
|
||||
|
||||
While the HelmChart has this Condition, the controller will not requeue the
|
||||
resource any further, and will stop reconciling the resource until a change to
|
||||
the spec is made.
|
||||
|
||||
### Observed Source Artifact Revision
|
||||
|
||||
The source-controller reports the revision of the last
|
||||
[Source reference's](#source-reference) Artifact the current chart was fetched
|
||||
from in the HelmChart's `.status.observedSourceArtifactRevision`. It is used to
|
||||
keep track of the source artifact revision and detect when a new source
|
||||
artifact is available.
|
||||
|
||||
### Observed Chart Name
|
||||
|
||||
The source-controller reports the last resolved chart name of the Artifact
|
||||
for the [`.spec.chart` field](#chart) in the HelmChart's
|
||||
`.status.observedChartName`. It is used to keep track of the chart and detect
|
||||
when a new chart is found.
|
||||
|
||||
### Observed Generation
|
||||
|
||||
The source-controller reports an [observed generation][typical-status-properties]
|
||||
in the HelmChart's `.status.observedGeneration`. The observed generation is the
|
||||
latest `.metadata.generation` which resulted in either a [ready state](#ready-helmchart),
|
||||
or stalled due to error it can not recover from without human
|
||||
intervention.
|
||||
|
||||
### Last Handled Reconcile At
|
||||
|
||||
The source-controller reports the last `reconcile.fluxcd.io/requestedAt`
|
||||
annotation value it acted on in the `.status.lastHandledReconcileAt` field.
|
||||
|
||||
For practical information about this field, see [triggering a
|
||||
reconcile](#triggering-a-reconcile).
|
||||
|
||||
[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
|
||||
[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus
|
||||
|
|
@ -0,0 +1,878 @@
|
|||
# Helm Repositories
|
||||
|
||||
<!-- menuweight:40 -->
|
||||
|
||||
There are 2 [Helm repository types](#type) defined by the `HelmRepository` API:
|
||||
- Helm HTTP/S repository, which defines a Source to produce an Artifact for a Helm
|
||||
repository index YAML (`index.yaml`).
|
||||
- OCI Helm repository, which defines a source that does not produce an Artifact.
|
||||
It's a data container to store the information about the OCI repository that
|
||||
can be used by [HelmChart](helmcharts.md) to access OCI Helm charts.
|
||||
|
||||
## Examples
|
||||
|
||||
### Helm HTTP/S repository
|
||||
|
||||
The following is an example of a HelmRepository. It creates a YAML (`.yaml`)
|
||||
Artifact from the fetched Helm repository index (in this example the [podinfo
|
||||
repository](https://github.com/stefanprodan/podinfo)):
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
url: https://stefanprodan.github.io/podinfo
|
||||
```
|
||||
|
||||
In the above example:
|
||||
|
||||
- A HelmRepository named `podinfo` is created, indicated by the
|
||||
`.metadata.name` field.
|
||||
- The source-controller fetches the Helm repository index YAML every five
|
||||
minutes from `https://stefanprodan.github.io/podinfo`, indicated by the
|
||||
`.spec.interval` and `.spec.url` fields.
|
||||
- The digest (algorithm defaults to SHA256) of the Helm repository index after
|
||||
stable sorting the entries is used as Artifact revision, reported in-cluster
|
||||
in the `.status.artifact.revision` field.
|
||||
- When the current HelmRepository revision differs from the latest fetched
|
||||
revision, it is stored as a new Artifact.
|
||||
- The new Artifact is reported in the `.status.artifact` field.
|
||||
|
||||
You can run this example by saving the manifest into `helmrepository.yaml`.
|
||||
|
||||
1. Apply the resource on the cluster:
|
||||
|
||||
```sh
|
||||
kubectl apply -f helmrepository.yaml
|
||||
```
|
||||
|
||||
2. Run `kubectl get helmrepository` to see the HelmRepository:
|
||||
|
||||
```console
|
||||
NAME URL AGE READY STATUS
|
||||
podinfo https://stefanprodan.github.io/podinfo 4s True stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
|
||||
```
|
||||
|
||||
3. Run `kubectl describe helmrepository podinfo` to see the [Artifact](#artifact)
|
||||
and [Conditions](#conditions) in the HelmRepository's Status:
|
||||
|
||||
```console
|
||||
...
|
||||
Status:
|
||||
Artifact:
|
||||
Digest: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
|
||||
Last Update Time: 2022-02-04T09:55:58Z
|
||||
Path: helmrepository/default/podinfo/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
|
||||
Revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
|
||||
Size: 40898
|
||||
URL: http://source-controller.flux-system.svc.cluster.local./helmrepository/default/podinfo/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
|
||||
Conditions:
|
||||
Last Transition Time: 2022-02-04T09:55:58Z
|
||||
Message: stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
|
||||
Observed Generation: 1
|
||||
Reason: Succeeded
|
||||
Status: True
|
||||
Type: Ready
|
||||
Last Transition Time: 2022-02-04T09:55:58Z
|
||||
Message: stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
|
||||
Observed Generation: 1
|
||||
Reason: Succeeded
|
||||
Status: True
|
||||
Type: ArtifactInStorage
|
||||
Observed Generation: 1
|
||||
URL: http://source-controller.flux-system.svc.cluster.local./helmrepository/default/podinfo/index.yaml
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Normal NewArtifact 1m source-controller fetched index of size 30.88kB from 'https://stefanprodan.github.io/podinfo'
|
||||
```
|
||||
|
||||
### Helm OCI repository
|
||||
|
||||
The following is an example of an OCI HelmRepository.
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
type: "oci"
|
||||
interval: 5m0s
|
||||
url: oci://ghcr.io/stefanprodan/charts
|
||||
```
|
||||
|
||||
In the above example:
|
||||
|
||||
- A HelmRepository named `podinfo` is created, indicated by the
|
||||
`.metadata.name` field.
|
||||
- A HelmChart that refers to this HelmRepository uses the URL in the `.spec.url`
|
||||
field to access the OCI Helm chart.
|
||||
|
||||
**NOTE:** The `.spec.interval` field is only used by the `default` Helm
|
||||
repository and is ignored for any value in `oci` Helm repository.
|
||||
|
||||
You can run this example by saving the manifest into `helmrepository.yaml`.
|
||||
|
||||
1. Apply the resource on the cluster:
|
||||
|
||||
```sh
|
||||
kubectl apply -f helmrepository.yaml
|
||||
```
|
||||
|
||||
2. Run `kubectl get helmrepository` to see the HelmRepository:
|
||||
|
||||
```console
|
||||
NAME URL AGE READY STATUS
|
||||
podinfo oci://ghcr.io/stefanprodan/charts 3m22s
|
||||
```
|
||||
|
||||
Because the OCI Helm repository is a data container, there's nothing to report
|
||||
for `READY` and `STATUS` columns above. The existence of the object can be
|
||||
considered to be ready for use.
|
||||
|
||||
## Writing a HelmRepository spec
|
||||
|
||||
As with all other Kubernetes config, a HelmRepository needs `apiVersion`,
|
||||
`kind`, and `metadata` fields. The name of a HelmRepository object must be a
|
||||
valid [DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
|
||||
|
||||
A HelmRepository also needs a
|
||||
[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
|
||||
|
||||
### Type
|
||||
|
||||
`.spec.type` is an optional field that specifies the Helm repository type.
|
||||
|
||||
Possible values are `default` for a Helm HTTP/S repository, or `oci` for an OCI Helm repository.
|
||||
|
||||
### Provider
|
||||
|
||||
`.spec.provider` is an optional field that allows specifying an OIDC provider used
|
||||
for authentication purposes.
|
||||
|
||||
Supported options are:
|
||||
- `generic`
|
||||
- `aws`
|
||||
- `azure`
|
||||
- `gcp`
|
||||
|
||||
The `generic` provider can be used for public repositories or when static credentials
|
||||
are used for authentication. If you do not specify `.spec.provider`, it defaults
|
||||
to `generic`.
|
||||
|
||||
**Note**: The provider field is supported only for Helm OCI repositories. The `spec.type`
|
||||
field must be set to `oci`.
|
||||
|
||||
#### AWS
|
||||
|
||||
The `aws` provider can be used to authenticate automatically using the EKS worker
|
||||
node IAM role or IAM Role for Service Accounts (IRSA), and by extension gain access
|
||||
to ECR.
|
||||
|
||||
##### EKS Worker Node IAM Role
|
||||
|
||||
When the worker node IAM role has access to ECR, source-controller running on it
|
||||
will also have access to ECR.
|
||||
|
||||
##### IAM Role for Service Accounts (IRSA)
|
||||
|
||||
When using IRSA to enable access to ECR, add the following patch to your bootstrap
|
||||
repository, in the `flux-system/kustomization.yaml` file:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- patch: |
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: source-controller
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: <role arn>
|
||||
target:
|
||||
kind: ServiceAccount
|
||||
name: source-controller
|
||||
```
|
||||
|
||||
Note that you can attach the AWS managed policy `arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly`
|
||||
to the IAM role when using IRSA.
|
||||
|
||||
#### Azure
|
||||
|
||||
The `azure` provider can be used to authenticate automatically using Workload Identity and Kubelet Managed
|
||||
Identity to gain access to ACR.
|
||||
|
||||
##### Kubelet Managed Identity
|
||||
|
||||
When the kubelet managed identity has access to ACR, source-controller running on
|
||||
it will also have access to ACR.
|
||||
|
||||
**Note:** If you have more than one identity configured on the cluster, you have to specify which one to use
|
||||
by setting the `AZURE_CLIENT_ID` environment variable in the source-controller deployment.
|
||||
|
||||
If you are running into further issues, please look at the
|
||||
[troubleshooting guide](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/TROUBLESHOOTING.md#azure-virtual-machine-managed-identity).
|
||||
|
||||
##### Azure Workload Identity
|
||||
|
||||
When using Workload Identity to enable access to ACR, add the following patch to
|
||||
your bootstrap repository, in the `flux-system/kustomization.yaml` file:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- patch: |-
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: source-controller
|
||||
namespace: flux-system
|
||||
annotations:
|
||||
azure.workload.identity/client-id: <AZURE_CLIENT_ID>
|
||||
labels:
|
||||
azure.workload.identity/use: "true"
|
||||
- patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: source-controller
|
||||
namespace: flux-system
|
||||
labels:
|
||||
azure.workload.identity/use: "true"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
azure.workload.identity/use: "true"
|
||||
```
|
||||
|
||||
Ensure Workload Identity is properly set up on your cluster and the mutating webhook is installed.
|
||||
Create an identity that has access to ACR. Next, establish
|
||||
a federated identity between the source-controller ServiceAccount and the
|
||||
identity. Patch the source-controller Deployment and ServiceAccount as shown in the patch
|
||||
above. Please take a look at this [guide](https://azure.github.io/azure-workload-identity/docs/quick-start.html#6-establish-federated-identity-credential-between-the-identity-and-the-service-account-issuer--subject).
|
||||
|
||||
#### GCP
|
||||
|
||||
The `gcp` provider can be used to authenticate automatically using OAuth scopes or
|
||||
Workload Identity, and by extension gain access to GCR or Artifact Registry.
|
||||
|
||||
##### Access Scopes
|
||||
|
||||
When the GKE nodes have the appropriate OAuth scope for accessing GCR and Artifact Registry,
|
||||
source-controller running on it will also have access to them.
|
||||
|
||||
##### GKE Workload Identity
|
||||
|
||||
When using Workload Identity to enable access to GCR or Artifact Registry, add the
|
||||
following patch to your bootstrap repository, in the `flux-system/kustomization.yaml`
|
||||
file:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- patch: |
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: source-controller
|
||||
annotations:
|
||||
iam.gke.io/gcp-service-account: <identity-name>
|
||||
target:
|
||||
kind: ServiceAccount
|
||||
name: source-controller
|
||||
```
|
||||
|
||||
The Artifact Registry service uses the permission `artifactregistry.repositories.downloadArtifacts`
|
||||
that is located under the Artifact Registry Reader role. If you are using Google Container Registry service,
|
||||
the needed permission is instead `storage.objects.list` which can be bound as part
|
||||
of the Container Registry Service Agent role. Take a look at [this guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
|
||||
for more information about setting up GKE Workload Identity.
|
||||
|
||||
### Insecure
|
||||
|
||||
`.spec.insecure` is an optional field to allow connecting to an insecure (HTTP)
|
||||
container registry server, if set to `true`. The default value is `false`,
|
||||
denying insecure non-TLS connections when fetching Helm chart OCI artifacts.
|
||||
|
||||
**Note**: The insecure field is supported only for Helm OCI repositories.
|
||||
The `spec.type` field must be set to `oci`.
|
||||
|
||||
### Interval
|
||||
|
||||
**Note:** This field is ineffectual for [OCI Helm
|
||||
Repositories](#helm-oci-repository).
|
||||
|
||||
`.spec.interval` is a an optional field that specifies the interval which the
|
||||
Helm repository index must be consulted at. When not set, the default value is
|
||||
`1m`.
|
||||
|
||||
After successfully reconciling a HelmRepository object, the source-controller
|
||||
requeues the object for inspection after the specified interval. The value
|
||||
must be in a [Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
|
||||
e.g. `10m0s` to fetch the HelmRepository index YAML every 10 minutes.
|
||||
|
||||
If the `.metadata.generation` of a resource changes (due to e.g. applying a
|
||||
change to the spec), this is handled instantly outside the interval window.
|
||||
|
||||
**Note:** The controller can be configured to apply a jitter to the interval in
|
||||
order to distribute the load more evenly when multiple HelmRepository objects
|
||||
are set up with the same interval. For more information, please refer to the
|
||||
[source-controller configuration options](https://fluxcd.io/flux/components/source/options/).
|
||||
|
||||
### URL
|
||||
|
||||
`.spec.url` is a required field that depending on the [type of the HelmRepository object](#type)
|
||||
specifies the HTTP/S or OCI address of a Helm repository.
|
||||
|
||||
For OCI, the URL is expected to point to a registry repository, e.g. `oci://ghcr.io/fluxcd/source-controller`.
|
||||
|
||||
For Helm repositories which require authentication, see [Secret reference](#secret-reference).
|
||||
|
||||
### Timeout
|
||||
|
||||
**Note:** This field is not applicable to [OCI Helm
|
||||
Repositories](#helm-oci-repository).
|
||||
|
||||
`.spec.timeout` is an optional field to specify a timeout for the fetch
|
||||
operation. The value must be in a
|
||||
[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
|
||||
e.g. `1m30s` for a timeout of one minute and thirty seconds. When not set, the
|
||||
default value is `1m`.
|
||||
|
||||
### Secret reference
|
||||
|
||||
`.spec.secretRef.name` is an optional field to specify a name reference to a
|
||||
Secret in the same namespace as the HelmRepository, containing authentication
|
||||
credentials for the repository.
|
||||
|
||||
#### Basic access authentication
|
||||
|
||||
To authenticate towards a Helm repository using basic access authentication
|
||||
(in other words: using a username and password), the referenced Secret is
|
||||
expected to contain `.data.username` and `.data.password` values.
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: example
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
url: https://example.com
|
||||
secretRef:
|
||||
name: example-user
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: example-user
|
||||
namespace: default
|
||||
stringData:
|
||||
username: "user-123456"
|
||||
password: "pass-123456"
|
||||
```
|
||||
|
||||
OCI Helm repository example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
url: oci://ghcr.io/my-user/my-private-repo
|
||||
type: "oci"
|
||||
secretRef:
|
||||
name: oci-creds
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: oci-creds
|
||||
namespace: default
|
||||
stringData:
|
||||
username: "user-123456"
|
||||
password: "pass-123456"
|
||||
```
|
||||
|
||||
For OCI Helm repositories, Kubernetes secrets of type [kubernetes.io/dockerconfigjson](https://kubernetes.io/docs/concepts/configuration/secret/#secret-types) are also supported.
|
||||
It is possible to create one such secret with `kubectl create secret docker-registry`
|
||||
or using the Flux CLI:
|
||||
|
||||
```yaml
|
||||
flux create secret oci ghcr-auth \
|
||||
--url=ghcr.io \
|
||||
--username=flux \
|
||||
--password=${GITHUB_PAT}
|
||||
```
|
||||
|
||||
**Warning:** Support for specifying TLS authentication data using this API has been
|
||||
deprecated. Please use [`.spec.certSecretRef`](#cert-secret-reference) instead.
|
||||
If the controller uses the secret specified by this field to configure TLS, then
|
||||
a deprecation warning will be logged.
|
||||
|
||||
### Cert secret reference
|
||||
|
||||
`.spec.certSecretRef.name` is an optional field to specify a secret containing
|
||||
TLS certificate data. The secret can contain the following keys:
|
||||
|
||||
* `tls.crt` and `tls.key`, to specify the client certificate and private key used
|
||||
for TLS client authentication. These must be used in conjunction, i.e.
|
||||
specifying one without the other will lead to an error.
|
||||
* `ca.crt`, to specify the CA certificate used to verify the server, which is
|
||||
required if the server is using a self-signed certificate.
|
||||
|
||||
If the server is using a self-signed certificate and has TLS client
|
||||
authentication enabled, all three values are required.
|
||||
|
||||
The Secret should be of type `Opaque` or `kubernetes.io/tls`. All the files in
|
||||
the Secret are expected to be [PEM-encoded][pem-encoding]. Assuming you have
|
||||
three files; `client.key`, `client.crt` and `ca.crt` for the client private key,
|
||||
client certificate and the CA certificate respectively, you can generate the
|
||||
required Secret using the `flux create secret tls` command:
|
||||
|
||||
```sh
|
||||
flux create secret tls --tls-key-file=client.key --tls-crt-file=client.crt --ca-crt-file=ca.crt
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: example
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
url: https://example.com
|
||||
certSecretRef:
|
||||
name: example-tls
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: example-tls
|
||||
namespace: default
|
||||
type: kubernetes.io/tls # or Opaque
|
||||
data:
|
||||
tls.crt: <BASE64>
|
||||
tls.key: <BASE64>
|
||||
# NOTE: Can be supplied without the above values
|
||||
ca.crt: <BASE64>
|
||||
```
|
||||
|
||||
### Pass credentials
|
||||
|
||||
`.spec.passCredentials` is an optional field to allow the credentials from the
|
||||
[Secret reference](#secret-reference) to be passed on to a host that does not
|
||||
match the host as defined in URL. This may for example be required if the host
|
||||
advertised chart URLs in the index differ from the specified URL.
|
||||
|
||||
Enabling this should be done with caution, as it can potentially result in
|
||||
credentials getting stolen in a man-in-the-middle attack. This feature only applies
|
||||
to HTTP/S Helm repositories.
|
||||
|
||||
### Suspend
|
||||
|
||||
**Note:** This field is not applicable to [OCI Helm
|
||||
Repositories](#helm-oci-repository).
|
||||
|
||||
`.spec.suspend` is an optional field to suspend the reconciliation of a
|
||||
HelmRepository. When set to `true`, the controller will stop reconciling the
|
||||
HelmRepository, and changes to the resource or the Helm repository index will
|
||||
not result in a new Artifact. When the field is set to `false` or removed, it
|
||||
will resume.
|
||||
|
||||
For practical information, see
|
||||
[suspending and resuming](#suspending-and-resuming).
|
||||
|
||||
## Working with HelmRepositories
|
||||
|
||||
**Note:** This section does not apply to [OCI Helm
|
||||
Repositories](#helm-oci-repository), being a data container, once created, they
|
||||
are ready to used by [HelmCharts](helmcharts.md).
|
||||
|
||||
### Triggering a reconcile
|
||||
|
||||
To manually tell the source-controller to reconcile a HelmRepository outside the
|
||||
[specified interval window](#interval), a HelmRepository can be annotated with
|
||||
`reconcile.fluxcd.io/requestedAt: <arbitrary value>`. Annotating the resource
|
||||
queues the object for reconciliation if the `<arbitrary-value>` differs from
|
||||
the last value the controller acted on, as reported in
|
||||
[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl annotate --field-manager=flux-client-side-apply --overwrite helmrepository/<repository-name> reconcile.fluxcd.io/requestedAt="$(date +%s)"
|
||||
```
|
||||
|
||||
Using `flux`:
|
||||
|
||||
```sh
|
||||
flux reconcile source helm <repository-name>
|
||||
```
|
||||
|
||||
### Waiting for `Ready`
|
||||
|
||||
When a change is applied, it is possible to wait for the HelmRepository to
|
||||
reach a [ready state](#ready-helmrepository) using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl wait helmrepository/<repository-name> --for=condition=ready --timeout=1m
|
||||
```
|
||||
|
||||
### Suspending and resuming
|
||||
|
||||
When you find yourself in a situation where you temporarily want to pause the
|
||||
reconciliation of a HelmRepository, you can suspend it using the
|
||||
[`.spec.suspend` field](#suspend).
|
||||
|
||||
#### Suspend a HelmRepository
|
||||
|
||||
In your YAML declaration:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: <repository-name>
|
||||
spec:
|
||||
suspend: true
|
||||
```
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl patch helmrepository <repository-name> --field-manager=flux-client-side-apply -p '{\"spec\": {\"suspend\" : true }}'
|
||||
```
|
||||
|
||||
Using `flux`:
|
||||
|
||||
```sh
|
||||
flux suspend source helm <repository-name>
|
||||
```
|
||||
|
||||
**Note:** When a HelmRepository has an Artifact and is suspended, and this
|
||||
Artifact later disappears from the storage due to e.g. the source-controller
|
||||
Pod being evicted from a Node, this will not be reflected in the
|
||||
HelmRepository's Status until it is resumed.
|
||||
|
||||
#### Resume a HelmRepository
|
||||
|
||||
In your YAML declaration, comment out (or remove) the field:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: <repository-name>
|
||||
spec:
|
||||
# suspend: true
|
||||
```
|
||||
|
||||
**Note:** Setting the field value to `false` has the same effect as removing
|
||||
it, but does not allow for "hot patching" using e.g. `kubectl` while practicing
|
||||
GitOps; as the manually applied patch would be overwritten by the declared
|
||||
state in Git.
|
||||
|
||||
Using `kubectl`:
|
||||
|
||||
```sh
|
||||
kubectl patch helmrepository <repository-name> --field-manager=flux-client-side-apply -p '{\"spec\" : {\"suspend\" : false }}'
|
||||
```
|
||||
|
||||
Using `flux`:
|
||||
|
||||
```sh
|
||||
flux resume source helm <repository-name>
|
||||
```
|
||||
|
||||
### Debugging a HelmRepository
|
||||
|
||||
**Note:** This section does not apply to [OCI Helm
|
||||
Repositories](#helm-oci-repository), being a data container, they are static
|
||||
objects that don't require debugging if valid.
|
||||
|
||||
There are several ways to gather information about a HelmRepository for debugging
|
||||
purposes.
|
||||
|
||||
#### Describe the HelmRepository
|
||||
|
||||
Describing a HelmRepository using `kubectl describe helmrepository <repository-name>`
|
||||
displays the latest recorded information for the resource in the `Status` and
|
||||
`Events` sections:
|
||||
|
||||
```console
|
||||
...
|
||||
Status:
|
||||
...
|
||||
Conditions:
|
||||
Last Transition Time: 2022-02-04T13:41:56Z
|
||||
Message: failed to construct Helm client: scheme "invalid" not supported
|
||||
Observed Generation: 2
|
||||
Reason: Failed
|
||||
Status: True
|
||||
Type: Stalled
|
||||
Last Transition Time: 2022-02-04T13:41:56Z
|
||||
Message: failed to construct Helm client: scheme "invalid" not supported
|
||||
Observed Generation: 2
|
||||
Reason: Failed
|
||||
Status: False
|
||||
Type: Ready
|
||||
Last Transition Time: 2022-02-04T13:41:56Z
|
||||
Message: failed to construct Helm client: scheme "invalid" not supported
|
||||
Observed Generation: 2
|
||||
Reason: Failed
|
||||
Status: True
|
||||
Type: FetchFailed
|
||||
Observed Generation: 2
|
||||
URL: http://source-controller.source-system.svc.cluster.local./helmrepository/default/podinfo/index.yaml
|
||||
Events:
|
||||
Type Reason Age From Message
|
||||
---- ------ ---- ---- -------
|
||||
Warning Failed 6s source-controller failed to construct Helm client: scheme "invalid" not supported
|
||||
```
|
||||
|
||||
#### Trace emitted Events
|
||||
|
||||
To view events for specific HelmRepository(s), `kubectl events` can be used in
|
||||
combination with `--for` to list the Events for specific objects. For example,
|
||||
running
|
||||
|
||||
```sh
|
||||
kubectl events --for HelmRepository/<repository-name>
|
||||
```
|
||||
|
||||
lists
|
||||
|
||||
```console
|
||||
LAST SEEN TYPE REASON OBJECT MESSAGE
|
||||
107s Warning Failed helmrepository/<repository-name> failed to construct Helm client: scheme "invalid" not supported
|
||||
7s Normal NewArtifact helmrepository/<repository-name> fetched index of size 30.88kB from 'https://stefanprodan.github.io/podinfo'
|
||||
3s Normal ArtifactUpToDate helmrepository/<repository-name> artifact up-to-date with remote revision: 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
|
||||
```
|
||||
|
||||
Besides being reported in Events, the reconciliation errors are also logged by
|
||||
the controller. The Flux CLI offer commands for filtering the logs for a
|
||||
specific HelmRepository, e.g. `flux logs --level=error --kind=HelmRepository --name=<chart-name>`.
|
||||
|
||||
## HelmRepository Status
|
||||
|
||||
**Note:** This section does not apply to [OCI Helm
|
||||
Repositories](#helm-oci-repository), they do not contain any information in the
|
||||
status.
|
||||
|
||||
### Artifact
|
||||
|
||||
The HelmRepository reports the last fetched repository index as an Artifact
|
||||
object in the `.status.artifact` of the resource.
|
||||
|
||||
The Artifact file is an exact copy of the Helm repository index YAML
|
||||
(`index-<revision>.yaml`) as fetched, and can be retrieved in-cluster from the
|
||||
`.status.artifact.url` HTTP address.
|
||||
|
||||
#### Artifact example
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: <repository-name>
|
||||
status:
|
||||
artifact:
|
||||
digest: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
|
||||
lastUpdateTime: "2022-02-04T09:55:58Z"
|
||||
path: helmrepository/<namespace>/<repository-name>/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
|
||||
revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
|
||||
size: 40898
|
||||
url: http://source-controller.flux-system.svc.cluster.local./helmrepository/<namespace>/<repository-name>/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
|
||||
```
|
||||
|
||||
### Conditions
|
||||
|
||||
A HelmRepository enters various states during its lifecycle, reflected as [Kubernetes
|
||||
Conditions][typical-status-properties].
|
||||
It can be [reconciling](#reconciling-helmrepository) while fetching the
|
||||
repository index, it can be [ready](#ready-helmrepository), it can
|
||||
[fail during reconciliation](#failed-helmrepository), or it can
|
||||
[stall](#stalled-helmrepository).
|
||||
|
||||
The HelmRepository API is compatible with the [kstatus
|
||||
specification][kstatus-spec],
|
||||
and reports `Reconciling` and `Stalled` conditions where applicable to
|
||||
provide better (timeout) support to solutions polling the HelmRepository to become
|
||||
`Ready`.
|
||||
|
||||
#### Reconciling HelmRepository
|
||||
|
||||
The source-controller marks a HelmRepository as _reconciling_ when one of the following
|
||||
is true:
|
||||
|
||||
- There is no current Artifact for the HelmRepository, or the reported Artifact
|
||||
is determined to have disappeared from the storage.
|
||||
- The generation of the HelmRepository is newer than the [Observed
|
||||
Generation](#observed-generation).
|
||||
- The newly fetched Artifact revision differs from the current Artifact.
|
||||
|
||||
When the HelmRepository is "reconciling", the `Ready` Condition status becomes
|
||||
`Unknown` when the controller detects drift, and the controller adds a Condition
|
||||
with the following attributes to the HelmRepository's `.status.conditions`:
|
||||
|
||||
- `type: Reconciling`
|
||||
- `status: "True"`
|
||||
- `reason: Progressing` | `reason: ProgressingWithRetry`
|
||||
|
||||
If the reconciling state is due to a new revision, it adds an additional
|
||||
Condition with the following attributes:
|
||||
|
||||
- `type: ArtifactOutdated`
|
||||
- `status: "True"`
|
||||
- `reason: NewRevision`
|
||||
|
||||
Both Conditions have a ["negative polarity"][typical-status-properties],
|
||||
and are only present on the HelmRepository while their status value is `"True"`.
|
||||
|
||||
#### Ready HelmRepository
|
||||
|
||||
The source-controller marks a HelmRepository as _ready_ when it has the following
|
||||
characteristics:
|
||||
|
||||
- The HelmRepository reports an [Artifact](#artifact).
|
||||
- The reported Artifact exists in the controller's Artifact storage.
|
||||
- The controller was able to fetch the Helm repository index using the current
|
||||
spec.
|
||||
- The revision of the reported Artifact is up-to-date with the latest
|
||||
revision of the Helm repository.
|
||||
|
||||
When the HelmRepository is "ready", the controller sets a Condition with the following
|
||||
attributes in the HelmRepository's `.status.conditions`:
|
||||
|
||||
- `type: Ready`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
This `Ready` Condition will retain a status value of `"True"` until the
|
||||
HelmRepository is marked as [reconciling](#reconciling-helmrepository), or e.g.
|
||||
a [transient error](#failed-helmrepository) occurs due to a temporary network
|
||||
issue.
|
||||
|
||||
When the HelmRepository Artifact is archived in the controller's Artifact
|
||||
storage, the controller sets a Condition with the following attributes in the
|
||||
HelmRepository's `.status.conditions`:
|
||||
|
||||
- `type: ArtifactInStorage`
|
||||
- `status: "True"`
|
||||
- `reason: Succeeded`
|
||||
|
||||
This `ArtifactInStorage` Condition will retain a status value of `"True"` until
|
||||
the Artifact in the storage no longer exists.
|
||||
|
||||
#### Failed HelmRepository
|
||||
|
||||
The source-controller may get stuck trying to produce an Artifact for a
|
||||
HelmRepository without completing. This can occur due to some of the following
|
||||
factors:
|
||||
|
||||
- The Helm repository [URL](#url) is temporarily unavailable.
|
||||
- The [Secret reference](#secret-reference) contains a reference to a
|
||||
non-existing Secret.
|
||||
- The credentials in the referenced Secret are invalid.
|
||||
- The HelmRepository spec contains a generic misconfiguration.
|
||||
- A storage related failure when storing the artifact.
|
||||
|
||||
When this happens, the controller sets the `Ready` Condition status to `False`,
|
||||
and adds a Condition with the following attributes to the HelmRepository's
|
||||
`.status.conditions`:
|
||||
|
||||
- `type: FetchFailed` | `type: StorageOperationFailed`
|
||||
- `status: "True"`
|
||||
- `reason: AuthenticationFailed` | `reason: IndexationFailed` | `reason: Failed`
|
||||
|
||||
This condition has a ["negative polarity"][typical-status-properties],
|
||||
and is only present on the HelmRepository while the status value is `"True"`.
|
||||
There may be more arbitrary values for the `reason` field to provide accurate
|
||||
reason for a condition.
|
||||
|
||||
While the HelmRepository has this Condition, the controller will continue to
|
||||
attempt to produce an Artifact for the resource with an exponential backoff,
|
||||
until it succeeds and the HelmRepository is marked as [ready](#ready-helmrepository).
|
||||
|
||||
Note that a HelmRepository can be [reconciling](#reconciling-helmrepository)
|
||||
while failing at the same time, for example due to a newly introduced
|
||||
configuration issue in the HelmRepository spec. When a reconciliation fails, the
|
||||
`Reconciling` Condition reason would be `ProgressingWithRetry`. When the
|
||||
reconciliation is performed again after the failure, the reason is updated to
|
||||
`Progressing`.
|
||||
|
||||
#### Stalled HelmRepository
|
||||
|
||||
The source-controller can mark a HelmRepository as _stalled_ when it determines
|
||||
that without changes to the spec, the reconciliation can not succeed.
|
||||
For example because a Helm repository URL with an unsupported protocol is
|
||||
specified.
|
||||
|
||||
When this happens, the controller sets the same Conditions as when it
|
||||
[fails](#failed-helmrepository), but adds another Condition with the following
|
||||
attributes to the HelmRepository's
|
||||
`.status.conditions`:
|
||||
|
||||
- `type: Stalled`
|
||||
- `status: "True"`
|
||||
- `reason: URLInvalid`
|
||||
|
||||
While the HelmRepository has this Condition, the controller will not requeue
|
||||
the resource any further, and will stop reconciling the resource until a change
|
||||
to the spec is made.
|
||||
|
||||
### Observed Generation
|
||||
|
||||
The source-controller reports an [observed generation][typical-status-properties]
|
||||
in the HelmRepository's `.status.observedGeneration`. The observed generation is
|
||||
the latest `.metadata.generation` which resulted in either a [ready state](#ready-helmrepository),
|
||||
or stalled due to error it can not recover from without human intervention.
|
||||
|
||||
### Last Handled Reconcile At
|
||||
|
||||
The source-controller reports the last `reconcile.fluxcd.io/requestedAt`
|
||||
annotation value it acted on in the `.status.lastHandledReconcileAt` field.
|
||||
|
||||
For practical information about this field, see [triggering a
|
||||
reconcile](#triggering-a-reconcile).
|
||||
|
||||
[pem-encoding]: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
|
||||
[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
|
||||
[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus
|
||||
|
|
@ -157,9 +157,8 @@ to the IAM role when using IRSA.
|
|||
|
||||
#### Azure
|
||||
|
||||
The `azure` provider can be used to authenticate automatically using Workload Identity, Kubelet Managed
|
||||
Identity or Azure Active Directory pod-managed identity (aad-pod-identity),
|
||||
and by extension gain access to ACR.
|
||||
The `azure` provider can be used to authenticate automatically using Workload Identity and Kubelet Managed
|
||||
Identity to gain access to ACR.
|
||||
|
||||
##### Kubelet Managed Identity
|
||||
|
||||
|
|
@ -215,41 +214,6 @@ a federated identity between the source-controller ServiceAccount and the
|
|||
identity. Patch the source-controller Deployment and ServiceAccount as shown in the patch
|
||||
above. Please take a look at this [guide](https://azure.github.io/azure-workload-identity/docs/quick-start.html#6-establish-federated-identity-credential-between-the-identity-and-the-service-account-issuer--subject).
|
||||
|
||||
##### Deprecated: AAD Pod Identity
|
||||
|
||||
**Note:** The AAD Pod Identity project will be archived in [September 2023](https://github.com/Azure/aad-pod-identity#-announcement),
|
||||
and you are advised to use Workload Identity instead.
|
||||
|
||||
When using aad-pod-identity to enable access to ACR, add the following patch to
|
||||
your bootstrap repository, in the `flux-system/kustomization.yaml` file:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- patch: |
|
||||
- op: add
|
||||
path: /spec/template/metadata/labels/aadpodidbinding
|
||||
value: <identity-name>
|
||||
target:
|
||||
kind: Deployment
|
||||
name: source-controller
|
||||
```
|
||||
|
||||
When using pod-managed identity on an AKS cluster, AAD Pod Identity
|
||||
has to be used to give the `source-controller` pod access to the ACR.
|
||||
To do this, you have to install `aad-pod-identity` on your cluster, create a managed identity
|
||||
that has access to the container registry (this can also be the Kubelet identity
|
||||
if it has `AcrPull` role assignment on the ACR), create an `AzureIdentity` and `AzureIdentityBinding`
|
||||
that describe the managed identity and then label the `source-controller` deployment
|
||||
with the name of the AzureIdentity as shown in the patch above. Please take a look
|
||||
at [this guide](https://azure.github.io/aad-pod-identity/docs/) or
|
||||
[this one](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity)
|
||||
if you want to use AKS pod-managed identities add-on that is in preview.
|
||||
|
||||
#### GCP
|
||||
|
||||
The `gcp` provider can be used to authenticate automatically using OAuth scopes
|
||||
|
|
|
|||
14
go.mod
14
go.mod
|
|
@ -28,8 +28,8 @@ require (
|
|||
github.com/fluxcd/pkg/helmtestserver v0.18.0
|
||||
github.com/fluxcd/pkg/lockedfile v0.3.0
|
||||
github.com/fluxcd/pkg/masktoken v0.4.0
|
||||
github.com/fluxcd/pkg/oci v0.37.0
|
||||
github.com/fluxcd/pkg/runtime v0.47.0
|
||||
github.com/fluxcd/pkg/oci v0.37.1
|
||||
github.com/fluxcd/pkg/runtime v0.47.1
|
||||
github.com/fluxcd/pkg/sourceignore v0.7.0
|
||||
github.com/fluxcd/pkg/ssh v0.13.0
|
||||
github.com/fluxcd/pkg/tar v0.7.0
|
||||
|
|
@ -46,7 +46,7 @@ require (
|
|||
github.com/minio/minio-go/v7 v7.0.70
|
||||
github.com/notaryproject/notation-core-go v1.0.2
|
||||
github.com/notaryproject/notation-go v1.1.0
|
||||
github.com/onsi/gomega v1.32.0
|
||||
github.com/onsi/gomega v1.33.1
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/go-digest/blake3 v0.0.0-20231212064514-429d0316a3dd
|
||||
github.com/opencontainers/image-spec v1.1.0
|
||||
|
|
@ -68,7 +68,7 @@ require (
|
|||
k8s.io/client-go v0.30.0
|
||||
k8s.io/utils v0.0.0-20240310230437-4693a0247e57
|
||||
oras.land/oras-go/v2 v2.5.0
|
||||
sigs.k8s.io/controller-runtime v0.18.0
|
||||
sigs.k8s.io/controller-runtime v0.18.1
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
|
|
@ -116,8 +116,8 @@ require (
|
|||
github.com/aliyun/credentials-go v1.3.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
|
||||
|
|
@ -126,7 +126,7 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.21.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
|
||||
github.com/aws/smithy-go v1.20.2 // indirect
|
||||
|
|
|
|||
39
go.sum
39
go.sum
|
|
@ -159,10 +159,10 @@ github.com/aws/aws-sdk-go v1.51.6 h1:Ld36dn9r7P9IjU8WZSaswQ8Y/XUCRpewim5980DwYiU
|
|||
github.com/aws/aws-sdk-go v1.51.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.10 h1:PS+65jThT0T/snC5WjyfHHyUgG+eBoupSDV+f838cro=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.10/go.mod h1:BePM7Vo4OBpHreKRUMuDXX+/+JWP38FLkzl5m27/Jjs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.10 h1:qDZ3EA2lv1KangvQB6y258OssCHD0xvaGiEDkG4X/10=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.10/go.mod h1:6t3sucOaYDwDssHQa0ojH1RpmVmF5/jArkye1b2FKMI=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
|
||||
|
|
@ -181,8 +181,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/g
|
|||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 h1:WzFol5Cd+yDxPAdnzTA5LmpHYSWinhmSj4rQChV0ee8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
|
||||
|
|
@ -352,10 +352,10 @@ github.com/fluxcd/pkg/lockedfile v0.3.0 h1:tZkBAffcxyt4zMigHIKc54cKgN5I/kFF005gy
|
|||
github.com/fluxcd/pkg/lockedfile v0.3.0/go.mod h1:5iCYXAs953LlXZq7nTId9ZSGnHVvTfZ0mDmrDE49upk=
|
||||
github.com/fluxcd/pkg/masktoken v0.4.0 h1:pRItymXzW8dhT9Fd4XfnbrgKeySPeeLCrr6W1pgrUbM=
|
||||
github.com/fluxcd/pkg/masktoken v0.4.0/go.mod h1:MP1nCsr2tJbH8hnhZP4+7TfTR0ggrKOJgi9Bo7Mj/6M=
|
||||
github.com/fluxcd/pkg/oci v0.37.0 h1:hiRNMIGN1jKC2SrC4uWkSEQkGJnrZmSFYOYRL8/vVro=
|
||||
github.com/fluxcd/pkg/oci v0.37.0/go.mod h1:shriYSpwJFwORG3djxg5V6mifC6jXyRYbcXqdLd2kmY=
|
||||
github.com/fluxcd/pkg/runtime v0.47.0 h1:m3BEgwTYJslIF0lqhZMw6ZcKD6bD+4Ut+Xd/8X86SZA=
|
||||
github.com/fluxcd/pkg/runtime v0.47.0/go.mod h1:UgHy8DTkU2MFHDe2q3b+OP4mBYTsopGhSzWb8rHJa9Q=
|
||||
github.com/fluxcd/pkg/oci v0.37.1 h1:p4rfCHZlBWL+Q5Xey51iiBRmoje0IevCBT0/r8iae3M=
|
||||
github.com/fluxcd/pkg/oci v0.37.1/go.mod h1:LrVuX6VACenJ5ycQJxec+I7YJegCsE4nzRUV+6RuxcY=
|
||||
github.com/fluxcd/pkg/runtime v0.47.1 h1:Q1tAFsp92uurWyoEe52AmMC4k+6DYTPBrUQDs+nz/9c=
|
||||
github.com/fluxcd/pkg/runtime v0.47.1/go.mod h1:97a+PqpWMgQsoqh91uH3EQz+/DC7Uxc8xcu/rDHFC5c=
|
||||
github.com/fluxcd/pkg/sourceignore v0.7.0 h1:qQrB2o543wA1o4vgR62ufwkAaDp8+f8Wdj1HKDlmDrU=
|
||||
github.com/fluxcd/pkg/sourceignore v0.7.0/go.mod h1:A4GuZt2seJJkBm3kMiIx9nheoYZs98KTMr/A6/2fIro=
|
||||
github.com/fluxcd/pkg/ssh v0.13.0 h1:lPU1Gst8XIz7AU2dhdqVFaaOWd54/O1LZu62vH4JB/s=
|
||||
|
|
@ -443,7 +443,8 @@ github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqw
|
|||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
|
||||
|
|
@ -526,8 +527,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
|
||||
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
|
|
@ -748,14 +749,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
|
|||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=
|
||||
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
||||
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/open-policy-agent/opa v0.63.0 h1:ztNNste1v8kH0/vJMJNquE45lRvqwrM5mY9Ctr9xIXw=
|
||||
github.com/open-policy-agent/opa v0.63.0/go.mod h1:9VQPqEfoB2N//AToTxzZ1pVTVPUoF2Mhd64szzjWPpU=
|
||||
github.com/opencontainers/go-digest v1.0.1-0.20220411205349-bde1400a84be h1:f2PlhC9pm5sqpBZFvnAoKj+KzXRzbjFMA+TqXfJdgho=
|
||||
|
|
@ -1311,8 +1312,8 @@ oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY=
|
|||
oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324=
|
||||
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
|
||||
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
|
||||
sigs.k8s.io/controller-runtime v0.18.0 h1:Z7jKuX784TQSUL1TIyeuF7j8KXZ4RtSX0YgtjKcSTME=
|
||||
sigs.k8s.io/controller-runtime v0.18.0/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
|
||||
sigs.k8s.io/controller-runtime v0.18.1 h1:RpWbigmuiylbxOCLy0tGnq1cU1qWPwNIQzoJk+QeJx4=
|
||||
sigs.k8s.io/controller-runtime v0.18.1/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.17.1 h1:MYJBOP/yQ3/5tp4/sf6HiiMfNNyO97LmtnirH9SLNr4=
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
Copyright 2024 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ import (
|
|||
"github.com/fluxcd/pkg/tar"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/fluxcd/source-controller/internal/cache"
|
||||
serror "github.com/fluxcd/source-controller/internal/error"
|
||||
"github.com/fluxcd/source-controller/internal/helm/chart"
|
||||
|
|
@ -159,29 +159,29 @@ type HelmChartReconcilerOptions struct {
|
|||
RateLimiter ratelimiter.RateLimiter
|
||||
}
|
||||
|
||||
// helmChartReconcileFunc is the function type for all the v1beta2.HelmChart
|
||||
// helmChartReconcileFunc is the function type for all the v1.HelmChart
|
||||
// (sub)reconcile functions. The type implementations are grouped and
|
||||
// executed serially to perform the complete reconcile of the object.
|
||||
type helmChartReconcileFunc func(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmChart, build *chart.Build) (sreconcile.Result, error)
|
||||
type helmChartReconcileFunc func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error)
|
||||
|
||||
func (r *HelmChartReconciler) SetupWithManagerAndOptions(ctx context.Context, mgr ctrl.Manager, opts HelmChartReconcilerOptions) error {
|
||||
r.patchOptions = getPatchOptions(helmChartReadyCondition.Owned, r.ControllerName)
|
||||
|
||||
if err := mgr.GetCache().IndexField(ctx, &helmv1.HelmRepository{}, helmv1.HelmRepositoryURLIndexKey,
|
||||
if err := mgr.GetCache().IndexField(ctx, &sourcev1.HelmRepository{}, sourcev1.HelmRepositoryURLIndexKey,
|
||||
r.indexHelmRepositoryByURL); err != nil {
|
||||
return fmt.Errorf("failed setting index fields: %w", err)
|
||||
}
|
||||
if err := mgr.GetCache().IndexField(ctx, &helmv1.HelmChart{}, sourcev1.SourceIndexKey,
|
||||
if err := mgr.GetCache().IndexField(ctx, &sourcev1.HelmChart{}, sourcev1.SourceIndexKey,
|
||||
r.indexHelmChartBySource); err != nil {
|
||||
return fmt.Errorf("failed setting index fields: %w", err)
|
||||
}
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&helmv1.HelmChart{}, builder.WithPredicates(
|
||||
For(&sourcev1.HelmChart{}, builder.WithPredicates(
|
||||
predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}),
|
||||
)).
|
||||
Watches(
|
||||
&helmv1.HelmRepository{},
|
||||
&sourcev1.HelmRepository{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.requestsForHelmRepositoryChange),
|
||||
builder.WithPredicates(SourceRevisionChangePredicate{}),
|
||||
).
|
||||
|
|
@ -191,7 +191,7 @@ func (r *HelmChartReconciler) SetupWithManagerAndOptions(ctx context.Context, mg
|
|||
builder.WithPredicates(SourceRevisionChangePredicate{}),
|
||||
).
|
||||
Watches(
|
||||
&helmv1.Bucket{},
|
||||
&sourcev1beta2.Bucket{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.requestsForBucketChange),
|
||||
builder.WithPredicates(SourceRevisionChangePredicate{}),
|
||||
).
|
||||
|
|
@ -206,7 +206,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
|
|||
log := ctrl.LoggerFrom(ctx)
|
||||
|
||||
// Fetch the HelmChart
|
||||
obj := &helmv1.HelmChart{}
|
||||
obj := &sourcev1.HelmChart{}
|
||||
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
|
@ -280,7 +280,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
|
|||
// reconcile iterates through the helmChartReconcileFunc tasks for the
|
||||
// object. It returns early on the first call that returns
|
||||
// reconcile.ResultRequeue, or produces an error.
|
||||
func (r *HelmChartReconciler) reconcile(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmChart, reconcilers []helmChartReconcileFunc) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) reconcile(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, reconcilers []helmChartReconcileFunc) (sreconcile.Result, error) {
|
||||
oldObj := obj.DeepCopy()
|
||||
|
||||
rreconcile.ProgressiveStatus(false, obj, meta.ProgressingReason, "reconciliation in progress")
|
||||
|
|
@ -333,7 +333,7 @@ func (r *HelmChartReconciler) reconcile(ctx context.Context, sp *patch.SerialPat
|
|||
}
|
||||
|
||||
// notify emits notification related to the reconciliation.
|
||||
func (r *HelmChartReconciler) notify(ctx context.Context, oldObj, newObj *helmv1.HelmChart, build *chart.Build, res sreconcile.Result, resErr error) {
|
||||
func (r *HelmChartReconciler) notify(ctx context.Context, oldObj, newObj *sourcev1.HelmChart, build *chart.Build, res sreconcile.Result, resErr error) {
|
||||
// Notify successful reconciliation for new artifact and recovery from any
|
||||
// failure.
|
||||
if resErr == nil && res == sreconcile.ResultSuccess && newObj.Status.Artifact != nil {
|
||||
|
|
@ -369,7 +369,7 @@ func (r *HelmChartReconciler) notify(ctx context.Context, oldObj, newObj *helmv1
|
|||
// condition is added.
|
||||
// The hostname of any URL in the Status of the object are updated, to ensure
|
||||
// they match the Storage server hostname of current runtime.
|
||||
func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
|
||||
// Garbage collect previous advertised artifact(s) from storage
|
||||
_ = r.garbageCollect(ctx, obj)
|
||||
|
||||
|
|
@ -423,7 +423,7 @@ func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, sp *patch.Se
|
|||
return sreconcile.ResultSuccess, nil
|
||||
}
|
||||
|
||||
func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmChart, build *chart.Build) (_ sreconcile.Result, retErr error) {
|
||||
func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, build *chart.Build) (_ sreconcile.Result, retErr error) {
|
||||
// Remove any failed verification condition.
|
||||
// The reason is that a failing verification should be recalculated.
|
||||
if conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
|
||||
|
|
@ -453,7 +453,7 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.Ser
|
|||
// Assert source has an artifact
|
||||
if s.GetArtifact() == nil || !r.Storage.ArtifactExist(*s.GetArtifact()) {
|
||||
// Set the condition to indicate that the source has no artifact for all types except OCI HelmRepository
|
||||
if helmRepo, ok := s.(*helmv1.HelmRepository); !ok || helmRepo.Spec.Type != helmv1.HelmRepositoryTypeOCI {
|
||||
if helmRepo, ok := s.(*sourcev1.HelmRepository); !ok || helmRepo.Spec.Type != sourcev1.HelmRepositoryTypeOCI {
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, "NoSourceArtifact",
|
||||
"no artifact available for %s source '%s'", obj.Spec.SourceRef.Kind, obj.Spec.SourceRef.Name)
|
||||
r.eventLogf(ctx, obj, eventv1.EventTypeTrace, "NoSourceArtifact",
|
||||
|
|
@ -500,9 +500,9 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.Ser
|
|||
|
||||
// Perform the build for the chart source type
|
||||
switch typedSource := s.(type) {
|
||||
case *helmv1.HelmRepository:
|
||||
case *sourcev1.HelmRepository:
|
||||
return r.buildFromHelmRepository(ctx, obj, typedSource, build)
|
||||
case *sourcev1.GitRepository, *helmv1.Bucket:
|
||||
case *sourcev1.GitRepository, *sourcev1beta2.Bucket:
|
||||
return r.buildFromTarballArtifact(ctx, obj, *typedSource.GetArtifact(), build)
|
||||
default:
|
||||
// Ending up here should generally not be possible
|
||||
|
|
@ -512,12 +512,12 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.Ser
|
|||
}
|
||||
|
||||
// buildFromHelmRepository attempts to pull and/or package a Helm chart with
|
||||
// the specified data from the v1beta2.HelmRepository and v1beta2.HelmChart
|
||||
// the specified data from the v1.HelmRepository and v1.HelmChart
|
||||
// objects.
|
||||
// In case of a failure it records v1beta2.FetchFailedCondition on the chart
|
||||
// In case of a failure it records v1.FetchFailedCondition on the chart
|
||||
// object, and returns early.
|
||||
func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *helmv1.HelmChart,
|
||||
repo *helmv1.HelmRepository, b *chart.Build) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *sourcev1.HelmChart,
|
||||
repo *sourcev1.HelmRepository, b *chart.Build) (sreconcile.Result, error) {
|
||||
// Used to login with the repository declared provider
|
||||
ctxTimeout, cancel := context.WithTimeout(ctx, repo.GetTimeout())
|
||||
defer cancel()
|
||||
|
|
@ -550,7 +550,7 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
|
|||
// Initialize the chart repository
|
||||
var chartRepo repository.Downloader
|
||||
switch repo.Spec.Type {
|
||||
case helmv1.HelmRepositoryTypeOCI:
|
||||
case sourcev1.HelmRepositoryTypeOCI:
|
||||
if !helmreg.IsOCI(normalizedURL) {
|
||||
err := fmt.Errorf("invalid OCI registry URL: %s", normalizedURL)
|
||||
return chartRepoConfigErrorReturn(err, obj)
|
||||
|
|
@ -696,11 +696,11 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
|
|||
}
|
||||
|
||||
// buildFromTarballArtifact attempts to pull and/or package a Helm chart with
|
||||
// the specified data from the v1beta2.HelmChart object and the given
|
||||
// v1beta2.Artifact.
|
||||
// In case of a failure it records v1beta2.FetchFailedCondition on the chart
|
||||
// the specified data from the v1.HelmChart object and the given
|
||||
// v1.Artifact.
|
||||
// In case of a failure it records v1.FetchFailedCondition on the chart
|
||||
// object, and returns early.
|
||||
func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj *helmv1.HelmChart, source sourcev1.Artifact, b *chart.Build) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj *sourcev1.HelmChart, source sourcev1.Artifact, b *chart.Build) (sreconcile.Result, error) {
|
||||
// Create temporary working directory
|
||||
tmpDir, err := util.TempDirForObj("", obj)
|
||||
if err != nil {
|
||||
|
|
@ -772,17 +772,17 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
|
|||
}
|
||||
|
||||
// Configure revision metadata for chart build if we should react to revision changes
|
||||
if obj.Spec.ReconcileStrategy == helmv1.ReconcileStrategyRevision {
|
||||
if obj.Spec.ReconcileStrategy == sourcev1.ReconcileStrategyRevision {
|
||||
rev := source.Revision
|
||||
if obj.Spec.SourceRef.Kind == sourcev1.GitRepositoryKind {
|
||||
rev = git.ExtractHashFromRevision(rev).String()
|
||||
}
|
||||
if obj.Spec.SourceRef.Kind == helmv1.BucketKind {
|
||||
if obj.Spec.SourceRef.Kind == sourcev1beta2.BucketKind {
|
||||
if dig := digest.Digest(rev); dig.Validate() == nil {
|
||||
rev = dig.Encoded()
|
||||
}
|
||||
}
|
||||
if kind := obj.Spec.SourceRef.Kind; kind == sourcev1.GitRepositoryKind || kind == helmv1.BucketKind {
|
||||
if kind := obj.Spec.SourceRef.Kind; kind == sourcev1.GitRepositoryKind || kind == sourcev1beta2.BucketKind {
|
||||
// The SemVer from the metadata is at times used in e.g. the label metadata for a resource
|
||||
// in a chart, which has a limited length of 63 characters.
|
||||
// To not fill most of this space with a full length SHA hex (40 characters for SHA-1, and
|
||||
|
|
@ -824,12 +824,12 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
|
|||
// (Status) data on the object does not match the given.
|
||||
//
|
||||
// The inspection of the given data to the object is differed, ensuring any
|
||||
// stale observations like v1beta2.ArtifactOutdatedCondition are removed.
|
||||
// stale observations like v1.ArtifactOutdatedCondition are removed.
|
||||
// If the given Artifact does not differ from the object's current, it returns
|
||||
// early.
|
||||
// On a successful archive, the Artifact in the Status of the object is set,
|
||||
// and the symlink in the Storage is updated to its path.
|
||||
func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, _ *patch.SerialPatcher, obj *helmv1.HelmChart, b *chart.Build) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, _ *patch.SerialPatcher, obj *sourcev1.HelmChart, b *chart.Build) (sreconcile.Result, error) {
|
||||
// Without a complete chart build, there is little to reconcile
|
||||
if !b.Complete() {
|
||||
return sreconcile.ResultRequeue, nil
|
||||
|
|
@ -909,15 +909,15 @@ func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, _ *patch.Se
|
|||
|
||||
// getSource returns the v1beta1.Source for the given object, or an error describing why the source could not be
|
||||
// returned.
|
||||
func (r *HelmChartReconciler) getSource(ctx context.Context, obj *helmv1.HelmChart) (sourcev1.Source, error) {
|
||||
func (r *HelmChartReconciler) getSource(ctx context.Context, obj *sourcev1.HelmChart) (sourcev1.Source, error) {
|
||||
namespacedName := types.NamespacedName{
|
||||
Namespace: obj.GetNamespace(),
|
||||
Name: obj.Spec.SourceRef.Name,
|
||||
}
|
||||
var s sourcev1.Source
|
||||
switch obj.Spec.SourceRef.Kind {
|
||||
case helmv1.HelmRepositoryKind:
|
||||
var repo helmv1.HelmRepository
|
||||
case sourcev1.HelmRepositoryKind:
|
||||
var repo sourcev1.HelmRepository
|
||||
if err := r.Client.Get(ctx, namespacedName, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -928,15 +928,15 @@ func (r *HelmChartReconciler) getSource(ctx context.Context, obj *helmv1.HelmCha
|
|||
return nil, err
|
||||
}
|
||||
s = &repo
|
||||
case helmv1.BucketKind:
|
||||
var bucket helmv1.Bucket
|
||||
case sourcev1beta2.BucketKind:
|
||||
var bucket sourcev1beta2.Bucket
|
||||
if err := r.Client.Get(ctx, namespacedName, &bucket); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s = &bucket
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported source kind '%s', must be one of: %v", obj.Spec.SourceRef.Kind, []string{
|
||||
helmv1.HelmRepositoryKind, sourcev1.GitRepositoryKind, helmv1.BucketKind})
|
||||
sourcev1.HelmRepositoryKind, sourcev1.GitRepositoryKind, sourcev1beta2.BucketKind})
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
|
@ -944,7 +944,7 @@ func (r *HelmChartReconciler) getSource(ctx context.Context, obj *helmv1.HelmCha
|
|||
// reconcileDelete handles the deletion of the object.
|
||||
// It first garbage collects all Artifacts for the object from the Storage.
|
||||
// Removing the finalizer from the object if successful.
|
||||
func (r *HelmChartReconciler) reconcileDelete(ctx context.Context, obj *helmv1.HelmChart) (sreconcile.Result, error) {
|
||||
func (r *HelmChartReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.HelmChart) (sreconcile.Result, error) {
|
||||
// Garbage collect the resource's artifacts
|
||||
if err := r.garbageCollect(ctx, obj); err != nil {
|
||||
// Return the error so we retry the failed garbage collection
|
||||
|
|
@ -963,7 +963,7 @@ func (r *HelmChartReconciler) reconcileDelete(ctx context.Context, obj *helmv1.H
|
|||
// It removes all but the current Artifact from the Storage, unless the
|
||||
// deletion timestamp on the object is set. Which will result in the
|
||||
// removal of all Artifacts for the objects.
|
||||
func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *helmv1.HelmChart) error {
|
||||
func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *sourcev1.HelmChart) error {
|
||||
if !obj.DeletionTimestamp.IsZero() {
|
||||
if deleted, err := r.Storage.RemoveAll(r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), "", "*")); err != nil {
|
||||
return serror.NewGeneric(
|
||||
|
|
@ -1010,8 +1010,8 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
|
|||
if apierrs.ReasonForError(err) != metav1.StatusReasonUnknown {
|
||||
return nil, err
|
||||
}
|
||||
obj = &helmv1.HelmRepository{
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
obj = &sourcev1.HelmRepository{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
URL: url,
|
||||
Timeout: &metav1.Duration{Duration: 60 * time.Second},
|
||||
},
|
||||
|
|
@ -1099,13 +1099,13 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
|
|||
}
|
||||
}
|
||||
|
||||
func (r *HelmChartReconciler) resolveDependencyRepository(ctx context.Context, url string, namespace string) (*helmv1.HelmRepository, error) {
|
||||
func (r *HelmChartReconciler) resolveDependencyRepository(ctx context.Context, url string, namespace string) (*sourcev1.HelmRepository, error) {
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(namespace),
|
||||
client.MatchingFields{helmv1.HelmRepositoryURLIndexKey: url},
|
||||
client.MatchingFields{sourcev1.HelmRepositoryURLIndexKey: url},
|
||||
client.Limit(1),
|
||||
}
|
||||
var list helmv1.HelmRepositoryList
|
||||
var list sourcev1.HelmRepositoryList
|
||||
err := r.Client.List(ctx, &list, listOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to retrieve HelmRepositoryList: %w", err)
|
||||
|
|
@ -1117,7 +1117,7 @@ func (r *HelmChartReconciler) resolveDependencyRepository(ctx context.Context, u
|
|||
}
|
||||
|
||||
func (r *HelmChartReconciler) indexHelmRepositoryByURL(o client.Object) []string {
|
||||
repo, ok := o.(*helmv1.HelmRepository)
|
||||
repo, ok := o.(*sourcev1.HelmRepository)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Expected a HelmRepository, got %T", o))
|
||||
}
|
||||
|
|
@ -1129,7 +1129,7 @@ func (r *HelmChartReconciler) indexHelmRepositoryByURL(o client.Object) []string
|
|||
}
|
||||
|
||||
func (r *HelmChartReconciler) indexHelmChartBySource(o client.Object) []string {
|
||||
hc, ok := o.(*helmv1.HelmChart)
|
||||
hc, ok := o.(*sourcev1.HelmChart)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Expected a HelmChart, got %T", o))
|
||||
}
|
||||
|
|
@ -1137,7 +1137,7 @@ func (r *HelmChartReconciler) indexHelmChartBySource(o client.Object) []string {
|
|||
}
|
||||
|
||||
func (r *HelmChartReconciler) requestsForHelmRepositoryChange(ctx context.Context, o client.Object) []reconcile.Request {
|
||||
repo, ok := o.(*helmv1.HelmRepository)
|
||||
repo, ok := o.(*sourcev1.HelmRepository)
|
||||
if !ok {
|
||||
ctrl.LoggerFrom(ctx).Error(fmt.Errorf("expected a HelmRepository, got %T", o), "failed to get requests for HelmRepository change")
|
||||
return nil
|
||||
|
|
@ -1148,9 +1148,9 @@ func (r *HelmChartReconciler) requestsForHelmRepositoryChange(ctx context.Contex
|
|||
return nil
|
||||
}
|
||||
|
||||
var list helmv1.HelmChartList
|
||||
var list sourcev1.HelmChartList
|
||||
if err := r.List(ctx, &list, client.MatchingFields{
|
||||
sourcev1.SourceIndexKey: fmt.Sprintf("%s/%s", helmv1.HelmRepositoryKind, repo.Name),
|
||||
sourcev1.SourceIndexKey: fmt.Sprintf("%s/%s", sourcev1.HelmRepositoryKind, repo.Name),
|
||||
}); err != nil {
|
||||
ctrl.LoggerFrom(ctx).Error(err, "failed to list HelmCharts for HelmRepository change")
|
||||
return nil
|
||||
|
|
@ -1178,7 +1178,7 @@ func (r *HelmChartReconciler) requestsForGitRepositoryChange(ctx context.Context
|
|||
return nil
|
||||
}
|
||||
|
||||
var list helmv1.HelmChartList
|
||||
var list sourcev1.HelmChartList
|
||||
if err := r.List(ctx, &list, client.MatchingFields{
|
||||
sourcev1.SourceIndexKey: fmt.Sprintf("%s/%s", sourcev1.GitRepositoryKind, repo.Name),
|
||||
}); err != nil {
|
||||
|
|
@ -1196,7 +1196,7 @@ func (r *HelmChartReconciler) requestsForGitRepositoryChange(ctx context.Context
|
|||
}
|
||||
|
||||
func (r *HelmChartReconciler) requestsForBucketChange(ctx context.Context, o client.Object) []reconcile.Request {
|
||||
bucket, ok := o.(*helmv1.Bucket)
|
||||
bucket, ok := o.(*sourcev1beta2.Bucket)
|
||||
if !ok {
|
||||
ctrl.LoggerFrom(ctx).Error(fmt.Errorf("expected a Bucket, got %T", o),
|
||||
"failed to get reconcile requests for Bucket change")
|
||||
|
|
@ -1208,9 +1208,9 @@ func (r *HelmChartReconciler) requestsForBucketChange(ctx context.Context, o cli
|
|||
return nil
|
||||
}
|
||||
|
||||
var list helmv1.HelmChartList
|
||||
var list sourcev1.HelmChartList
|
||||
if err := r.List(ctx, &list, client.MatchingFields{
|
||||
sourcev1.SourceIndexKey: fmt.Sprintf("%s/%s", helmv1.BucketKind, bucket.Name),
|
||||
sourcev1.SourceIndexKey: fmt.Sprintf("%s/%s", sourcev1beta2.BucketKind, bucket.Name),
|
||||
}); err != nil {
|
||||
ctrl.LoggerFrom(ctx).Error(err, "failed to list HelmCharts for Bucket change")
|
||||
return nil
|
||||
|
|
@ -1242,7 +1242,7 @@ func (r *HelmChartReconciler) eventLogf(ctx context.Context, obj runtime.Object,
|
|||
}
|
||||
|
||||
// observeChartBuild records the observation on the given given build and error on the object.
|
||||
func observeChartBuild(ctx context.Context, sp *patch.SerialPatcher, pOpts []patch.Option, obj *helmv1.HelmChart, build *chart.Build, err error) {
|
||||
func observeChartBuild(ctx context.Context, sp *patch.SerialPatcher, pOpts []patch.Option, obj *sourcev1.HelmChart, build *chart.Build, err error) {
|
||||
if build.HasMetadata() {
|
||||
if build.Name != obj.Status.ObservedChartName || !obj.GetArtifact().HasRevision(build.Version) {
|
||||
if obj.GetArtifact() != nil {
|
||||
|
|
@ -1297,12 +1297,12 @@ func reasonForBuild(build *chart.Build) string {
|
|||
return ""
|
||||
}
|
||||
if build.Packaged {
|
||||
return helmv1.ChartPackageSucceededReason
|
||||
return sourcev1.ChartPackageSucceededReason
|
||||
}
|
||||
return helmv1.ChartPullSucceededReason
|
||||
return sourcev1.ChartPullSucceededReason
|
||||
}
|
||||
|
||||
func chartRepoConfigErrorReturn(err error, obj *helmv1.HelmChart) (sreconcile.Result, error) {
|
||||
func chartRepoConfigErrorReturn(err error, obj *sourcev1.HelmChart) (sreconcile.Result, error) {
|
||||
switch err.(type) {
|
||||
case *url.Error:
|
||||
e := serror.NewStalling(
|
||||
|
|
@ -1322,7 +1322,7 @@ func chartRepoConfigErrorReturn(err error, obj *helmv1.HelmChart) (sreconcile.Re
|
|||
}
|
||||
|
||||
// makeVerifiers returns a list of verifiers for the given chart.
|
||||
func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *helmv1.HelmChart, clientOpts getter.ClientOpts) ([]soci.Verifier, error) {
|
||||
func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *sourcev1.HelmChart, clientOpts getter.ClientOpts) ([]soci.Verifier, error) {
|
||||
var verifiers []soci.Verifier
|
||||
verifyOpts := []remote.Option{}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -49,7 +49,6 @@ import (
|
|||
rreconcile "github.com/fluxcd/pkg/runtime/reconcile"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/fluxcd/source-controller/internal/cache"
|
||||
intdigest "github.com/fluxcd/source-controller/internal/digest"
|
||||
serror "github.com/fluxcd/source-controller/internal/error"
|
||||
|
|
@ -61,7 +60,7 @@ import (
|
|||
)
|
||||
|
||||
// helmRepositoryReadyCondition contains the information required to summarize a
|
||||
// v1beta2.HelmRepository Ready Condition.
|
||||
// v1.HelmRepository Ready Condition.
|
||||
var helmRepositoryReadyCondition = summarize.Conditions{
|
||||
Target: meta.ReadyCondition,
|
||||
Owned: []string{
|
||||
|
|
@ -102,7 +101,7 @@ var helmRepositoryFailConditions = []string{
|
|||
// +kubebuilder:rbac:groups=source.toolkit.fluxcd.io,resources=helmrepositories/finalizers,verbs=get;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
|
||||
|
||||
// HelmRepositoryReconciler reconciles a v1beta2.HelmRepository object.
|
||||
// HelmRepositoryReconciler reconciles a v1.HelmRepository object.
|
||||
type HelmRepositoryReconciler struct {
|
||||
client.Client
|
||||
kuberecorder.EventRecorder
|
||||
|
|
@ -124,10 +123,10 @@ type HelmRepositoryReconcilerOptions struct {
|
|||
}
|
||||
|
||||
// helmRepositoryReconcileFunc is the function type for all the
|
||||
// v1beta2.HelmRepository (sub)reconcile functions. The type implementations
|
||||
// v1.HelmRepository (sub)reconcile functions. The type implementations
|
||||
// are grouped and executed serially to perform the complete reconcile of the
|
||||
// object.
|
||||
type helmRepositoryReconcileFunc func(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error)
|
||||
type helmRepositoryReconcileFunc func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error)
|
||||
|
||||
func (r *HelmRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return r.SetupWithManagerAndOptions(mgr, HelmRepositoryReconcilerOptions{})
|
||||
|
|
@ -137,7 +136,7 @@ func (r *HelmRepositoryReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager,
|
|||
r.patchOptions = getPatchOptions(helmRepositoryReadyCondition.Owned, r.ControllerName)
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&helmv1.HelmRepository{}).
|
||||
For(&sourcev1.HelmRepository{}).
|
||||
WithEventFilter(
|
||||
predicate.And(
|
||||
intpredicates.HelmRepositoryOCIMigrationPredicate{},
|
||||
|
|
@ -155,7 +154,7 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
|||
log := ctrl.LoggerFrom(ctx)
|
||||
|
||||
// Fetch the HelmRepository
|
||||
obj := &helmv1.HelmRepository{}
|
||||
obj := &sourcev1.HelmRepository{}
|
||||
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
|
@ -164,7 +163,7 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
|||
serialPatcher := patch.NewSerialPatcher(obj, r.Client)
|
||||
|
||||
// If it's of type OCI, migrate the object to static.
|
||||
if obj.Spec.Type == helmv1.HelmRepositoryTypeOCI {
|
||||
if obj.Spec.Type == sourcev1.HelmRepositoryTypeOCI {
|
||||
return r.migrationToStatic(ctx, serialPatcher, obj)
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +233,7 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
|||
// object. It returns early on the first call that returns
|
||||
// reconcile.ResultRequeue, or produces an error.
|
||||
func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, sp *patch.SerialPatcher,
|
||||
obj *helmv1.HelmRepository, reconcilers []helmRepositoryReconcileFunc) (sreconcile.Result, error) {
|
||||
obj *sourcev1.HelmRepository, reconcilers []helmRepositoryReconcileFunc) (sreconcile.Result, error) {
|
||||
oldObj := obj.DeepCopy()
|
||||
|
||||
rreconcile.ProgressiveStatus(false, obj, meta.ProgressingReason, "reconciliation in progress")
|
||||
|
|
@ -287,7 +286,7 @@ func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, sp *patch.Seri
|
|||
}
|
||||
|
||||
// notify emits notification related to the reconciliation.
|
||||
func (r *HelmRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *helmv1.HelmRepository, chartRepo *repository.ChartRepository, res sreconcile.Result, resErr error) {
|
||||
func (r *HelmRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *sourcev1.HelmRepository, chartRepo *repository.ChartRepository, res sreconcile.Result, resErr error) {
|
||||
// Notify successful reconciliation for new artifact and recovery from any
|
||||
// failure.
|
||||
if resErr == nil && res == sreconcile.ResultSuccess && newObj.Status.Artifact != nil {
|
||||
|
|
@ -331,7 +330,7 @@ func (r *HelmRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *h
|
|||
// The hostname of any URL in the Status of the object are updated, to ensure
|
||||
// they match the Storage server hostname of current runtime.
|
||||
func (r *HelmRepositoryReconciler) reconcileStorage(ctx context.Context, sp *patch.SerialPatcher,
|
||||
obj *helmv1.HelmRepository, _ *sourcev1.Artifact, _ *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
obj *sourcev1.HelmRepository, _ *sourcev1.Artifact, _ *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
// Garbage collect previous advertised artifact(s) from storage
|
||||
_ = r.garbageCollect(ctx, obj)
|
||||
|
||||
|
|
@ -386,15 +385,15 @@ func (r *HelmRepositoryReconciler) reconcileStorage(ctx context.Context, sp *pat
|
|||
}
|
||||
|
||||
// reconcileSource attempts to fetch the Helm repository index using the
|
||||
// specified configuration on the v1beta2.HelmRepository object.
|
||||
// specified configuration on the v1.HelmRepository object.
|
||||
//
|
||||
// When the fetch fails, it records v1beta2.FetchFailedCondition=True and
|
||||
// When the fetch fails, it records v1.FetchFailedCondition=True and
|
||||
// returns early.
|
||||
// If successful and the index is valid, any previous
|
||||
// v1beta2.FetchFailedCondition is removed, and the repository.ChartRepository
|
||||
// v1.FetchFailedCondition is removed, and the repository.ChartRepository
|
||||
// pointer is set to the newly fetched index.
|
||||
func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch.SerialPatcher,
|
||||
obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, chartRepo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, chartRepo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
// Ensure it's not an OCI URL. API validation ensures that only
|
||||
// http/https/oci scheme are allowed.
|
||||
if strings.HasPrefix(obj.Spec.URL, helmreg.OCIScheme) {
|
||||
|
|
@ -483,7 +482,7 @@ func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, sp *patc
|
|||
if err := chartRepo.LoadFromPath(); err != nil {
|
||||
e := serror.NewGeneric(
|
||||
fmt.Errorf("failed to load Helm repository from index YAML: %w", err),
|
||||
helmv1.IndexationFailedReason,
|
||||
sourcev1.IndexationFailedReason,
|
||||
)
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
|
||||
return sreconcile.ResultEmpty, e
|
||||
|
|
@ -496,7 +495,7 @@ func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, sp *patc
|
|||
if revision.Validate() != nil {
|
||||
e := serror.NewGeneric(
|
||||
fmt.Errorf("failed to calculate revision: %w", err),
|
||||
helmv1.IndexationFailedReason,
|
||||
sourcev1.IndexationFailedReason,
|
||||
)
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Err.Error())
|
||||
return sreconcile.ResultEmpty, e
|
||||
|
|
@ -526,12 +525,12 @@ func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, sp *patc
|
|||
// (Status) data on the object does not match the given.
|
||||
//
|
||||
// The inspection of the given data to the object is differed, ensuring any
|
||||
// stale observations like v1beta2.ArtifactOutdatedCondition are removed.
|
||||
// stale observations like v1.ArtifactOutdatedCondition are removed.
|
||||
// If the given Artifact does not differ from the object's current, it returns
|
||||
// early.
|
||||
// On a successful archive, the Artifact in the Status of the object is set,
|
||||
// and the symlink in the Storage is updated to its path.
|
||||
func (r *HelmRepositoryReconciler) reconcileArtifact(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, chartRepo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
func (r *HelmRepositoryReconciler) reconcileArtifact(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, chartRepo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
// Set the ArtifactInStorageCondition if there's no drift.
|
||||
defer func() {
|
||||
if obj.GetArtifact().HasRevision(artifact.Revision) {
|
||||
|
|
@ -623,7 +622,7 @@ func (r *HelmRepositoryReconciler) reconcileArtifact(ctx context.Context, sp *pa
|
|||
// reconcileDelete handles the deletion of the object.
|
||||
// It first garbage collects all Artifacts for the object from the Storage.
|
||||
// Removing the finalizer from the object if successful.
|
||||
func (r *HelmRepositoryReconciler) reconcileDelete(ctx context.Context, obj *helmv1.HelmRepository) (sreconcile.Result, error) {
|
||||
func (r *HelmRepositoryReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.HelmRepository) (sreconcile.Result, error) {
|
||||
// Garbage collect the resource's artifacts
|
||||
if err := r.garbageCollect(ctx, obj); err != nil {
|
||||
// Return the error so we retry the failed garbage collection
|
||||
|
|
@ -651,8 +650,8 @@ func (r *HelmRepositoryReconciler) reconcileDelete(ctx context.Context, obj *hel
|
|||
// - the deletion timestamp on the object is set
|
||||
// - the obj.Spec.Type has changed and artifacts are not supported by the new type
|
||||
// Which will result in the removal of all Artifacts for the objects.
|
||||
func (r *HelmRepositoryReconciler) garbageCollect(ctx context.Context, obj *helmv1.HelmRepository) error {
|
||||
if !obj.DeletionTimestamp.IsZero() || (obj.Spec.Type != "" && obj.Spec.Type != helmv1.HelmRepositoryTypeDefault) {
|
||||
func (r *HelmRepositoryReconciler) garbageCollect(ctx context.Context, obj *sourcev1.HelmRepository) error {
|
||||
if !obj.DeletionTimestamp.IsZero() || (obj.Spec.Type != "" && obj.Spec.Type != sourcev1.HelmRepositoryTypeDefault) {
|
||||
if deleted, err := r.Storage.RemoveAll(r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), "", "*")); err != nil {
|
||||
return serror.NewGeneric(
|
||||
fmt.Errorf("garbage collection for deleted resource failed: %w", err),
|
||||
|
|
@ -703,7 +702,7 @@ func (r *HelmRepositoryReconciler) eventLogf(ctx context.Context, obj runtime.Ob
|
|||
}
|
||||
|
||||
// migrateToStatic is HelmRepository OCI migration to static object.
|
||||
func (r *HelmRepositoryReconciler) migrationToStatic(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository) (result ctrl.Result, err error) {
|
||||
func (r *HelmRepositoryReconciler) migrationToStatic(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository) (result ctrl.Result, err error) {
|
||||
// Skip migration if suspended and not being deleted.
|
||||
if obj.Spec.Suspend && obj.DeletionTimestamp.IsZero() {
|
||||
return ctrl.Result{}, nil
|
||||
|
|
@ -721,7 +720,7 @@ func (r *HelmRepositoryReconciler) migrationToStatic(ctx context.Context, sp *pa
|
|||
}
|
||||
// Delete finalizer and reset the status.
|
||||
controllerutil.RemoveFinalizer(obj, sourcev1.SourceFinalizer)
|
||||
obj.Status = helmv1.HelmRepositoryStatus{}
|
||||
obj.Status = sourcev1.HelmRepositoryStatus{}
|
||||
|
||||
if err := sp.Patch(ctx, obj); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import (
|
|||
"github.com/fluxcd/pkg/runtime/patch"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/fluxcd/source-controller/internal/cache"
|
||||
intdigest "github.com/fluxcd/source-controller/internal/digest"
|
||||
"github.com/fluxcd/source-controller/internal/helm/getter"
|
||||
|
|
@ -73,10 +72,10 @@ func TestHelmRepositoryReconciler_deleteBeforeFinalizer(t *testing.T) {
|
|||
g.Expect(k8sClient.Delete(ctx, namespace)).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
helmrepo := &helmv1.HelmRepository{}
|
||||
helmrepo := &sourcev1.HelmRepository{}
|
||||
helmrepo.Name = "test-helmrepo"
|
||||
helmrepo.Namespace = namespaceName
|
||||
helmrepo.Spec = helmv1.HelmRepositorySpec{
|
||||
helmrepo.Spec = sourcev1.HelmRepositorySpec{
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
URL: "https://example.com",
|
||||
}
|
||||
|
|
@ -109,12 +108,12 @@ func TestHelmRepositoryReconciler_Reconcile(t *testing.T) {
|
|||
testServer.Start()
|
||||
defer testServer.Stop()
|
||||
|
||||
origObj := &helmv1.HelmRepository{
|
||||
origObj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "helmrepository-reconcile-",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
URL: testServer.URL(),
|
||||
},
|
||||
|
|
@ -175,7 +174,7 @@ func TestHelmRepositoryReconciler_Reconcile(t *testing.T) {
|
|||
func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
beforeFunc func(obj *helmv1.HelmRepository, storage *Storage) error
|
||||
beforeFunc func(obj *sourcev1.HelmRepository, storage *Storage) error
|
||||
want sreconcile.Result
|
||||
wantErr bool
|
||||
assertArtifact *sourcev1.Artifact
|
||||
|
|
@ -184,7 +183,7 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "garbage collects",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository, storage *Storage) error {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository, storage *Storage) error {
|
||||
revisions := []string{"a", "b", "c", "d"}
|
||||
for n := range revisions {
|
||||
v := revisions[n]
|
||||
|
|
@ -234,7 +233,7 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "notices missing artifact in storage",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository, storage *Storage) error {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository, storage *Storage) error {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
Path: "/reconcile-storage/invalid.txt",
|
||||
Revision: "d",
|
||||
|
|
@ -253,7 +252,7 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "notices empty artifact digest",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository, storage *Storage) error {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository, storage *Storage) error {
|
||||
f := "empty-digest.txt"
|
||||
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
|
|
@ -284,7 +283,7 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "notices artifact digest mismatch",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository, storage *Storage) error {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository, storage *Storage) error {
|
||||
f := "digest-mismatch.txt"
|
||||
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
|
|
@ -315,7 +314,7 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "updates hostname on diff from current",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository, storage *Storage) error {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository, storage *Storage) error {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
Path: "/reconcile-storage/hostname.txt",
|
||||
Revision: "f",
|
||||
|
|
@ -354,14 +353,14 @@ func TestHelmRepositoryReconciler_reconcileStorage(t *testing.T) {
|
|||
r := &HelmRepositoryReconciler{
|
||||
Client: fakeclient.NewClientBuilder().
|
||||
WithScheme(testEnv.GetScheme()).
|
||||
WithStatusSubresource(&helmv1.HelmRepository{}).
|
||||
WithStatusSubresource(&sourcev1.HelmRepository{}).
|
||||
Build(),
|
||||
EventRecorder: record.NewFakeRecorder(32),
|
||||
Storage: testStorage,
|
||||
patchOptions: getPatchOptions(helmRepositoryReadyCondition.Owned, "sc"),
|
||||
}
|
||||
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "test-",
|
||||
Generation: 1,
|
||||
|
|
@ -421,8 +420,8 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
server options
|
||||
url string
|
||||
secret *corev1.Secret
|
||||
beforeFunc func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest)
|
||||
afterFunc func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository)
|
||||
beforeFunc func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest)
|
||||
afterFunc func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository)
|
||||
want sreconcile.Result
|
||||
wantErr bool
|
||||
assertConditions []metav1.Condition
|
||||
|
|
@ -440,7 +439,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"ca.crt": tlsCA,
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.CertSecretRef = &meta.LocalObjectReference{Name: "ca-file"}
|
||||
},
|
||||
assertConditions: []metav1.Condition{
|
||||
|
|
@ -464,7 +463,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"ca.crt": tlsCA,
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.CertSecretRef = &meta.LocalObjectReference{Name: "ca-file"}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -472,7 +471,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -494,7 +493,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"caFile": tlsCA,
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "ca-file"}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -502,7 +501,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -526,7 +525,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
},
|
||||
Type: corev1.SecretTypeDockerConfigJson,
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "ca-file"}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -534,7 +533,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -548,7 +547,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -570,7 +569,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"password": []byte("1234"),
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "basic-auth"}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -578,7 +577,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -602,7 +601,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
},
|
||||
Type: corev1.SecretTypeDockerConfigJson,
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "basic-auth"}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -610,7 +609,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
t.Expect(artifact.Revision).ToNot(BeEmpty())
|
||||
|
|
@ -632,7 +631,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"ca.crt": []byte("invalid"),
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.CertSecretRef = &meta.LocalObjectReference{Name: "invalid-ca"}
|
||||
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
|
||||
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
|
||||
|
|
@ -643,7 +642,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
// No repo index due to fetch fail.
|
||||
t.Expect(chartRepo.Path).To(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
|
@ -653,7 +652,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Invalid URL makes FetchFailed=True and returns stalling error",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.URL = strings.ReplaceAll(obj.Spec.URL, "http://", "")
|
||||
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
|
||||
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
|
||||
|
|
@ -665,7 +664,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
// No repo index due to fetch fail.
|
||||
t.Expect(chartRepo.Path).To(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
|
@ -675,7 +674,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Unsupported scheme makes FetchFailed=True and returns stalling error",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.URL = strings.ReplaceAll(obj.Spec.URL, "http://", "ftp://")
|
||||
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
|
||||
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
|
||||
|
|
@ -687,7 +686,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
// No repo index due to fetch fail.
|
||||
t.Expect(chartRepo.Path).To(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
|
@ -697,7 +696,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Missing secret returns FetchFailed=True and returns error",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "non-existing"}
|
||||
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
|
||||
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
|
||||
|
|
@ -708,7 +707,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
// No repo index due to fetch fail.
|
||||
t.Expect(chartRepo.Path).To(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
|
@ -726,7 +725,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
"username": []byte("git"),
|
||||
},
|
||||
},
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{Name: "malformed-basic-auth"}
|
||||
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
|
||||
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
|
||||
|
|
@ -737,7 +736,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
// No repo index due to fetch fail.
|
||||
t.Expect(chartRepo.Path).To(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
|
@ -747,7 +746,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Stored index with same revision",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
Revision: rev.String(),
|
||||
}
|
||||
|
|
@ -760,7 +759,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).To(BeNil())
|
||||
|
||||
|
|
@ -771,7 +770,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Stored index with different revision",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
Revision: "80bb3dd67c63095d985850459834ea727603727a370079de90d221191d375a86",
|
||||
}
|
||||
|
|
@ -784,7 +783,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new index revision"),
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, chartRepo *repository.ChartRepository) {
|
||||
t.Expect(chartRepo.Path).ToNot(BeEmpty())
|
||||
t.Expect(chartRepo.Index).ToNot(BeNil())
|
||||
|
||||
|
|
@ -796,7 +795,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
{
|
||||
name: "Existing artifact makes ArtifactOutdated=True",
|
||||
protocol: "http",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, rev digest.Digest) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, rev digest.Digest) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{
|
||||
Path: "some-path",
|
||||
Revision: "some-rev",
|
||||
|
|
@ -812,12 +811,12 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "auth-strategy-",
|
||||
Generation: 1,
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
Timeout: &metav1.Duration{Duration: timeout},
|
||||
},
|
||||
|
|
@ -868,7 +867,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
|
|||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(testEnv.GetScheme()).
|
||||
WithStatusSubresource(&helmv1.HelmRepository{})
|
||||
WithStatusSubresource(&sourcev1.HelmRepository{})
|
||||
|
||||
if secret != nil {
|
||||
clientBuilder.WithObjects(secret.DeepCopy())
|
||||
|
|
@ -960,19 +959,19 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
cache *cache.Cache
|
||||
beforeFunc func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository)
|
||||
afterFunc func(t *WithT, obj *helmv1.HelmRepository, cache *cache.Cache)
|
||||
beforeFunc func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository)
|
||||
afterFunc func(t *WithT, obj *sourcev1.HelmRepository, cache *cache.Cache)
|
||||
want sreconcile.Result
|
||||
wantErr bool
|
||||
assertConditions []metav1.Condition
|
||||
}{
|
||||
{
|
||||
name: "Archiving artifact to storage makes ArtifactInStorage=True and artifact is stored as JSON",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
obj.Spec.Interval = metav1.Duration{Duration: interval}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, cache *cache.Cache) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, cache *cache.Cache) {
|
||||
localPath := testStorage.LocalPath(*obj.GetArtifact())
|
||||
b, err := os.ReadFile(localPath)
|
||||
t.Expect(err).To(Not(HaveOccurred()))
|
||||
|
|
@ -985,7 +984,7 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
{
|
||||
name: "Archiving (loaded) artifact to storage adds to cache",
|
||||
cache: cache.New(10, time.Minute),
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
index.Index = &repo.IndexFile{
|
||||
APIVersion: "v1",
|
||||
Generated: time.Now(),
|
||||
|
|
@ -993,7 +992,7 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
obj.Spec.Interval = metav1.Duration{Duration: interval}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, cache *cache.Cache) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, cache *cache.Cache) {
|
||||
i, ok := cache.Get(obj.GetArtifact().Path)
|
||||
t.Expect(ok).To(BeTrue())
|
||||
t.Expect(i).To(BeAssignableToTypeOf(&repo.IndexFile{}))
|
||||
|
|
@ -1004,11 +1003,11 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "Up-to-date artifact should not update status",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
obj.Spec.Interval = metav1.Duration{Duration: interval}
|
||||
obj.Status.Artifact = artifact.DeepCopy()
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, _ *cache.Cache) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, _ *cache.Cache) {
|
||||
t.Expect(obj.Status.URL).To(BeEmpty())
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
|
|
@ -1018,7 +1017,7 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "Removes ArtifactOutdatedCondition after creating a new artifact",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
obj.Spec.Interval = metav1.Duration{Duration: interval}
|
||||
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "Foo", "")
|
||||
},
|
||||
|
|
@ -1029,10 +1028,10 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "Creates latest symlink to the created artifact",
|
||||
beforeFunc: func(t *WithT, obj *helmv1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
beforeFunc: func(t *WithT, obj *sourcev1.HelmRepository, artifact sourcev1.Artifact, index *repository.ChartRepository) {
|
||||
obj.Spec.Interval = metav1.Duration{Duration: interval}
|
||||
},
|
||||
afterFunc: func(t *WithT, obj *helmv1.HelmRepository, _ *cache.Cache) {
|
||||
afterFunc: func(t *WithT, obj *sourcev1.HelmRepository, _ *cache.Cache) {
|
||||
localPath := testStorage.LocalPath(*obj.GetArtifact())
|
||||
symlinkPath := filepath.Join(filepath.Dir(localPath), "index.yaml")
|
||||
targetFile, err := os.Readlink(symlinkPath)
|
||||
|
|
@ -1053,7 +1052,7 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
r := &HelmRepositoryReconciler{
|
||||
Client: fakeclient.NewClientBuilder().
|
||||
WithScheme(testEnv.GetScheme()).
|
||||
WithStatusSubresource(&helmv1.HelmRepository{}).
|
||||
WithStatusSubresource(&sourcev1.HelmRepository{}).
|
||||
Build(),
|
||||
EventRecorder: record.NewFakeRecorder(32),
|
||||
Storage: testStorage,
|
||||
|
|
@ -1062,16 +1061,16 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
patchOptions: getPatchOptions(helmRepositoryReadyCondition.Owned, "sc"),
|
||||
}
|
||||
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: helmv1.HelmRepositoryKind,
|
||||
Kind: sourcev1.HelmRepositoryKind,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "test-bucket-",
|
||||
Generation: 1,
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
Timeout: &metav1.Duration{Duration: timeout},
|
||||
URL: "https://example.com/index.yaml",
|
||||
},
|
||||
|
|
@ -1111,7 +1110,7 @@ func TestHelmRepositoryReconciler_reconcileArtifact(t *testing.T) {
|
|||
func TestHelmRepositoryReconciler_reconcileSubRecs(t *testing.T) {
|
||||
// Helper to build simple helmRepositoryReconcileFunc with result and error.
|
||||
buildReconcileFuncs := func(r sreconcile.Result, e error) helmRepositoryReconcileFunc {
|
||||
return func(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
return func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
return r, e
|
||||
}
|
||||
}
|
||||
|
|
@ -1166,11 +1165,11 @@ func TestHelmRepositoryReconciler_reconcileSubRecs(t *testing.T) {
|
|||
{
|
||||
name: "multiple object status conditions mutations",
|
||||
reconcileFuncs: []helmRepositoryReconcileFunc{
|
||||
func(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision")
|
||||
return sreconcile.ResultSuccess, nil
|
||||
},
|
||||
func(ctx context.Context, sp *patch.SerialPatcher, obj *helmv1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmRepository, artifact *sourcev1.Artifact, repo *repository.ChartRepository) (sreconcile.Result, error) {
|
||||
conditions.MarkTrue(obj, meta.ReconcilingCondition, meta.ProgressingReason, "creating artifact")
|
||||
return sreconcile.ResultSuccess, nil
|
||||
},
|
||||
|
|
@ -1220,16 +1219,16 @@ func TestHelmRepositoryReconciler_reconcileSubRecs(t *testing.T) {
|
|||
r := &HelmRepositoryReconciler{
|
||||
Client: fakeclient.NewClientBuilder().
|
||||
WithScheme(testEnv.GetScheme()).
|
||||
WithStatusSubresource(&helmv1.HelmRepository{}).
|
||||
WithStatusSubresource(&sourcev1.HelmRepository{}).
|
||||
Build(),
|
||||
patchOptions: getPatchOptions(helmRepositoryReadyCondition.Owned, "sc"),
|
||||
}
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "test-",
|
||||
Generation: tt.generation,
|
||||
},
|
||||
Status: helmv1.HelmRepositoryStatus{
|
||||
Status: sourcev1.HelmRepositoryStatus{
|
||||
ObservedGeneration: tt.observedGeneration,
|
||||
},
|
||||
}
|
||||
|
|
@ -1254,13 +1253,13 @@ func TestHelmRepositoryReconciler_reconcileSubRecs(t *testing.T) {
|
|||
func TestHelmRepositoryReconciler_statusConditions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
beforeFunc func(obj *helmv1.HelmRepository)
|
||||
beforeFunc func(obj *sourcev1.HelmRepository)
|
||||
assertConditions []metav1.Condition
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "positive conditions only",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
conditions.MarkTrue(obj, sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision")
|
||||
},
|
||||
assertConditions: []metav1.Condition{
|
||||
|
|
@ -1271,7 +1270,7 @@ func TestHelmRepositoryReconciler_statusConditions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "multiple failures",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, sourcev1.AuthenticationFailedReason, "failed to get secret")
|
||||
conditions.MarkTrue(obj, sourcev1.StorageOperationFailedCondition, sourcev1.DirCreationFailedReason, "failed to create directory")
|
||||
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "some error")
|
||||
|
|
@ -1286,7 +1285,7 @@ func TestHelmRepositoryReconciler_statusConditions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "mixed positive and negative conditions",
|
||||
beforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
beforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
conditions.MarkTrue(obj, sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision")
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, sourcev1.AuthenticationFailedReason, "failed to get secret")
|
||||
},
|
||||
|
|
@ -1303,10 +1302,10 @@ func TestHelmRepositoryReconciler_statusConditions(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: helmv1.HelmRepositoryKind,
|
||||
APIVersion: helmv1.GroupVersion.String(),
|
||||
Kind: sourcev1.HelmRepositoryKind,
|
||||
APIVersion: sourcev1.GroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "helmrepo",
|
||||
|
|
@ -1316,7 +1315,7 @@ func TestHelmRepositoryReconciler_statusConditions(t *testing.T) {
|
|||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithObjects(obj).
|
||||
WithStatusSubresource(&helmv1.HelmRepository{})
|
||||
WithStatusSubresource(&sourcev1.HelmRepository{})
|
||||
|
||||
c := clientBuilder.Build()
|
||||
|
||||
|
|
@ -1351,8 +1350,8 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name string
|
||||
res sreconcile.Result
|
||||
resErr error
|
||||
oldObjBeforeFunc func(obj *helmv1.HelmRepository)
|
||||
newObjBeforeFunc func(obj *helmv1.HelmRepository)
|
||||
oldObjBeforeFunc func(obj *sourcev1.HelmRepository)
|
||||
newObjBeforeFunc func(obj *sourcev1.HelmRepository)
|
||||
wantEvent string
|
||||
}{
|
||||
{
|
||||
|
|
@ -1364,7 +1363,7 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name: "new artifact with nil size",
|
||||
res: sreconcile.ResultSuccess,
|
||||
resErr: nil,
|
||||
newObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
newObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: nil}
|
||||
},
|
||||
wantEvent: "Normal NewArtifact stored fetched index of unknown size",
|
||||
|
|
@ -1373,7 +1372,7 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name: "new artifact",
|
||||
res: sreconcile.ResultSuccess,
|
||||
resErr: nil,
|
||||
newObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
newObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
},
|
||||
wantEvent: "Normal NewArtifact stored fetched index of size",
|
||||
|
|
@ -1382,12 +1381,12 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name: "recovery from failure",
|
||||
res: sreconcile.ResultSuccess,
|
||||
resErr: nil,
|
||||
oldObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
oldObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, sourcev1.GitOperationFailedReason, "fail")
|
||||
conditions.MarkFalse(obj, meta.ReadyCondition, meta.FailedReason, "foo")
|
||||
},
|
||||
newObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
newObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "ready")
|
||||
},
|
||||
|
|
@ -1397,12 +1396,12 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name: "recovery and new artifact",
|
||||
res: sreconcile.ResultSuccess,
|
||||
resErr: nil,
|
||||
oldObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
oldObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, sourcev1.GitOperationFailedReason, "fail")
|
||||
conditions.MarkFalse(obj, meta.ReadyCondition, meta.FailedReason, "foo")
|
||||
},
|
||||
newObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
newObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "aaa", Digest: "bbb", Size: &aSize}
|
||||
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "ready")
|
||||
},
|
||||
|
|
@ -1412,11 +1411,11 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
name: "no updates",
|
||||
res: sreconcile.ResultSuccess,
|
||||
resErr: nil,
|
||||
oldObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
oldObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "ready")
|
||||
},
|
||||
newObjBeforeFunc: func(obj *helmv1.HelmRepository) {
|
||||
newObjBeforeFunc: func(obj *sourcev1.HelmRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Digest: "yyy", Size: &aSize}
|
||||
conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason, "ready")
|
||||
},
|
||||
|
|
@ -1428,7 +1427,7 @@ func TestHelmRepositoryReconciler_notify(t *testing.T) {
|
|||
g := NewWithT(t)
|
||||
recorder := record.NewFakeRecorder(32)
|
||||
|
||||
oldObj := &helmv1.HelmRepository{}
|
||||
oldObj := &sourcev1.HelmRepository{}
|
||||
newObj := oldObj.DeepCopy()
|
||||
|
||||
if tt.oldObjBeforeFunc != nil {
|
||||
|
|
@ -1475,12 +1474,12 @@ func TestHelmRepositoryReconciler_ReconcileTypeUpdatePredicateFilter(t *testing.
|
|||
testServer.Start()
|
||||
defer testServer.Stop()
|
||||
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "helmrepository-reconcile-",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
URL: testServer.URL(),
|
||||
},
|
||||
|
|
@ -1524,7 +1523,7 @@ func TestHelmRepositoryReconciler_ReconcileTypeUpdatePredicateFilter(t *testing.
|
|||
g.Expect(res.Status).To(Equal(kstatus.CurrentStatus))
|
||||
|
||||
// Switch to a OCI helm repository type
|
||||
obj.Spec.Type = helmv1.HelmRepositoryTypeOCI
|
||||
obj.Spec.Type = sourcev1.HelmRepositoryTypeOCI
|
||||
obj.Spec.URL = fmt.Sprintf("oci://%s", testRegistryServer.registryHost)
|
||||
|
||||
oldGen := obj.GetGeneration()
|
||||
|
|
@ -1564,12 +1563,12 @@ func TestHelmRepositoryReconciler_ReconcileSpecUpdatePredicateFilter(t *testing.
|
|||
testServer.Start()
|
||||
defer testServer.Stop()
|
||||
|
||||
obj := &helmv1.HelmRepository{
|
||||
obj := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "helmrepository-reconcile-",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
URL: testServer.URL(),
|
||||
},
|
||||
|
|
@ -1666,12 +1665,12 @@ func TestHelmRepositoryReconciler_InMemoryCaching(t *testing.T) {
|
|||
g.Expect(err).ToNot(HaveOccurred())
|
||||
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
|
||||
|
||||
helmRepo := &helmv1.HelmRepository{
|
||||
helmRepo := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "helmrepository-",
|
||||
Namespace: ns.Name,
|
||||
},
|
||||
Spec: helmv1.HelmRepositorySpec{
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
URL: testServer.URL(),
|
||||
},
|
||||
}
|
||||
|
|
@ -1725,7 +1724,7 @@ func TestHelmRepositoryReconciler_ociMigration(t *testing.T) {
|
|||
g.Expect(testEnv.Cleanup(ctx, testns)).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
hr := &helmv1.HelmRepository{
|
||||
hr := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("hr-%s", randStringRunes(5)),
|
||||
Namespace: testns.Name,
|
||||
|
|
@ -1736,8 +1735,8 @@ func TestHelmRepositoryReconciler_ociMigration(t *testing.T) {
|
|||
// Migrates newly created object with finalizer.
|
||||
|
||||
hr.ObjectMeta.Finalizers = append(hr.ObjectMeta.Finalizers, "foo.bar", sourcev1.SourceFinalizer)
|
||||
hr.Spec = helmv1.HelmRepositorySpec{
|
||||
Type: helmv1.HelmRepositoryTypeOCI,
|
||||
hr.Spec = sourcev1.HelmRepositorySpec{
|
||||
Type: sourcev1.HelmRepositoryTypeOCI,
|
||||
URL: "oci://foo/bar",
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1393,7 +1393,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignatureNotation(t *testi
|
|||
},
|
||||
Spec: ociv1.OCIRepositorySpec{
|
||||
URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost),
|
||||
Verify: &ociv1.OCIRepositoryVerification{
|
||||
Verify: &sourcev1.OCIRepositoryVerification{
|
||||
Provider: "notation",
|
||||
},
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
|
|
@ -1713,7 +1713,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceTrustPolicyNotation(t *tes
|
|||
},
|
||||
Spec: ociv1.OCIRepositorySpec{
|
||||
URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost),
|
||||
Verify: &ociv1.OCIRepositoryVerification{
|
||||
Verify: &sourcev1.OCIRepositoryVerification{
|
||||
Provider: "notation",
|
||||
},
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
|
|
@ -2037,7 +2037,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignatureCosign(t *testing
|
|||
},
|
||||
Spec: ociv1.OCIRepositorySpec{
|
||||
URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost),
|
||||
Verify: &ociv1.OCIRepositoryVerification{
|
||||
Verify: &sourcev1.OCIRepositoryVerification{
|
||||
Provider: "cosign",
|
||||
},
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
|
|
@ -2159,7 +2159,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature_keyless(t *testi
|
|||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
beforeFunc: func(obj *ociv1.OCIRepository) {
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []ociv1.OIDCIdentityMatch{
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []sourcev1.OIDCIdentityMatch{
|
||||
{
|
||||
|
||||
Subject: "^https://github.com/stefanprodan/podinfo.*$",
|
||||
|
|
@ -2181,7 +2181,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature_keyless(t *testi
|
|||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
beforeFunc: func(obj *ociv1.OCIRepository) {
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []ociv1.OIDCIdentityMatch{
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []sourcev1.OIDCIdentityMatch{
|
||||
{
|
||||
Subject: "intruder",
|
||||
Issuer: "^https://honeypot.com$",
|
||||
|
|
@ -2208,7 +2208,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature_keyless(t *testi
|
|||
wantErr: true,
|
||||
want: sreconcile.ResultEmpty,
|
||||
beforeFunc: func(obj *ociv1.OCIRepository) {
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []ociv1.OIDCIdentityMatch{
|
||||
obj.Spec.Verify.MatchOIDCIdentity = []sourcev1.OIDCIdentityMatch{
|
||||
{
|
||||
Subject: "intruder",
|
||||
Issuer: "^https://honeypot.com$",
|
||||
|
|
@ -2260,7 +2260,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature_keyless(t *testi
|
|||
},
|
||||
Spec: ociv1.OCIRepositorySpec{
|
||||
URL: "oci://ghcr.io/stefanprodan/manifests/podinfo",
|
||||
Verify: &ociv1.OCIRepositoryVerification{
|
||||
Verify: &sourcev1.OCIRepositoryVerification{
|
||||
Provider: "cosign",
|
||||
},
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/fluxcd/source-controller/internal/helm/registry"
|
||||
soci "github.com/fluxcd/source-controller/internal/oci"
|
||||
stls "github.com/fluxcd/source-controller/internal/tls"
|
||||
|
|
@ -69,7 +70,7 @@ func (o ClientOpts) MustLoginToRegistry() bool {
|
|||
// auth mechanisms.
|
||||
// A temporary directory is created to store the certs files if needed and its path is returned along with the options object. It is the
|
||||
// caller's responsibility to clean up the directory.
|
||||
func GetClientOpts(ctx context.Context, c client.Client, obj *helmv1.HelmRepository, url string) (*ClientOpts, string, error) {
|
||||
func GetClientOpts(ctx context.Context, c client.Client, obj *sourcev1.HelmRepository, url string) (*ClientOpts, string, error) {
|
||||
hrOpts := &ClientOpts{
|
||||
GetterOpts: []helmgetter.Option{
|
||||
helmgetter.WithURL(url),
|
||||
|
|
@ -77,7 +78,7 @@ func GetClientOpts(ctx context.Context, c client.Client, obj *helmv1.HelmReposit
|
|||
helmgetter.WithPassCredentialsAll(obj.Spec.PassCredentials),
|
||||
},
|
||||
}
|
||||
ociRepo := obj.Spec.Type == helmv1.HelmRepositoryTypeOCI
|
||||
ociRepo := obj.Spec.Type == sourcev1.HelmRepositoryTypeOCI
|
||||
|
||||
var (
|
||||
certSecret *corev1.Secret
|
||||
|
|
@ -135,7 +136,7 @@ func GetClientOpts(ctx context.Context, c client.Client, obj *helmv1.HelmReposit
|
|||
return nil, "", fmt.Errorf("failed to configure login options: %w", err)
|
||||
}
|
||||
}
|
||||
} else if obj.Spec.Provider != helmv1.GenericOCIProvider && obj.Spec.Type == helmv1.HelmRepositoryTypeOCI && ociRepo {
|
||||
} else if obj.Spec.Provider != sourcev1beta2.GenericOCIProvider && obj.Spec.Type == sourcev1.HelmRepositoryTypeOCI && ociRepo {
|
||||
authenticator, authErr := soci.OIDCAuth(ctx, obj.Spec.URL, obj.Spec.Provider)
|
||||
if authErr != nil && !errors.Is(authErr, oci.ErrUnconfiguredProvider) {
|
||||
return nil, "", fmt.Errorf("failed to get credential from '%s': %w", obj.Spec.Provider, authErr)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
helmv1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
func TestGetClientOpts(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
// HelmRepositoryOCIMigrationPredicate implements predicate functions to allow
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ import (
|
|||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/runtime/conditions"
|
||||
|
||||
v1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
func TestHelmRepositoryOCIMigrationPredicate_Create(t *testing.T) {
|
||||
|
|
@ -161,7 +160,7 @@ func TestHelmRepositoryOCIMigrationPredicate_Update(t *testing.T) {
|
|||
Type: sourcev1.HelmRepositoryTypeDefault,
|
||||
}
|
||||
oldObj.Status = sourcev1.HelmRepositoryStatus{
|
||||
Artifact: &v1.Artifact{},
|
||||
Artifact: &sourcev1.Artifact{},
|
||||
URL: "http://some-address",
|
||||
ObservedGeneration: 3,
|
||||
}
|
||||
|
|
|
|||
16
main.go
16
main.go
|
|
@ -50,7 +50,7 @@ import (
|
|||
"github.com/fluxcd/pkg/runtime/pprof"
|
||||
"github.com/fluxcd/pkg/runtime/probes"
|
||||
|
||||
v1 "github.com/fluxcd/source-controller/api/v1"
|
||||
"github.com/fluxcd/source-controller/api/v1"
|
||||
"github.com/fluxcd/source-controller/api/v1beta2"
|
||||
|
||||
// +kubebuilder:scaffold:imports
|
||||
|
|
@ -199,7 +199,7 @@ func main() {
|
|||
DependencyRequeueInterval: requeueDependency,
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1beta2.GitRepositoryKind)
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1.GitRepositoryKind)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ func main() {
|
|||
}).SetupWithManagerAndOptions(mgr, controller.HelmRepositoryReconcilerOptions{
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1beta2.HelmRepositoryKind)
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1.HelmRepositoryKind)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ func main() {
|
|||
}).SetupWithManagerAndOptions(ctx, mgr, controller.HelmChartReconcilerOptions{
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1beta2.HelmChartKind)
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1.HelmChartKind)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ func main() {
|
|||
}).SetupWithManagerAndOptions(mgr, controller.BucketReconcilerOptions{
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "Bucket")
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1beta2.BucketKind)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +260,7 @@ func main() {
|
|||
}).SetupWithManagerAndOptions(mgr, controller.OCIRepositoryReconcilerOptions{
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "OCIRepository")
|
||||
setupLog.Error(err, "unable to create controller", "controller", v1beta2.OCIRepositoryKind)
|
||||
os.Exit(1)
|
||||
}
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
|
@ -349,8 +349,8 @@ func mustSetupManager(metricsAddr, healthAddr string, maxConcurrent int,
|
|||
Cache: ctrlcache.Options{
|
||||
ByObject: map[ctrlclient.Object]ctrlcache.ByObject{
|
||||
&v1.GitRepository{}: {Label: watchSelector},
|
||||
&v1beta2.HelmRepository{}: {Label: watchSelector},
|
||||
&v1beta2.HelmChart{}: {Label: watchSelector},
|
||||
&v1.HelmRepository{}: {Label: watchSelector},
|
||||
&v1.HelmChart{}: {Label: watchSelector},
|
||||
&v1beta2.Bucket{}: {Label: watchSelector},
|
||||
&v1beta2.OCIRepository{}: {Label: watchSelector},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue