...

Source file src/helm.sh/helm/v3/pkg/storage/driver/mock_test.go

Documentation: helm.sh/helm/v3/pkg/storage/driver

     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 "helm.sh/helm/v3/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 "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  		// rls-a
    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  		// rls-b
    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  		// rls-c in other namespace
    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  // newTestFixture initializes a MockConfigMapsInterface.
    84  // ConfigMaps are created for each release provided.
    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  // MockConfigMapsInterface mocks a kubernetes ConfigMapsInterface
    93  type MockConfigMapsInterface struct {
    94  	corev1.ConfigMapInterface
    95  
    96  	objects map[string]*v1.ConfigMap
    97  }
    98  
    99  // Init initializes the MockConfigMapsInterface with the set of releases.
   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  // Get returns the ConfigMap by name.
   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  // List returns the a of ConfigMaps.
   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  // Create creates a new ConfigMap.
   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  // Update updates a ConfigMap.
   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  // Delete deletes a ConfigMap by name.
   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  // newTestFixture initializes a MockSecretsInterface.
   170  // Secrets are created for each release provided.
   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  // MockSecretsInterface mocks a kubernetes SecretsInterface
   179  type MockSecretsInterface struct {
   180  	corev1.SecretInterface
   181  
   182  	objects map[string]*v1.Secret
   183  }
   184  
   185  // Init initializes the MockSecretsInterface with the set of releases.
   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  // Get returns the Secret by name.
   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  // List returns the a of Secret.
   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  // Create creates a new Secret.
   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  // Update updates a Secret.
   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  // Delete deletes a Secret by name.
   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  // newTestFixtureSQL mocks the SQL database (for testing purposes)
   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