Updating API to use UID
This commit is contained in:
@@ -3,7 +3,6 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
@@ -37,17 +36,17 @@ func RegisterApi(
|
||||
return api
|
||||
}
|
||||
|
||||
// RegisterAPIEndpoints Registers Endpoints on Grafana Router
|
||||
// registerEndpoints Registers Endpoints on Grafana Router
|
||||
func (cma *CloudMigrationAPI) registerEndpoints() {
|
||||
cma.routeRegister.Group("/api/cloudmigration", func(cloudMigrationRoute routing.RouteRegister) {
|
||||
// migration
|
||||
cloudMigrationRoute.Get("/migration", routing.Wrap(cma.GetMigrationList))
|
||||
cloudMigrationRoute.Post("/migration", routing.Wrap(cma.CreateMigration))
|
||||
cloudMigrationRoute.Get("/migration/:id", routing.Wrap(cma.GetMigration))
|
||||
cloudMigrationRoute.Delete("/migration/:id", routing.Wrap(cma.DeleteMigration))
|
||||
cloudMigrationRoute.Post("/migration/:id/run", routing.Wrap(cma.RunMigration))
|
||||
cloudMigrationRoute.Get("/migration/:id/run", routing.Wrap(cma.GetMigrationRunList))
|
||||
cloudMigrationRoute.Get("/migration/:id/run/:runID", routing.Wrap(cma.GetMigrationRun))
|
||||
cloudMigrationRoute.Get("/migration/:uid", routing.Wrap(cma.GetMigration))
|
||||
cloudMigrationRoute.Delete("/migration/:uid", routing.Wrap(cma.DeleteMigration))
|
||||
cloudMigrationRoute.Post("/migration/:uid/run", routing.Wrap(cma.RunMigration))
|
||||
cloudMigrationRoute.Get("/migration/:uid/run", routing.Wrap(cma.GetMigrationRunList))
|
||||
cloudMigrationRoute.Get("/migration/:uid/run/:runUID", routing.Wrap(cma.GetMigrationRun))
|
||||
cloudMigrationRoute.Post("/token", routing.Wrap(cma.CreateToken))
|
||||
}, middleware.ReqOrgAdmin)
|
||||
}
|
||||
@@ -97,7 +96,7 @@ func (cma *CloudMigrationAPI) GetMigrationList(c *contextmodel.ReqContext) respo
|
||||
return response.JSON(http.StatusOK, cloudMigrations)
|
||||
}
|
||||
|
||||
// swagger:route GET /cloudmigration/migration/{id} migrations getCloudMigration
|
||||
// swagger:route GET /cloudmigration/migration/{uid} migrations getCloudMigration
|
||||
//
|
||||
// Get a cloud migration.
|
||||
//
|
||||
@@ -112,11 +111,10 @@ func (cma *CloudMigrationAPI) GetMigration(c *contextmodel.ReqContext) response.
|
||||
ctx, span := cma.tracer.Start(c.Req.Context(), "MigrationAPI.GetMigration")
|
||||
defer span.End()
|
||||
|
||||
id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||
}
|
||||
cloudMigration, err := cma.cloudMigrationService.GetMigration(ctx, id)
|
||||
// TODO LND Should we validate with ValidateUID()? validate for empty?
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
|
||||
cloudMigration, err := cma.cloudMigrationService.GetMigration(ctx, uid)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusNotFound, "migration not found", err)
|
||||
}
|
||||
@@ -125,10 +123,10 @@ func (cma *CloudMigrationAPI) GetMigration(c *contextmodel.ReqContext) response.
|
||||
|
||||
// swagger:parameters getCloudMigration
|
||||
type GetCloudMigrationRequest struct {
|
||||
// ID of an migration
|
||||
// UID of an migration
|
||||
//
|
||||
// in: path
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
// swagger:route POST /cloudmigration/migration migrations createMigration
|
||||
@@ -155,7 +153,7 @@ func (cma *CloudMigrationAPI) CreateMigration(c *contextmodel.ReqContext) respon
|
||||
return response.JSON(http.StatusOK, cloudMigration)
|
||||
}
|
||||
|
||||
// swagger:route POST /cloudmigration/migration/{id}/run migrations runCloudMigration
|
||||
// swagger:route POST /cloudmigration/migration/{uid}/run migrations runCloudMigration
|
||||
//
|
||||
// Trigger the run of a migration to the Grafana Cloud.
|
||||
//
|
||||
@@ -170,13 +168,8 @@ func (cma *CloudMigrationAPI) RunMigration(c *contextmodel.ReqContext) response.
|
||||
ctx, span := cma.tracer.Start(c.Req.Context(), "MigrationAPI.RunMigration")
|
||||
defer span.End()
|
||||
|
||||
stringID := web.Params(c.Req)[":id"]
|
||||
id, err := strconv.ParseInt(stringID, 10, 64)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||
}
|
||||
|
||||
result, err := cma.cloudMigrationService.RunMigration(ctx, id)
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
result, err := cma.cloudMigrationService.RunMigration(ctx, uid)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "migration run error", err)
|
||||
}
|
||||
@@ -186,13 +179,13 @@ func (cma *CloudMigrationAPI) RunMigration(c *contextmodel.ReqContext) response.
|
||||
|
||||
// swagger:parameters runCloudMigration
|
||||
type RunCloudMigrationRequest struct {
|
||||
// ID of an migration
|
||||
// UID of an migration
|
||||
//
|
||||
// in: path
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
// swagger:route GET /cloudmigration/migration/{id}/run/{runID} migrations getCloudMigrationRun
|
||||
// swagger:route GET /cloudmigration/migration/{uid}/run/{runUID} migrations getCloudMigrationRun
|
||||
//
|
||||
// Get the result of a single migration run.
|
||||
//
|
||||
@@ -202,10 +195,14 @@ type RunCloudMigrationRequest struct {
|
||||
// 403: forbiddenError
|
||||
// 500: internalServerError
|
||||
func (cma *CloudMigrationAPI) GetMigrationRun(c *contextmodel.ReqContext) response.Response {
|
||||
// TODO Parameter 'uid' is not actually used at the moment, since we just need the run UID.
|
||||
// Will be cleaned in another PR
|
||||
|
||||
ctx, span := cma.tracer.Start(c.Req.Context(), "MigrationAPI.GetMigrationRun")
|
||||
defer span.End()
|
||||
|
||||
migrationStatus, err := cma.cloudMigrationService.GetMigrationStatus(ctx, web.Params(c.Req)[":id"], web.Params(c.Req)[":runID"])
|
||||
// [OLD] migrationStatus, err := cma.cloudMigrationService.GetMigrationStatus(ctx, web.Params(c.Req)[":id"], web.Params(c.Req)[":runID"])
|
||||
migrationStatus, err := cma.cloudMigrationService.GetMigrationStatus(ctx, web.Params(c.Req)[":runUID"])
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "migration status error", err)
|
||||
}
|
||||
@@ -221,18 +218,18 @@ func (cma *CloudMigrationAPI) GetMigrationRun(c *contextmodel.ReqContext) respon
|
||||
|
||||
// swagger:parameters getCloudMigrationRun
|
||||
type GetMigrationRunParams struct {
|
||||
// ID of an migration
|
||||
// UID of an migration
|
||||
//
|
||||
// in: path
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
|
||||
// Run ID of a migration run
|
||||
// RunUID of a migration run
|
||||
//
|
||||
// in: path
|
||||
RunID int64 `json:"runID"`
|
||||
RunUID string `json:"runUID"`
|
||||
}
|
||||
|
||||
// swagger:route GET /cloudmigration/migration/{id}/run migrations getCloudMigrationRunList
|
||||
// swagger:route GET /cloudmigration/migration/{uid}/run migrations getCloudMigrationRunList
|
||||
//
|
||||
// Get a list of migration runs for a migration.
|
||||
//
|
||||
@@ -245,7 +242,7 @@ func (cma *CloudMigrationAPI) GetMigrationRunList(c *contextmodel.ReqContext) re
|
||||
ctx, span := cma.tracer.Start(c.Req.Context(), "MigrationAPI.GetMigrationRunList")
|
||||
defer span.End()
|
||||
|
||||
runList, err := cma.cloudMigrationService.GetMigrationRunList(ctx, web.Params(c.Req)[":id"])
|
||||
runList, err := cma.cloudMigrationService.GetMigrationRunList(ctx, web.Params(c.Req)[":uid"])
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "list migration status error", err)
|
||||
}
|
||||
@@ -255,13 +252,13 @@ func (cma *CloudMigrationAPI) GetMigrationRunList(c *contextmodel.ReqContext) re
|
||||
|
||||
// swagger:parameters getCloudMigrationRunList
|
||||
type GetCloudMigrationRunList struct {
|
||||
// ID of an migration
|
||||
// UID of an migration
|
||||
//
|
||||
// in: path
|
||||
ID int64 `json:"id"`
|
||||
UID int64 `json:"uid"`
|
||||
}
|
||||
|
||||
// swagger:route DELETE /cloudmigration/migration/{id} migrations deleteCloudMigration
|
||||
// swagger:route DELETE /cloudmigration/migration/{uid} migrations deleteCloudMigration
|
||||
//
|
||||
// Delete a migration.
|
||||
//
|
||||
@@ -274,15 +271,11 @@ func (cma *CloudMigrationAPI) DeleteMigration(c *contextmodel.ReqContext) respon
|
||||
ctx, span := cma.tracer.Start(c.Req.Context(), "MigrationAPI.DeleteMigration")
|
||||
defer span.End()
|
||||
|
||||
idStr := web.Params(c.Req)[":id"]
|
||||
if idStr == "" {
|
||||
return response.Error(http.StatusBadRequest, "missing migration id", fmt.Errorf("missing migration id"))
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
if uid == "" {
|
||||
return response.Error(http.StatusBadRequest, "missing migration uid", fmt.Errorf("missing migration uid"))
|
||||
}
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "migration id should be numeric", fmt.Errorf("migration id should be numeric"))
|
||||
}
|
||||
_, err = cma.cloudMigrationService.DeleteMigration(ctx, id)
|
||||
_, err := cma.cloudMigrationService.DeleteMigration(ctx, uid)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "migration delete error", err)
|
||||
}
|
||||
@@ -291,10 +284,10 @@ func (cma *CloudMigrationAPI) DeleteMigration(c *contextmodel.ReqContext) respon
|
||||
|
||||
// swagger:parameters deleteCloudMigration
|
||||
type DeleteMigrationRequest struct {
|
||||
// ID of an migration
|
||||
// UID of an migration
|
||||
//
|
||||
// in: path
|
||||
ID int64 `json:"id"`
|
||||
UID int64 `json:"iud"`
|
||||
}
|
||||
|
||||
// swagger:response cloudMigrationRunResponse
|
||||
|
||||
@@ -9,13 +9,13 @@ type Service interface {
|
||||
ValidateToken(context.Context, CloudMigration) error
|
||||
|
||||
CreateMigration(context.Context, CloudMigrationRequest) (*CloudMigrationResponse, error)
|
||||
GetMigration(context.Context, int64) (*CloudMigration, error)
|
||||
DeleteMigration(context.Context, int64) (*CloudMigration, error)
|
||||
UpdateMigration(context.Context, int64, CloudMigrationRequest) (*CloudMigrationResponse, error)
|
||||
GetMigration(ctx context.Context, uid string) (*CloudMigration, error)
|
||||
DeleteMigration(ctx context.Context, uid string) (*CloudMigration, error)
|
||||
UpdateMigration(ctx context.Context, uid string, request CloudMigrationRequest) (*CloudMigrationResponse, error)
|
||||
GetMigrationList(context.Context) (*CloudMigrationListResponse, error)
|
||||
|
||||
RunMigration(context.Context, int64) (*MigrateDataResponseDTO, error)
|
||||
SaveMigrationRun(context.Context, *CloudMigrationRun) (int64, error)
|
||||
GetMigrationStatus(context.Context, string, string) (*CloudMigrationRun, error)
|
||||
RunMigration(ctx context.Context, uid string) (*MigrateDataResponseDTO, error)
|
||||
SaveMigrationRun(context.Context, *CloudMigrationRun) (string, error)
|
||||
GetMigrationStatus(ctx context.Context, runUID string) (*CloudMigrationRun, error)
|
||||
GetMigrationRunList(context.Context, string) (*CloudMigrationRunList, error)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -238,10 +237,10 @@ func (s *Service) ValidateToken(ctx context.Context, cm cloudmigration.CloudMigr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetMigration(ctx context.Context, id int64) (*cloudmigration.CloudMigration, error) {
|
||||
func (s *Service) GetMigration(ctx context.Context, uid string) (*cloudmigration.CloudMigration, error) {
|
||||
ctx, span := s.tracer.Start(ctx, "CloudMigrationService.GetMigration")
|
||||
defer span.End()
|
||||
migration, err := s.store.GetMigration(ctx, id)
|
||||
migration, err := s.store.GetMigrationByUID(ctx, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -258,7 +257,7 @@ func (s *Service) GetMigrationList(ctx context.Context) (*cloudmigration.CloudMi
|
||||
migrations := make([]cloudmigration.CloudMigrationResponse, 0)
|
||||
for _, v := range values {
|
||||
migrations = append(migrations, cloudmigration.CloudMigrationResponse{
|
||||
ID: v.ID,
|
||||
UID: v.UID,
|
||||
Stack: v.Stack,
|
||||
Created: v.Created,
|
||||
Updated: v.Updated,
|
||||
@@ -293,21 +292,21 @@ func (s *Service) CreateMigration(ctx context.Context, cmd cloudmigration.CloudM
|
||||
}
|
||||
|
||||
return &cloudmigration.CloudMigrationResponse{
|
||||
ID: cm.ID,
|
||||
UID: cm.UID,
|
||||
Stack: token.Instance.Slug,
|
||||
Created: cm.Created,
|
||||
Updated: cm.Updated,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateMigration(ctx context.Context, id int64, cm cloudmigration.CloudMigrationRequest) (*cloudmigration.CloudMigrationResponse, error) {
|
||||
func (s *Service) UpdateMigration(ctx context.Context, uid string, request cloudmigration.CloudMigrationRequest) (*cloudmigration.CloudMigrationResponse, error) {
|
||||
// TODO: Implement method
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *Service) RunMigration(ctx context.Context, id int64) (*cloudmigration.MigrateDataResponseDTO, error) {
|
||||
func (s *Service) RunMigration(ctx context.Context, uid string) (*cloudmigration.MigrateDataResponseDTO, error) {
|
||||
// Get migration to read the auth token
|
||||
migration, err := s.GetMigration(ctx, id)
|
||||
migration, err := s.GetMigration(ctx, uid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("migration get error: %w", err)
|
||||
}
|
||||
@@ -334,15 +333,15 @@ func (s *Service) RunMigration(ctx context.Context, id int64) (*cloudmigration.M
|
||||
}
|
||||
|
||||
// save the result of the migration
|
||||
runID, err := s.SaveMigrationRun(ctx, &cloudmigration.CloudMigrationRun{
|
||||
CloudMigrationUID: strconv.Itoa(int(id)),
|
||||
runUID, err := s.SaveMigrationRun(ctx, &cloudmigration.CloudMigrationRun{
|
||||
CloudMigrationUID: migration.UID,
|
||||
Result: respData,
|
||||
})
|
||||
if err != nil {
|
||||
response.Error(http.StatusInternalServerError, "migration run save error", err)
|
||||
}
|
||||
|
||||
resp.RunID = runID
|
||||
resp.RunUID = runUID
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -470,29 +469,28 @@ func (s *Service) getDashboards(ctx context.Context) ([]dashboards.Dashboard, er
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Service) SaveMigrationRun(ctx context.Context, cmr *cloudmigration.CloudMigrationRun) (int64, error) {
|
||||
func (s *Service) SaveMigrationRun(ctx context.Context, cmr *cloudmigration.CloudMigrationRun) (string, error) {
|
||||
cmr.Created = time.Now()
|
||||
cmr.Updated = time.Now()
|
||||
cmr.Finished = time.Now()
|
||||
err := s.store.SaveMigrationRun(ctx, cmr)
|
||||
if err != nil {
|
||||
s.log.Error("Failed to save migration run", "err", err)
|
||||
return -1, err
|
||||
return "", err
|
||||
}
|
||||
return cmr.ID, nil
|
||||
return cmr.UID, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetMigrationStatus(ctx context.Context, id string, runID string) (*cloudmigration.CloudMigrationRun, error) {
|
||||
cmr, err := s.store.GetMigrationStatus(ctx, id, runID)
|
||||
func (s *Service) GetMigrationStatus(ctx context.Context, runUID string) (*cloudmigration.CloudMigrationRun, error) {
|
||||
cmr, err := s.store.GetMigrationStatus(ctx, runUID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving migration status from db: %w", err)
|
||||
}
|
||||
|
||||
return cmr, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetMigrationRunList(ctx context.Context, migrationID string) (*cloudmigration.CloudMigrationRunList, error) {
|
||||
runs, err := s.store.GetMigrationStatusList(ctx, migrationID)
|
||||
func (s *Service) GetMigrationRunList(ctx context.Context, migUID string) (*cloudmigration.CloudMigrationRunList, error) {
|
||||
runs, err := s.store.GetMigrationStatusList(ctx, migUID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving migration statuses from db: %w", err)
|
||||
}
|
||||
@@ -506,15 +504,15 @@ func (s *Service) GetMigrationRunList(ctx context.Context, migrationID string) (
|
||||
if err := json.Unmarshal(s.Result, &r); err != nil {
|
||||
return nil, fmt.Errorf("error unmarshalling migration response items: %w", err)
|
||||
}
|
||||
r.RunID = s.ID
|
||||
r.RunUID = s.UID
|
||||
runList.Runs = append(runList.Runs, r)
|
||||
}
|
||||
|
||||
return runList, nil
|
||||
}
|
||||
|
||||
func (s *Service) DeleteMigration(ctx context.Context, id int64) (*cloudmigration.CloudMigration, error) {
|
||||
c, err := s.store.DeleteMigration(ctx, id)
|
||||
func (s *Service) DeleteMigration(ctx context.Context, uid string) (*cloudmigration.CloudMigration, error) {
|
||||
c, err := s.store.DeleteMigration(ctx, uid)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("deleting migration from db: %w", err)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
||||
)
|
||||
|
||||
// CloudMigrationsServiceImpl Define the Service Implementation.
|
||||
// NoopServiceImpl Define the Service Implementation.
|
||||
type NoopServiceImpl struct{}
|
||||
|
||||
var _ cloudmigration.Service = (*NoopServiceImpl)(nil)
|
||||
@@ -22,7 +22,7 @@ func (s *NoopServiceImpl) ValidateToken(ctx context.Context, cm cloudmigration.C
|
||||
return cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) GetMigration(ctx context.Context, id int64) (*cloudmigration.CloudMigration, error) {
|
||||
func (s *NoopServiceImpl) GetMigration(ctx context.Context, uid string) (*cloudmigration.CloudMigration, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
@@ -34,26 +34,26 @@ func (s *NoopServiceImpl) CreateMigration(ctx context.Context, cm cloudmigration
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) UpdateMigration(ctx context.Context, id int64, cm cloudmigration.CloudMigrationRequest) (*cloudmigration.CloudMigrationResponse, error) {
|
||||
func (s *NoopServiceImpl) UpdateMigration(ctx context.Context, uid string, cm cloudmigration.CloudMigrationRequest) (*cloudmigration.CloudMigrationResponse, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) GetMigrationStatus(ctx context.Context, id string, runID string) (*cloudmigration.CloudMigrationRun, error) {
|
||||
func (s *NoopServiceImpl) GetMigrationStatus(ctx context.Context, runUID string) (*cloudmigration.CloudMigrationRun, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) GetMigrationRunList(ctx context.Context, id string) (*cloudmigration.CloudMigrationRunList, error) {
|
||||
func (s *NoopServiceImpl) GetMigrationRunList(ctx context.Context, uid string) (*cloudmigration.CloudMigrationRunList, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) DeleteMigration(ctx context.Context, id int64) (*cloudmigration.CloudMigration, error) {
|
||||
func (s *NoopServiceImpl) DeleteMigration(ctx context.Context, uid string) (*cloudmigration.CloudMigration, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) SaveMigrationRun(ctx context.Context, cmr *cloudmigration.CloudMigrationRun) (int64, error) {
|
||||
return -1, cloudmigration.ErrInternalNotImplementedError
|
||||
func (s *NoopServiceImpl) SaveMigrationRun(context.Context, *cloudmigration.CloudMigrationRun) (string, error) {
|
||||
return "", cloudmigration.ErrInternalNotImplementedError
|
||||
}
|
||||
|
||||
func (s *NoopServiceImpl) RunMigration(context.Context, int64) (*cloudmigration.MigrateDataResponseDTO, error) {
|
||||
func (s *NoopServiceImpl) RunMigration(context.Context, string) (*cloudmigration.MigrateDataResponseDTO, error) {
|
||||
return nil, cloudmigration.ErrFeatureDisabledError
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user