diff --git a/api-tests/tests/backup-storages.spec.ts b/api-tests/tests/backup-storages.spec.ts index 58adf3e4..c1e91d4c 100644 --- a/api-tests/tests/backup-storages.spec.ts +++ b/api-tests/tests/backup-storages.spec.ts @@ -14,10 +14,7 @@ // limitations under the License. import { expect, test } from '@fixtures' -let req - -test('add/list/get/delete backup storage success', async ({ request }) => { - req = request +test('add/list/get/delete s3 backup storage success', async ({ request }) => { const payload = { type: 's3', name: 'backup-storage-1', @@ -92,9 +89,78 @@ test('add/list/get/delete backup storage success', async ({ request }) => { expect(deleted.ok()).toBeTruthy() }) -test('create backup storage failures', async ({ request }) => { - req = request +test('add/list/get/delete azure backup storage success', async ({ request }) => { + const payload = { + type: 'azure', + name: 'backup-storage-azure', + description: 'Dev storage', + bucketName: 'percona-test-backup-storage', + accessKey: 'sdfs', + secretKey: 'sdfsdfsd', + } + const response = await request.post('/v1/backup-storages', { + data: payload, + }) + + // create + expect(response.ok()).toBeTruthy() + const created = await response.json() + + const name = created.name + + expect(created.name).toBe(payload.name) + expect(created.bucketName).toBe(payload.bucketName) + expect(created.type).toBe(payload.type) + expect(created.description).toBe(payload.description) + + // list + const listResponse = await request.get('/v1/backup-storages') + + expect(listResponse.ok()).toBeTruthy() + const list = await listResponse.json() + + expect(list.length).toBeGreaterThan(0) + + // get + const one = await request.get(`/v1/backup-storages/${name}`) + + expect(one.ok()).toBeTruthy() + expect((await one.json()).name).toBe(payload.name) + + // update + const updatePayload = { + description: 'some description', + bucketName: 'percona-test-backup-storage1', + accessKey: 'otherAccessKey', + secretKey: 'otherSecret', + } + const updated = await request.patch(`/v1/backup-storages/${name}`, { + data: updatePayload, + }) + + expect(updated.ok()).toBeTruthy() + const result = await updated.json() + + expect(result.bucketName).toBe(updatePayload.bucketName) + expect(result.region).toBe(created.region) + expect(result.type).toBe(created.type) + expect(result.description).toBe(updatePayload.description) + + // backup storage already exists + const createAgain = await request.post('/v1/backup-storages', { + data: payload, + }) + + expect(createAgain.status()).toBe(409) + + // delete + const deleted = await request.delete(`/v1/backup-storages/${name}`) + + expect(deleted.ok()).toBeTruthy() +}) + +test('create backup storage failures', async ({ request }) => { const testCases = [ { payload: {}, @@ -135,14 +201,24 @@ test('create backup storage failures', async ({ request }) => { }, { payload: { - type: 'azure', + type: 's3', + name: 'missing-region', + bucketName: 'invalid', + accessKey: 'ssdssd', + secretKey: 'ssdssdssdssd', + }, + errorText: 'Region is required', + }, + { + payload: { + type: 'gcs', name: 'invalid', region: 'us-east-2', bucketName: 'invalid', accessKey: 'ssdssd', secretKey: 'ssdssdssdssd', }, - errorText: `Creating storage is not implemented for 'azure'`, + errorText: `"/type": value is not one of the allowed values`, }, ] @@ -157,7 +233,6 @@ test('create backup storage failures', async ({ request }) => { }) test('update backup storage failures', async ({ request }) => { - req = request const createPayload = { type: 's3', name: 'backup-storage-2', @@ -198,6 +273,9 @@ test('update backup storage failures', async ({ request }) => { expect((await response.json()).message).toMatch(testCase.errorText) expect(response.status()).toBe(400) } + + const deleted = await request.delete(`/v1/backup-storages/${name}`) + expect(deleted.ok()).toBeTruthy() }) test('update: backup storage not found', async ({ request }) => { diff --git a/api/backup_storage.go b/api/backup_storage.go index 541316ff..387460c5 100644 --- a/api/backup_storage.go +++ b/api/backup_storage.go @@ -236,7 +236,12 @@ func (e *EverestServer) GetBackupStorage(ctx echo.Context, backupStorageID strin // UpdateBackupStorage updates of the specified backup storage. func (e *EverestServer) UpdateBackupStorage(ctx echo.Context, backupStorageName string) error { - params, err := validateUpdateBackupStorageRequest(ctx) + bs, err := e.storage.GetBackupStorage(ctx.Request().Context(), nil, backupStorageName) + if err != nil { + return ctx.JSON(http.StatusNotFound, Error{Message: pointer.ToString("Could not find backup storage")}) + } + + params, err := validateUpdateBackupStorageRequest(ctx, bs) if err != nil { return ctx.JSON(http.StatusBadRequest, Error{Message: pointer.ToString(err.Error())}) } @@ -422,7 +427,7 @@ func (e *EverestServer) checkStorageAccessByUpdate(ctx context.Context, storageN storage: *s, } - err = validateStorageAccessByUpdate(oldData, params, e.l) + err = validateStorageAccessByUpdate(ctx, oldData, params, e.l) if err != nil { return nil, err } diff --git a/api/everest-server.gen.go b/api/everest-server.gen.go index ff764892..f2b77bbe 100644 --- a/api/everest-server.gen.go +++ b/api/everest-server.gen.go @@ -23,14 +23,12 @@ import ( // Defines values for BackupStorageType. const ( BackupStorageTypeAzure BackupStorageType = "azure" - BackupStorageTypeGcs BackupStorageType = "gcs" BackupStorageTypeS3 BackupStorageType = "s3" ) // Defines values for CreateBackupStorageParamsType. const ( CreateBackupStorageParamsTypeAzure CreateBackupStorageParamsType = "azure" - CreateBackupStorageParamsTypeGcs CreateBackupStorageParamsType = "gcs" CreateBackupStorageParamsTypeS3 CreateBackupStorageParamsType = "s3" ) @@ -73,7 +71,7 @@ type BackupStorage struct { BucketName string `json:"bucketName"` Description *string `json:"description,omitempty"` Name string `json:"name"` - Region string `json:"region"` + Region string `json:"region,omitempty"` Type BackupStorageType `json:"type"` Url *string `json:"url,omitempty"` } @@ -94,7 +92,7 @@ type CreateBackupStorageParams struct { // Name A user defined string name of the storage in the DNS name format https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names Name string `json:"name"` - Region string `json:"region"` + Region string `json:"region,omitempty"` SecretKey string `json:"secretKey"` Type CreateBackupStorageParamsType `json:"type"` Url *string `json:"url,omitempty"` @@ -2025,132 +2023,134 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/validation.go b/api/validation.go index 9f5658fb..55ce75c5 100644 --- a/api/validation.go +++ b/api/validation.go @@ -17,6 +17,7 @@ package api import ( "bytes" + "context" "errors" "fmt" "net/http" @@ -24,6 +25,7 @@ import ( "regexp" "github.com/AlekSi/pointer" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" @@ -120,16 +122,18 @@ func validateURL(urlStr string) bool { return err == nil } -func validateStorageAccessByCreate(params CreateBackupStorageParams, l *zap.SugaredLogger) error { - switch params.Type { //nolint:exhaustive +func validateStorageAccessByCreate(ctx context.Context, params CreateBackupStorageParams, l *zap.SugaredLogger) error { + switch params.Type { case CreateBackupStorageParamsTypeS3: return s3Access(l, params.Url, params.AccessKey, params.SecretKey, params.BucketName, params.Region) + case CreateBackupStorageParamsTypeAzure: + return azureAccess(ctx, l, params.AccessKey, params.SecretKey, params.BucketName) default: return ErrCreateStorageNotSupported(string(params.Type)) } } -func validateStorageAccessByUpdate(oldData *storageData, params UpdateBackupStorageParams, l *zap.SugaredLogger) error { +func validateStorageAccessByUpdate(ctx context.Context, oldData *storageData, params UpdateBackupStorageParams, l *zap.SugaredLogger) error { endpoint := &oldData.storage.URL if params.Url != nil { endpoint = params.Url @@ -158,6 +162,8 @@ func validateStorageAccessByUpdate(oldData *storageData, params UpdateBackupStor switch oldData.storage.Type { case string(BackupStorageTypeS3): return s3Access(l, endpoint, accessKey, secretKey, bucketName, region) + case string(BackupStorageTypeAzure): + return azureAccess(ctx, l, accessKey, secretKey, bucketName) default: return ErrUpdateStorageNotSupported(oldData.storage.Type) } @@ -232,7 +238,51 @@ func s3Access(l *zap.SugaredLogger, endpoint *string, accessKey, secretKey, buck return nil } -func validateUpdateBackupStorageRequest(ctx echo.Context) (*UpdateBackupStorageParams, error) { +func azureAccess(ctx context.Context, l *zap.SugaredLogger, accountName, accountKey, containerName string) error { + if config.Debug { + return nil + } + + cred, err := azblob.NewSharedKeyCredential(accountName, accountKey) + if err != nil { + l.Error(err) + return errors.New("could not initialize Azure credentials") + } + + client, err := azblob.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", url.PathEscape(accountName)), cred, nil) + if err != nil { + l.Error(err) + return errors.New("could not initialize Azure client") + } + + pager := client.NewListBlobsFlatPager(containerName, nil) + if pager.More() { + if _, err := pager.NextPage(ctx); err != nil { + l.Error(err) + return errors.New("could not list blobs in Azure container") + } + } + + blobName := "everest-test-blob" + if _, err = client.UploadBuffer(ctx, containerName, blobName, []byte{}, nil); err != nil { + l.Error(err) + return errors.New("could not write to Azure container") + } + + if _, err = client.DownloadBuffer(ctx, containerName, blobName, []byte{}, nil); err != nil { + l.Error(err) + return errors.New("could not read from Azure container") + } + + if _, err = client.DeleteBlob(ctx, containerName, blobName, nil); err != nil { + l.Error(err) + return errors.New("could not delete a blob from Azure container") + } + + return nil +} + +func validateUpdateBackupStorageRequest(ctx echo.Context, bs *model.BackupStorage) (*UpdateBackupStorageParams, error) { var params UpdateBackupStorageParams if err := ctx.Bind(¶ms); err != nil { return nil, err @@ -245,6 +295,12 @@ func validateUpdateBackupStorageRequest(ctx echo.Context) (*UpdateBackupStorageP } } + if bs.Type == string(BackupStorageTypeS3) { + if params.Region != nil && *params.Region == "" { + return nil, errors.New("region is required when using S3 storage type") + } + } + return ¶ms, nil } @@ -265,8 +321,14 @@ func validateCreateBackupStorageRequest(ctx echo.Context, l *zap.SugaredLogger) } } + if params.Type == CreateBackupStorageParamsTypeS3 { + if params.Region == "" { + return nil, errors.New("region is required when using S3 storage type") + } + } + // check data access - if err := validateStorageAccessByCreate(params, l); err != nil { + if err := validateStorageAccessByCreate(ctx.Request().Context(), params, l); err != nil { l.Error(err) return nil, err } diff --git a/client/everest-client.gen.go b/client/everest-client.gen.go index 5d4086d6..0daca389 100644 --- a/client/everest-client.gen.go +++ b/client/everest-client.gen.go @@ -24,14 +24,12 @@ import ( // Defines values for BackupStorageType. const ( BackupStorageTypeAzure BackupStorageType = "azure" - BackupStorageTypeGcs BackupStorageType = "gcs" BackupStorageTypeS3 BackupStorageType = "s3" ) // Defines values for CreateBackupStorageParamsType. const ( CreateBackupStorageParamsTypeAzure CreateBackupStorageParamsType = "azure" - CreateBackupStorageParamsTypeGcs CreateBackupStorageParamsType = "gcs" CreateBackupStorageParamsTypeS3 CreateBackupStorageParamsType = "s3" ) @@ -74,7 +72,7 @@ type BackupStorage struct { BucketName string `json:"bucketName"` Description *string `json:"description,omitempty"` Name string `json:"name"` - Region string `json:"region"` + Region string `json:"region,omitempty"` Type BackupStorageType `json:"type"` Url *string `json:"url,omitempty"` } @@ -95,7 +93,7 @@ type CreateBackupStorageParams struct { // Name A user defined string name of the storage in the DNS name format https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names Name string `json:"name"` - Region string `json:"region"` + Region string `json:"region,omitempty"` SecretKey string `json:"secretKey"` Type CreateBackupStorageParamsType `json:"type"` Url *string `json:"url,omitempty"` @@ -6297,132 +6295,134 @@ func ParseUpdateMonitoringInstanceResponse(rsp *http.Response) (*UpdateMonitorin // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/docs/spec/openapi.yml b/docs/spec/openapi.yml index 45acd921..b0a4b93f 100644 --- a/docs/spec/openapi.yml +++ b/docs/spec/openapi.yml @@ -1001,7 +1001,30 @@ paths: tags: - backupStorage summary: Create a new backup storage object - description: Create a new backup storage object + description: | + Create a new backup storage object. + + **Examples**: + ``` + { + "name": "s3-storage", + "type": "s3", + "bucketName": "bucket1", + "accessKey": "access_key", + "secretKey": "secret_key", + "region": "eu-central-1" + } + ``` + + ``` + { + "name": "azure-storage", + "type": "azure", + "bucketName": "container1", + "accessKey": "storage_account_name", + "secretKey": "storage_account_key", + } + ``` operationId: createBackupStorage responses: '200': @@ -1357,7 +1380,6 @@ components: enum: - s3 - azure - - gcs bucketName: type: string description: The cloud storage bucket/container name @@ -1369,12 +1391,12 @@ components: type: string region: type: string + x-go-type-skip-optional-pointer: true required: - name - bucketName - accessKey - secretKey - - region - type additionalProperties: false UpdateBackupStorageParams: @@ -1404,7 +1426,6 @@ components: enum: - s3 - azure - - gcs name: type: string description: @@ -1415,11 +1436,11 @@ components: type: string region: type: string + x-go-type-skip-optional-pointer: true additionalProperties: false required: - name - bucketName - - region - type BackupStoragesList: type: array diff --git a/go.mod b/go.mod index 152eb7fc..0d6abb1c 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/AlekSi/pointer v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 github.com/aws/aws-sdk-go v1.45.24 github.com/deepmap/oapi-codegen v1.15.0 github.com/getkin/kin-openapi v0.120.0 @@ -26,6 +27,8 @@ require ( ) require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect @@ -75,15 +78,15 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.13.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/oauth2 v0.11.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.16.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index c44cf3e8..e8c032a6 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,20 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -30,6 +42,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw= github.com/dhui/dktest v0.3.16/go.mod h1:gYaA3LRmM8Z4vJl2MA0THIigJoZrwOansEOsp+kqxp0= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= @@ -74,6 +88,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA= github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= @@ -81,7 +97,6 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2V github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -90,6 +105,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -152,6 +168,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= @@ -201,6 +219,8 @@ github.com/percona/everest-operator v0.3.0 h1:UBRcK7y4RkxO3fY5Ow6QtB7f0SBN2W246B github.com/percona/everest-operator v0.3.0/go.mod h1:BVLJ4t6ARCrsjb5cH73VHYw5WUFLDJ2QMqBKLxPX8gE= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -261,8 +281,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -280,7 +300,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -290,11 +309,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -322,18 +341,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= @@ -357,8 +376,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=