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)
|
||||
}
|
||||
|
||||
// Use literal chart copy from remote if no custom value files options are set
|
||||
if len(opts.GetValueFiles()) == 0 {
|
||||
// Use literal chart copy from remote if no custom value files options are
|
||||
// set or build option version metadata isn't set.
|
||||
if len(opts.GetValueFiles()) == 0 && opts.VersionMetadata == "" {
|
||||
if err = validatePackageAndWriteToPath(res, p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,6 +128,8 @@ func (b *remoteChartBuilder) Build(_ context.Context, ref Reference, p string, o
|
|||
result.ValueFiles = opts.GetValueFiles()
|
||||
}
|
||||
|
||||
chart.Metadata.Version = result.Version
|
||||
|
||||
// Package the chart with the custom values
|
||||
if err = packageToPath(chart, p); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -17,13 +17,200 @@ limitations under the License.
|
|||
package chart
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
helmchart "helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
"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) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue