Permalink
378 lines (323 sloc) 10.8 KB
/*
Copyright The Helm 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 helm // import "k8s.io/helm/pkg/helm"
import (
"errors"
"os/exec"
"path/filepath"
"reflect"
"strings"
"testing"
"github.com/golang/protobuf/proto"
"golang.org/x/net/context"
"k8s.io/helm/pkg/chartutil"
cpb "k8s.io/helm/pkg/proto/hapi/chart"
rls "k8s.io/helm/pkg/proto/hapi/release"
tpb "k8s.io/helm/pkg/proto/hapi/services"
)
// Path to example charts relative to pkg/helm.
const chartsDir = "../../docs/examples/"
// Sentinel error to indicate to the Helm client to not send the request to Tiller.
var errSkip = errors.New("test: skip")
// Verify each ReleaseListOption is applied to a ListReleasesRequest correctly.
func TestListReleases_VerifyOptions(t *testing.T) {
// Options testdata
var limit = 2
var offset = "offset"
var filter = "filter"
var sortBy = int32(2)
var sortOrd = int32(1)
var codes = []rls.Status_Code{
rls.Status_FAILED,
rls.Status_DELETED,
rls.Status_DEPLOYED,
rls.Status_SUPERSEDED,
}
var namespace = "namespace"
// Expected ListReleasesRequest message
exp := &tpb.ListReleasesRequest{
Limit: int64(limit),
Offset: offset,
Filter: filter,
SortBy: tpb.ListSort_SortBy(sortBy),
SortOrder: tpb.ListSort_SortOrder(sortOrd),
StatusCodes: codes,
Namespace: namespace,
}
// Options used in ListReleases
ops := []ReleaseListOption{
ReleaseListSort(sortBy),
ReleaseListOrder(sortOrd),
ReleaseListLimit(limit),
ReleaseListOffset(offset),
ReleaseListFilter(filter),
ReleaseListStatuses(codes),
ReleaseListNamespace(namespace),
}
// BeforeCall option to intercept Helm client ListReleasesRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.ListReleasesRequest:
t.Logf("ListReleasesRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type ListReleasesRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.ListReleases(ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.listReq.Filter)
}
// Verify each InstallOption is applied to an InstallReleaseRequest correctly.
func TestInstallRelease_VerifyOptions(t *testing.T) {
// Options testdata
var disableHooks = true
var releaseName = "test"
var namespace = "default"
var reuseName = true
var dryRun = true
var chartName = "alpine"
var chartPath = filepath.Join(chartsDir, chartName)
var overrides = []byte("key1=value1,key2=value2")
// Expected InstallReleaseRequest message
exp := &tpb.InstallReleaseRequest{
Chart: loadChart(t, chartName),
Values: &cpb.Config{Raw: string(overrides)},
DryRun: dryRun,
Name: releaseName,
DisableHooks: disableHooks,
Namespace: namespace,
ReuseName: reuseName,
}
// Options used in InstallRelease
ops := []InstallOption{
ValueOverrides(overrides),
InstallDryRun(dryRun),
ReleaseName(releaseName),
InstallReuseName(reuseName),
InstallDisableHooks(disableHooks),
}
// BeforeCall option to intercept Helm client InstallReleaseRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.InstallReleaseRequest:
t.Logf("InstallReleaseRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type InstallReleaseRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.InstallRelease(chartPath, namespace, ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.instReq.Name)
}
// Verify each DeleteOptions is applied to an UninstallReleaseRequest correctly.
func TestDeleteRelease_VerifyOptions(t *testing.T) {
// Options testdata
var releaseName = "test"
var disableHooks = true
var purgeFlag = true
// Expected DeleteReleaseRequest message
exp := &tpb.UninstallReleaseRequest{
Name: releaseName,
Purge: purgeFlag,
DisableHooks: disableHooks,
}
// Options used in DeleteRelease
ops := []DeleteOption{
DeletePurge(purgeFlag),
DeleteDisableHooks(disableHooks),
}
// BeforeCall option to intercept Helm client DeleteReleaseRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.UninstallReleaseRequest:
t.Logf("UninstallReleaseRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type UninstallReleaseRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.DeleteRelease(releaseName, ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.uninstallReq.Name)
}
// Verify each UpdateOption is applied to an UpdateReleaseRequest correctly.
func TestUpdateRelease_VerifyOptions(t *testing.T) {
// Options testdata
var chartName = "alpine"
var chartPath = filepath.Join(chartsDir, chartName)
var releaseName = "test"
var disableHooks = true
var overrides = []byte("key1=value1,key2=value2")
var dryRun = false
// Expected UpdateReleaseRequest message
exp := &tpb.UpdateReleaseRequest{
Name: releaseName,
Chart: loadChart(t, chartName),
Values: &cpb.Config{Raw: string(overrides)},
DryRun: dryRun,
DisableHooks: disableHooks,
}
// Options used in UpdateRelease
ops := []UpdateOption{
UpgradeDryRun(dryRun),
UpdateValueOverrides(overrides),
UpgradeDisableHooks(disableHooks),
}
// BeforeCall option to intercept Helm client UpdateReleaseRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.UpdateReleaseRequest:
t.Logf("UpdateReleaseRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type UpdateReleaseRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.UpdateRelease(releaseName, chartPath, ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.updateReq.Name)
}
// Verify each RollbackOption is applied to a RollbackReleaseRequest correctly.
func TestRollbackRelease_VerifyOptions(t *testing.T) {
// Options testdata
var disableHooks = true
var releaseName = "test"
var revision = int32(2)
var dryRun = true
// Expected RollbackReleaseRequest message
exp := &tpb.RollbackReleaseRequest{
Name: releaseName,
DryRun: dryRun,
Version: revision,
DisableHooks: disableHooks,
}
// Options used in RollbackRelease
ops := []RollbackOption{
RollbackDryRun(dryRun),
RollbackVersion(revision),
RollbackDisableHooks(disableHooks),
}
// BeforeCall option to intercept Helm client RollbackReleaseRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.RollbackReleaseRequest:
t.Logf("RollbackReleaseRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type RollbackReleaseRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.RollbackRelease(releaseName, ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.rollbackReq.Name)
}
// Verify each StatusOption is applied to a GetReleaseStatusRequest correctly.
func TestReleaseStatus_VerifyOptions(t *testing.T) {
// Options testdata
var releaseName = "test"
var revision = int32(2)
// Expected GetReleaseStatusRequest message
exp := &tpb.GetReleaseStatusRequest{
Name: releaseName,
Version: revision,
}
// BeforeCall option to intercept Helm client GetReleaseStatusRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.GetReleaseStatusRequest:
t.Logf("GetReleaseStatusRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type GetReleaseStatusRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.ReleaseStatus(releaseName, StatusReleaseVersion(revision)); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.statusReq.Name)
}
// Verify each ContentOption is applied to a GetReleaseContentRequest correctly.
func TestReleaseContent_VerifyOptions(t *testing.T) {
// Options testdata
var releaseName = "test"
var revision = int32(2)
// Expected GetReleaseContentRequest message
exp := &tpb.GetReleaseContentRequest{
Name: releaseName,
Version: revision,
}
// BeforeCall option to intercept Helm client GetReleaseContentRequest
b4c := BeforeCall(func(_ context.Context, msg proto.Message) error {
switch act := msg.(type) {
case *tpb.GetReleaseContentRequest:
t.Logf("GetReleaseContentRequest: %#+v\n", act)
assert(t, exp, act)
default:
t.Fatalf("expected message of type GetReleaseContentRequest, got %T\n", act)
}
return errSkip
})
client := NewClient(b4c)
if _, err := client.ReleaseContent(releaseName, ContentReleaseVersion(revision)); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err)
}
// ensure options for call are not saved to client
assert(t, "", client.opts.contentReq.Name)
}
func assert(t *testing.T, expect, actual interface{}) {
if !reflect.DeepEqual(expect, actual) {
t.Fatalf("expected %#+v, actual %#+v\n", expect, actual)
}
}
func loadChart(t *testing.T, name string) *cpb.Chart {
c, err := chartutil.Load(filepath.Join(chartsDir, name))
if err != nil {
t.Fatalf("failed to load test chart (%q): %s\n", name, err)
}
return c
}
func TestDoesNotImportKubernetes(t *testing.T) {
cmd := exec.Command("go", "list", "-f", "{{.Deps}}", ".")
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("Failed to execute %s %s: %s", cmd.Path, strings.Join(cmd.Args, " "), err)
}
if strings.Contains(string(output), "k8s.io/kubernetes") {
t.Fatal("k8s.io/helm/pkg/helm contains a dependency on k8s.io/kubernetes. See https://github.com/helm/helm/pull/4499 for more details.")
}
}