portainer/pkg/libhelm/validate_repo.go

66 lines
1.6 KiB
Go

package libhelm
import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/portainer/portainer/pkg/libhelm/sdk"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/repo"
)
func ValidateHelmRepositoryURL(repoUrl string, _ *http.Client) error {
if repoUrl == "" {
return errors.New("URL is required")
}
if strings.HasPrefix(repoUrl, "oci://") {
return errors.New("OCI repositories are not supported yet")
}
url, err := url.ParseRequestURI(repoUrl)
if err != nil {
return fmt.Errorf("invalid helm repository URL '%s': %w", repoUrl, err)
}
if !strings.EqualFold(url.Scheme, "http") && !strings.EqualFold(url.Scheme, "https") {
return fmt.Errorf("invalid helm repository URL '%s'", repoUrl)
}
// Mirror Helm CLI behavior: download and parse index.yaml using getters
settings := cli.New()
// Use a deterministic repo name shared with the SDK helper so cache aligns
repoName, err := sdk.GetRepoNameFromURL(repoUrl)
if err != nil {
return fmt.Errorf("failed to derive repo name: %w", err)
}
r, err := repo.NewChartRepository(
&repo.Entry{
Name: repoName,
URL: repoUrl,
},
getter.All(settings),
)
if err != nil {
return fmt.Errorf("%s is not a valid chart repository or cannot be reached: %w", repoUrl, err)
}
indexPath, err := r.DownloadIndexFile()
if err != nil {
return fmt.Errorf("%s is not a valid chart repository or cannot be reached: %w", repoUrl, err)
}
// Best-effort: load and seed in-memory cache for future SearchRepo calls
if indexFile, err := repo.LoadIndexFile(indexPath); err == nil {
sdk.UpdateCache(repoUrl, indexFile)
}
return nil
}