From 9fab67cad28e3e1deddce40c324f4179ebb21001 Mon Sep 17 00:00:00 2001 From: Yunkon Kim Date: Fri, 15 Nov 2024 02:29:29 +0900 Subject: [PATCH] Support SQL DB APIs for AWS, Azure, GCP, and NCP * Support APIs to Create, Read, and Delete SQL DB * Note - This API requires mc-terrarium. --- docker-compose.yaml | 3 +- go.mod | 2 +- go.sum | 4 + go.work.sum | 2 + src/api/rest/docs/docs.go | 77 +---- src/api/rest/docs/swagger.json | 77 +---- src/api/rest/docs/swagger.yaml | 68 +--- src/api/rest/server/resource/sqlDb.go | 102 +++--- src/api/rest/server/server.go | 2 +- src/core/model/sqlDb.go | 8 +- src/core/resource/sqlDb.go | 452 ++++++++++---------------- 11 files changed, 264 insertions(+), 533 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 158d5666..6f73dfee 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -166,7 +166,7 @@ services: # # mc-terrarium (PoC): resource extentions such as VPN for CB-Tumblebug by using OpenTofu # mc-terrarium: - # image: cloudbaristaorg/mc-terrarium:0.0.10 + # image: cloudbaristaorg/mc-terrarium:0.0.16 # container_name: mc-terrarium # # build: # # context: . @@ -180,6 +180,7 @@ services: # env_file: # - ${HOME}/.cloud-barista/secrets/credentials # AWS credentials # - ${HOME}/.cloud-barista/secrets/credential-azure.env # Azure credentials + # - ${HOME}/.cloud-barista/secrets/credential-ncp.env # NCP credentials # volumes: # - ${HOME}/.cloud-barista/secrets:/app/secrets:ro # GCP credentials # - ./container-volume/mc-terrarium-container/.terrarium:/app/.terrarium diff --git a/go.mod b/go.mod index a1a425c8..48d656ff 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/cloud-barista/cb-tumblebug go 1.23.0 require ( - github.com/cloud-barista/mc-terrarium v0.0.12 + github.com/cloud-barista/mc-terrarium v0.0.16 github.com/fsnotify/fsnotify v1.7.0 github.com/go-playground/validator/v10 v10.17.0 github.com/go-resty/resty/v2 v2.13.1 diff --git a/go.sum b/go.sum index 85137141..4ddc5413 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,10 @@ github.com/cloud-barista/mc-terrarium v0.0.9 h1:bJrGg0VZyflw1ncyrD8/6qzMW0YiK2LD github.com/cloud-barista/mc-terrarium v0.0.9/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= github.com/cloud-barista/mc-terrarium v0.0.10 h1:WrK/bHyiQZ9ZxRLVoUTY4c3CVH7z+vEzdh7yxo9X4ZM= github.com/cloud-barista/mc-terrarium v0.0.10/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= +github.com/cloud-barista/mc-terrarium v0.0.15 h1:1yJjCsNMwYZJyYSku9HQPOdj1PwAf5ybYI+DqB1TKsc= +github.com/cloud-barista/mc-terrarium v0.0.15/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= +github.com/cloud-barista/mc-terrarium v0.0.16 h1:0TpSnFk5IpStpQc1YJSbMzB8q1jgVZ639Cjh7YAyxh4= +github.com/cloud-barista/mc-terrarium v0.0.16/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= diff --git a/go.work.sum b/go.work.sum index 01c4b858..a33b0bf1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -388,6 +388,8 @@ github.com/cloud-barista/mc-terrarium v0.0.11 h1:qfwie72bzJzYSca24BugO23Iv9aq4gI github.com/cloud-barista/mc-terrarium v0.0.11/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= github.com/cloud-barista/mc-terrarium v0.0.12 h1:A8vGrm7bF6xBwta9uy5BguMEzUUn3X1WvP7xaacJ014= github.com/cloud-barista/mc-terrarium v0.0.12/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= +github.com/cloud-barista/mc-terrarium v0.0.16 h1:0TpSnFk5IpStpQc1YJSbMzB8q1jgVZ639Cjh7YAyxh4= +github.com/cloud-barista/mc-terrarium v0.0.16/go.mod h1:iQxZNRa04d7mHA0h5dEPfF7ch1SBUS/ZFGUynKsKJ6I= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= diff --git a/src/api/rest/docs/docs.go b/src/api/rest/docs/docs.go index d2b64ed1..89f02c2c 100644 --- a/src/api/rest/docs/docs.go +++ b/src/api/rest/docs/docs.go @@ -8166,7 +8166,7 @@ const docTemplate = `{ }, "/ns/{nsId}/resources/sqlDb": { "get": { - "description": "Get all SQL Databases", + "description": "Get all SQL Databases (TBD)", "consumes": [ "application/json" ], @@ -8176,7 +8176,7 @@ const docTemplate = `{ "tags": [ "[Infra Resource] SQL Database Management (under development)" ], - "summary": "Get all SQL Databases", + "summary": "Get all SQL Databases (TBD)", "operationId": "GetAllSqlDb", "parameters": [ { @@ -8227,7 +8227,7 @@ const docTemplate = `{ } }, "post": { - "description": "Create a SQL Databases\n\n- Supported CSPs: AWS (Upcoming CSPs: Azure, GCP, NCP)\n\n- Please check the values ​​required for each CSP through the ` + "`" + `requiredCSPResource` + "`" + ` property.\n", + "description": "Create a SQL Databases\n\nSupported CSPs: AWS, Azure, GCP, NCP\n- Note - ` + "`" + `connectionName` + "`" + ` example: aws-ap-northeast-2, azure-koreacentral, gcp-asia-northeast3, ncpvpc-kr\n\n- Note - Please check the ` + "`" + `requiredCSPResource` + "`" + ` property which includes CSP specific values.\n\n- Note - You can find the API usage examples on this link, https://github.com/cloud-barista/mc-terrarium/discussions/110\n", "consumes": [ "application/json" ], @@ -8420,73 +8420,6 @@ const docTemplate = `{ } } }, - "/ns/{nsId}/resources/sqlDb/{sqlDbId}/request/{requestId}": { - "get": { - "description": "Check the status of a specific request by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "[Infra Resource] SQL Database Management (under development)" - ], - "summary": "Check the status of a specific request by its ID", - "operationId": "GetRequestStatusOfSqlDb", - "parameters": [ - { - "type": "string", - "default": "default", - "description": "Namespace ID", - "name": "nsId", - "in": "path", - "required": true - }, - { - "type": "string", - "default": "sqldb01", - "description": "SQL DB ID", - "name": "sqlDbId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Request ID", - "name": "requestId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Response" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - }, - "503": { - "description": "Service Unavailable", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - } - } - } - }, "/ns/{nsId}/resources/sshKey": { "get": { "description": "List all SSH Keys or SSH Keys' ID", @@ -12348,7 +12281,7 @@ const docTemplate = `{ "properties": { "resourceGroup": { "type": "string", - "example": "rg-xxxx" + "example": "koreacentral" } } }, @@ -12371,7 +12304,7 @@ const docTemplate = `{ "properties": { "subnetID": { "type": "string", - "example": "subnet-xxxx" + "example": "123456" } } }, diff --git a/src/api/rest/docs/swagger.json b/src/api/rest/docs/swagger.json index b68aa303..458510a0 100644 --- a/src/api/rest/docs/swagger.json +++ b/src/api/rest/docs/swagger.json @@ -8159,7 +8159,7 @@ }, "/ns/{nsId}/resources/sqlDb": { "get": { - "description": "Get all SQL Databases", + "description": "Get all SQL Databases (TBD)", "consumes": [ "application/json" ], @@ -8169,7 +8169,7 @@ "tags": [ "[Infra Resource] SQL Database Management (under development)" ], - "summary": "Get all SQL Databases", + "summary": "Get all SQL Databases (TBD)", "operationId": "GetAllSqlDb", "parameters": [ { @@ -8220,7 +8220,7 @@ } }, "post": { - "description": "Create a SQL Databases\n\n- Supported CSPs: AWS (Upcoming CSPs: Azure, GCP, NCP)\n\n- Please check the values ​​required for each CSP through the `requiredCSPResource` property.\n", + "description": "Create a SQL Databases\n\nSupported CSPs: AWS, Azure, GCP, NCP\n- Note - `connectionName` example: aws-ap-northeast-2, azure-koreacentral, gcp-asia-northeast3, ncpvpc-kr\n\n- Note - Please check the `requiredCSPResource` property which includes CSP specific values.\n\n- Note - You can find the API usage examples on this link, https://github.com/cloud-barista/mc-terrarium/discussions/110\n", "consumes": [ "application/json" ], @@ -8413,73 +8413,6 @@ } } }, - "/ns/{nsId}/resources/sqlDb/{sqlDbId}/request/{requestId}": { - "get": { - "description": "Check the status of a specific request by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "[Infra Resource] SQL Database Management (under development)" - ], - "summary": "Check the status of a specific request by its ID", - "operationId": "GetRequestStatusOfSqlDb", - "parameters": [ - { - "type": "string", - "default": "default", - "description": "Namespace ID", - "name": "nsId", - "in": "path", - "required": true - }, - { - "type": "string", - "default": "sqldb01", - "description": "SQL DB ID", - "name": "sqlDbId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Request ID", - "name": "requestId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/model.Response" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - }, - "503": { - "description": "Service Unavailable", - "schema": { - "$ref": "#/definitions/model.SimpleMsg" - } - } - } - } - }, "/ns/{nsId}/resources/sshKey": { "get": { "description": "List all SSH Keys or SSH Keys' ID", @@ -12341,7 +12274,7 @@ "properties": { "resourceGroup": { "type": "string", - "example": "rg-xxxx" + "example": "koreacentral" } } }, @@ -12364,7 +12297,7 @@ "properties": { "subnetID": { "type": "string", - "example": "subnet-xxxx" + "example": "123456" } } }, diff --git a/src/api/rest/docs/swagger.yaml b/src/api/rest/docs/swagger.yaml index a4cb1fcc..049dcd93 100644 --- a/src/api/rest/docs/swagger.yaml +++ b/src/api/rest/docs/swagger.yaml @@ -6213,8 +6213,8 @@ paths: get: tags: - "[Infra Resource] SQL Database Management (under development)" - summary: Get all SQL Databases - description: Get all SQL Databases + summary: Get all SQL Databases (TBD) + description: Get all SQL Databases (TBD) operationId: GetAllSqlDb parameters: - name: nsId @@ -6265,9 +6265,12 @@ paths: description: | Create a SQL Databases - - Supported CSPs: AWS (Upcoming CSPs: Azure, GCP, NCP) + Supported CSPs: AWS, Azure, GCP, NCP + - Note - `connectionName` example: aws-ap-northeast-2, azure-koreacentral, gcp-asia-northeast3, ncpvpc-kr - - Please check the values ​​required for each CSP through the `requiredCSPResource` property. + - Note - Please check the `requiredCSPResource` property which includes CSP specific values. + + - Note - You can find the API usage examples on this link, https://github.com/cloud-barista/mc-terrarium/discussions/110 operationId: PostSqlDb parameters: - name: nsId @@ -6416,59 +6419,6 @@ paths: application/json: schema: $ref: '#/components/schemas/model.SimpleMsg' - /ns/{nsId}/resources/sqlDb/{sqlDbId}/request/{requestId}: - get: - tags: - - "[Infra Resource] SQL Database Management (under development)" - summary: Check the status of a specific request by its ID - description: Check the status of a specific request by its ID - operationId: GetRequestStatusOfSqlDb - parameters: - - name: nsId - in: path - description: Namespace ID - required: true - schema: - type: string - default: default - - name: sqlDbId - in: path - description: SQL DB ID - required: true - schema: - type: string - default: sqldb01 - - name: requestId - in: path - description: Request ID - required: true - schema: - type: string - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/model.Response' - "400": - description: Bad Request - content: - application/json: - schema: - $ref: '#/components/schemas/model.SimpleMsg' - "500": - description: Internal Server Error - content: - application/json: - schema: - $ref: '#/components/schemas/model.SimpleMsg' - "503": - description: Service Unavailable - content: - application/json: - schema: - $ref: '#/components/schemas/model.SimpleMsg' /ns/{nsId}/resources/sshKey: get: tags: @@ -9259,7 +9209,7 @@ components: properties: resourceGroup: type: string - example: rg-xxxx + example: koreacentral model.RequiredCSPResource: type: object properties: @@ -9274,7 +9224,7 @@ components: properties: subnetID: type: string - example: subnet-xxxx + example: "123456" model.ResourceCountOverview: type: object properties: diff --git a/src/api/rest/server/resource/sqlDb.go b/src/api/rest/server/resource/sqlDb.go index 90baf341..f45e7dec 100644 --- a/src/api/rest/server/resource/sqlDb.go +++ b/src/api/rest/server/resource/sqlDb.go @@ -218,8 +218,8 @@ import ( // RestGetAllSqlDb godoc // @ID GetAllSqlDb -// @Summary Get all SQL Databases -// @Description Get all SQL Databases +// @Summary Get all SQL Databases (TBD) +// @Description Get all SQL Databases (TBD) // @Tags [Infra Resource] SQL Database Management (under development) // @Accept json // @Produce json @@ -278,7 +278,6 @@ func RestGetAllSqlDb(c echo.Context) error { // } return c.JSON(http.StatusOK, model.VpnInfoList{}) - } // RestPostSqlDb godoc @@ -286,9 +285,12 @@ func RestGetAllSqlDb(c echo.Context) error { // @Summary Create a SQL Databases // @Description Create a SQL Databases // @Description -// @Description - Supported CSPs: AWS (Upcoming CSPs: Azure, GCP, NCP) +// @Description Supported CSPs: AWS, Azure, GCP, NCP +// @Description - Note - `connectionName` example: aws-ap-northeast-2, azure-koreacentral, gcp-asia-northeast3, ncpvpc-kr +// @Description +// @Description - Note - Please check the `requiredCSPResource` property which includes CSP specific values. // @Description -// @Description - Please check the values ​​required for each CSP through the `requiredCSPResource` property. +// @Description - Note - You can find the API usage examples on this link, https://github.com/cloud-barista/mc-terrarium/discussions/110 // @Description // @Tags [Infra Resource] SQL Database Management (under development) // @Accept json @@ -569,52 +571,52 @@ func RestDeleteSqlDb(c echo.Context) error { // // return nil // } -// RestGetRequestStatusOfSqlDb godoc -// @ID GetRequestStatusOfSqlDb -// @Summary Check the status of a specific request by its ID -// @Description Check the status of a specific request by its ID -// @Tags [Infra Resource] SQL Database Management (under development) -// @Accept json -// @Produce json -// @Param nsId path string true "Namespace ID" default(default) -// @Param sqlDbId path string true "SQL DB ID" default(sqldb01) -// @Param requestId path string true "Request ID" -// @Success 200 {object} model.Response "OK" -// @Failure 400 {object} model.SimpleMsg "Bad Request" -// @Failure 500 {object} model.SimpleMsg "Internal Server Error" -// @Failure 503 {object} model.SimpleMsg "Service Unavailable" -// @Router /ns/{nsId}/resources/sqlDb/{sqlDbId}/request/{requestId} [get] -func RestGetRequestStatusOfSqlDb(c echo.Context) error { +// // RestGetRequestStatusOfSqlDb godoc +// // @ID GetRequestStatusOfSqlDb +// // @Summary Check the status of a specific request by its ID +// // @Description Check the status of a specific request by its ID +// // @Tags [Infra Resource] SQL Database Management (under development) +// // @Accept json +// // @Produce json +// // @Param nsId path string true "Namespace ID" default(default) +// // @Param sqlDbId path string true "SQL DB ID" default(sqldb01) +// // @Param requestId path string true "Request ID" +// // @Success 200 {object} model.Response "OK" +// // @Failure 400 {object} model.SimpleMsg "Bad Request" +// // @Failure 500 {object} model.SimpleMsg "Internal Server Error" +// // @Failure 503 {object} model.SimpleMsg "Service Unavailable" +// // @Router /ns/{nsId}/resources/sqlDb/{sqlDbId}/request/{requestId} [get] +// func RestGetRequestStatusOfSqlDb(c echo.Context) error { - nsId := c.Param("nsId") - err := common.CheckString(nsId) - if err != nil { - errMsg := fmt.Errorf("invalid nsId (%s)", nsId) - log.Warn().Err(err).Msgf(errMsg.Error()) - return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) - } +// nsId := c.Param("nsId") +// err := common.CheckString(nsId) +// if err != nil { +// errMsg := fmt.Errorf("invalid nsId (%s)", nsId) +// log.Warn().Err(err).Msgf(errMsg.Error()) +// return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) +// } - sqlDbId := c.Param("sqlDbId") - err = common.CheckString(sqlDbId) - if err != nil { - errMsg := fmt.Errorf("invalid sqlDbId (%s)", sqlDbId) - log.Warn().Err(err).Msgf(errMsg.Error()) - return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) - } - reqId := c.Param("requestId") - if reqId == "" { - errMsg := fmt.Errorf("invalid reqId (%s)", reqId) - log.Warn().Err(err).Msgf(errMsg.Error()) - return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) - } - reqId = strings.TrimSpace(reqId) +// sqlDbId := c.Param("sqlDbId") +// err = common.CheckString(sqlDbId) +// if err != nil { +// errMsg := fmt.Errorf("invalid sqlDbId (%s)", sqlDbId) +// log.Warn().Err(err).Msgf(errMsg.Error()) +// return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) +// } +// reqId := c.Param("requestId") +// if reqId == "" { +// errMsg := fmt.Errorf("invalid reqId (%s)", reqId) +// log.Warn().Err(err).Msgf(errMsg.Error()) +// return c.JSON(http.StatusBadRequest, model.SimpleMsg{Message: errMsg.Error()}) +// } +// reqId = strings.TrimSpace(reqId) - var resp model.Response - resp, err = resource.GetRequestStatusOfSqlDb(nsId, sqlDbId, reqId) - if err != nil { - log.Err(err).Msg("") - return c.JSON(http.StatusInternalServerError, model.SimpleMsg{Message: err.Error()}) - } +// var resp model.Response +// resp, err = resource.GetRequestStatusOfSqlDb(nsId, sqlDbId, reqId) +// if err != nil { +// log.Err(err).Msg("") +// return c.JSON(http.StatusInternalServerError, model.SimpleMsg{Message: err.Error()}) +// } - return c.JSON(http.StatusOK, resp) -} +// return c.JSON(http.StatusOK, resp) +// } diff --git a/src/api/rest/server/server.go b/src/api/rest/server/server.go index 2422638c..b154cf50 100644 --- a/src/api/rest/server/server.go +++ b/src/api/rest/server/server.go @@ -504,7 +504,7 @@ func RunServer() { sqlDbGroup.POST("", rest_resource.RestPostSqlDb) sqlDbGroup.GET("/:sqlDbId", rest_resource.RestGetSqlDb) sqlDbGroup.DELETE("/:sqlDbId", rest_resource.RestDeleteSqlDb) - sqlDbGroup.GET("/:sqlDbId/request/:requestId", rest_resource.RestGetRequestStatusOfSqlDb) + // sqlDbGroup.GET("/:sqlDbId/request/:requestId", rest_resource.RestGetRequestStatusOfSqlDb) // sqlDbGroup.PUT("//:sqlDbId", rest_resource.RestPutSqlDs) /* diff --git a/src/core/model/sqlDb.go b/src/core/model/sqlDb.go index dfd233a7..fc1679d9 100644 --- a/src/core/model/sqlDb.go +++ b/src/core/model/sqlDb.go @@ -19,9 +19,9 @@ type RestPostSqlDbRequest struct { ConnectionName string `json:"connectionName" validate:"required" example:"aws-ap-northeast-2"` CSP string `json:"csp" validate:"required" example:"aws"` Region string `json:"region" validate:"required" example:"ap-northeast-2"` - DBInstanceSpec string `json:"dbInstanceSpec" validate:"required" example:"db.t3.micro"` + DBInstanceSpec string `json:"dbInstanceSpec,omitempty" validate:"required" example:"db.t3.micro"` DBEnginePort int `json:"dbEnginePort,omitempty" validate:"required" example:"3306"` - DBEngineVersion string `json:"dbEngineVersion" validate:"required" example:"8.0.39"` + DBEngineVersion string `json:"dbEngineVersion,omitempty" validate:"required" example:"8.0.39"` DBAdminUsername string `json:"dbAdminUsername" validate:"required" example:"mydbadmin"` DBAdminPassword string `json:"dbAdminPassword" validate:"required" example:"Password1234!"` RequiredCSPResource RequiredCSPResource `json:"requiredCSPResource,omitempty"` @@ -40,11 +40,11 @@ type RequiredAWSResource struct { } type RequiredAzureResource struct { - ResourceGroup string `json:"resourceGroup,omitempty" example:"rg-xxxx"` + ResourceGroup string `json:"resourceGroup,omitempty" example:"koreacentral"` } type RequiredNCPResource struct { - SubnetID string `json:"subnetID,omitempty" example:"subnet-xxxx"` + SubnetID string `json:"subnetID,omitempty" example:"123456"` } type SqlDBInfo struct { diff --git a/src/core/resource/sqlDb.go b/src/core/resource/sqlDb.go index dc6e4acb..b299afc2 100644 --- a/src/core/resource/sqlDb.go +++ b/src/core/resource/sqlDb.go @@ -15,11 +15,9 @@ limitations under the License. package resource import ( - "context" "encoding/json" "fmt" "os" - "time" "github.com/cloud-barista/cb-tumblebug/src/core/common" "github.com/cloud-barista/cb-tumblebug/src/core/common/label" @@ -195,6 +193,16 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string log.Error().Err(err).Msg("") return emptyRet, err } + + sqlDBInfo.Name = sqlDbReq.Name + sqlDBInfo.Id = sqlDbReq.Name + sqlDBInfo.Description = "SQL DB at " + sqlDbReq.Region + " in " + sqlDbReq.CSP + sqlDBInfo.ConnectionName = sqlDbReq.ConnectionName + sqlDBInfo.ConnectionConfig, err = common.GetConnConfig(sqlDBInfo.ConnectionName) + if err != nil { + err = fmt.Errorf("Cannot retrieve ConnectionConfig" + err.Error()) + log.Error().Err(err).Msg("") + } } // [Set and store status] @@ -228,42 +236,38 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string // Set a terrarium ID trId := sqlDBInfo.Uid - // Check the CSPs of the sites - switch sqlDbReq.CSP { - case "aws": - if !retried { - // Issue a terrarium - method := "POST" - url := fmt.Sprintf("%s/tr", epTerrarium) - reqTr := new(terrariumModel.TerrariumInfo) - reqTr.Id = trId - reqTr.Description = "SQL DB at " + sqlDbReq.Region + " in " + sqlDbReq.CSP - - resTrInfo := new(terrariumModel.TerrariumInfo) - - err = common.ExecuteHttpRequest( - client, - method, - url, - nil, - common.SetUseBody(*reqTr), - reqTr, - resTrInfo, - common.VeryShortDuration, - ) - - if err != nil { - log.Err(err).Msg("") - return emptyRet, err - } - - log.Debug().Msgf("resTrInfo.Id: %s", resTrInfo.Id) - log.Trace().Msgf("resTrInfo: %+v", resTrInfo) + if !retried { + // Issue a terrarium + method := "POST" + url := fmt.Sprintf("%s/tr", epTerrarium) + reqTr := new(terrariumModel.TerrariumInfo) + reqTr.Id = trId + reqTr.Description = "SQL DB at " + sqlDbReq.Region + " in " + sqlDbReq.CSP + + resTrInfo := new(terrariumModel.TerrariumInfo) + + err = common.ExecuteHttpRequest( + client, + method, + url, + nil, + common.SetUseBody(*reqTr), + reqTr, + resTrInfo, + common.VeryShortDuration, + ) + + if err != nil { + log.Err(err).Msg("") + return emptyRet, err } + log.Debug().Msgf("resTrInfo.Id: %s", resTrInfo.Id) + log.Trace().Msgf("resTrInfo: %+v", resTrInfo) + // init env - method := "POST" - url := fmt.Sprintf("%s/tr/%s/sql-db/env", epTerrarium, trId) + method = "POST" + url = fmt.Sprintf("%s/tr/%s/sql-db/env", epTerrarium, trId) queryParams := "provider=" + sqlDbReq.CSP url += "?" + queryParams @@ -288,10 +292,16 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string log.Debug().Msgf("resInit: %+v", resTerrariumEnv.Message) log.Trace().Msgf("resInit: %+v", resTerrariumEnv.Detail) + } + /* + * [Via Terrarium] Generate the infracode for the SQL DB of each CSP + */ + switch sqlDbReq.CSP { + case "aws": // generate infracode - method = "POST" - url = fmt.Sprintf("%s/tr/%s/sql-db/infracode", epTerrarium, trId) + method := "POST" + url := fmt.Sprintf("%s/tr/%s/sql-db/infracode", epTerrarium, trId) reqInfracode := new(terrariumModel.CreateInfracodeOfSqlDbRequest) reqInfracode.TfVars.TerrariumID = trId reqInfracode.TfVars.CSPRegion = sqlDbReq.Region @@ -327,20 +337,29 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string log.Debug().Msgf("resInfracode: %+v", resInfracode.Message) log.Trace().Msgf("resInfracode: %+v", resInfracode.Detail) - // check the infracode by plan - method = "POST" - url = fmt.Sprintf("%s/tr/%s/sql-db/plan", epTerrarium, trId) - requestBody = common.NoBody - resPlan := new(model.Response) + case "azure": + // generate infracode + method := "POST" + url := fmt.Sprintf("%s/tr/%s/sql-db/infracode", epTerrarium, trId) + reqInfracode := new(terrariumModel.CreateInfracodeOfSqlDbRequest) + reqInfracode.TfVars.TerrariumID = trId + reqInfracode.TfVars.CSPRegion = sqlDbReq.Region + reqInfracode.TfVars.DBInstanceSpec = sqlDbReq.DBInstanceSpec + reqInfracode.TfVars.DBEngineVersion = sqlDbReq.DBEngineVersion + reqInfracode.TfVars.DBAdminPassword = sqlDbReq.DBAdminPassword + reqInfracode.TfVars.DBAdminUsername = sqlDbReq.DBAdminUsername + reqInfracode.TfVars.CSPResourceGroup = sqlDbReq.RequiredCSPResource.Azure.ResourceGroup + + resInfracode := new(model.Response) err = common.ExecuteHttpRequest( client, method, url, nil, - common.SetUseBody(requestBody), - &requestBody, - resPlan, + common.SetUseBody(*reqInfracode), + reqInfracode, + resInfracode, common.VeryShortDuration, ) @@ -348,26 +367,31 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string log.Err(err).Msg("") return emptyRet, err } - log.Debug().Msgf("resPlan: %+v", resPlan.Message) - log.Trace().Msgf("resPlan: %+v", resPlan.Detail) + log.Debug().Msgf("resInfracode: %+v", resInfracode.Message) + log.Trace().Msgf("resInfracode: %+v", resInfracode.Detail) - // apply - // wait until the task is completed - // or response immediately with requestId as it is a time-consuming task - // and provide seperate api to check the status - method = "POST" - url = fmt.Sprintf("%s/tr/%s/sql-db", epTerrarium, trId) - requestBody = common.NoBody - resApply := new(model.Response) + case "gcp": + // generate infracode + method := "POST" + url := fmt.Sprintf("%s/tr/%s/sql-db/infracode", epTerrarium, trId) + reqInfracode := new(terrariumModel.CreateInfracodeOfSqlDbRequest) + reqInfracode.TfVars.TerrariumID = trId + reqInfracode.TfVars.CSPRegion = sqlDbReq.Region + reqInfracode.TfVars.DBInstanceSpec = sqlDbReq.DBInstanceSpec + reqInfracode.TfVars.DBEngineVersion = sqlDbReq.DBEngineVersion + reqInfracode.TfVars.DBAdminUsername = sqlDbReq.DBAdminUsername + reqInfracode.TfVars.DBAdminPassword = sqlDbReq.DBAdminPassword + + resInfracode := new(model.Response) err = common.ExecuteHttpRequest( client, method, url, nil, - common.SetUseBody(requestBody), - &requestBody, - resApply, + common.SetUseBody(*reqInfracode), + reqInfracode, + resInfracode, common.VeryShortDuration, ) @@ -375,237 +399,118 @@ func CreateSqlDb(nsId string, sqlDbReq *model.RestPostSqlDbRequest, retry string log.Err(err).Msg("") return emptyRet, err } - log.Debug().Msgf("resApply: %+v", resApply.Message) - log.Trace().Msgf("resApply: %+v", resApply.Detail) + log.Debug().Msgf("resInfracode: %+v", resInfracode.Message) + log.Trace().Msgf("resInfracode: %+v", resInfracode.Detail) - /* - * [Via Terrarium] Retrieve the SQL DB info recursively until the SQL DB is created - */ + case "ncp": + // generate infracode + method := "POST" + url := fmt.Sprintf("%s/tr/%s/sql-db/infracode", epTerrarium, trId) + reqInfracode := new(terrariumModel.CreateInfracodeOfSqlDbRequest) + reqInfracode.TfVars.TerrariumID = trId + reqInfracode.TfVars.CSPRegion = sqlDbReq.Region + reqInfracode.TfVars.DBAdminUsername = sqlDbReq.DBAdminUsername + reqInfracode.TfVars.DBAdminPassword = sqlDbReq.DBAdminPassword + reqInfracode.TfVars.CSPSubnet1ID = sqlDbReq.RequiredCSPResource.NCP.SubnetID - // Recursively call the function to get the SQL DB info - // An expected completion duration is 15 minutes - expectedCompletionDuration := 15 * time.Minute + resInfracode := new(model.Response) - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) - defer cancel() + err = common.ExecuteHttpRequest( + client, + method, + url, + nil, + common.SetUseBody(*reqInfracode), + reqInfracode, + resInfracode, + common.VeryShortDuration, + ) - ret, err := retrieveEnrichmentsInfoInTerrarium(ctx, trId, "sql-db", expectedCompletionDuration) if err != nil { log.Err(err).Msg("") return emptyRet, err } + log.Debug().Msgf("resInfracode: %+v", resInfracode.Message) + log.Trace().Msgf("resInfracode: %+v", resInfracode.Detail) - // Set the SQL DB info - var trSqlDBInfo terrariumModel.OutputAWSSqlDbInfo - jsonData, err := json.Marshal(ret.Object) - if err != nil { - log.Error().Err(err).Msg("") - } - err = json.Unmarshal(jsonData, &trSqlDBInfo) - if err != nil { - log.Error().Err(err).Msg("") - } - - sqlDBInfo.CspResourceId = trSqlDBInfo.AWS.InstanceIdentifier - // sqlDBInfo.CspResourceName - sqlDBInfo.Details = trSqlDBInfo.AWS - - // case "azure,gcp": - - // if !retried { - // // issue a terrarium - // method := "POST" - // url := fmt.Sprintf("%s/tr", epTerrarium) - // reqTr := new(terrariumModel.TerrariumInfo) - // reqTr.Id = trId - // reqTr.Description = "VPN between GCP and Azure" - - // resTrInfo := new(terrariumModel.TerrariumInfo) - - // err = common.ExecuteHttpRequest( - // client, - // method, - // url, - // nil, - // common.SetUseBody(*reqTr), - // reqTr, - // resTrInfo, - // common.VeryShortDuration, - // ) - - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } - - // log.Debug().Msgf("resTrInfo.Id: %s", resTrInfo.Id) - // log.Trace().Msgf("resTrInfo: %+v", resTrInfo) - - // // init env - // method = "POST" - // url = fmt.Sprintf("%s/tr/%s/vpn/gcp-azure/env", epTerrarium, trId) - // requestBody := common.NoBody - // resTerrariumEnv := new(model.Response) - - // err = common.ExecuteHttpRequest( - // client, - // method, - // url, - // nil, - // common.SetUseBody(requestBody), - // &requestBody, - // resTerrariumEnv, - // common.VeryShortDuration, - // ) - - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } - - // log.Debug().Msgf("resInit: %+v", resTerrariumEnv.Message) - // log.Trace().Msgf("resInit: %+v", resTerrariumEnv.Detail) - // } - - // // generate infracode - // method := "POST" - // url := fmt.Sprintf("%s/tr/%s/vpn/gcp-azure/infracode", epTerrarium, trId) - // reqInfracode := new(terrariumModel.CreateInfracodeOfGcpAzureVpnRequest) - - // if vpnReq.Site1.CSP == "azure" { - // // Site1 is Azure - // reqInfracode.TfVars.AzureRegion = vpnReq.Site1.Region - // reqInfracode.TfVars.AzureVirtualNetworkName = vpnReq.Site1.VNet - // reqInfracode.TfVars.AzureResourceGroupName = vpnReq.Site1.ResourceGroup - // reqInfracode.TfVars.AzureGatewaySubnetCidrBlock = vpnReq.Site1.GatewaySubnetCidr - // // Site2 is GCP - // reqInfracode.TfVars.GcpRegion = vpnReq.Site2.Region - // reqInfracode.TfVars.GcpVpcNetworkName = vpnReq.Site2.VNet - // } else { - // // Site1 is GCP - // reqInfracode.TfVars.GcpRegion = vpnReq.Site1.Region - // reqInfracode.TfVars.GcpVpcNetworkName = vpnReq.Site1.VNet - // // site2 is Azure - // reqInfracode.TfVars.AzureRegion = vpnReq.Site2.Region - // reqInfracode.TfVars.AzureVirtualNetworkName = vpnReq.Site2.VNet - // reqInfracode.TfVars.AzureResourceGroupName = vpnReq.Site2.ResourceGroup - // reqInfracode.TfVars.AzureGatewaySubnetCidrBlock = vpnReq.Site2.GatewaySubnetCidr - // } - - // resInfracode := new(model.Response) - - // err = common.ExecuteHttpRequest( - // client, - // method, - // url, - // nil, - // common.SetUseBody(*reqInfracode), - // reqInfracode, - // resInfracode, - // common.VeryShortDuration, - // ) - - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } - - // log.Debug().Msgf("resInfracode: %+v", resInfracode.Message) - // log.Trace().Msgf("resInfracode: %+v", resInfracode.Detail) - - // // check the infracode by plan - // method = "POST" - // url = fmt.Sprintf("%s/tr/%s/vpn/gcp-azure/plan", epTerrarium, trId) - // requestBody := common.NoBody - // resPlan := new(model.Response) - - // err = common.ExecuteHttpRequest( - // client, - // method, - // url, - // nil, - // common.SetUseBody(requestBody), - // &requestBody, - // resPlan, - // common.VeryShortDuration, - // ) - - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } - - // log.Debug().Msgf("resPlan: %+v", resPlan.Message) - // log.Trace().Msgf("resPlan: %+v", resPlan.Detail) - - // // apply - // // wait until the task is completed - // // or response immediately with requestId as it is a time-consuming task - // // and provide seperate api to check the status - // method = "POST" - // url = fmt.Sprintf("%s/tr/%s/vpn/gcp-azure", epTerrarium, trId) - // requestBody = common.NoBody - // resApply := new(model.Response) - - // err = common.ExecuteHttpRequest( - // client, - // method, - // url, - // nil, - // common.SetUseBody(requestBody), - // &requestBody, - // resApply, - // common.VeryShortDuration, - // ) + default: + log.Warn().Msgf("not valid CSP: %s", sqlDbReq.CSP) + } - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } + /* + * [Via Terrarium] Check the infracode + */ - // log.Debug().Msgf("resApply: %+v", resApply.Message) - // log.Trace().Msgf("resApply: %+v", resApply.Detail) + // check the infracode (by `tofu plan`) + method := "POST" + url := fmt.Sprintf("%s/tr/%s/sql-db/plan", epTerrarium, trId) + requestBody := common.NoBody + resPlan := new(model.Response) - // /* - // * [Via Terrarium] Retrieve the VPN info recursively until the VPN is created - // */ + err = common.ExecuteHttpRequest( + client, + method, + url, + nil, + common.SetUseBody(requestBody), + &requestBody, + resPlan, + common.VeryShortDuration, + ) - // // Recursively call the function to get the VPN info - // // An expected completion duration is 15 minutes - // expectedCompletionDuration := 30 * time.Minute + if err != nil { + log.Err(err).Msg("") + return emptyRet, err + } + log.Debug().Msgf("resPlan: %+v", resPlan.Message) + log.Trace().Msgf("resPlan: %+v", resPlan.Detail) + + // apply + // wait until the task is completed + // or response immediately with requestId as it is a time-consuming task + // and provide seperate api to check the status + method = "POST" + url = fmt.Sprintf("%s/tr/%s/sql-db", epTerrarium, trId) + requestBody = common.NoBody + resApply := new(model.Response) - // ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) - // defer cancel() + err = common.ExecuteHttpRequest( + client, + method, + url, + nil, + common.SetUseBody(requestBody), + &requestBody, + resApply, + common.VeryShortDuration, + ) - // ret, err := retrieveVPNInfo(ctx, trId, "gcp-azure", expectedCompletionDuration) - // if err != nil { - // log.Err(err).Msg("") - // return emptyRet, err - // } + if err != nil { + log.Err(err).Msg("") + return emptyRet, err + } + log.Debug().Msgf("resApply: %+v", resApply.Message) + log.Trace().Msgf("resApply: %+v", resApply.Detail) - // // Set the VPN info - // var trVpnInfo terrariumModel.OutputGcpAzureVpnInfo - // jsonData, err := json.Marshal(ret.Object) - // if err != nil { - // log.Error().Err(err).Msg("") - // } - // err = json.Unmarshal(jsonData, &trVpnInfo) - // if err != nil { - // log.Error().Err(err).Msg("") - // } + // Set the SQL DB info + var trSqlDBInfo terrariumModel.OutputSQLDBInfo + jsonData, err := json.Marshal(resApply.Object) + if err != nil { + log.Error().Err(err).Msg("") + } + err = json.Unmarshal(jsonData, &trSqlDBInfo) + if err != nil { + log.Error().Err(err).Msg("") + } - // sqlDBInfo.VPNGatewayInfo[0].CspResourceId = trVpnInfo.Azure.VirtualNetworkGateway.ID - // sqlDBInfo.VPNGatewayInfo[0].CspResourceName = trVpnInfo.Azure.VirtualNetworkGateway.Name - // sqlDBInfo.VPNGatewayInfo[0].Details = trVpnInfo.Azure - // sqlDBInfo.VPNGatewayInfo[1].CspResourceId = trVpnInfo.GCP.HaVpnGateway.ID - // sqlDBInfo.VPNGatewayInfo[1].CspResourceName = trVpnInfo.GCP.HaVpnGateway.Name - // sqlDBInfo.VPNGatewayInfo[1].Details = trVpnInfo.GCP + sqlDBInfo.CspResourceId = trSqlDBInfo.SQLDBDetail.InstanceResourceID + sqlDBInfo.CspResourceName = trSqlDBInfo.SQLDBDetail.InstanceName + sqlDBInfo.Details = trSqlDBInfo.SQLDBDetail - default: - log.Warn().Msgf("not valid CSP: %s", sqlDbReq.CSP) - } + /* + * Set opeartion status and store sqlDBInfo + */ - // [Set and store status] sqlDBInfo.Status = string(SqlDBAvailable) log.Debug().Msgf("SQL DB Info(final): %+v", sqlDBInfo) @@ -783,7 +688,7 @@ func GetSqlDb(nsId string, sqlDbId string, detail string) (model.SqlDBInfo, erro // switch enrichments { // case "vpn/gcp-aws": - var trVpnInfo terrariumModel.OutputAWSSqlDbInfo + var trVpnInfo terrariumModel.OutputSQLDBInfo jsonData, err := json.Marshal(resResourceInfo.Object) if err != nil { log.Error().Err(err).Msg("") @@ -793,8 +698,9 @@ func GetSqlDb(nsId string, sqlDbId string, detail string) (model.SqlDBInfo, erro log.Error().Err(err).Msg("") } - sqlDBInfo.CspResourceId = trVpnInfo.AWS.InstanceIdentifier - sqlDBInfo.Details = trVpnInfo.AWS + sqlDBInfo.CspResourceId = trVpnInfo.SQLDBDetail.InstanceResourceID + sqlDBInfo.CspResourceName = trVpnInfo.SQLDBDetail.InstanceName + sqlDBInfo.Details = trVpnInfo.SQLDBDetail // case "vpn/gcp-azure": // var trVpnInfo terrariumModel.OutputGcpAzureVpnInfo