...

Source file src/edge-infra.dev/pkg/edge/bsl-reconciler/bsl_reconciler_test.go

Documentation: edge-infra.dev/pkg/edge/bsl-reconciler

     1  package edgebsl
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/json"
     7  	"errors"
     8  	"testing"
     9  	"time"
    10  
    11  	"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
    12  	"github.com/DATA-DOG/go-sqlmock"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/stretchr/testify/assert"
    15  
    16  	"edge-infra.dev/pkg/edge/api/graph/model"
    17  	"edge-infra.dev/pkg/edge/api/mocks"
    18  	"edge-infra.dev/pkg/edge/api/testutils/seededpostgres"
    19  	btypes "edge-infra.dev/pkg/edge/api/types"
    20  	"edge-infra.dev/pkg/edge/bsl"
    21  	"edge-infra.dev/pkg/edge/constants"
    22  	secretMgrApi "edge-infra.dev/pkg/lib/gcp/secretmanager"
    23  	logger "edge-infra.dev/pkg/lib/logging"
    24  )
    25  
    26  const (
    27  	testRootOrg            = "/test_root_org/"
    28  	testOrganizationPrefix = "test-prefix"
    29  	databaseHost           = "localhost"
    30  	databaseName           = "bsl_reconciler"
    31  	databaseUser           = "test"
    32  	databasePassword       = "12345"
    33  )
    34  
    35  var (
    36  	databasePort int
    37  	testTenant   = &model.TenantInput{
    38  		TenantBSLId: "testingTenantBSLId",
    39  		OrgName:     "testingTenantBSLName",
    40  	}
    41  )
    42  
    43  func TestBSLController(t *testing.T) {
    44  	ctx := context.Background()
    45  
    46  	srv := createBSLServer(t, false)
    47  	defer srv.Close()
    48  
    49  	mockCtrl := gomock.NewController(t)
    50  	mockSecretManager := mocks.NewMockSecretManagerService(mockCtrl)
    51  	log := logger.NewLogger().Logger
    52  	fn := func(_ context.Context, _ string) (btypes.SecretManagerService, error) {
    53  		return mockSecretManager, nil
    54  	}
    55  	config := BslConfig{
    56  		RootOrg:               testRootOrg,
    57  		OrgPrefix:             testOrganizationPrefix,
    58  		RootURI:               srv.URL,
    59  		TopLevelProjectID:     testForemanProject,
    60  		BslReconcilesInterval: DefaultReconcileInterval,
    61  		SQL: SQLConfig{
    62  			ConnectionName: databaseHost,
    63  			User:           databaseUser,
    64  			DatabaseName:   databaseName,
    65  		},
    66  		AccessKey: &bsl.AccessKey{
    67  			SharedKey: testSharedKey,
    68  			SecretKey: testSecretKey,
    69  		},
    70  		Client: nil,
    71  	}
    72  
    73  	db, sqlMock := setup(t)
    74  	sqlMock.MatchExpectationsInOrder(false)
    75  	defer db.Close()
    76  
    77  	setUpSecretManagerMocks(t, mockSecretManager)
    78  	bslReconciler := New(fn, log, config, db)
    79  	err := bslReconciler.Reconcile(ctx)
    80  	assert.NoError(t, err)
    81  }
    82  
    83  func TestBSLControllerWithSQLConnection(t *testing.T) {
    84  	ctx := context.Background()
    85  
    86  	srv := createBSLServer(t, true)
    87  	defer srv.Close()
    88  
    89  	mockCtrl := gomock.NewController(t)
    90  	mockSecretManager := mocks.NewMockSecretManagerService(mockCtrl)
    91  	log := logger.NewLogger().Logger
    92  	fn := func(_ context.Context, _ string) (btypes.SecretManagerService, error) {
    93  		return mockSecretManager, nil
    94  	}
    95  	config := BslConfig{
    96  		RootOrg:               testRootOrg,
    97  		OrgPrefix:             testOrganizationPrefix,
    98  		RootURI:               srv.URL,
    99  		TopLevelProjectID:     testForemanProject,
   100  		BslReconcilesInterval: DefaultReconcileInterval,
   101  		SQL: SQLConfig{
   102  			ConnectionName: databaseHost,
   103  			User:           databaseUser,
   104  			DatabaseName:   databaseName,
   105  		},
   106  		AccessKey: &bsl.AccessKey{
   107  			SharedKey: testSharedKey,
   108  			SecretKey: testSecretKey,
   109  		},
   110  		Client: nil,
   111  	}
   112  
   113  	setUpSecretManagerMocks(t, mockSecretManager)
   114  
   115  	dbConnection, sp, err := SetupSQLDB()
   116  	assert.NoError(t, err)
   117  
   118  	bslReconciler := New(fn, log, config, dbConnection)
   119  
   120  	reconcileErr := bslReconciler.Reconcile(ctx)
   121  	assert.NoError(t, reconcileErr)
   122  
   123  	tenants, err := bslReconciler.TenantService.List(ctx)
   124  	assert.Equal(t, 2, len(tenants))
   125  	assert.NoError(t, err)
   126  
   127  	_, err = bslReconciler.TenantService.Create(ctx, testTenant)
   128  	assert.NoError(t, err)
   129  
   130  	tenants, err = bslReconciler.TenantService.List(ctx)
   131  	assert.Equal(t, 3, len(tenants))
   132  	assert.NoError(t, err)
   133  
   134  	t.Cleanup(func() {
   135  		_ = dbConnection.Close()
   136  		_ = sp.Close()
   137  	})
   138  }
   139  
   140  func setUpSecretManagerMocks(t *testing.T, mockSecretManager *mocks.MockSecretManagerService) {
   141  	mockSecretManager.EXPECT().AddSecret(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). //nolint: dupl
   142  																		DoAndReturn(func(_ context.Context, secretID string, secretValue []byte, labels map[string]string, _ bool, _ *time.Time, _ string) error {
   143  			assert.Contains(t, []string{"test-prefix-test-1", "test-prefix-test-1-org-admin", "test-prefix-test-2", "test-prefix-test-2-org-admin", "test-prefix-test-3", "test-prefix-test-3-org-admin"}, secretID)
   144  			assert.Len(t, labels, 4)
   145  			assert.Equal(t, labels[secretMgrApi.SecretLabel], "platform")
   146  			assert.Equal(t, labels[secretMgrApi.SecretTypeLabel], "bsl-secret")
   147  			assert.Equal(t, labels[secretMgrApi.SecretOwnerLabel], "edge")
   148  			assert.Equal(t, labels[secretMgrApi.SecretNamespaceSelectorLabel], string(constants.PlatformNamespaceSelector))
   149  			var userPassword struct {
   150  				Username  string `json:"username"`
   151  				Password  string `json:"password"`
   152  				SharedKey string `json:"shared_key"`
   153  				SecretKey string `json:"secret_key"`
   154  			}
   155  			err := json.Unmarshal(secretValue, &userPassword)
   156  			assert.NoError(t, err)
   157  			assert.NotEmpty(t, userPassword.Username)
   158  			assert.NotEmpty(t, userPassword.Password)
   159  			assert.NotEmpty(t, userPassword.SharedKey)
   160  			assert.NotEmpty(t, userPassword.SecretKey)
   161  			return nil
   162  		}).AnyTimes()
   163  	mockSecretManager.EXPECT().GetSecret(gomock.Any(), gomock.Any()). //nolint: dupl
   164  										DoAndReturn(func(_ context.Context, secretID string) (*secretmanagerpb.Secret, error) {
   165  			assert.Contains(t, []string{"test-prefix-test-1", "test-prefix-test-1-org-admin", "test-prefix-test-2", "test-prefix-test-2-org-admin", "test-prefix-test-3", "test-prefix-test-3-org-admin"}, secretID)
   166  			return &secretmanagerpb.Secret{}, errors.New("not found")
   167  		}).AnyTimes()
   168  }
   169  
   170  func SetupSQLDB() (*sql.DB, *seededpostgres.SeededPostgres, error) {
   171  	sp, err := seededpostgres.NewWithUser(databaseName, databaseUser, databasePassword)
   172  	if err != nil {
   173  		return nil, nil, err
   174  	}
   175  	db, err := sp.DB()
   176  	if err != nil {
   177  		_ = sp.Close()
   178  		return nil, nil, err
   179  	}
   180  	databasePort = sp.Port()
   181  	return db, sp, nil
   182  }
   183  
   184  func setup(t *testing.T) (*sql.DB, sqlmock.Sqlmock) {
   185  	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
   186  	if err != nil {
   187  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   188  	}
   189  
   190  	return db, mock
   191  }
   192  

View as plain text