github.com/cloudposse/helm@v2.2.3+incompatible/pkg/helm/client.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package helm // import "k8s.io/helm/pkg/helm"
    18  
    19  import (
    20  	"io"
    21  
    22  	"golang.org/x/net/context"
    23  	"google.golang.org/grpc"
    24  
    25  	"k8s.io/helm/pkg/chartutil"
    26  	"k8s.io/helm/pkg/proto/hapi/chart"
    27  	rls "k8s.io/helm/pkg/proto/hapi/services"
    28  )
    29  
    30  // Client manages client side of the helm-tiller protocol
    31  type Client struct {
    32  	opts options
    33  }
    34  
    35  // NewClient creates a new client.
    36  func NewClient(opts ...Option) *Client {
    37  	var c Client
    38  	return c.Option(opts...)
    39  }
    40  
    41  // Option configures the helm client with the provided options
    42  func (h *Client) Option(opts ...Option) *Client {
    43  	for _, opt := range opts {
    44  		opt(&h.opts)
    45  	}
    46  	return h
    47  }
    48  
    49  // ListReleases lists the current releases.
    50  func (h *Client) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) {
    51  	for _, opt := range opts {
    52  		opt(&h.opts)
    53  	}
    54  	req := &h.opts.listReq
    55  	ctx := NewContext()
    56  
    57  	if h.opts.before != nil {
    58  		if err := h.opts.before(ctx, req); err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  	return h.list(ctx, req)
    63  }
    64  
    65  // InstallRelease loads a chart from chstr, installs it and returns the release response.
    66  func (h *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
    67  	// load the chart to install
    68  	chart, err := chartutil.Load(chstr)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	return h.InstallReleaseFromChart(chart, ns, opts...)
    74  }
    75  
    76  // InstallReleaseFromChart installs a new chart and returns the release response.
    77  func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
    78  	// apply the install options
    79  	for _, opt := range opts {
    80  		opt(&h.opts)
    81  	}
    82  	req := &h.opts.instReq
    83  	req.Chart = chart
    84  	req.Namespace = ns
    85  	req.DryRun = h.opts.dryRun
    86  	req.DisableHooks = h.opts.disableHooks
    87  	req.ReuseName = h.opts.reuseName
    88  	ctx := NewContext()
    89  
    90  	if h.opts.before != nil {
    91  		if err := h.opts.before(ctx, req); err != nil {
    92  			return nil, err
    93  		}
    94  	}
    95  	err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	return h.install(ctx, req)
   101  }
   102  
   103  // DeleteRelease uninstalls a named release and returns the response.
   104  func (h *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) {
   105  	// apply the uninstall options
   106  	for _, opt := range opts {
   107  		opt(&h.opts)
   108  	}
   109  
   110  	if h.opts.dryRun {
   111  		// In the dry run case, just see if the release exists
   112  		r, err := h.ReleaseContent(rlsName)
   113  		if err != nil {
   114  			return &rls.UninstallReleaseResponse{}, err
   115  		}
   116  		return &rls.UninstallReleaseResponse{Release: r.Release}, nil
   117  	}
   118  
   119  	req := &h.opts.uninstallReq
   120  	req.Name = rlsName
   121  	req.DisableHooks = h.opts.disableHooks
   122  	ctx := NewContext()
   123  
   124  	if h.opts.before != nil {
   125  		if err := h.opts.before(ctx, req); err != nil {
   126  			return nil, err
   127  		}
   128  	}
   129  	return h.delete(ctx, req)
   130  }
   131  
   132  // UpdateRelease loads a chart from chstr and updates a release to a new/different chart
   133  func (h *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
   134  	// load the chart to update
   135  	chart, err := chartutil.Load(chstr)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	return h.UpdateReleaseFromChart(rlsName, chart, opts...)
   141  }
   142  
   143  // UpdateReleaseFromChart updates a release to a new/different chart
   144  func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
   145  
   146  	// apply the update options
   147  	for _, opt := range opts {
   148  		opt(&h.opts)
   149  	}
   150  	req := &h.opts.updateReq
   151  	req.Chart = chart
   152  	req.DryRun = h.opts.dryRun
   153  	req.Name = rlsName
   154  	req.DisableHooks = h.opts.disableHooks
   155  	req.Recreate = h.opts.recreate
   156  	req.ResetValues = h.opts.resetValues
   157  	ctx := NewContext()
   158  
   159  	if h.opts.before != nil {
   160  		if err := h.opts.before(ctx, req); err != nil {
   161  			return nil, err
   162  		}
   163  	}
   164  	err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	return h.update(ctx, req)
   170  }
   171  
   172  // GetVersion returns the server version
   173  func (h *Client) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) {
   174  	for _, opt := range opts {
   175  		opt(&h.opts)
   176  	}
   177  	req := &rls.GetVersionRequest{}
   178  	ctx := NewContext()
   179  
   180  	if h.opts.before != nil {
   181  		if err := h.opts.before(ctx, req); err != nil {
   182  			return nil, err
   183  		}
   184  	}
   185  	return h.version(ctx, req)
   186  }
   187  
   188  // RollbackRelease rolls back a release to the previous version
   189  func (h *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) {
   190  	for _, opt := range opts {
   191  		opt(&h.opts)
   192  	}
   193  	req := &h.opts.rollbackReq
   194  	req.DisableHooks = h.opts.disableHooks
   195  	req.DryRun = h.opts.dryRun
   196  	req.Name = rlsName
   197  	ctx := NewContext()
   198  
   199  	if h.opts.before != nil {
   200  		if err := h.opts.before(ctx, req); err != nil {
   201  			return nil, err
   202  		}
   203  	}
   204  	return h.rollback(ctx, req)
   205  }
   206  
   207  // ReleaseStatus returns the given release's status.
   208  func (h *Client) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) {
   209  	for _, opt := range opts {
   210  		opt(&h.opts)
   211  	}
   212  	req := &h.opts.statusReq
   213  	req.Name = rlsName
   214  	ctx := NewContext()
   215  
   216  	if h.opts.before != nil {
   217  		if err := h.opts.before(ctx, req); err != nil {
   218  			return nil, err
   219  		}
   220  	}
   221  	return h.status(ctx, req)
   222  }
   223  
   224  // ReleaseContent returns the configuration for a given release.
   225  func (h *Client) ReleaseContent(rlsName string, opts ...ContentOption) (*rls.GetReleaseContentResponse, error) {
   226  	for _, opt := range opts {
   227  		opt(&h.opts)
   228  	}
   229  	req := &h.opts.contentReq
   230  	req.Name = rlsName
   231  	ctx := NewContext()
   232  
   233  	if h.opts.before != nil {
   234  		if err := h.opts.before(ctx, req); err != nil {
   235  			return nil, err
   236  		}
   237  	}
   238  	return h.content(ctx, req)
   239  }
   240  
   241  // ReleaseHistory returns a release's revision history.
   242  func (h *Client) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) {
   243  	for _, opt := range opts {
   244  		opt(&h.opts)
   245  	}
   246  
   247  	req := &h.opts.histReq
   248  	req.Name = rlsName
   249  	ctx := NewContext()
   250  
   251  	if h.opts.before != nil {
   252  		if err := h.opts.before(ctx, req); err != nil {
   253  			return nil, err
   254  		}
   255  	}
   256  	return h.history(ctx, req)
   257  }
   258  
   259  // RunReleaseTest executes a pre-defined test on a release
   260  func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) {
   261  	for _, opt := range opts {
   262  		opt(&h.opts)
   263  	}
   264  
   265  	req := &h.opts.testReq
   266  	req.Name = rlsName
   267  	ctx := NewContext()
   268  
   269  	return h.test(ctx, req)
   270  }
   271  
   272  // Executes tiller.ListReleases RPC.
   273  func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) {
   274  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	defer c.Close()
   279  
   280  	rlc := rls.NewReleaseServiceClient(c)
   281  	s, err := rlc.ListReleases(ctx, req)
   282  	if err != nil {
   283  		return nil, err
   284  	}
   285  
   286  	return s.Recv()
   287  }
   288  
   289  // Executes tiller.InstallRelease RPC.
   290  func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) {
   291  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	defer c.Close()
   296  
   297  	rlc := rls.NewReleaseServiceClient(c)
   298  	return rlc.InstallRelease(ctx, req)
   299  }
   300  
   301  // Executes tiller.UninstallRelease RPC.
   302  func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) {
   303  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   304  	if err != nil {
   305  		return nil, err
   306  	}
   307  	defer c.Close()
   308  
   309  	rlc := rls.NewReleaseServiceClient(c)
   310  	return rlc.UninstallRelease(ctx, req)
   311  }
   312  
   313  // Executes tiller.UpdateRelease RPC.
   314  func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) {
   315  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	defer c.Close()
   320  
   321  	rlc := rls.NewReleaseServiceClient(c)
   322  	return rlc.UpdateRelease(ctx, req)
   323  }
   324  
   325  // Executes tiller.RollbackRelease RPC.
   326  func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) {
   327  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   328  	if err != nil {
   329  		return nil, err
   330  	}
   331  	defer c.Close()
   332  
   333  	rlc := rls.NewReleaseServiceClient(c)
   334  	return rlc.RollbackRelease(ctx, req)
   335  }
   336  
   337  // Executes tiller.GetReleaseStatus RPC.
   338  func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) {
   339  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   340  	if err != nil {
   341  		return nil, err
   342  	}
   343  	defer c.Close()
   344  
   345  	rlc := rls.NewReleaseServiceClient(c)
   346  	return rlc.GetReleaseStatus(ctx, req)
   347  }
   348  
   349  // Executes tiller.GetReleaseContent RPC.
   350  func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) {
   351  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   352  	if err != nil {
   353  		return nil, err
   354  	}
   355  	defer c.Close()
   356  
   357  	rlc := rls.NewReleaseServiceClient(c)
   358  	return rlc.GetReleaseContent(ctx, req)
   359  }
   360  
   361  // Executes tiller.GetVersion RPC.
   362  func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) {
   363  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   364  	if err != nil {
   365  		return nil, err
   366  	}
   367  	defer c.Close()
   368  
   369  	rlc := rls.NewReleaseServiceClient(c)
   370  	return rlc.GetVersion(ctx, req)
   371  }
   372  
   373  // Executes tiller.GetHistory RPC.
   374  func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) {
   375  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  	defer c.Close()
   380  
   381  	rlc := rls.NewReleaseServiceClient(c)
   382  	return rlc.GetHistory(ctx, req)
   383  }
   384  
   385  // Executes tiller.TestRelease RPC.
   386  func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) {
   387  	errc := make(chan error, 1)
   388  	c, err := grpc.Dial(h.opts.host, grpc.WithInsecure())
   389  	if err != nil {
   390  		errc <- err
   391  		return nil, errc
   392  	}
   393  
   394  	ch := make(chan *rls.TestReleaseResponse, 1)
   395  	go func() {
   396  		defer close(errc)
   397  		defer close(ch)
   398  		defer c.Close()
   399  
   400  		rlc := rls.NewReleaseServiceClient(c)
   401  		s, err := rlc.RunReleaseTest(ctx, req)
   402  		if err != nil {
   403  			errc <- err
   404  			return
   405  		}
   406  
   407  		for {
   408  			msg, err := s.Recv()
   409  			if err == io.EOF {
   410  				return
   411  			}
   412  			if err != nil {
   413  				errc <- err
   414  				return
   415  			}
   416  			ch <- msg
   417  		}
   418  	}()
   419  
   420  	return ch, errc
   421  }