diff --git a/api/swagger/docs.go b/api/swagger/docs.go index d73ddbde..e74d51a3 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3447,6 +3447,12 @@ const docTemplate = `{ "sessionToken": { "type": "string" }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, "updatedAt": { "type": "string" }, @@ -3488,6 +3494,9 @@ const docTemplate = `{ "resource": { "type": "string" }, + "status": { + "type": "string" + }, "updatedAt": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 1ddeecec..be63706c 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3440,6 +3440,12 @@ "sessionToken": { "type": "string" }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, "updatedAt": { "type": "string" }, @@ -3481,6 +3487,9 @@ "resource": { "type": "string" }, + "status": { + "type": "string" + }, "updatedAt": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 01dd89bc..db8bf5b4 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -289,6 +289,10 @@ definitions: type: string sessionToken: type: string + status: + type: integer + statusDesc: + type: string updatedAt: type: string updator: @@ -316,6 +320,8 @@ definitions: type: string resource: type: string + status: + type: string updatedAt: type: string updator: diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index afa7640e..499d1778 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -1,6 +1,8 @@ package repository import ( + "fmt" + "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -16,6 +18,7 @@ type ICloudAccountRepository interface { Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) Update(dto domain.CloudAccount) (err error) Delete(dto domain.CloudAccount) (err error) + InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) } type CloudAccountRepository struct { @@ -39,6 +42,9 @@ type CloudAccount struct { Description string Resource string CloudService string + WorkflowId string + Status domain.CloudAccountStatus + StatusDesc string CreatorId *uuid.UUID `gorm:"type:uuid"` Creator User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` @@ -92,6 +98,7 @@ func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId Description: dto.Description, CloudService: dto.CloudService, Resource: dto.Resource, + Status: domain.CloudAccountStatus_PENDING, CreatorId: &dto.CreatorId} res := r.db.Create(&cloudAccount) if res.Error != nil { @@ -118,6 +125,18 @@ func (r *CloudAccountRepository) Delete(dto domain.CloudAccount) (err error) { return nil } +func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { + res := r.db.Model(&CloudAccount{}). + Where("ID = ?", cloudAccountId). + Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) + + if res.Error != nil || res.RowsAffected == 0 { + return fmt.Errorf("nothing updated in cloud-account with id %s", &cloudAccountId) + } + + return nil +} + func reflectCloudAccount(cloudAccount CloudAccount) domain.CloudAccount { return domain.CloudAccount{ ID: cloudAccount.ID, @@ -126,6 +145,8 @@ func reflectCloudAccount(cloudAccount CloudAccount) domain.CloudAccount { Description: cloudAccount.Description, Resource: cloudAccount.Resource, CloudService: cloudAccount.CloudService, + Status: cloudAccount.Status, + StatusDesc: cloudAccount.StatusDesc, Creator: reflectSimpleUser(cloudAccount.Creator), Updator: reflectSimpleUser(cloudAccount.Updator), CreatedAt: cloudAccount.CreatedAt, diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 3252103c..0d0edbda 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -3,8 +3,6 @@ package usecase import ( "context" "fmt" - "strings" - "time" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -80,41 +78,12 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccoun return uuid.Nil, fmt.Errorf("Failed to call argo workflow : %s", err) } log.Info("submited workflow :", workflowId) - //workflowId := "tks-create-aws-cloud-account-dfw95" - // wait & get clusterId ( max 1min ) - for i := 0; i < MAX_WORKFLOW_TIME; i++ { - time.Sleep(time.Second * 2) - workflow, err := u.argo.GetWorkflow("argo", workflowId) - if err != nil { - return uuid.Nil, err - } - - if workflow.Status.Phase == "Succeeded" { - return cloudAccountId, nil - } - if workflow.Status.Phase == "Failed" { - logs, err := u.argo.GetWorkflowLog("argo", "main", workflowId) - if err != nil { - return uuid.Nil, errors.Wrap(err, "Failed to get workflow log") - } - - arr := strings.Split(logs, "\n") - for _, line := range arr { - if strings.Contains(line, "Error:") { - return uuid.Nil, httpErrors.NewInternalServerError(fmt.Errorf("%s", line), "INVALID_CLIENT_TOKEN_ID", "") - } - } - - return uuid.Nil, errors.Wrap(err, logs) - } - - if workflow.Status.Phase != "" && workflow.Status.Phase != "Running" { - return uuid.Nil, fmt.Errorf("Invalid workflow status [%s]", workflow.Status.Phase) - } + if err := u.repo.InitWorkflow(cloudAccountId, workflowId, domain.CloudAccountStatus_CREATING); err != nil { + return uuid.Nil, errors.Wrap(err, "Failed to initialize status") } - return uuid.Nil, fmt.Errorf("Failed to creating cloud account") + return cloudAccountId, nil } func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccount) error { @@ -183,9 +152,26 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto domain.CloudAccoun return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") } - err = u.repo.Delete(dto) + workflowId, err := u.argo.SumbitWorkflowFromWftpl( + "tks-delete-aws-cloud-account", + argowf.SubmitOptions{ + Parameters: []string{ + "aws_region=" + "ap-northeast-2", + "tks_cloud_account_id=" + dto.ID.String(), + "aws_account_id=" + dto.AwsAccountId, + "aws_access_key_id=" + dto.AccessKeyId, + "aws_secret_access_key=" + dto.SecretAccessKey, + "aws_session_token=" + dto.SessionToken, + }, + }) if err != nil { - return err + log.Error("failed to submit argo workflow template. err : ", err) + return fmt.Errorf("Failed to call argo workflow : %s", err) + } + log.Info("submited workflow :", workflowId) + + if err := u.repo.InitWorkflow(dto.ID, workflowId, domain.CloudAccountStatus_DELETING); err != nil { + return errors.Wrap(err, "Failed to initialize status") } return nil diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index d3a799dd..a07d43ad 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -13,6 +13,37 @@ const ( CloudService_GCP = "GCP" ) +// enum +type CloudAccountStatus int32 + +const ( + CloudAccountStatus_PENDING CloudAccountStatus = iota + CloudAccountStatus_CREATING + CloudAccountStatus_CREATED + CloudAccountStatus_DELETING + CloudAccountStatus_DELETED + CloudAccountStatus_ERROR +) + +var cloudAccountStatus = [...]string{ + "PENDING", + "CREATING", + "CREATED", + "DELETING", + "DELETED", + "ERROR", +} + +func (m CloudAccountStatus) String() string { return cloudAccountStatus[(m)] } +func (m CloudAccountStatus) FromString(s string) CloudAccountStatus { + for i, v := range cloudAccountStatus { + if v == s { + return CloudAccountStatus(i) + } + } + return CloudAccountStatus_ERROR +} + // 내부 type CloudAccount struct { ID uuid.UUID @@ -26,6 +57,8 @@ type CloudAccount struct { AccessKeyId string SecretAccessKey string SessionToken string + Status CloudAccountStatus + StatusDesc string CreatorId uuid.UUID Creator User UpdatorId uuid.UUID @@ -42,6 +75,7 @@ type CloudAccountResponse struct { CloudService string `json:"cloudService"` Resource string `json:"resource"` Clusters int `json:"clusters"` + Status string `json:"status"` Creator SimpleUserResponse `json:"creator"` Updator SimpleUserResponse `json:"updator"` CreatedAt time.Time `json:"createdAt"` diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go index 7188558c..26733524 100644 --- a/pkg/domain/mapper.go +++ b/pkg/domain/mapper.go @@ -130,5 +130,11 @@ func Map(src interface{}, dst interface{}) error { {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ApplicationType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { return new(ApplicationType).FromString(i.(string)), nil }, + {srcType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(CloudAccountStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(CloudAccountStatus).FromString(i.(string)), nil + }, }) }