1
16
17 package driver
18
19 import (
20 "context"
21 "fmt"
22 "testing"
23
24 sqlmock "github.com/DATA-DOG/go-sqlmock"
25 sq "github.com/Masterminds/squirrel"
26 "github.com/jmoiron/sqlx"
27
28 v1 "k8s.io/api/core/v1"
29 apierrors "k8s.io/apimachinery/pkg/api/errors"
30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31 kblabels "k8s.io/apimachinery/pkg/labels"
32 corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
33
34 rspb "helm.sh/helm/v3/pkg/release"
35 )
36
37 func releaseStub(name string, vers int, namespace string, status rspb.Status) *rspb.Release {
38 return &rspb.Release{
39 Name: name,
40 Version: vers,
41 Namespace: namespace,
42 Info: &rspb.Info{Status: status},
43 Labels: map[string]string{
44 "key1": "val1",
45 "key2": "val2",
46 },
47 }
48 }
49
50 func testKey(name string, vers int) string {
51 return fmt.Sprintf("%s.v%d", name, vers)
52 }
53
54 func tsFixtureMemory(t *testing.T) *Memory {
55 hs := []*rspb.Release{
56
57 releaseStub("rls-a", 4, "default", rspb.StatusDeployed),
58 releaseStub("rls-a", 1, "default", rspb.StatusSuperseded),
59 releaseStub("rls-a", 3, "default", rspb.StatusSuperseded),
60 releaseStub("rls-a", 2, "default", rspb.StatusSuperseded),
61
62 releaseStub("rls-b", 4, "default", rspb.StatusDeployed),
63 releaseStub("rls-b", 1, "default", rspb.StatusSuperseded),
64 releaseStub("rls-b", 3, "default", rspb.StatusSuperseded),
65 releaseStub("rls-b", 2, "default", rspb.StatusSuperseded),
66
67 releaseStub("rls-c", 4, "mynamespace", rspb.StatusDeployed),
68 releaseStub("rls-c", 1, "mynamespace", rspb.StatusSuperseded),
69 releaseStub("rls-c", 3, "mynamespace", rspb.StatusSuperseded),
70 releaseStub("rls-c", 2, "mynamespace", rspb.StatusSuperseded),
71 }
72
73 mem := NewMemory()
74 for _, tt := range hs {
75 err := mem.Create(testKey(tt.Name, tt.Version), tt)
76 if err != nil {
77 t.Fatalf("Test setup failed to create: %s\n", err)
78 }
79 }
80 return mem
81 }
82
83
84
85 func newTestFixtureCfgMaps(t *testing.T, releases ...*rspb.Release) *ConfigMaps {
86 var mock MockConfigMapsInterface
87 mock.Init(t, releases...)
88
89 return NewConfigMaps(&mock)
90 }
91
92
93 type MockConfigMapsInterface struct {
94 corev1.ConfigMapInterface
95
96 objects map[string]*v1.ConfigMap
97 }
98
99
100 func (mock *MockConfigMapsInterface) Init(t *testing.T, releases ...*rspb.Release) {
101 mock.objects = map[string]*v1.ConfigMap{}
102
103 for _, rls := range releases {
104 objkey := testKey(rls.Name, rls.Version)
105
106 cfgmap, err := newConfigMapsObject(objkey, rls, nil)
107 if err != nil {
108 t.Fatalf("Failed to create configmap: %s", err)
109 }
110 mock.objects[objkey] = cfgmap
111 }
112 }
113
114
115 func (mock *MockConfigMapsInterface) Get(_ context.Context, name string, _ metav1.GetOptions) (*v1.ConfigMap, error) {
116 object, ok := mock.objects[name]
117 if !ok {
118 return nil, apierrors.NewNotFound(v1.Resource("tests"), name)
119 }
120 return object, nil
121 }
122
123
124 func (mock *MockConfigMapsInterface) List(_ context.Context, opts metav1.ListOptions) (*v1.ConfigMapList, error) {
125 var list v1.ConfigMapList
126
127 labelSelector, err := kblabels.Parse(opts.LabelSelector)
128 if err != nil {
129 return nil, err
130 }
131
132 for _, cfgmap := range mock.objects {
133 if labelSelector.Matches(kblabels.Set(cfgmap.ObjectMeta.Labels)) {
134 list.Items = append(list.Items, *cfgmap)
135 }
136 }
137 return &list, nil
138 }
139
140
141 func (mock *MockConfigMapsInterface) Create(_ context.Context, cfgmap *v1.ConfigMap, _ metav1.CreateOptions) (*v1.ConfigMap, error) {
142 name := cfgmap.ObjectMeta.Name
143 if object, ok := mock.objects[name]; ok {
144 return object, apierrors.NewAlreadyExists(v1.Resource("tests"), name)
145 }
146 mock.objects[name] = cfgmap
147 return cfgmap, nil
148 }
149
150
151 func (mock *MockConfigMapsInterface) Update(_ context.Context, cfgmap *v1.ConfigMap, _ metav1.UpdateOptions) (*v1.ConfigMap, error) {
152 name := cfgmap.ObjectMeta.Name
153 if _, ok := mock.objects[name]; !ok {
154 return nil, apierrors.NewNotFound(v1.Resource("tests"), name)
155 }
156 mock.objects[name] = cfgmap
157 return cfgmap, nil
158 }
159
160
161 func (mock *MockConfigMapsInterface) Delete(_ context.Context, name string, _ metav1.DeleteOptions) error {
162 if _, ok := mock.objects[name]; !ok {
163 return apierrors.NewNotFound(v1.Resource("tests"), name)
164 }
165 delete(mock.objects, name)
166 return nil
167 }
168
169
170
171 func newTestFixtureSecrets(t *testing.T, releases ...*rspb.Release) *Secrets {
172 var mock MockSecretsInterface
173 mock.Init(t, releases...)
174
175 return NewSecrets(&mock)
176 }
177
178
179 type MockSecretsInterface struct {
180 corev1.SecretInterface
181
182 objects map[string]*v1.Secret
183 }
184
185
186 func (mock *MockSecretsInterface) Init(t *testing.T, releases ...*rspb.Release) {
187 mock.objects = map[string]*v1.Secret{}
188
189 for _, rls := range releases {
190 objkey := testKey(rls.Name, rls.Version)
191
192 secret, err := newSecretsObject(objkey, rls, nil)
193 if err != nil {
194 t.Fatalf("Failed to create secret: %s", err)
195 }
196 mock.objects[objkey] = secret
197 }
198 }
199
200
201 func (mock *MockSecretsInterface) Get(_ context.Context, name string, _ metav1.GetOptions) (*v1.Secret, error) {
202 object, ok := mock.objects[name]
203 if !ok {
204 return nil, apierrors.NewNotFound(v1.Resource("tests"), name)
205 }
206 return object, nil
207 }
208
209
210 func (mock *MockSecretsInterface) List(_ context.Context, opts metav1.ListOptions) (*v1.SecretList, error) {
211 var list v1.SecretList
212
213 labelSelector, err := kblabels.Parse(opts.LabelSelector)
214 if err != nil {
215 return nil, err
216 }
217
218 for _, secret := range mock.objects {
219 if labelSelector.Matches(kblabels.Set(secret.ObjectMeta.Labels)) {
220 list.Items = append(list.Items, *secret)
221 }
222 }
223 return &list, nil
224 }
225
226
227 func (mock *MockSecretsInterface) Create(_ context.Context, secret *v1.Secret, _ metav1.CreateOptions) (*v1.Secret, error) {
228 name := secret.ObjectMeta.Name
229 if object, ok := mock.objects[name]; ok {
230 return object, apierrors.NewAlreadyExists(v1.Resource("tests"), name)
231 }
232 mock.objects[name] = secret
233 return secret, nil
234 }
235
236
237 func (mock *MockSecretsInterface) Update(_ context.Context, secret *v1.Secret, _ metav1.UpdateOptions) (*v1.Secret, error) {
238 name := secret.ObjectMeta.Name
239 if _, ok := mock.objects[name]; !ok {
240 return nil, apierrors.NewNotFound(v1.Resource("tests"), name)
241 }
242 mock.objects[name] = secret
243 return secret, nil
244 }
245
246
247 func (mock *MockSecretsInterface) Delete(_ context.Context, name string, _ metav1.DeleteOptions) error {
248 if _, ok := mock.objects[name]; !ok {
249 return apierrors.NewNotFound(v1.Resource("tests"), name)
250 }
251 delete(mock.objects, name)
252 return nil
253 }
254
255
256 func newTestFixtureSQL(t *testing.T, _ ...*rspb.Release) (*SQL, sqlmock.Sqlmock) {
257 sqlDB, mock, err := sqlmock.New()
258 if err != nil {
259 t.Fatalf("error when opening stub database connection: %v", err)
260 }
261
262 sqlxDB := sqlx.NewDb(sqlDB, "sqlmock")
263 return &SQL{
264 db: sqlxDB,
265 Log: func(_ string, _ ...interface{}) {},
266 namespace: "default",
267 statementBuilder: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
268 }, mock
269 }
270
View as plain text