github.com/azlyth/helm@v2.8.2+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  // PingTiller pings the Tiller pod and ensure's that it is up and runnning
   188  func (c *FakeClient) PingTiller() error {
   189  	return nil
   190  }
   191  
   192  // MockHookTemplate is the hook template used for all mock release objects.
   193  var MockHookTemplate = `apiVersion: v1
   194  kind: Job
   195  metadata:
   196    annotations:
   197      "helm.sh/hooks": pre-install
   198  `
   199  
   200  // MockManifest is the manifest used for all mock release objects.
   201  var MockManifest = `apiVersion: v1
   202  kind: Secret
   203  metadata:
   204    name: fixture
   205  `
   206  
   207  // MockReleaseOptions allows for user-configurable options on mock release objects.
   208  type MockReleaseOptions struct {
   209  	Name       string
   210  	Version    int32
   211  	Chart      *chart.Chart
   212  	StatusCode release.Status_Code
   213  	Namespace  string
   214  }
   215  
   216  // ReleaseMock creates a mock release object based on options set by MockReleaseOptions. This function should typically not be used outside of testing.
   217  func ReleaseMock(opts *MockReleaseOptions) *release.Release {
   218  	date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0}
   219  
   220  	name := opts.Name
   221  	if name == "" {
   222  		name = "testrelease-" + string(rand.Intn(100))
   223  	}
   224  
   225  	var version int32 = 1
   226  	if opts.Version != 0 {
   227  		version = opts.Version
   228  	}
   229  
   230  	namespace := opts.Namespace
   231  	if namespace == "" {
   232  		namespace = "default"
   233  	}
   234  
   235  	ch := opts.Chart
   236  	if opts.Chart == nil {
   237  		ch = &chart.Chart{
   238  			Metadata: &chart.Metadata{
   239  				Name:    "foo",
   240  				Version: "0.1.0-beta.1",
   241  			},
   242  			Templates: []*chart.Template{
   243  				{Name: "templates/foo.tpl", Data: []byte(MockManifest)},
   244  			},
   245  		}
   246  	}
   247  
   248  	scode := release.Status_DEPLOYED
   249  	if opts.StatusCode > 0 {
   250  		scode = opts.StatusCode
   251  	}
   252  
   253  	return &release.Release{
   254  		Name: name,
   255  		Info: &release.Info{
   256  			FirstDeployed: &date,
   257  			LastDeployed:  &date,
   258  			Status:        &release.Status{Code: scode},
   259  			Description:   "Release mock",
   260  		},
   261  		Chart:     ch,
   262  		Config:    &chart.Config{Raw: `name: "value"`},
   263  		Version:   version,
   264  		Namespace: namespace,
   265  		Hooks: []*release.Hook{
   266  			{
   267  				Name:     "pre-install-hook",
   268  				Kind:     "Job",
   269  				Path:     "pre-install-hook.yaml",
   270  				Manifest: MockHookTemplate,
   271  				LastRun:  &date,
   272  				Events:   []release.Hook_Event{release.Hook_PRE_INSTALL},
   273  			},
   274  		},
   275  		Manifest: MockManifest,
   276  	}
   277  }