1/*
2Copyright The Helm Authors.
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6    http://www.apache.org/licenses/LICENSE-2.0
7Unless required by applicable law or agreed to in writing, software
8distributed under the License is distributed on an "AS IS" BASIS,
9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10See the License for the specific language governing permissions and
11limitations under the License.
12*/
13
14package driver
15
16import (
17	"encoding/base64"
18	"encoding/json"
19	"reflect"
20	"testing"
21
22	v1 "k8s.io/api/core/v1"
23
24	rspb "helm.sh/helm/v3/pkg/release"
25)
26
27func TestConfigMapName(t *testing.T) {
28	c := newTestFixtureCfgMaps(t)
29	if c.Name() != ConfigMapsDriverName {
30		t.Errorf("Expected name to be %q, got %q", ConfigMapsDriverName, c.Name())
31	}
32}
33
34func TestConfigMapGet(t *testing.T) {
35	vers := 1
36	name := "smug-pigeon"
37	namespace := "default"
38	key := testKey(name, vers)
39	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
40
41	cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{rel}...)
42
43	// get release with key
44	got, err := cfgmaps.Get(key)
45	if err != nil {
46		t.Fatalf("Failed to get release: %s", err)
47	}
48	// compare fetched release with original
49	if !reflect.DeepEqual(rel, got) {
50		t.Errorf("Expected {%v}, got {%v}", rel, got)
51	}
52}
53
54func TestUncompressedConfigMapGet(t *testing.T) {
55	vers := 1
56	name := "smug-pigeon"
57	namespace := "default"
58	key := testKey(name, vers)
59	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
60
61	// Create a test fixture which contains an uncompressed release
62	cfgmap, err := newConfigMapsObject(key, rel, nil)
63	if err != nil {
64		t.Fatalf("Failed to create configmap: %s", err)
65	}
66	b, err := json.Marshal(rel)
67	if err != nil {
68		t.Fatalf("Failed to marshal release: %s", err)
69	}
70	cfgmap.Data["release"] = base64.StdEncoding.EncodeToString(b)
71	var mock MockConfigMapsInterface
72	mock.objects = map[string]*v1.ConfigMap{key: cfgmap}
73	cfgmaps := NewConfigMaps(&mock)
74
75	// get release with key
76	got, err := cfgmaps.Get(key)
77	if err != nil {
78		t.Fatalf("Failed to get release: %s", err)
79	}
80	// compare fetched release with original
81	if !reflect.DeepEqual(rel, got) {
82		t.Errorf("Expected {%v}, got {%v}", rel, got)
83	}
84}
85
86func TestConfigMapList(t *testing.T) {
87	cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{
88		releaseStub("key-1", 1, "default", rspb.StatusUninstalled),
89		releaseStub("key-2", 1, "default", rspb.StatusUninstalled),
90		releaseStub("key-3", 1, "default", rspb.StatusDeployed),
91		releaseStub("key-4", 1, "default", rspb.StatusDeployed),
92		releaseStub("key-5", 1, "default", rspb.StatusSuperseded),
93		releaseStub("key-6", 1, "default", rspb.StatusSuperseded),
94	}...)
95
96	// list all deleted releases
97	del, err := cfgmaps.List(func(rel *rspb.Release) bool {
98		return rel.Info.Status == rspb.StatusUninstalled
99	})
100	// check
101	if err != nil {
102		t.Errorf("Failed to list deleted: %s", err)
103	}
104	if len(del) != 2 {
105		t.Errorf("Expected 2 deleted, got %d:\n%v\n", len(del), del)
106	}
107
108	// list all deployed releases
109	dpl, err := cfgmaps.List(func(rel *rspb.Release) bool {
110		return rel.Info.Status == rspb.StatusDeployed
111	})
112	// check
113	if err != nil {
114		t.Errorf("Failed to list deployed: %s", err)
115	}
116	if len(dpl) != 2 {
117		t.Errorf("Expected 2 deployed, got %d", len(dpl))
118	}
119
120	// list all superseded releases
121	ssd, err := cfgmaps.List(func(rel *rspb.Release) bool {
122		return rel.Info.Status == rspb.StatusSuperseded
123	})
124	// check
125	if err != nil {
126		t.Errorf("Failed to list superseded: %s", err)
127	}
128	if len(ssd) != 2 {
129		t.Errorf("Expected 2 superseded, got %d", len(ssd))
130	}
131}
132
133func TestConfigMapQuery(t *testing.T) {
134	cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{
135		releaseStub("key-1", 1, "default", rspb.StatusUninstalled),
136		releaseStub("key-2", 1, "default", rspb.StatusUninstalled),
137		releaseStub("key-3", 1, "default", rspb.StatusDeployed),
138		releaseStub("key-4", 1, "default", rspb.StatusDeployed),
139		releaseStub("key-5", 1, "default", rspb.StatusSuperseded),
140		releaseStub("key-6", 1, "default", rspb.StatusSuperseded),
141	}...)
142
143	rls, err := cfgmaps.Query(map[string]string{"status": "deployed"})
144	if err != nil {
145		t.Errorf("Failed to query: %s", err)
146	}
147	if len(rls) != 2 {
148		t.Errorf("Expected 2 results, got %d", len(rls))
149	}
150
151	_, err = cfgmaps.Query(map[string]string{"name": "notExist"})
152	if err != ErrReleaseNotFound {
153		t.Errorf("Expected {%v}, got {%v}", ErrReleaseNotFound, err)
154	}
155}
156
157func TestConfigMapCreate(t *testing.T) {
158	cfgmaps := newTestFixtureCfgMaps(t)
159
160	vers := 1
161	name := "smug-pigeon"
162	namespace := "default"
163	key := testKey(name, vers)
164	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
165
166	// store the release in a configmap
167	if err := cfgmaps.Create(key, rel); err != nil {
168		t.Fatalf("Failed to create release with key %q: %s", key, err)
169	}
170
171	// get the release back
172	got, err := cfgmaps.Get(key)
173	if err != nil {
174		t.Fatalf("Failed to get release with key %q: %s", key, err)
175	}
176
177	// compare created release with original
178	if !reflect.DeepEqual(rel, got) {
179		t.Errorf("Expected {%v}, got {%v}", rel, got)
180	}
181}
182
183func TestConfigMapUpdate(t *testing.T) {
184	vers := 1
185	name := "smug-pigeon"
186	namespace := "default"
187	key := testKey(name, vers)
188	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
189
190	cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{rel}...)
191
192	// modify release status code
193	rel.Info.Status = rspb.StatusSuperseded
194
195	// perform the update
196	if err := cfgmaps.Update(key, rel); err != nil {
197		t.Fatalf("Failed to update release: %s", err)
198	}
199
200	// fetch the updated release
201	got, err := cfgmaps.Get(key)
202	if err != nil {
203		t.Fatalf("Failed to get release with key %q: %s", key, err)
204	}
205
206	// check release has actually been updated by comparing modified fields
207	if rel.Info.Status != got.Info.Status {
208		t.Errorf("Expected status %s, got status %s", rel.Info.Status.String(), got.Info.Status.String())
209	}
210}
211
212func TestConfigMapDelete(t *testing.T) {
213	vers := 1
214	name := "smug-pigeon"
215	namespace := "default"
216	key := testKey(name, vers)
217	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
218
219	cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{rel}...)
220
221	// perform the delete on a non-existent release
222	_, err := cfgmaps.Delete("nonexistent")
223	if err != ErrReleaseNotFound {
224		t.Fatalf("Expected ErrReleaseNotFound: got {%v}", err)
225	}
226
227	// perform the delete
228	rls, err := cfgmaps.Delete(key)
229	if err != nil {
230		t.Fatalf("Failed to delete release with key %q: %s", key, err)
231	}
232	if !reflect.DeepEqual(rel, rls) {
233		t.Errorf("Expected {%v}, got {%v}", rel, rls)
234	}
235
236	// fetch the deleted release
237	_, err = cfgmaps.Get(key)
238	if !reflect.DeepEqual(ErrReleaseNotFound, err) {
239		t.Errorf("Expected {%v}, got {%v}", ErrReleaseNotFound, err)
240	}
241}
242