internal/helm: add remote builder tests
- For remote builds, if the build option has a version metadata, the chart should be repackaged with the provided version. - Update internal/helm/testdata/charts/helmchart-0.1.0.tgz to include value files for testing merge chart values. Signed-off-by: Sunny <darkowlzz@protonmail.com>
This commit is contained in:
parent
7c910e37a2
commit
753abed30c
|
|
@ -100,8 +100,9 @@ func (b *remoteChartBuilder) Build(_ context.Context, ref Reference, p string, o
|
||||||
return nil, fmt.Errorf("failed to download chart for remote reference: %w", err)
|
return nil, fmt.Errorf("failed to download chart for remote reference: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use literal chart copy from remote if no custom value files options are set
|
// Use literal chart copy from remote if no custom value files options are
|
||||||
if len(opts.GetValueFiles()) == 0 {
|
// set or build option version metadata isn't set.
|
||||||
|
if len(opts.GetValueFiles()) == 0 && opts.VersionMetadata == "" {
|
||||||
if err = validatePackageAndWriteToPath(res, p); err != nil {
|
if err = validatePackageAndWriteToPath(res, p); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -127,6 +128,8 @@ func (b *remoteChartBuilder) Build(_ context.Context, ref Reference, p string, o
|
||||||
result.ValueFiles = opts.GetValueFiles()
|
result.ValueFiles = opts.GetValueFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chart.Metadata.Version = result.Version
|
||||||
|
|
||||||
// Package the chart with the custom values
|
// Package the chart with the custom values
|
||||||
if err = packageToPath(chart, p); err != nil {
|
if err = packageToPath(chart, p); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,200 @@ limitations under the License.
|
||||||
package chart
|
package chart
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
helmchart "helm.sh/helm/v3/pkg/chart"
|
helmchart "helm.sh/helm/v3/pkg/chart"
|
||||||
|
"helm.sh/helm/v3/pkg/chart/loader"
|
||||||
"helm.sh/helm/v3/pkg/chartutil"
|
"helm.sh/helm/v3/pkg/chartutil"
|
||||||
|
helmgetter "helm.sh/helm/v3/pkg/getter"
|
||||||
|
|
||||||
|
"github.com/fluxcd/source-controller/internal/helm/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890")
|
||||||
|
|
||||||
|
func randStringRunes(n int) string {
|
||||||
|
b := make([]rune, n)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
// mockIndexChartGetter returns specific response for index and chart queries.
|
||||||
|
type mockIndexChartGetter struct {
|
||||||
|
IndexResponse []byte
|
||||||
|
ChartResponse []byte
|
||||||
|
requestedURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *mockIndexChartGetter) Get(u string, _ ...helmgetter.Option) (*bytes.Buffer, error) {
|
||||||
|
g.requestedURL = u
|
||||||
|
r := g.ChartResponse
|
||||||
|
if strings.HasSuffix(u, "index.yaml") {
|
||||||
|
r = g.IndexResponse
|
||||||
|
}
|
||||||
|
return bytes.NewBuffer(r), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *mockIndexChartGetter) LastGet() string {
|
||||||
|
return g.requestedURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteBuilder_Build(t *testing.T) {
|
||||||
|
g := NewWithT(t)
|
||||||
|
|
||||||
|
chartGrafana, err := os.ReadFile("./../testdata/charts/helmchart-0.1.0.tgz")
|
||||||
|
g.Expect(err).ToNot(HaveOccurred())
|
||||||
|
g.Expect(chartGrafana).ToNot(BeEmpty())
|
||||||
|
|
||||||
|
index := []byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
entries:
|
||||||
|
grafana:
|
||||||
|
- urls:
|
||||||
|
- https://example.com/grafana.tgz
|
||||||
|
description: string
|
||||||
|
version: 6.17.4
|
||||||
|
`)
|
||||||
|
|
||||||
|
mockGetter := &mockIndexChartGetter{
|
||||||
|
IndexResponse: index,
|
||||||
|
ChartResponse: chartGrafana,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRepo := func() *repository.ChartRepository {
|
||||||
|
return &repository.ChartRepository{
|
||||||
|
URL: "https://grafana.github.io/helm-charts/",
|
||||||
|
Client: mockGetter,
|
||||||
|
RWMutex: &sync.RWMutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
reference Reference
|
||||||
|
buildOpts BuildOptions
|
||||||
|
repository *repository.ChartRepository
|
||||||
|
wantValues chartutil.Values
|
||||||
|
wantVersion string
|
||||||
|
wantPackaged bool
|
||||||
|
wantErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid reference",
|
||||||
|
reference: LocalReference{},
|
||||||
|
wantErr: "expected remote chart reference",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid reference - no name",
|
||||||
|
reference: RemoteReference{},
|
||||||
|
wantErr: "no name set for remote chart reference",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "chart not in repo",
|
||||||
|
reference: RemoteReference{Name: "foo"},
|
||||||
|
repository: mockRepo(),
|
||||||
|
wantErr: "failed to get chart version for remote reference",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "chart version not in repo",
|
||||||
|
reference: RemoteReference{Name: "grafana", Version: "1.1.1"},
|
||||||
|
repository: mockRepo(),
|
||||||
|
wantErr: "failed to get chart version for remote reference",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid version metadata",
|
||||||
|
reference: RemoteReference{Name: "grafana"},
|
||||||
|
repository: mockRepo(),
|
||||||
|
buildOpts: BuildOptions{VersionMetadata: "^"},
|
||||||
|
wantErr: "Invalid Metadata string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with version metadata",
|
||||||
|
reference: RemoteReference{Name: "grafana"},
|
||||||
|
repository: mockRepo(),
|
||||||
|
buildOpts: BuildOptions{VersionMetadata: "foo"},
|
||||||
|
wantVersion: "6.17.4+foo",
|
||||||
|
wantPackaged: true,
|
||||||
|
},
|
||||||
|
// TODO: Test setting BuildOptions CachedChart and Force.
|
||||||
|
{
|
||||||
|
name: "default values",
|
||||||
|
reference: RemoteReference{Name: "grafana"},
|
||||||
|
repository: mockRepo(),
|
||||||
|
wantVersion: "0.1.0",
|
||||||
|
wantValues: chartutil.Values{
|
||||||
|
"replicaCount": float64(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "merge values",
|
||||||
|
reference: RemoteReference{Name: "grafana"},
|
||||||
|
buildOpts: BuildOptions{
|
||||||
|
ValueFiles: []string{"a.yaml", "b.yaml", "c.yaml"},
|
||||||
|
},
|
||||||
|
repository: mockRepo(),
|
||||||
|
wantVersion: "6.17.4",
|
||||||
|
wantValues: chartutil.Values{
|
||||||
|
"a": "b",
|
||||||
|
"b": "d",
|
||||||
|
},
|
||||||
|
wantPackaged: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
g := NewWithT(t)
|
||||||
|
|
||||||
|
targetPath := "/tmp/remote-chart-builder-" + randStringRunes(5) + ".tgz"
|
||||||
|
defer os.RemoveAll(targetPath)
|
||||||
|
|
||||||
|
if tt.repository != nil {
|
||||||
|
_, err := tt.repository.CacheIndex()
|
||||||
|
g.Expect(err).ToNot(HaveOccurred())
|
||||||
|
// Cleanup the cache index path.
|
||||||
|
defer os.Remove(tt.repository.CachePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
b := NewRemoteBuilder(tt.repository)
|
||||||
|
|
||||||
|
cb, err := b.Build(context.TODO(), tt.reference, targetPath, tt.buildOpts)
|
||||||
|
|
||||||
|
if tt.wantErr != "" {
|
||||||
|
g.Expect(err).To(HaveOccurred())
|
||||||
|
g.Expect(err.Error()).To(ContainSubstring(tt.wantErr))
|
||||||
|
g.Expect(cb).To(BeZero())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.Expect(err).ToNot(HaveOccurred())
|
||||||
|
g.Expect(cb.Packaged).To(Equal(tt.wantPackaged), "unexpected Build.Packaged value")
|
||||||
|
g.Expect(cb.Path).ToNot(BeEmpty(), "empty Build.Path")
|
||||||
|
|
||||||
|
// Load the resulting chart and verify the values.
|
||||||
|
resultChart, err := loader.Load(cb.Path)
|
||||||
|
g.Expect(err).ToNot(HaveOccurred())
|
||||||
|
g.Expect(resultChart.Metadata.Version).To(Equal(tt.wantVersion))
|
||||||
|
|
||||||
|
for k, v := range tt.wantValues {
|
||||||
|
g.Expect(v).To(Equal(resultChart.Values[k]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_mergeChartValues(t *testing.T) {
|
func Test_mergeChartValues(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue