github.com/darkowlzz/helm@v2.5.1-0.20171213183701-6707fe0468d4+incompatible/pkg/helm/fake.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  	"errors"
    21  	"fmt"
    22  	"math/rand"
    23  	"sync"
    24  
    25  	"github.com/golang/protobuf/ptypes/timestamp"
    26  	"k8s.io/helm/pkg/proto/hapi/chart"
    27  	"k8s.io/helm/pkg/proto/hapi/release"
    28  	rls "k8s.io/helm/pkg/proto/hapi/services"
    29  	"k8s.io/helm/pkg/proto/hapi/version"
    30  )
    31  
    32  // FakeClient implements Interface
    33  type FakeClient struct {
    34  	Rels      []*release.Release
    35  	Responses map[string]release.TestRun_Status
    36  	Opts      options
    37  }
    38  
    39  // Option returns the fake release client
    40  func (c *FakeClient) Option(opts ...Option) Interface {
    41  	for _, opt := range opts {
    42  		opt(&c.Opts)
    43  	}
    44  	return c
    45  }
    46  
    47  var _ Interface = &FakeClient{}
    48  var _ Interface = (*FakeClient)(nil)
    49  
    50  // ListReleases lists the current releases
    51  func (c *FakeClient) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) {
    52  	resp := &rls.ListReleasesResponse{
    53  		Count:    int64(len(c.Rels)),
    54  		Releases: c.Rels,
    55  	}
    56  	return resp, nil
    57  }
    58  
    59  // InstallRelease creates a new release and returns a InstallReleaseResponse containing that release
    60  func (c *FakeClient) InstallRelease(chStr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
    61  	chart := &chart.Chart{}
    62  	return c.InstallReleaseFromChart(chart, ns, opts...)
    63  }
    64  
    65  // InstallReleaseFromChart adds a new MockRelease to the fake client and returns a InstallReleaseResponse containing that release
    66  func (c *FakeClient) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) {
    67  	for _, opt := range opts {
    68  		opt(&c.Opts)
    69  	}
    70  
    71  	releaseName := c.Opts.instReq.Name
    72  
    73  	// Check to see if the release already exists.
    74  	rel, err := c.ReleaseStatus(releaseName, nil)
    75  	if err == nil && rel != nil {
    76  		return nil, errors.New("cannot re-use a name that is still in use")
    77  	}
    78  
    79  	release := ReleaseMock(&MockReleaseOptions{Name: releaseName, Namespace: ns})
    80  	c.Rels = append(c.Rels, release)
    81  
    82  	return &rls.InstallReleaseResponse{
    83  		Release: release,
    84  	}, nil
    85  }
    86  
    87  // DeleteRelease deletes a release from the FakeClient
    88  func (c *FakeClient) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) {
    89  	for i, rel := range c.Rels {
    90  		if rel.Name == rlsName {
    91  			c.Rels = append(c.Rels[:i], c.Rels[i+1:]...)
    92  			return &rls.UninstallReleaseResponse{
    93  				Release: rel,
    94  			}, nil
    95  		}
    96  	}
    97  
    98  	return nil, fmt.Errorf("No such release: %s", rlsName)
    99  }
   100  
   101  // GetVersion returns a fake version
   102  func (c *FakeClient) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) {
   103  	return &rls.GetVersionResponse{
   104  		Version: &version.Version{
   105  			SemVer: "1.2.3-fakeclient+testonly",
   106  		},
   107  	}, nil
   108  }
   109  
   110  // UpdateRelease returns an UpdateReleaseResponse containing the updated release, if it exists
   111  func (c *FakeClient) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
   112  	return c.UpdateReleaseFromChart(rlsName, &chart.Chart{}, opts...)
   113  }
   114  
   115  // UpdateReleaseFromChart returns an UpdateReleaseResponse containing the updated release, if it exists
   116  func (c *FakeClient) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) {
   117  	// Check to see if the release already exists.
   118  	rel, err := c.ReleaseContent(rlsName, nil)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	return &rls.UpdateReleaseResponse{Release: rel.Release}, nil
   124  }
   125  
   126  // RollbackRelease returns nil, nil
   127  func (c *FakeClient) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) {
   128  	return nil, nil
   129  }
   130  
   131  // ReleaseStatus returns a release status response with info from the matching release name.
   132  func (c *FakeClient) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) {
   133  	for _, rel := range c.Rels {
   134  		if rel.Name == rlsName {
   135  			return &rls.GetReleaseStatusResponse{
   136  				Name:      rel.Name,
   137  				Info:      rel.Info,
   138  				Namespace: rel.Namespace,
   139  			}, nil
   140  		}
   141  	}
   142  	return nil, fmt.Errorf("No such release: %s", rlsName)
   143  }
   144  
   145  // ReleaseContent returns the configuration for the matching release name in the fake release client.
   146  func (c *FakeClient) ReleaseContent(rlsName string, opts ...ContentOption) (resp *rls.GetReleaseContentResponse, err error) {
   147  	for _, rel := range c.Rels {
   148  		if rel.Name == rlsName {
   149  			return &rls.GetReleaseContentResponse{
   150  				Release: rel,
   151  			}, nil
   152  		}
   153  	}
   154  	return resp, fmt.Errorf("No such release: %s", rlsName)
   155  }
   156  
   157  // ReleaseHistory returns a release's revision history.
   158  func (c *FakeClient) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) {
   159  	return &rls.GetHistoryResponse{Releases: c.Rels}, nil
   160  }
   161  
   162  // RunReleaseTest executes a pre-defined tests on a release
   163  func (c *FakeClient) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) {
   164  
   165  	results := make(chan *rls.TestReleaseResponse)
   166  	errc := make(chan error, 1)
   167  
   168  	go func() {
   169  		var wg sync.WaitGroup
   170  		for m, s := range c.Responses {
   171  			wg.Add(1)
   172  
   173  			go func(msg string, status release.TestRun_Status) {
   174  				defer wg.Done()
   175  				results <- &rls.TestReleaseResponse{Msg: msg, Status: status}
   176  			}(m, s)
   177  		}
   178  
   179  		wg.Wait()
   180  		close(results)
   181  		close(errc)
   182  	}()
   183  
   184  	return results, errc
   185  }
   186  
   187  // MockHookTemplate is the hook template used for all mock release objects.
   188  var MockHookTemplate = `apiVersion: v1
   189  kind: Job
   190  metadata:
   191    annotations:
   192      "helm.sh/hooks": pre-install
   193  `
   194  
   195  // MockManifest is the manifest used for all mock release objects.
   196  var MockManifest = `apiVersion: v1
   197  kind: Secret
   198  metadata:
   199    name: fixture
   200  `
   201  
   202  // MockReleaseOptions allows for user-configurable options on mock release objects.
   203  type MockReleaseOptions struct {
   204  	Name       string
   205  	Version    int32
   206  	Chart      *chart.Chart
   207  	StatusCode release.Status_Code
   208  	Namespace  string
   209  }
   210  
   211  // ReleaseMock creates a mock release object based on options set by MockReleaseOptions. This function should typically not be used outside of testing.
   212  func ReleaseMock(opts *MockReleaseOptions) *release.Release {
   213  	date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0}
   214  
   215  	name := opts.Name
   216  	if name == "" {
   217  		name = "testrelease-" + string(rand.Intn(100))
   218  	}
   219  
   220  	var version int32 = 1
   221  	if opts.Version != 0 {
   222  		version = opts.Version
   223  	}
   224  
   225  	namespace := opts.Namespace
   226  	if namespace == "" {
   227  		namespace = "default"
   228  	}
   229  
   230  	ch := opts.Chart
   231  	if opts.Chart == nil {
   232  		ch = &chart.Chart{
   233  			Metadata: &chart.Metadata{
   234  				Name:    "foo",
   235  				Version: "0.1.0-beta.1",
   236  			},
   237  			Templates: []*chart.Template{
   238  				{Name: "templates/foo.tpl", Data: []byte(MockManifest)},
   239  			},
   240  		}
   241  	}
   242  
   243  	scode := release.Status_DEPLOYED
   244  	if opts.StatusCode > 0 {
   245  		scode = opts.StatusCode
   246  	}
   247  
   248  	return &release.Release{
   249  		Name: name,
   250  		Info: &release.Info{
   251  			FirstDeployed: &date,
   252  			LastDeployed:  &date,
   253  			Status:        &release.Status{Code: scode},
   254  			Description:   "Release mock",
   255  		},
   256  		Chart:     ch,
   257  		Config:    &chart.Config{Raw: `name: "value"`},
   258  		Version:   version,
   259  		Namespace: namespace,
   260  		Hooks: []*release.Hook{
   261  			{
   262  				Name:     "pre-install-hook",
   263  				Kind:     "Job",
   264  				Path:     "pre-install-hook.yaml",
   265  				Manifest: MockHookTemplate,
   266  				LastRun:  &date,
   267  				Events:   []release.Hook_Event{release.Hook_PRE_INSTALL},
   268  			},
   269  		},
   270  		Manifest: MockManifest,
   271  	}
   272  }