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()).
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()).
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