helm: typed errors from GetChartVersion()

Update the implementations of the helm repository downloaders to return
implementation specific typed error from GetChartVersion(). This is
needed to distinguish between persistent build error and transient build
error.
In the case of OCI charts, a transient network failure shouldn't be
considered a persistent build failure of the chart and should be
retried.

Two repository errors, ErrReference and ErrExternal are introduced for
the repository downloader implementations to provide enough context
about the failure which can be used by the caller to add appropriate
context as per the needs. In case of chart builder, it adds the build
error context based on the repository error value.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
This commit is contained in:
Sunny 2022-12-16 15:26:17 +00:00
parent 0f7a263d71
commit 8018b450a1
4 changed files with 72 additions and 1 deletions

View File

@ -128,8 +128,17 @@ func (b *remoteChartBuilder) downloadFromRepository(ctx context.Context, remote
// Get the current version for the RemoteReference
cv, err := remote.GetChartVersion(remoteRef.Name, remoteRef.Version)
if err != nil {
var reason BuildErrorReason
switch err.(type) {
case *repository.ErrReference:
reason = ErrChartReference
case *repository.ErrExternal:
reason = ErrChartPull
default:
reason = ErrUnknown
}
err = fmt.Errorf("failed to get chart version for remote reference: %w", err)
return nil, nil, &BuildError{Reason: ErrChartReference, Err: err}
return nil, nil, &BuildError{Reason: reason, Err: err}
}
// Verify the chart if necessary

View File

@ -156,6 +156,14 @@ func newChartRepository() *ChartRepository {
// to be a semver.Constraints compatible string. If version is empty, the latest
// stable version will be returned and prerelease versions will be ignored.
func (r *ChartRepository) GetChartVersion(name, ver string) (*repo.ChartVersion, error) {
cv, err := r.getChartVersion(name, ver)
if err != nil {
return nil, &ErrReference{Err: err}
}
return cv, nil
}
func (r *ChartRepository) getChartVersion(name, ver string) (*repo.ChartVersion, error) {
// See if we already have the index in cache or try to load it.
if err := r.StrategicallyLoadIndex(); err != nil {
return nil, err

View File

@ -0,0 +1,47 @@
/*
Copyright 2022 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 repository
// ErrReference indicate invalid chart reference.
type ErrReference struct {
Err error
}
// Error implements the error interface.
func (er *ErrReference) Error() string {
return er.Err.Error()
}
// Unwrap returns the underlying error.
func (er *ErrReference) Unwrap() error {
return er.Err
}
// ErrExternal is a generic error for errors related to external API calls.
type ErrExternal struct {
Err error
}
// Error implements the error interface.
func (ee *ErrExternal) Error() string {
return ee.Err.Error()
}
// Unwrap returns the underlying error.
func (ee *ErrExternal) Unwrap() error {
return ee.Err
}

View File

@ -146,7 +146,14 @@ func NewOCIChartRepository(repositoryURL string, chartRepoOpts ...OCIChartReposi
// stable version will be returned and prerelease versions will be ignored.
// adapted from https://github.com/helm/helm/blob/49819b4ef782e80b0c7f78c30bd76b51ebb56dc8/pkg/downloader/chart_downloader.go#L162
func (r *OCIChartRepository) GetChartVersion(name, ver string) (*repo.ChartVersion, error) {
cv, err := r.getChartVersion(name, ver)
if err != nil {
return nil, &ErrExternal{Err: err}
}
return cv, nil
}
func (r *OCIChartRepository) getChartVersion(name, ver string) (*repo.ChartVersion, error) {
cpURL := r.URL
cpURL.Path = path.Join(cpURL.Path, name)