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(®istry.Authorizer{ 68 Client: client, 69 }), 70 registry.ClientOptResolver(®istry.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 }