github.com/minio/console@v1.3.0/api/admin_remote_buckets_test.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2023 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "errors" 22 "net/http" 23 "net/http/httptest" 24 "os" 25 "testing" 26 27 "github.com/minio/console/pkg/utils" 28 29 "github.com/go-openapi/swag" 30 "github.com/minio/console/api/operations" 31 bucketApi "github.com/minio/console/api/operations/bucket" 32 "github.com/minio/console/models" 33 "github.com/minio/madmin-go/v3" 34 "github.com/stretchr/testify/assert" 35 "github.com/stretchr/testify/suite" 36 ) 37 38 type RemoteBucketsTestSuite struct { 39 suite.Suite 40 assert *assert.Assertions 41 currentServer string 42 isServerSet bool 43 server *httptest.Server 44 adminClient AdminClientMock 45 minioClient minioClientMock 46 mockRemoteBucket *models.RemoteBucket 47 mockBucketTarget *madmin.BucketTarget 48 mockListBuckets *models.ListBucketsResponse 49 } 50 51 func (suite *RemoteBucketsTestSuite) SetupSuite() { 52 suite.assert = assert.New(suite.T()) 53 suite.adminClient = AdminClientMock{} 54 suite.minioClient = minioClientMock{} 55 suite.mockObjects() 56 } 57 58 func (suite *RemoteBucketsTestSuite) mockObjects() { 59 suite.mockListBuckets = &models.ListBucketsResponse{ 60 Buckets: []*models.Bucket{}, 61 Total: 0, 62 } 63 suite.mockRemoteBucket = &models.RemoteBucket{ 64 AccessKey: swag.String("accessKey"), 65 SecretKey: "secretKey", 66 RemoteARN: swag.String("remoteARN"), 67 Service: "replication", 68 SourceBucket: swag.String("sourceBucket"), 69 TargetBucket: "targetBucket", 70 TargetURL: "targetURL", 71 Status: "", 72 } 73 suite.mockBucketTarget = &madmin.BucketTarget{ 74 Credentials: &madmin.Credentials{ 75 AccessKey: *suite.mockRemoteBucket.AccessKey, 76 SecretKey: suite.mockRemoteBucket.SecretKey, 77 }, 78 Arn: *suite.mockRemoteBucket.RemoteARN, 79 SourceBucket: *suite.mockRemoteBucket.SourceBucket, 80 TargetBucket: suite.mockRemoteBucket.TargetBucket, 81 Endpoint: suite.mockRemoteBucket.TargetURL, 82 } 83 } 84 85 func (suite *RemoteBucketsTestSuite) SetupTest() { 86 suite.server = httptest.NewServer(http.HandlerFunc(suite.serverHandler)) 87 suite.currentServer, suite.isServerSet = os.LookupEnv(ConsoleMinIOServer) 88 os.Setenv(ConsoleMinIOServer, suite.server.URL) 89 } 90 91 func (suite *RemoteBucketsTestSuite) serverHandler(w http.ResponseWriter, _ *http.Request) { 92 w.WriteHeader(400) 93 } 94 95 func (suite *RemoteBucketsTestSuite) TearDownSuite() { 96 } 97 98 func (suite *RemoteBucketsTestSuite) TearDownTest() { 99 if suite.isServerSet { 100 os.Setenv(ConsoleMinIOServer, suite.currentServer) 101 } else { 102 os.Unsetenv(ConsoleMinIOServer) 103 } 104 } 105 106 func (suite *RemoteBucketsTestSuite) TestRegisterRemoteBucketsHandlers() { 107 api := &operations.ConsoleAPI{} 108 suite.assertHandlersAreNil(api) 109 registerAdminBucketRemoteHandlers(api) 110 suite.assertHandlersAreNotNil(api) 111 } 112 113 func (suite *RemoteBucketsTestSuite) assertHandlersAreNil(api *operations.ConsoleAPI) { 114 suite.assert.Nil(api.BucketListRemoteBucketsHandler) 115 suite.assert.Nil(api.BucketRemoteBucketDetailsHandler) 116 suite.assert.Nil(api.BucketDeleteRemoteBucketHandler) 117 suite.assert.Nil(api.BucketAddRemoteBucketHandler) 118 suite.assert.Nil(api.BucketSetMultiBucketReplicationHandler) 119 suite.assert.Nil(api.BucketListExternalBucketsHandler) 120 suite.assert.Nil(api.BucketDeleteBucketReplicationRuleHandler) 121 suite.assert.Nil(api.BucketDeleteAllReplicationRulesHandler) 122 suite.assert.Nil(api.BucketDeleteSelectedReplicationRulesHandler) 123 suite.assert.Nil(api.BucketUpdateMultiBucketReplicationHandler) 124 } 125 126 func (suite *RemoteBucketsTestSuite) assertHandlersAreNotNil(api *operations.ConsoleAPI) { 127 suite.assert.NotNil(api.BucketListRemoteBucketsHandler) 128 suite.assert.NotNil(api.BucketRemoteBucketDetailsHandler) 129 suite.assert.NotNil(api.BucketDeleteRemoteBucketHandler) 130 suite.assert.NotNil(api.BucketAddRemoteBucketHandler) 131 suite.assert.NotNil(api.BucketSetMultiBucketReplicationHandler) 132 suite.assert.NotNil(api.BucketListExternalBucketsHandler) 133 suite.assert.NotNil(api.BucketDeleteBucketReplicationRuleHandler) 134 suite.assert.NotNil(api.BucketDeleteAllReplicationRulesHandler) 135 suite.assert.NotNil(api.BucketDeleteSelectedReplicationRulesHandler) 136 suite.assert.NotNil(api.BucketUpdateMultiBucketReplicationHandler) 137 } 138 139 func (suite *RemoteBucketsTestSuite) TestListRemoteBucketsHandlerWithError() { 140 params, api := suite.initListRemoteBucketsRequest() 141 response := api.BucketListRemoteBucketsHandler.Handle(params, &models.Principal{}) 142 _, ok := response.(*bucketApi.ListRemoteBucketsDefault) 143 suite.assert.True(ok) 144 } 145 146 func (suite *RemoteBucketsTestSuite) initListRemoteBucketsRequest() (params bucketApi.ListRemoteBucketsParams, api operations.ConsoleAPI) { 147 registerAdminBucketRemoteHandlers(&api) 148 params.HTTPRequest = &http.Request{} 149 return params, api 150 } 151 152 func (suite *RemoteBucketsTestSuite) TestListRemoteBucketsWithoutError() { 153 ctx := context.Background() 154 minioListRemoteBucketsMock = func(_ context.Context, _, _ string) (targets []madmin.BucketTarget, err error) { 155 return []madmin.BucketTarget{{ 156 Credentials: &madmin.Credentials{ 157 AccessKey: "accessKey", 158 SecretKey: "secretKey", 159 }, 160 }}, nil 161 } 162 res, err := listRemoteBuckets(ctx, &suite.adminClient) 163 suite.assert.NotNil(res) 164 suite.assert.Nil(err) 165 } 166 167 func (suite *RemoteBucketsTestSuite) TestRemoteBucketDetailsHandlerWithError() { 168 params, api := suite.initRemoteBucketDetailsRequest() 169 response := api.BucketRemoteBucketDetailsHandler.Handle(params, &models.Principal{}) 170 _, ok := response.(*bucketApi.RemoteBucketDetailsDefault) 171 suite.assert.True(ok) 172 } 173 174 func (suite *RemoteBucketsTestSuite) initRemoteBucketDetailsRequest() (params bucketApi.RemoteBucketDetailsParams, api operations.ConsoleAPI) { 175 registerAdminBucketRemoteHandlers(&api) 176 params.HTTPRequest = &http.Request{} 177 return params, api 178 } 179 180 func (suite *RemoteBucketsTestSuite) TestGetRemoteBucketWithoutError() { 181 ctx := context.Background() 182 minioGetRemoteBucketMock = func(_ context.Context, _, _ string) (targets *madmin.BucketTarget, err error) { 183 return suite.mockBucketTarget, nil 184 } 185 res, err := getRemoteBucket(ctx, &suite.adminClient, "bucketName") 186 suite.assert.Nil(err) 187 suite.assert.NotNil(res) 188 suite.assert.Equal(suite.mockRemoteBucket, res) 189 } 190 191 func (suite *RemoteBucketsTestSuite) TestDeleteRemoteBucketHandlerWithError() { 192 params, api := suite.initDeleteRemoteBucketRequest() 193 response := api.BucketDeleteRemoteBucketHandler.Handle(params, &models.Principal{}) 194 _, ok := response.(*bucketApi.DeleteRemoteBucketDefault) 195 suite.assert.True(ok) 196 } 197 198 func (suite *RemoteBucketsTestSuite) initDeleteRemoteBucketRequest() (params bucketApi.DeleteRemoteBucketParams, api operations.ConsoleAPI) { 199 registerAdminBucketRemoteHandlers(&api) 200 params.HTTPRequest = &http.Request{} 201 return params, api 202 } 203 204 func (suite *RemoteBucketsTestSuite) TestAddRemoteBucketHandlerWithError() { 205 params, api := suite.initAddRemoteBucketRequest() 206 response := api.BucketAddRemoteBucketHandler.Handle(params, &models.Principal{}) 207 _, ok := response.(*bucketApi.AddRemoteBucketDefault) 208 suite.assert.True(ok) 209 } 210 211 func (suite *RemoteBucketsTestSuite) initAddRemoteBucketRequest() (params bucketApi.AddRemoteBucketParams, api operations.ConsoleAPI) { 212 registerAdminBucketRemoteHandlers(&api) 213 url := "^&*&^%^" 214 accessKey := "accessKey" 215 secretKey := "secretKey" 216 params.HTTPRequest = &http.Request{} 217 params.Body = &models.CreateRemoteBucket{ 218 TargetURL: &url, 219 AccessKey: &accessKey, 220 SecretKey: &secretKey, 221 } 222 return params, api 223 } 224 225 func (suite *RemoteBucketsTestSuite) TestAddRemoteBucketWithoutError() { 226 ctx := context.Background() 227 minioAddRemoteBucketMock = func(_ context.Context, _ string, _ *madmin.BucketTarget) (string, error) { 228 return "bucketName", nil 229 } 230 url := "https://localhost" 231 accessKey := "accessKey" 232 secretKey := "secretKey" 233 targetBucket := "targetBucket" 234 syncMode := "async" 235 sourceBucket := "sourceBucket" 236 data := models.CreateRemoteBucket{ 237 TargetURL: &url, 238 TargetBucket: &targetBucket, 239 AccessKey: &accessKey, 240 SecretKey: &secretKey, 241 SyncMode: &syncMode, 242 HealthCheckPeriod: 10, 243 SourceBucket: &sourceBucket, 244 } 245 res, err := addRemoteBucket(ctx, &suite.adminClient, data) 246 suite.assert.NotNil(res) 247 suite.assert.Nil(err) 248 } 249 250 func (suite *RemoteBucketsTestSuite) TestSetMultiBucketReplicationHandlerWithError() { 251 params, api := suite.initSetMultiBucketReplicationRequest() 252 response := api.BucketSetMultiBucketReplicationHandler.Handle(params, &models.Principal{}) 253 _, ok := response.(*bucketApi.SetMultiBucketReplicationOK) 254 suite.assert.True(ok) 255 } 256 257 func (suite *RemoteBucketsTestSuite) initSetMultiBucketReplicationRequest() (params bucketApi.SetMultiBucketReplicationParams, api operations.ConsoleAPI) { 258 registerAdminBucketRemoteHandlers(&api) 259 accessKey := "accessKey" 260 secretKey := "secretKey" 261 targetURL := "https://localhost" 262 syncMode := "async" 263 params.HTTPRequest = &http.Request{} 264 params.Body = &models.MultiBucketReplication{ 265 BucketsRelation: []*models.MultiBucketsRelation{{}}, 266 AccessKey: &accessKey, 267 SecretKey: &secretKey, 268 Region: "region", 269 TargetURL: &targetURL, 270 SyncMode: &syncMode, 271 Bandwidth: 10, 272 HealthCheckPeriod: 10, 273 } 274 return params, api 275 } 276 277 func (suite *RemoteBucketsTestSuite) TestListExternalBucketsHandlerWithError() { 278 params, api := suite.initListExternalBucketsRequest() 279 response := api.BucketListExternalBucketsHandler.Handle(params, &models.Principal{}) 280 _, ok := response.(*bucketApi.ListExternalBucketsDefault) 281 suite.assert.True(ok) 282 } 283 284 func (suite *RemoteBucketsTestSuite) initListExternalBucketsRequest() (params bucketApi.ListExternalBucketsParams, api operations.ConsoleAPI) { 285 registerAdminBucketRemoteHandlers(&api) 286 url := "http://localhost:9000" 287 accessKey := "accessKey" 288 secretKey := "secretKey" 289 tls := false 290 params.HTTPRequest = &http.Request{} 291 params.Body = &models.ListExternalBucketsParams{ 292 TargetURL: &url, 293 AccessKey: &accessKey, 294 SecretKey: &secretKey, 295 UseTLS: &tls, 296 } 297 return params, api 298 } 299 300 func (suite *RemoteBucketsTestSuite) TestListExternalBucketsWithError() { 301 ctx := context.Background() 302 minioAccountInfoMock = func(_ context.Context) (madmin.AccountInfo, error) { 303 return madmin.AccountInfo{}, errors.New("error") 304 } 305 res, err := listExternalBuckets(ctx, &suite.adminClient) 306 suite.assert.NotNil(err) 307 suite.assert.Nil(res) 308 } 309 310 func (suite *RemoteBucketsTestSuite) TestListExternalBucketsWithoutError() { 311 ctx := context.Background() 312 minioAccountInfoMock = func(_ context.Context) (madmin.AccountInfo, error) { 313 return madmin.AccountInfo{ 314 Buckets: []madmin.BucketAccessInfo{}, 315 }, nil 316 } 317 res, err := listExternalBuckets(ctx, &suite.adminClient) 318 suite.assert.Nil(err) 319 suite.assert.NotNil(res) 320 suite.assert.Equal(suite.mockListBuckets, res) 321 } 322 323 func (suite *RemoteBucketsTestSuite) TestDeleteBucketReplicationRuleHandlerWithError() { 324 params, api := suite.initDeleteBucketReplicationRuleRequest() 325 response := api.BucketDeleteBucketReplicationRuleHandler.Handle(params, &models.Principal{}) 326 _, ok := response.(*bucketApi.DeleteBucketReplicationRuleDefault) 327 suite.assert.True(ok) 328 } 329 330 func (suite *RemoteBucketsTestSuite) initDeleteBucketReplicationRuleRequest() (params bucketApi.DeleteBucketReplicationRuleParams, api operations.ConsoleAPI) { 331 registerAdminBucketRemoteHandlers(&api) 332 params.HTTPRequest = &http.Request{} 333 return params, api 334 } 335 336 func (suite *RemoteBucketsTestSuite) TestDeleteAllReplicationRulesHandlerWithError() { 337 params, api := suite.initDeleteAllReplicationRulesRequest() 338 response := api.BucketDeleteAllReplicationRulesHandler.Handle(params, &models.Principal{}) 339 _, ok := response.(*bucketApi.DeleteAllReplicationRulesDefault) 340 suite.assert.True(ok) 341 } 342 343 func (suite *RemoteBucketsTestSuite) initDeleteAllReplicationRulesRequest() (params bucketApi.DeleteAllReplicationRulesParams, api operations.ConsoleAPI) { 344 registerAdminBucketRemoteHandlers(&api) 345 params.HTTPRequest = &http.Request{} 346 return params, api 347 } 348 349 func (suite *RemoteBucketsTestSuite) TestDeleteSelectedReplicationRulesHandlerWithError() { 350 params, api := suite.initDeleteSelectedReplicationRulesRequest() 351 response := api.BucketDeleteSelectedReplicationRulesHandler.Handle(params, &models.Principal{}) 352 _, ok := response.(*bucketApi.DeleteSelectedReplicationRulesDefault) 353 suite.assert.True(ok) 354 } 355 356 func (suite *RemoteBucketsTestSuite) initDeleteSelectedReplicationRulesRequest() (params bucketApi.DeleteSelectedReplicationRulesParams, api operations.ConsoleAPI) { 357 registerAdminBucketRemoteHandlers(&api) 358 params.HTTPRequest = &http.Request{} 359 params.BucketName = "bucketName" 360 params.Rules = &models.BucketReplicationRuleList{ 361 Rules: []string{"rule1", "rule2"}, 362 } 363 364 return params, api 365 } 366 367 func (suite *RemoteBucketsTestSuite) TestUpdateMultiBucketReplicationHandlerWithError() { 368 params, api := suite.initUpdateMultiBucketReplicationRequest() 369 response := api.BucketUpdateMultiBucketReplicationHandler.Handle(params, &models.Principal{}) 370 _, ok := response.(*bucketApi.UpdateMultiBucketReplicationDefault) 371 suite.assert.True(ok) 372 } 373 374 func (suite *RemoteBucketsTestSuite) initUpdateMultiBucketReplicationRequest() (params bucketApi.UpdateMultiBucketReplicationParams, api operations.ConsoleAPI) { 375 registerAdminBucketRemoteHandlers(&api) 376 r := &http.Request{} 377 ctx := context.WithValue(context.Background(), utils.ContextClientIP, "127.0.0.1") 378 rc := r.WithContext(ctx) 379 params.HTTPRequest = rc 380 params.Body = &models.MultiBucketReplicationEdit{} 381 return params, api 382 } 383 384 func TestRemoteBuckets(t *testing.T) { 385 suite.Run(t, new(RemoteBucketsTestSuite)) 386 }