mirror of
https://github.com/helm/helm.git
synced 2026-08-08 17:11:18 +00:00
Merge pull request #1253 from fibonacci1729/chore/pkg-helm-tests
chore(helm): add test coverage to pkg/helm
This commit is contained in:
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package helm // import "k8s.io/helm/pkg/helm"
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
@@ -44,7 +45,8 @@ type Client struct {
|
||||
|
||||
// NewClient creates a new client.
|
||||
func NewClient(opts ...Option) *Client {
|
||||
return new(Client).Init().Option(opts...)
|
||||
var c Client
|
||||
return c.Option(opts...)
|
||||
}
|
||||
|
||||
// Option configures the helm client with the provided options
|
||||
@@ -55,117 +57,271 @@ func (h *Client) Option(opts ...Option) *Client {
|
||||
return h
|
||||
}
|
||||
|
||||
// Init initializes the helm client with default options
|
||||
func (h *Client) Init() *Client {
|
||||
return h
|
||||
}
|
||||
|
||||
// ListReleases lists the current releases.
|
||||
func (h *Client) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
defer c.Close()
|
||||
req := &h.opts.listReq
|
||||
ctx := NewContext()
|
||||
|
||||
return h.opts.rpcListReleases(rls.NewReleaseServiceClient(c), opts...)
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.list(ctx, req)
|
||||
}
|
||||
|
||||
// InstallRelease installs a new chart and returns the release response.
|
||||
func (h *Client) InstallRelease(chStr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
chart, err := chartutil.Load(chStr)
|
||||
func (h *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
|
||||
// load the chart to install
|
||||
chart, err := chartutil.Load(chstr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h.opts.rpcInstallRelease(chart, rls.NewReleaseServiceClient(c), ns, opts...)
|
||||
// apply the install options
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
req := &h.opts.instReq
|
||||
req.Chart = chart
|
||||
req.Namespace = ns
|
||||
req.DryRun = h.opts.dryRun
|
||||
req.DisableHooks = h.opts.disableHooks
|
||||
req.ReuseName = h.opts.reuseName
|
||||
ctx := NewContext()
|
||||
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.install(ctx, req)
|
||||
}
|
||||
|
||||
// DeleteRelease uninstalls a named release and returns the response.
|
||||
//
|
||||
// Note: there aren't currently any supported DeleteOptions, but they are
|
||||
// kept in the API signature as a placeholder for future additions.
|
||||
func (h *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if h.opts.dryRun {
|
||||
// In the dry run case, just see if the release exists
|
||||
r, err := h.ReleaseContent(rlsName, nil)
|
||||
if err != nil {
|
||||
return &rls.UninstallReleaseResponse{}, err
|
||||
}
|
||||
return &rls.UninstallReleaseResponse{Release: r.Release}, nil
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
return h.opts.rpcDeleteRelease(rlsName, rls.NewReleaseServiceClient(c), opts...)
|
||||
// apply the uninstall options
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
|
||||
req := &h.opts.uninstallReq
|
||||
req.Name = rlsName
|
||||
req.DisableHooks = h.opts.disableHooks
|
||||
ctx := NewContext()
|
||||
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.delete(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateRelease updates a release to a new/different chart
|
||||
func (h *Client) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
chart, err := chartutil.Load(chStr)
|
||||
func (h *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
|
||||
// load the chart to update
|
||||
chart, err := chartutil.Load(chstr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h.opts.rpcUpdateRelease(rlsName, chart, rls.NewReleaseServiceClient(c), opts...)
|
||||
// apply the update options
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
req := &h.opts.updateReq
|
||||
req.Chart = chart
|
||||
req.DryRun = h.opts.dryRun
|
||||
req.Name = rlsName
|
||||
ctx := NewContext()
|
||||
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.update(ctx, req)
|
||||
}
|
||||
|
||||
// GetVersion returns the server version
|
||||
//
|
||||
// Note: there aren't currently any supported StatusOptions,
|
||||
// but they are kept in the API signature as a placeholder for future additions.
|
||||
func (h *Client) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
defer c.Close()
|
||||
req := &rls.GetVersionRequest{}
|
||||
ctx := NewContext()
|
||||
|
||||
return h.opts.rpcGetVersion(rls.NewReleaseServiceClient(c), opts...)
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.version(ctx, req)
|
||||
}
|
||||
|
||||
// RollbackRelease rolls back a release to the previous version
|
||||
func (h *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
defer c.Close()
|
||||
req := &h.opts.rollbackReq
|
||||
req.DisableHooks = h.opts.disableHooks
|
||||
req.DryRun = h.opts.dryRun
|
||||
req.Name = rlsName
|
||||
ctx := NewContext()
|
||||
|
||||
return h.opts.rpcRollbackRelease(rlsName, rls.NewReleaseServiceClient(c), opts...)
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.rollback(ctx, req)
|
||||
}
|
||||
|
||||
// ReleaseStatus returns the given release's status.
|
||||
//
|
||||
// Note: there aren't currently any supported StatusOptions,
|
||||
// but they are kept in the API signature as a placeholder for future additions.
|
||||
func (h *Client) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
defer c.Close()
|
||||
req := &h.opts.statusReq
|
||||
req.Name = rlsName
|
||||
ctx := NewContext()
|
||||
|
||||
return h.opts.rpcGetReleaseStatus(rlsName, rls.NewReleaseServiceClient(c), opts...)
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.status(ctx, req)
|
||||
}
|
||||
|
||||
// ReleaseContent returns the configuration for a given release.
|
||||
//
|
||||
// Note: there aren't currently any supported ContentOptions, but
|
||||
// they are kept in the API signature as a placeholder for future additions.
|
||||
func (h *Client) ReleaseContent(rlsName string, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(&h.opts)
|
||||
}
|
||||
req := &h.opts.contentReq
|
||||
req.Name = rlsName
|
||||
ctx := NewContext()
|
||||
|
||||
if h.opts.before != nil {
|
||||
if err := h.opts.before(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return h.content(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.ListReleases RPC.
|
||||
func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
return h.opts.rpcGetReleaseContent(rlsName, rls.NewReleaseServiceClient(c), opts...)
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
s, err := rlc.ListReleases(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.Recv()
|
||||
}
|
||||
|
||||
// Executes tiller.InstallRelease RPC.
|
||||
func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.InstallRelease(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.UninstallRelease RPC.
|
||||
func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.UninstallRelease(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.UpdateRelease RPC.
|
||||
func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.UpdateRelease(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.RollbackRelease RPC.
|
||||
func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.RollbackRelease(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.GetReleaseStatus RPC.
|
||||
func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.GetReleaseStatus(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.GetReleaseContent RPC.
|
||||
func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.GetReleaseContent(ctx, req)
|
||||
}
|
||||
|
||||
// Executes tiller.GetVersion RPC.
|
||||
func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) {
|
||||
c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
rlc := rls.NewReleaseServiceClient(c)
|
||||
return rlc.GetVersion(ctx, req)
|
||||
}
|
||||
|
||||
315
pkg/helm/helm_test.go
Normal file
315
pkg/helm/helm_test.go
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"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 ReleaseListOption's are 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,
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
// Options used in ListReleases
|
||||
ops := []ReleaseListOption{
|
||||
ReleaseListSort(sortBy),
|
||||
ReleaseListOrder(sortOrd),
|
||||
ReleaseListLimit(limit),
|
||||
ReleaseListOffset(offset),
|
||||
ReleaseListFilter(filter),
|
||||
ReleaseListStatuses(codes),
|
||||
}
|
||||
|
||||
// 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
|
||||
})
|
||||
|
||||
NewClient(b4c).ListReleases(ops...)
|
||||
}
|
||||
|
||||
// Verify InstallOption's are 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 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
|
||||
})
|
||||
|
||||
NewClient(b4c).InstallRelease(chartName, namespace, ops...)
|
||||
}
|
||||
|
||||
// Verify DeleteOptions's are 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
|
||||
})
|
||||
|
||||
NewClient(b4c).DeleteRelease(releaseName, ops...)
|
||||
}
|
||||
|
||||
// Verify UpdateOption's are applied to an UpdateReleaseRequest correctly.
|
||||
func TestUpdateRelease_VerifyOptions(t *testing.T) {
|
||||
// Options testdata
|
||||
var chartName = "alpine"
|
||||
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
|
||||
})
|
||||
|
||||
NewClient(b4c).UpdateRelease(releaseName, chartName, ops...)
|
||||
}
|
||||
|
||||
// Verify RollbackOption's are 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
|
||||
})
|
||||
|
||||
NewClient(b4c).RollbackRelease(releaseName, ops...)
|
||||
}
|
||||
|
||||
// Verify StatusOption's are 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
|
||||
})
|
||||
|
||||
NewClient(b4c).ReleaseStatus(releaseName, StatusReleaseVersion(revision))
|
||||
}
|
||||
|
||||
// Verify ContentOption's are 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
|
||||
})
|
||||
|
||||
NewClient(b4c).ReleaseContent(releaseName, ContentReleaseVersion(revision))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package helm
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
@@ -41,6 +42,8 @@ type options struct {
|
||||
reuseName bool
|
||||
// if set, skip running hooks
|
||||
disableHooks bool
|
||||
// name of release
|
||||
releaseName string
|
||||
// release list options are applied directly to the list releases request
|
||||
listReq rls.ListReleasesRequest
|
||||
// release install options are applied directly to the install release request
|
||||
@@ -55,6 +58,8 @@ type options struct {
|
||||
contentReq rls.GetReleaseContentRequest
|
||||
// release rollback options are applied directly to the rollback release request
|
||||
rollbackReq rls.RollbackReleaseRequest
|
||||
// before intercepts client calls before sending
|
||||
before func(context.Context, proto.Message) error
|
||||
}
|
||||
|
||||
// Host specifies the host address of the Tiller release server, (default = ":44134").
|
||||
@@ -64,6 +69,15 @@ func Host(host string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// BeforeCall returns an option that allows intercepting a helm client rpc
|
||||
// before being sent OTA to tiller. The intercepting function should return
|
||||
// an error to indicate that the call should not proceed or nil otherwise.
|
||||
func BeforeCall(fn func(context.Context, proto.Message) error) Option {
|
||||
return func(opts *options) {
|
||||
opts.before = fn
|
||||
}
|
||||
}
|
||||
|
||||
// ReleaseListOption allows specifying various settings
|
||||
// configurable by the helm client user for overriding
|
||||
// the defaults used when running the `helm list` command.
|
||||
@@ -258,111 +272,8 @@ type UpdateOption func(*options)
|
||||
// running the `helm rollback` command.
|
||||
type RollbackOption func(*options)
|
||||
|
||||
// RPC helpers defined on `options` type. Note: These actually execute the
|
||||
// the corresponding tiller RPC. There is no particular reason why these
|
||||
// are APIs are hung off `options`, they are internal to pkg/helm to remain
|
||||
// malleable.
|
||||
|
||||
// Executes tiller.ListReleases RPC.
|
||||
func (o *options) rpcListReleases(rlc rls.ReleaseServiceClient, opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) {
|
||||
// apply release list options
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
s, err := rlc.ListReleases(NewContext(), &o.listReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.Recv()
|
||||
}
|
||||
|
||||
// NewContext creates a versioned context.
|
||||
func NewContext() context.Context {
|
||||
md := metadata.Pairs("x-helm-api-client", version.Version)
|
||||
return metadata.NewContext(context.TODO(), md)
|
||||
}
|
||||
|
||||
// Executes tiller.InstallRelease RPC.
|
||||
func (o *options) rpcInstallRelease(chr *cpb.Chart, rlc rls.ReleaseServiceClient, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
|
||||
// apply the install options
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
o.instReq.Chart = chr
|
||||
o.instReq.Namespace = ns
|
||||
o.instReq.DryRun = o.dryRun
|
||||
o.instReq.DisableHooks = o.disableHooks
|
||||
o.instReq.ReuseName = o.reuseName
|
||||
|
||||
return rlc.InstallRelease(NewContext(), &o.instReq)
|
||||
}
|
||||
|
||||
// Executes tiller.UninstallRelease RPC.
|
||||
func (o *options) rpcDeleteRelease(rlsName string, rlc rls.ReleaseServiceClient, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
if o.dryRun {
|
||||
// In the dry run case, just see if the release exists
|
||||
r, err := o.rpcGetReleaseContent(rlsName, rlc)
|
||||
if err != nil {
|
||||
return &rls.UninstallReleaseResponse{}, err
|
||||
}
|
||||
return &rls.UninstallReleaseResponse{Release: r.Release}, nil
|
||||
}
|
||||
|
||||
o.uninstallReq.Name = rlsName
|
||||
o.uninstallReq.DisableHooks = o.disableHooks
|
||||
|
||||
return rlc.UninstallRelease(NewContext(), &o.uninstallReq)
|
||||
}
|
||||
|
||||
// Executes tiller.UpdateRelease RPC.
|
||||
func (o *options) rpcUpdateRelease(rlsName string, chr *cpb.Chart, rlc rls.ReleaseServiceClient, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
o.updateReq.Chart = chr
|
||||
o.updateReq.DryRun = o.dryRun
|
||||
o.updateReq.Name = rlsName
|
||||
|
||||
return rlc.UpdateRelease(NewContext(), &o.updateReq)
|
||||
}
|
||||
|
||||
// Executes tiller.UpdateRelease RPC.
|
||||
func (o *options) rpcRollbackRelease(rlsName string, rlc rls.ReleaseServiceClient, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
o.rollbackReq.DryRun = o.dryRun
|
||||
o.rollbackReq.Name = rlsName
|
||||
|
||||
return rlc.RollbackRelease(NewContext(), &o.rollbackReq)
|
||||
}
|
||||
|
||||
// Executes tiller.GetReleaseStatus RPC.
|
||||
func (o *options) rpcGetReleaseStatus(rlsName string, rlc rls.ReleaseServiceClient, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
o.statusReq.Name = rlsName
|
||||
return rlc.GetReleaseStatus(NewContext(), &o.statusReq)
|
||||
}
|
||||
|
||||
// Executes tiller.GetReleaseContent.
|
||||
func (o *options) rpcGetReleaseContent(rlsName string, rlc rls.ReleaseServiceClient, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) {
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
o.contentReq.Name = rlsName
|
||||
return rlc.GetReleaseContent(NewContext(), &o.contentReq)
|
||||
}
|
||||
|
||||
// Executes tiller.GetVersion RPC.
|
||||
func (o *options) rpcGetVersion(rlc rls.ReleaseServiceClient, opts ...VersionOption) (*rls.GetVersionResponse, error) {
|
||||
req := &rls.GetVersionRequest{}
|
||||
return rlc.GetVersion(NewContext(), req)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user