diff --git a/pkg/app/piped/chartrepo/BUILD.bazel b/pkg/app/piped/chartrepo/BUILD.bazel new file mode 100644 index 0000000000..b5fe7c35d3 --- /dev/null +++ b/pkg/app/piped/chartrepo/BUILD.bazel @@ -0,0 +1,12 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["chartrepo.go"], + importpath = "github.com/pipe-cd/pipe/pkg/app/piped/chartrepo", + visibility = ["//visibility:public"], + deps = [ + "//pkg/config:go_default_library", + "@org_uber_go_zap//:go_default_library", + ], +) diff --git a/pkg/app/piped/chartrepo/chartrepo.go b/pkg/app/piped/chartrepo/chartrepo.go new file mode 100644 index 0000000000..ad9e334091 --- /dev/null +++ b/pkg/app/piped/chartrepo/chartrepo.go @@ -0,0 +1,54 @@ +// Copyright 2020 The PipeCD 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 chartrepo manages a list of configured helm repositories. +package chartrepo + +import ( + "context" + "fmt" + "os/exec" + + "go.uber.org/zap" + + "github.com/pipe-cd/pipe/pkg/config" +) + +type registry interface { + Helm(ctx context.Context, version string) (string, bool, error) +} + +// Add installs all specified Helm Chart repositories. +// https://helm.sh/docs/topics/chart_repository/ +// helm repo add fantastic-charts https://fantastic-charts.storage.googleapis.com +// helm repo add fantastic-charts https://fantastic-charts.storage.googleapis.com --username my-username --password my-password +func Add(ctx context.Context, repos []config.HelmChartRepository, reg registry, logger *zap.Logger) error { + helm, _, err := reg.Helm(ctx, "") + if err != nil { + return fmt.Errorf("failed to find helm to add repos (%v)", err) + } + for _, repo := range repos { + args := []string{"repo", "add", repo.Address} + if repo.Username != "" || repo.Password != "" { + args = append(args, "--username", repo.Username, "--password", repo.Password) + } + cmd := exec.CommandContext(ctx, helm, args...) + out, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to add chart repository %s: %s (%w)", repo.Name, string(out), err) + } + logger.Info(fmt.Sprintf("successfully added chart repository %s", repo.Name)) + } + return nil +} diff --git a/pkg/app/piped/cmd/piped/BUILD.bazel b/pkg/app/piped/cmd/piped/BUILD.bazel index ac8e8c64e1..dc247d0efe 100644 --- a/pkg/app/piped/cmd/piped/BUILD.bazel +++ b/pkg/app/piped/cmd/piped/BUILD.bazel @@ -12,6 +12,7 @@ go_library( "//pkg/app/piped/apistore/applicationstore:go_default_library", "//pkg/app/piped/apistore/commandstore:go_default_library", "//pkg/app/piped/apistore/deploymentstore:go_default_library", + "//pkg/app/piped/chartrepo:go_default_library", "//pkg/app/piped/controller:go_default_library", "//pkg/app/piped/driftdetector:go_default_library", "//pkg/app/piped/executor/registry:go_default_library", diff --git a/pkg/app/piped/cmd/piped/piped.go b/pkg/app/piped/cmd/piped/piped.go index fbc9c44176..91dbac8b1d 100644 --- a/pkg/app/piped/cmd/piped/piped.go +++ b/pkg/app/piped/cmd/piped/piped.go @@ -33,6 +33,7 @@ import ( "github.com/pipe-cd/pipe/pkg/app/piped/apistore/applicationstore" "github.com/pipe-cd/pipe/pkg/app/piped/apistore/commandstore" "github.com/pipe-cd/pipe/pkg/app/piped/apistore/deploymentstore" + "github.com/pipe-cd/pipe/pkg/app/piped/chartrepo" "github.com/pipe-cd/pipe/pkg/app/piped/controller" "github.com/pipe-cd/pipe/pkg/app/piped/driftdetector" "github.com/pipe-cd/pipe/pkg/app/piped/livestatereporter" @@ -122,6 +123,14 @@ func (p *piped) run(ctx context.Context, t cli.Telemetry) error { return err } + // Add configured Helm chart repositories. + if len(cfg.ChartRepositories) > 0 { + if err := chartrepo.Add(ctx, cfg.ChartRepositories, toolregistry.DefaultRegistry(), t.Logger); err != nil { + t.Logger.Error("failed to add configured chart repositories", zap.Error(err)) + return err + } + } + // Make gRPC client and connect to the API. apiClient, err := p.createAPIClient(ctx, cfg.ProjectID, cfg.PipedID, cfg.PipedKeyFile, t.Logger) if err != nil { diff --git a/pkg/app/piped/helmrepo/BUILD.bazel b/pkg/app/piped/helmrepo/BUILD.bazel deleted file mode 100644 index 5349eacbde..0000000000 --- a/pkg/app/piped/helmrepo/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["helmrepo.go"], - importpath = "github.com/pipe-cd/pipe/pkg/app/piped/helmrepo", - visibility = ["//visibility:public"], -) diff --git a/pkg/app/piped/helmrepo/helmrepo.go b/pkg/app/piped/helmrepo/helmrepo.go deleted file mode 100644 index c5f3c36514..0000000000 --- a/pkg/app/piped/helmrepo/helmrepo.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 The PipeCD 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 helmrepo manages a list of configured helm repositories. -package helmrepo diff --git a/pkg/config/piped.go b/pkg/config/piped.go index 0b9a6e77e1..0da1bcd2b3 100644 --- a/pkg/config/piped.go +++ b/pkg/config/piped.go @@ -40,7 +40,9 @@ type PipedSpec struct { // Git configuration needed for git commands. Git PipedGit `json:"git"` // List of git repositories this piped will handle. - Repositories []PipedRepository `json:"repositories"` + Repositories []PipedRepository `json:"repositories"` + // List of helm chart repositories that should be added while starting up. + ChartRepositories []HelmChartRepository `json:"chartRepositories"` CloudProviders []PipedCloudProvider `json:"cloudProviders"` AnalysisProviders []PipedAnalysisProvider `json:"analysisProviders"` } @@ -149,6 +151,13 @@ type PipedRepository struct { Branch string `json:"branch"` } +type HelmChartRepository struct { + Name string `json:"name"` + Address string `json:"address"` + Username string `json:"username"` + Password string `json:"password"` +} + type PipedCloudProvider struct { Name string Type model.CloudProviderType diff --git a/pkg/config/piped_test.go b/pkg/config/piped_test.go index 9a26954b73..1d3dc8a814 100644 --- a/pkg/config/piped_test.go +++ b/pkg/config/piped_test.go @@ -58,6 +58,18 @@ func TestPipedConfig(t *testing.T) { Branch: "master", }, }, + ChartRepositories: []HelmChartRepository{ + { + Name: "fantastic-charts", + Address: "https://fantastic-charts.storage.googleapis.com", + }, + { + Name: "private-charts", + Address: "https://private-charts.com", + Username: "basic-username", + Password: "basic-password", + }, + }, CloudProviders: []PipedCloudProvider{ { Name: "kubernetes-default", diff --git a/pkg/config/testdata/piped/piped-config.yaml b/pkg/config/testdata/piped/piped-config.yaml index f123f5cd1c..740ac0cf86 100644 --- a/pkg/config/testdata/piped/piped-config.yaml +++ b/pkg/config/testdata/piped/piped-config.yaml @@ -19,6 +19,14 @@ spec: remote: git@github.com:org/repo2.git branch: master + chartRepositories: + - name: fantastic-charts + address: https://fantastic-charts.storage.googleapis.com + - name: private-charts + address: https://private-charts.com + username: basic-username + password: basic-password + cloudProviders: - name: kubernetes-default type: KUBERNETES