api: add timeout field to GitRepositorySpec
This commit adds a timeout field to the GitRepositorySpec to be used during the git clone operation when reconciling the resource. When no interval is defined the default timeout returned by the getter is 20 seconds. The timeout can not be added yet to the Helm related sources as it is currently not possible to inject anything custom into the HTTP client from the Helm HTTP getter except for the authentication options built in. A submit has been submitted to make this possible and is waiting for review. This commit includes some context changes to the other reconcilers to tidy them up and make them depend on a single background context. It also includes some added docblocks that crossed my path.
This commit is contained in:
parent
2f1390dda3
commit
920d37fcda
|
@ -17,6 +17,8 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
@ -40,6 +42,11 @@ type GitRepositorySpec struct {
|
||||||
// +required
|
// +required
|
||||||
Interval metav1.Duration `json:"interval"`
|
Interval metav1.Duration `json:"interval"`
|
||||||
|
|
||||||
|
// The timeout for remote git operations like cloning.
|
||||||
|
// +kubebuilder:validation:Default=20s
|
||||||
|
// +optional
|
||||||
|
Timeout *metav1.Duration `json:"timeout,omitempty"`
|
||||||
|
|
||||||
// The git reference to checkout and monitor for changes, defaults to
|
// The git reference to checkout and monitor for changes, defaults to
|
||||||
// master branch.
|
// master branch.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -105,6 +112,10 @@ const (
|
||||||
GitOperationFailedReason string = "GitOperationFailed"
|
GitOperationFailedReason string = "GitOperationFailed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GitRepositoryReady sets the given artifact and url on the
|
||||||
|
// HelmRepository and resets the conditions to SourceCondition of
|
||||||
|
// type Ready with status true and the given reason and message.
|
||||||
|
// It returns the modified GitRepository.
|
||||||
func GitRepositoryReady(repository GitRepository, artifact Artifact, url, reason, message string) GitRepository {
|
func GitRepositoryReady(repository GitRepository, artifact Artifact, url, reason, message string) GitRepository {
|
||||||
repository.Status.Conditions = []SourceCondition{
|
repository.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -128,6 +139,9 @@ func GitRepositoryReady(repository GitRepository, artifact Artifact, url, reason
|
||||||
return repository
|
return repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GitRepositoryNotReady resets the conditions of the HelmRepository
|
||||||
|
// to SourceCondition of type Ready with status false and the given
|
||||||
|
// reason and message. It returns the modified GitRepository.
|
||||||
func GitRepositoryNotReady(repository GitRepository, reason, message string) GitRepository {
|
func GitRepositoryNotReady(repository GitRepository, reason, message string) GitRepository {
|
||||||
repository.Status.Conditions = []SourceCondition{
|
repository.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -141,15 +155,25 @@ func GitRepositoryNotReady(repository GitRepository, reason, message string) Git
|
||||||
return repository
|
return repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadyMessage returns the message of the SourceCondition
|
||||||
|
// of type Ready with status true if present, or an empty string.
|
||||||
func GitRepositoryReadyMessage(repository GitRepository) string {
|
func GitRepositoryReadyMessage(repository GitRepository) string {
|
||||||
for _, condition := range repository.Status.Conditions {
|
for _, condition := range repository.Status.Conditions {
|
||||||
if condition.Type == ReadyCondition {
|
if condition.Type == ReadyCondition && condition.Status == corev1.ConditionTrue {
|
||||||
return condition.Message
|
return condition.Message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTimeout returns the configured timeout or the default.
|
||||||
|
func (in *GitRepository) GetTimeout() time.Duration {
|
||||||
|
if in.Spec.Timeout != nil {
|
||||||
|
return in.Spec.Timeout.Duration
|
||||||
|
}
|
||||||
|
return time.Second * 20
|
||||||
|
}
|
||||||
|
|
||||||
// GetArtifact returns the latest artifact from the source
|
// GetArtifact returns the latest artifact from the source
|
||||||
// if present in the status sub-resource.
|
// if present in the status sub-resource.
|
||||||
func (in *GitRepository) GetArtifact() *Artifact {
|
func (in *GitRepository) GetArtifact() *Artifact {
|
||||||
|
|
|
@ -66,6 +66,10 @@ const (
|
||||||
ChartPullSucceededReason string = "ChartPullSucceeded"
|
ChartPullSucceededReason string = "ChartPullSucceeded"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HelmChartReady sets the given artifact and url on the HelmChart
|
||||||
|
// and resets the conditions to SourceCondition of type Ready with
|
||||||
|
// status true and the given reason and message. It returns the
|
||||||
|
// modified HelmChart.
|
||||||
func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message string) HelmChart {
|
func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message string) HelmChart {
|
||||||
chart.Status.Conditions = []SourceCondition{
|
chart.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -89,6 +93,9 @@ func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message str
|
||||||
return chart
|
return chart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelmChartNotReady resets the conditions of the HelmChart to
|
||||||
|
// SourceCondition of type Ready with status false and the given
|
||||||
|
// reason and message. It returns the modified HelmChart.
|
||||||
func HelmChartNotReady(chart HelmChart, reason, message string) HelmChart {
|
func HelmChartNotReady(chart HelmChart, reason, message string) HelmChart {
|
||||||
chart.Status.Conditions = []SourceCondition{
|
chart.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -102,6 +109,8 @@ func HelmChartNotReady(chart HelmChart, reason, message string) HelmChart {
|
||||||
return chart
|
return chart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelmChartReadyMessage returns the message of the SourceCondition
|
||||||
|
// of type Ready with status true if present, or an empty string.
|
||||||
func HelmChartReadyMessage(chart HelmChart) string {
|
func HelmChartReadyMessage(chart HelmChart) string {
|
||||||
for _, condition := range chart.Status.Conditions {
|
for _, condition := range chart.Status.Conditions {
|
||||||
if condition.Type == ReadyCondition && condition.Status == corev1.ConditionTrue {
|
if condition.Type == ReadyCondition && condition.Status == corev1.ConditionTrue {
|
||||||
|
|
|
@ -65,6 +65,10 @@ const (
|
||||||
IndexationSucceededReason string = "IndexationSucceed"
|
IndexationSucceededReason string = "IndexationSucceed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HelmRepositoryReady sets the given artifact and url on the
|
||||||
|
// HelmRepository and resets the conditions to SourceCondition of
|
||||||
|
// type Ready with status true and the given reason and message.
|
||||||
|
// It returns the modified HelmRepository.
|
||||||
func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reason, message string) HelmRepository {
|
func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reason, message string) HelmRepository {
|
||||||
repository.Status.Conditions = []SourceCondition{
|
repository.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -88,6 +92,9 @@ func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reas
|
||||||
return repository
|
return repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelmRepositoryNotReady resets the conditions of the HelmRepository
|
||||||
|
// to SourceCondition of type Ready with status false and the given
|
||||||
|
// reason and message. It returns the modified HelmRepository.
|
||||||
func HelmRepositoryNotReady(repository HelmRepository, reason, message string) HelmRepository {
|
func HelmRepositoryNotReady(repository HelmRepository, reason, message string) HelmRepository {
|
||||||
repository.Status.Conditions = []SourceCondition{
|
repository.Status.Conditions = []SourceCondition{
|
||||||
{
|
{
|
||||||
|
@ -101,6 +108,8 @@ func HelmRepositoryNotReady(repository HelmRepository, reason, message string) H
|
||||||
return repository
|
return repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HelmRepositoryReadyMessage returns the message of the SourceCondition
|
||||||
|
// of type Ready with status true if present, or an empty string.
|
||||||
func HelmRepositoryReadyMessage(repository HelmRepository) string {
|
func HelmRepositoryReadyMessage(repository HelmRepository) string {
|
||||||
for _, condition := range repository.Status.Conditions {
|
for _, condition := range repository.Status.Conditions {
|
||||||
if condition.Type == ReadyCondition && condition.Status == corev1.ConditionTrue {
|
if condition.Type == ReadyCondition && condition.Status == corev1.ConditionTrue {
|
||||||
|
|
|
@ -22,6 +22,7 @@ package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -124,6 +125,11 @@ func (in *GitRepositorySpec) DeepCopyInto(out *GitRepositorySpec) {
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
out.Interval = in.Interval
|
out.Interval = in.Interval
|
||||||
|
if in.Timeout != nil {
|
||||||
|
in, out := &in.Timeout, &out.Timeout
|
||||||
|
*out = new(metav1.Duration)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.Reference != nil {
|
if in.Reference != nil {
|
||||||
in, out := &in.Reference, &out.Reference
|
in, out := &in.Reference, &out.Reference
|
||||||
*out = new(GitRepositoryRef)
|
*out = new(GitRepositoryRef)
|
||||||
|
|
|
@ -82,6 +82,9 @@ spec:
|
||||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
timeout:
|
||||||
|
description: The timeout for remote git operations like cloning.
|
||||||
|
type: string
|
||||||
url:
|
url:
|
||||||
description: The repository URL, can be a HTTP or SSH address.
|
description: The repository URL, can be a HTTP or SSH address.
|
||||||
pattern: ^(http|https|ssh)://
|
pattern: ^(http|https|ssh)://
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/blang/semver"
|
"github.com/blang/semver"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
|
@ -51,8 +50,7 @@ type GitRepositoryReconciler struct {
|
||||||
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories/status,verbs=get;update;patch
|
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=gitrepositories/status,verbs=get;update;patch
|
||||||
|
|
||||||
func (r *GitRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
func (r *GitRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
ctx := context.Background()
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
var repo sourcev1.GitRepository
|
var repo sourcev1.GitRepository
|
||||||
if err := r.Get(ctx, req.NamespacedName, &repo); err != nil {
|
if err := r.Get(ctx, req.NamespacedName, &repo); err != nil {
|
||||||
|
@ -164,7 +162,8 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
|
||||||
defer os.RemoveAll(tmpGit)
|
defer os.RemoveAll(tmpGit)
|
||||||
|
|
||||||
// clone to tmp
|
// clone to tmp
|
||||||
repo, err := git.PlainClone(tmpGit, false, &git.CloneOptions{
|
gitCtx, cancel := context.WithTimeout(ctx, repository.GetTimeout())
|
||||||
|
repo, err := git.PlainCloneContext(gitCtx, tmpGit, false, &git.CloneOptions{
|
||||||
URL: repository.Spec.URL,
|
URL: repository.Spec.URL,
|
||||||
Auth: auth,
|
Auth: auth,
|
||||||
RemoteName: "origin",
|
RemoteName: "origin",
|
||||||
|
@ -176,6 +175,7 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
|
||||||
Progress: nil,
|
Progress: nil,
|
||||||
Tags: tagMode,
|
Tags: tagMode,
|
||||||
})
|
})
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("git clone error: %w", err)
|
err = fmt.Errorf("git clone error: %w", err)
|
||||||
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
|
||||||
|
@ -340,6 +340,8 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
|
||||||
return sourcev1.GitRepositoryReady(repository, artifact, url, sourcev1.GitOperationSucceedReason, message), nil
|
return sourcev1.GitRepositoryReady(repository, artifact, url, sourcev1.GitOperationSucceedReason, message), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldResetStatus returns a boolean indicating if the status of the
|
||||||
|
// given repository should be reset and a reset HelmChartStatus.
|
||||||
func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepository) (bool, sourcev1.GitRepositoryStatus) {
|
func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepository) (bool, sourcev1.GitRepositoryStatus) {
|
||||||
resetStatus := false
|
resetStatus := false
|
||||||
if repository.Status.Artifact != nil {
|
if repository.Status.Artifact != nil {
|
||||||
|
@ -364,6 +366,8 @@ func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gc performs a garbage collection on all but current artifacts of
|
||||||
|
// the given repository.
|
||||||
func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error {
|
func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error {
|
||||||
if repository.Status.Artifact != nil {
|
if repository.Status.Artifact != nil {
|
||||||
return r.Storage.RemoveAllButCurrent(*repository.Status.Artifact)
|
return r.Storage.RemoveAllButCurrent(*repository.Status.Artifact)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"helm.sh/helm/v3/pkg/getter"
|
"helm.sh/helm/v3/pkg/getter"
|
||||||
|
@ -51,8 +50,7 @@ type HelmChartReconciler struct {
|
||||||
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=helmcharts/status,verbs=get;update;patch
|
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=helmcharts/status,verbs=get;update;patch
|
||||||
|
|
||||||
func (r *HelmChartReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
func (r *HelmChartReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
ctx := context.Background()
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
var chart sourcev1.HelmChart
|
var chart sourcev1.HelmChart
|
||||||
if err := r.Get(ctx, req.NamespacedName, &chart); err != nil {
|
if err := r.Get(ctx, req.NamespacedName, &chart); err != nil {
|
||||||
|
@ -77,7 +75,7 @@ func (r *HelmChartReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get referenced chart repository
|
// get referenced chart repository
|
||||||
repository, err := r.chartRepository(ctx, chart)
|
repository, err := r.getChartRepositoryWithArtifact(ctx, chart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chart = sourcev1.HelmChartNotReady(*chart.DeepCopy(), sourcev1.ChartPullFailedReason, err.Error())
|
chart = sourcev1.HelmChartNotReady(*chart.DeepCopy(), sourcev1.ChartPullFailedReason, err.Error())
|
||||||
if err := r.Status().Update(ctx, &chart); err != nil {
|
if err := r.Status().Update(ctx, &chart); err != nil {
|
||||||
|
@ -93,7 +91,7 @@ func (r *HelmChartReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to pull chart
|
// try to pull chart
|
||||||
pulledChart, err := r.sync(repository, *chart.DeepCopy())
|
pulledChart, err := r.sync(ctx, repository, *chart.DeepCopy())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "Helm chart sync failed")
|
log.Error(err, "Helm chart sync failed")
|
||||||
if err := r.Status().Update(ctx, &pulledChart); err != nil {
|
if err := r.Status().Update(ctx, &pulledChart); err != nil {
|
||||||
|
@ -122,7 +120,7 @@ func (r *HelmChartReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HelmChartReconciler) sync(repository sourcev1.HelmRepository, chart sourcev1.HelmChart) (sourcev1.HelmChart, error) {
|
func (r *HelmChartReconciler) sync(ctx context.Context, repository sourcev1.HelmRepository, chart sourcev1.HelmChart) (sourcev1.HelmChart, error) {
|
||||||
indexBytes, err := ioutil.ReadFile(repository.Status.Artifact.Path)
|
indexBytes, err := ioutil.ReadFile(repository.Status.Artifact.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("failed to read Helm repository index file: %w", err)
|
err = fmt.Errorf("failed to read Helm repository index file: %w", err)
|
||||||
|
@ -172,7 +170,7 @@ func (r *HelmChartReconciler) sync(repository sourcev1.HelmRepository, chart sou
|
||||||
}
|
}
|
||||||
|
|
||||||
var secret corev1.Secret
|
var secret corev1.Secret
|
||||||
err := r.Client.Get(context.TODO(), name, &secret)
|
err := r.Client.Get(ctx, name, &secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("auth secret error: %w", err)
|
err = fmt.Errorf("auth secret error: %w", err)
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
|
@ -189,6 +187,8 @@ func (r *HelmChartReconciler) sync(repository sourcev1.HelmRepository, chart sou
|
||||||
clientOpts = opts
|
clientOpts = opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(hidde): implement timeout from the HelmRepository
|
||||||
|
// https://github.com/helm/helm/pull/7950
|
||||||
res, err := c.Get(u.String(), clientOpts...)
|
res, err := c.Get(u.String(), clientOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPullFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPullFailedReason, err.Error()), err
|
||||||
|
@ -236,7 +236,10 @@ func (r *HelmChartReconciler) sync(repository sourcev1.HelmRepository, chart sou
|
||||||
return sourcev1.HelmChartReady(chart, artifact, chartUrl, sourcev1.ChartPullSucceededReason, message), nil
|
return sourcev1.HelmChartReady(chart, artifact, chartUrl, sourcev1.ChartPullSucceededReason, message), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HelmChartReconciler) chartRepository(ctx context.Context, chart sourcev1.HelmChart) (sourcev1.HelmRepository, error) {
|
// getChartRepositoryWithArtifact attempts to get the ChartRepository
|
||||||
|
// for the given chart. It returns an error if the HelmRepository could
|
||||||
|
// not be retrieved or if does not have an artifact.
|
||||||
|
func (r *HelmChartReconciler) getChartRepositoryWithArtifact(ctx context.Context, chart sourcev1.HelmChart) (sourcev1.HelmRepository, error) {
|
||||||
if chart.Spec.HelmRepositoryRef.Name == "" {
|
if chart.Spec.HelmRepositoryRef.Name == "" {
|
||||||
return sourcev1.HelmRepository{}, fmt.Errorf("no HelmRepository reference given")
|
return sourcev1.HelmRepository{}, fmt.Errorf("no HelmRepository reference given")
|
||||||
}
|
}
|
||||||
|
@ -260,6 +263,8 @@ func (r *HelmChartReconciler) chartRepository(ctx context.Context, chart sourcev
|
||||||
return repository, err
|
return repository, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldResetStatus returns a boolean indicating if the status of the
|
||||||
|
// given chart should be reset and a reset HelmChartStatus.
|
||||||
func (r *HelmChartReconciler) shouldResetStatus(chart sourcev1.HelmChart) (bool, sourcev1.HelmChartStatus) {
|
func (r *HelmChartReconciler) shouldResetStatus(chart sourcev1.HelmChart) (bool, sourcev1.HelmChartStatus) {
|
||||||
resetStatus := false
|
resetStatus := false
|
||||||
if chart.Status.Artifact != nil {
|
if chart.Status.Artifact != nil {
|
||||||
|
@ -285,6 +290,8 @@ func (r *HelmChartReconciler) shouldResetStatus(chart sourcev1.HelmChart) (bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gc performs a garbage collection on all but current artifacts of
|
||||||
|
// the given chart.
|
||||||
func (r *HelmChartReconciler) gc(chart sourcev1.HelmChart) error {
|
func (r *HelmChartReconciler) gc(chart sourcev1.HelmChart) error {
|
||||||
if chart.Status.Artifact != nil {
|
if chart.Status.Artifact != nil {
|
||||||
return r.Storage.RemoveAllButCurrent(*chart.Status.Artifact)
|
return r.Storage.RemoveAllButCurrent(*chart.Status.Artifact)
|
||||||
|
@ -292,11 +299,14 @@ func (r *HelmChartReconciler) gc(chart sourcev1.HelmChart) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setOwnerRef appends the owner reference of the given chart to the
|
||||||
|
// repository if it is not present.
|
||||||
func (r *HelmChartReconciler) setOwnerRef(ctx context.Context, chart *sourcev1.HelmChart, repository sourcev1.HelmRepository) error {
|
func (r *HelmChartReconciler) setOwnerRef(ctx context.Context, chart *sourcev1.HelmChart, repository sourcev1.HelmRepository) error {
|
||||||
if !metav1.IsControlledBy(chart.GetObjectMeta(), repository.GetObjectMeta()) {
|
if metav1.IsControlledBy(chart.GetObjectMeta(), repository.GetObjectMeta()) {
|
||||||
chart.SetOwnerReferences(append(chart.GetOwnerReferences(),
|
return nil
|
||||||
*metav1.NewControllerRef(repository.GetObjectMeta(), repository.GroupVersionKind())))
|
|
||||||
return r.Update(ctx, chart)
|
|
||||||
}
|
}
|
||||||
return nil
|
chart.SetOwnerReferences(append(chart.GetOwnerReferences(), *metav1.NewControllerRef(
|
||||||
|
repository.GetObjectMeta(), repository.GroupVersionKind(),
|
||||||
|
)))
|
||||||
|
return r.Update(ctx, chart)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"helm.sh/helm/v3/pkg/getter"
|
"helm.sh/helm/v3/pkg/getter"
|
||||||
|
@ -53,8 +52,7 @@ type HelmRepositoryReconciler struct {
|
||||||
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=helmcharts/finalizers,verbs=get;update;patch
|
// +kubebuilder:rbac:groups=source.fluxcd.io,resources=helmcharts/finalizers,verbs=get;update;patch
|
||||||
|
|
||||||
func (r *HelmRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
func (r *HelmRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
ctx := context.Background()
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
var repository sourcev1.HelmRepository
|
var repository sourcev1.HelmRepository
|
||||||
if err := r.Get(ctx, req.NamespacedName, &repository); err != nil {
|
if err := r.Get(ctx, req.NamespacedName, &repository); err != nil {
|
||||||
|
@ -79,7 +77,7 @@ func (r *HelmRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to download index
|
// try to download index
|
||||||
syncedRepo, err := r.sync(*repository.DeepCopy())
|
syncedRepo, err := r.sync(ctx, *repository.DeepCopy())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "Helm repository sync failed")
|
log.Error(err, "Helm repository sync failed")
|
||||||
if err := r.Status().Update(ctx, &syncedRepo); err != nil {
|
if err := r.Status().Update(ctx, &syncedRepo); err != nil {
|
||||||
|
@ -107,7 +105,7 @@ func (r *HelmRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HelmRepositoryReconciler) sync(repository sourcev1.HelmRepository) (sourcev1.HelmRepository, error) {
|
func (r *HelmRepositoryReconciler) sync(ctx context.Context, repository sourcev1.HelmRepository) (sourcev1.HelmRepository, error) {
|
||||||
u, err := url.Parse(repository.Spec.URL)
|
u, err := url.Parse(repository.Spec.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.URLInvalidReason, err.Error()), err
|
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.URLInvalidReason, err.Error()), err
|
||||||
|
@ -129,7 +127,7 @@ func (r *HelmRepositoryReconciler) sync(repository sourcev1.HelmRepository) (sou
|
||||||
}
|
}
|
||||||
|
|
||||||
var secret corev1.Secret
|
var secret corev1.Secret
|
||||||
err := r.Client.Get(context.TODO(), name, &secret)
|
err := r.Client.Get(ctx, name, &secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("auth secret error: %w", err)
|
err = fmt.Errorf("auth secret error: %w", err)
|
||||||
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
|
@ -146,6 +144,8 @@ func (r *HelmRepositoryReconciler) sync(repository sourcev1.HelmRepository) (sou
|
||||||
clientOpts = opts
|
clientOpts = opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(hidde): implement timeout from the HelmRepository
|
||||||
|
// https://github.com/helm/helm/pull/7950
|
||||||
res, err := c.Get(u.String(), clientOpts...)
|
res, err := c.Get(u.String(), clientOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.IndexationFailedReason, err.Error()), err
|
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.IndexationFailedReason, err.Error()), err
|
||||||
|
@ -204,6 +204,8 @@ func (r *HelmRepositoryReconciler) sync(repository sourcev1.HelmRepository) (sou
|
||||||
return sourcev1.HelmRepositoryReady(repository, artifact, indexURL, sourcev1.IndexationSucceededReason, message), nil
|
return sourcev1.HelmRepositoryReady(repository, artifact, indexURL, sourcev1.IndexationSucceededReason, message), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shouldResetStatus returns a boolean indicating if the status of the
|
||||||
|
// given repository should be reset and a reset HelmChartStatus.
|
||||||
func (r *HelmRepositoryReconciler) shouldResetStatus(repository sourcev1.HelmRepository) (bool, sourcev1.HelmRepositoryStatus) {
|
func (r *HelmRepositoryReconciler) shouldResetStatus(repository sourcev1.HelmRepository) (bool, sourcev1.HelmRepositoryStatus) {
|
||||||
resetStatus := false
|
resetStatus := false
|
||||||
if repository.Status.Artifact != nil {
|
if repository.Status.Artifact != nil {
|
||||||
|
@ -229,6 +231,8 @@ func (r *HelmRepositoryReconciler) shouldResetStatus(repository sourcev1.HelmRep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gc performs a garbage collection on all but current artifacts of
|
||||||
|
// the given repository.
|
||||||
func (r *HelmRepositoryReconciler) gc(repository sourcev1.HelmRepository) error {
|
func (r *HelmRepositoryReconciler) gc(repository sourcev1.HelmRepository) error {
|
||||||
if repository.Status.Artifact != nil {
|
if repository.Status.Artifact != nil {
|
||||||
return r.Storage.RemoveAllButCurrent(*repository.Status.Artifact)
|
return r.Storage.RemoveAllButCurrent(*repository.Status.Artifact)
|
||||||
|
|
Loading…
Reference in New Issue