github.com/zsuzhengdu/helm@v3.0.0-beta.3+incompatible/pkg/action/action_test.go (about)

     1  /*
     2  Copyright The Helm Authors.
     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  package action
    17  
    18  import (
    19  	"context"
    20  	"flag"
    21  	"io/ioutil"
    22  	"path/filepath"
    23  	"testing"
    24  	"time"
    25  
    26  	dockerauth "github.com/deislabs/oras/pkg/auth/docker"
    27  	fakeclientset "k8s.io/client-go/kubernetes/fake"
    28  
    29  	"helm.sh/helm/internal/experimental/registry"
    30  	"helm.sh/helm/pkg/chart"
    31  	"helm.sh/helm/pkg/chartutil"
    32  	kubefake "helm.sh/helm/pkg/kube/fake"
    33  	"helm.sh/helm/pkg/release"
    34  	"helm.sh/helm/pkg/storage"
    35  	"helm.sh/helm/pkg/storage/driver"
    36  )
    37  
    38  var verbose = flag.Bool("test.log", false, "enable test logging")
    39  
    40  func actionConfigFixture(t *testing.T) *Configuration {
    41  	t.Helper()
    42  
    43  	client, err := dockerauth.NewClient()
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	resolver, err := client.Resolver(context.Background())
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	tdir, err := ioutil.TempDir("", "helm-action-test")
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	cache, err := registry.NewCache(
    59  		registry.CacheOptDebug(true),
    60  		registry.CacheOptRoot(filepath.Join(tdir, registry.CacheRootDir)),
    61  	)
    62  	if err != nil {
    63  		t.Fatal(err)
    64  	}
    65  
    66  	registryClient, err := registry.NewClient(
    67  		registry.ClientOptAuthorizer(&registry.Authorizer{
    68  			Client: client,
    69  		}),
    70  		registry.ClientOptResolver(&registry.Resolver{
    71  			Resolver: resolver,
    72  		}),
    73  		registry.ClientOptCache(cache),
    74  	)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	return &Configuration{
    80  		Releases:       storage.Init(driver.NewMemory()),
    81  		KubeClient:     &kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: ioutil.Discard}},
    82  		Capabilities:   chartutil.DefaultCapabilities,
    83  		RegistryClient: registryClient,
    84  		Log: func(format string, v ...interface{}) {
    85  			t.Helper()
    86  			if *verbose {
    87  				t.Logf(format, v...)
    88  			}
    89  		},
    90  	}
    91  }
    92  
    93  var manifestWithHook = `kind: ConfigMap
    94  metadata:
    95    name: test-cm
    96    annotations:
    97      "helm.sh/hook": post-install,pre-delete,post-upgrade
    98  data:
    99    name: value`
   100  
   101  var manifestWithTestHook = `kind: Pod
   102    metadata:
   103  	name: finding-nemo,
   104  	annotations:
   105  	  "helm.sh/hook": test
   106    spec:
   107  	containers:
   108  	- name: nemo-test
   109  	  image: fake-image
   110  	  cmd: fake-command
   111    `
   112  
   113  var rbacManifests = `apiVersion: rbac.authorization.k8s.io/v1
   114  kind: Role
   115  metadata:
   116    name: schedule-agents
   117  rules:
   118  - apiGroups: [""]
   119    resources: ["pods", "pods/exec", "pods/log"]
   120    verbs: ["*"]
   121  
   122  ---
   123  
   124  apiVersion: rbac.authorization.k8s.io/v1
   125  kind: RoleBinding
   126  metadata:
   127    name: schedule-agents
   128    namespace: {{ default .Release.Namespace}}
   129  roleRef:
   130    apiGroup: rbac.authorization.k8s.io
   131    kind: Role
   132    name: schedule-agents
   133  subjects:
   134  - kind: ServiceAccount
   135    name: schedule-agents
   136    namespace: {{ .Release.Namespace }}
   137  `
   138  
   139  type chartOptions struct {
   140  	*chart.Chart
   141  }
   142  
   143  type chartOption func(*chartOptions)
   144  
   145  func buildChart(opts ...chartOption) *chart.Chart {
   146  	c := &chartOptions{
   147  		Chart: &chart.Chart{
   148  			// TODO: This should be more complete.
   149  			Metadata: &chart.Metadata{
   150  				APIVersion: "v1",
   151  				Name:       "hello",
   152  				Version:    "0.1.0",
   153  			},
   154  			// This adds a basic template and hooks.
   155  			Templates: []*chart.File{
   156  				{Name: "templates/hello", Data: []byte("hello: world")},
   157  				{Name: "templates/hooks", Data: []byte(manifestWithHook)},
   158  			},
   159  		},
   160  	}
   161  
   162  	for _, opt := range opts {
   163  		opt(c)
   164  	}
   165  
   166  	return c.Chart
   167  }
   168  
   169  func withNotes(notes string) chartOption {
   170  	return func(opts *chartOptions) {
   171  		opts.Templates = append(opts.Templates, &chart.File{
   172  			Name: "templates/NOTES.txt",
   173  			Data: []byte(notes),
   174  		})
   175  	}
   176  }
   177  
   178  func withDependency(dependencyOpts ...chartOption) chartOption {
   179  	return func(opts *chartOptions) {
   180  		opts.AddDependency(buildChart(dependencyOpts...))
   181  	}
   182  }
   183  
   184  func withSampleTemplates() chartOption {
   185  	return func(opts *chartOptions) {
   186  		sampleTemplates := []*chart.File{
   187  			// This adds basic templates and partials.
   188  			{Name: "templates/goodbye", Data: []byte("goodbye: world")},
   189  			{Name: "templates/empty", Data: []byte("")},
   190  			{Name: "templates/with-partials", Data: []byte(`hello: {{ template "_planet" . }}`)},
   191  			{Name: "templates/partials/_planet", Data: []byte(`{{define "_planet"}}Earth{{end}}`)},
   192  		}
   193  		opts.Templates = append(opts.Templates, sampleTemplates...)
   194  	}
   195  }
   196  
   197  func withMultipleManifestTemplate() chartOption {
   198  	return func(opts *chartOptions) {
   199  		sampleTemplates := []*chart.File{
   200  			{Name: "templates/rbac", Data: []byte(rbacManifests)},
   201  		}
   202  		opts.Templates = append(opts.Templates, sampleTemplates...)
   203  	}
   204  }
   205  
   206  func withKube(version string) chartOption {
   207  	return func(opts *chartOptions) {
   208  		opts.Metadata.KubeVersion = version
   209  	}
   210  }
   211  
   212  // releaseStub creates a release stub, complete with the chartStub as its chart.
   213  func releaseStub() *release.Release {
   214  	return namedReleaseStub("angry-panda", release.StatusDeployed)
   215  }
   216  
   217  func namedReleaseStub(name string, status release.Status) *release.Release {
   218  	now := time.Now()
   219  	return &release.Release{
   220  		Name: name,
   221  		Info: &release.Info{
   222  			FirstDeployed: now,
   223  			LastDeployed:  now,
   224  			Status:        status,
   225  			Description:   "Named Release Stub",
   226  		},
   227  		Chart:   buildChart(withSampleTemplates()),
   228  		Config:  map[string]interface{}{"name": "value"},
   229  		Version: 1,
   230  		Hooks: []*release.Hook{
   231  			{
   232  				Name:     "test-cm",
   233  				Kind:     "ConfigMap",
   234  				Path:     "test-cm",
   235  				Manifest: manifestWithHook,
   236  				Events: []release.HookEvent{
   237  					release.HookPostInstall,
   238  					release.HookPreDelete,
   239  				},
   240  			},
   241  			{
   242  				Name:     "finding-nemo",
   243  				Kind:     "Pod",
   244  				Path:     "finding-nemo",
   245  				Manifest: manifestWithTestHook,
   246  				Events: []release.HookEvent{
   247  					release.HookTest,
   248  				},
   249  			},
   250  		},
   251  	}
   252  }
   253  
   254  func TestGetVersionSet(t *testing.T) {
   255  	client := fakeclientset.NewSimpleClientset()
   256  
   257  	vs, err := GetVersionSet(client.Discovery())
   258  	if err != nil {
   259  		t.Error(err)
   260  	}
   261  
   262  	if !vs.Has("v1") {
   263  		t.Errorf("Expected supported versions to at least include v1.")
   264  	}
   265  	if vs.Has("nosuchversion/v1") {
   266  		t.Error("Non-existent version is reported found.")
   267  	}
   268  }