github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/storage/driver/mock_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 17 package driver // import "github.com/stefanmcshane/helm/pkg/storage/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 "github.com/stefanmcshane/helm/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 } 44 } 45 46 func testKey(name string, vers int) string { 47 return fmt.Sprintf("%s.v%d", name, vers) 48 } 49 50 func tsFixtureMemory(t *testing.T) *Memory { 51 hs := []*rspb.Release{ 52 // rls-a 53 releaseStub("rls-a", 4, "default", rspb.StatusDeployed), 54 releaseStub("rls-a", 1, "default", rspb.StatusSuperseded), 55 releaseStub("rls-a", 3, "default", rspb.StatusSuperseded), 56 releaseStub("rls-a", 2, "default", rspb.StatusSuperseded), 57 // rls-b 58 releaseStub("rls-b", 4, "default", rspb.StatusDeployed), 59 releaseStub("rls-b", 1, "default", rspb.StatusSuperseded), 60 releaseStub("rls-b", 3, "default", rspb.StatusSuperseded), 61 releaseStub("rls-b", 2, "default", rspb.StatusSuperseded), 62 // rls-c in other namespace 63 releaseStub("rls-c", 4, "mynamespace", rspb.StatusDeployed), 64 releaseStub("rls-c", 1, "mynamespace", rspb.StatusSuperseded), 65 releaseStub("rls-c", 3, "mynamespace", rspb.StatusSuperseded), 66 releaseStub("rls-c", 2, "mynamespace", rspb.StatusSuperseded), 67 } 68 69 mem := NewMemory() 70 for _, tt := range hs { 71 err := mem.Create(testKey(tt.Name, tt.Version), tt) 72 if err != nil { 73 t.Fatalf("Test setup failed to create: %s\n", err) 74 } 75 } 76 return mem 77 } 78 79 // newTestFixture initializes a MockConfigMapsInterface. 80 // ConfigMaps are created for each release provided. 81 func newTestFixtureCfgMaps(t *testing.T, releases ...*rspb.Release) *ConfigMaps { 82 var mock MockConfigMapsInterface 83 mock.Init(t, releases...) 84 85 return NewConfigMaps(&mock) 86 } 87 88 // MockConfigMapsInterface mocks a kubernetes ConfigMapsInterface 89 type MockConfigMapsInterface struct { 90 corev1.ConfigMapInterface 91 92 objects map[string]*v1.ConfigMap 93 } 94 95 // Init initializes the MockConfigMapsInterface with the set of releases. 96 func (mock *MockConfigMapsInterface) Init(t *testing.T, releases ...*rspb.Release) { 97 mock.objects = map[string]*v1.ConfigMap{} 98 99 for _, rls := range releases { 100 objkey := testKey(rls.Name, rls.Version) 101 102 cfgmap, err := newConfigMapsObject(objkey, rls, nil) 103 if err != nil { 104 t.Fatalf("Failed to create configmap: %s", err) 105 } 106 mock.objects[objkey] = cfgmap 107 } 108 } 109 110 // Get returns the ConfigMap by name. 111 func (mock *MockConfigMapsInterface) Get(_ context.Context, name string, _ metav1.GetOptions) (*v1.ConfigMap, error) { 112 object, ok := mock.objects[name] 113 if !ok { 114 return nil, apierrors.NewNotFound(v1.Resource("tests"), name) 115 } 116 return object, nil 117 } 118 119 // List returns the a of ConfigMaps. 120 func (mock *MockConfigMapsInterface) List(_ context.Context, opts metav1.ListOptions) (*v1.ConfigMapList, error) { 121 var list v1.ConfigMapList 122 123 labelSelector, err := kblabels.Parse(opts.LabelSelector) 124 if err != nil { 125 return nil, err 126 } 127 128 for _, cfgmap := range mock.objects { 129 if labelSelector.Matches(kblabels.Set(cfgmap.ObjectMeta.Labels)) { 130 list.Items = append(list.Items, *cfgmap) 131 } 132 } 133 return &list, nil 134 } 135 136 // Create creates a new ConfigMap. 137 func (mock *MockConfigMapsInterface) Create(_ context.Context, cfgmap *v1.ConfigMap, _ metav1.CreateOptions) (*v1.ConfigMap, error) { 138 name := cfgmap.ObjectMeta.Name 139 if object, ok := mock.objects[name]; ok { 140 return object, apierrors.NewAlreadyExists(v1.Resource("tests"), name) 141 } 142 mock.objects[name] = cfgmap 143 return cfgmap, nil 144 } 145 146 // Update updates a ConfigMap. 147 func (mock *MockConfigMapsInterface) Update(_ context.Context, cfgmap *v1.ConfigMap, _ metav1.UpdateOptions) (*v1.ConfigMap, error) { 148 name := cfgmap.ObjectMeta.Name 149 if _, ok := mock.objects[name]; !ok { 150 return nil, apierrors.NewNotFound(v1.Resource("tests"), name) 151 } 152 mock.objects[name] = cfgmap 153 return cfgmap, nil 154 } 155 156 // Delete deletes a ConfigMap by name. 157 func (mock *MockConfigMapsInterface) Delete(_ context.Context, name string, _ metav1.DeleteOptions) error { 158 if _, ok := mock.objects[name]; !ok { 159 return apierrors.NewNotFound(v1.Resource("tests"), name) 160 } 161 delete(mock.objects, name) 162 return nil 163 } 164 165 // newTestFixture initializes a MockSecretsInterface. 166 // Secrets are created for each release provided. 167 func newTestFixtureSecrets(t *testing.T, releases ...*rspb.Release) *Secrets { 168 var mock MockSecretsInterface 169 mock.Init(t, releases...) 170 171 return NewSecrets(&mock) 172 } 173 174 // MockSecretsInterface mocks a kubernetes SecretsInterface 175 type MockSecretsInterface struct { 176 corev1.SecretInterface 177 178 objects map[string]*v1.Secret 179 } 180 181 // Init initializes the MockSecretsInterface with the set of releases. 182 func (mock *MockSecretsInterface) Init(t *testing.T, releases ...*rspb.Release) { 183 mock.objects = map[string]*v1.Secret{} 184 185 for _, rls := range releases { 186 objkey := testKey(rls.Name, rls.Version) 187 188 secret, err := newSecretsObject(objkey, rls, nil) 189 if err != nil { 190 t.Fatalf("Failed to create secret: %s", err) 191 } 192 mock.objects[objkey] = secret 193 } 194 } 195 196 // Get returns the Secret by name. 197 func (mock *MockSecretsInterface) Get(_ context.Context, name string, _ metav1.GetOptions) (*v1.Secret, error) { 198 object, ok := mock.objects[name] 199 if !ok { 200 return nil, apierrors.NewNotFound(v1.Resource("tests"), name) 201 } 202 return object, nil 203 } 204 205 // List returns the a of Secret. 206 func (mock *MockSecretsInterface) List(_ context.Context, opts metav1.ListOptions) (*v1.SecretList, error) { 207 var list v1.SecretList 208 209 labelSelector, err := kblabels.Parse(opts.LabelSelector) 210 if err != nil { 211 return nil, err 212 } 213 214 for _, secret := range mock.objects { 215 if labelSelector.Matches(kblabels.Set(secret.ObjectMeta.Labels)) { 216 list.Items = append(list.Items, *secret) 217 } 218 } 219 return &list, nil 220 } 221 222 // Create creates a new Secret. 223 func (mock *MockSecretsInterface) Create(_ context.Context, secret *v1.Secret, _ metav1.CreateOptions) (*v1.Secret, error) { 224 name := secret.ObjectMeta.Name 225 if object, ok := mock.objects[name]; ok { 226 return object, apierrors.NewAlreadyExists(v1.Resource("tests"), name) 227 } 228 mock.objects[name] = secret 229 return secret, nil 230 } 231 232 // Update updates a Secret. 233 func (mock *MockSecretsInterface) Update(_ context.Context, secret *v1.Secret, _ metav1.UpdateOptions) (*v1.Secret, error) { 234 name := secret.ObjectMeta.Name 235 if _, ok := mock.objects[name]; !ok { 236 return nil, apierrors.NewNotFound(v1.Resource("tests"), name) 237 } 238 mock.objects[name] = secret 239 return secret, nil 240 } 241 242 // Delete deletes a Secret by name. 243 func (mock *MockSecretsInterface) Delete(_ context.Context, name string, _ metav1.DeleteOptions) error { 244 if _, ok := mock.objects[name]; !ok { 245 return apierrors.NewNotFound(v1.Resource("tests"), name) 246 } 247 delete(mock.objects, name) 248 return nil 249 } 250 251 // newTestFixtureSQL mocks the SQL database (for testing purposes) 252 func newTestFixtureSQL(t *testing.T, releases ...*rspb.Release) (*SQL, sqlmock.Sqlmock) { 253 sqlDB, mock, err := sqlmock.New() 254 if err != nil { 255 t.Fatalf("error when opening stub database connection: %v", err) 256 } 257 258 sqlxDB := sqlx.NewDb(sqlDB, "sqlmock") 259 return &SQL{ 260 db: sqlxDB, 261 Log: func(a string, b ...interface{}) {}, 262 namespace: "default", 263 statementBuilder: sq.StatementBuilder.PlaceholderFormat(sq.Dollar), 264 }, mock 265 }