From 7d5c7ae3c24f4a45e9d4e50043d967e8412739e5 Mon Sep 17 00:00:00 2001 From: Lance52259 Date: Thu, 29 Aug 2024 17:22:13 +0800 Subject: [PATCH] feat(dataarts/apis): add new resource to query apis under catalog --- .../dataarts_dataservice_catalog_apis.md | 122 ++++++++ huaweicloud/provider.go | 1 + ..._dataarts_dataservice_catalog_apis_test.go | 123 ++++++++ ...cloud_dataarts_dataservice_catalog_apis.go | 264 ++++++++++++++++++ 4 files changed, 510 insertions(+) create mode 100644 docs/data-sources/dataarts_dataservice_catalog_apis.md create mode 100644 huaweicloud/services/acceptance/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis_test.go create mode 100644 huaweicloud/services/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis.go diff --git a/docs/data-sources/dataarts_dataservice_catalog_apis.md b/docs/data-sources/dataarts_dataservice_catalog_apis.md new file mode 100644 index 0000000000..891363b24e --- /dev/null +++ b/docs/data-sources/dataarts_dataservice_catalog_apis.md @@ -0,0 +1,122 @@ +--- +subcategory: "DataArts Studio" +layout: "huaweicloud" +page_title: "HuaweiCLoud: huaweicloud_dataarts_dataservice_catalog_apis" +description: |- + Use this data source to get the list of Data Service APIs under a specified catalog within HuaweiCloud. +--- + +# huaweicloud_dataarts_dataservice_catalog_apis + +Use this data source to get the list of Data Service APIs under a specified catalog within HuaweiCloud. + +## Example Usage + +```hcl +variable "workspace_id" {} +variable "catalog_id" {} + +data "huaweicloud_dataarts_dataservice_catalog_apis" "test" { + workspace_id = var.workspace_id + dlm_type = "EXCLUSIVE" + catalog_id = var.catalog_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String) Specifies the region in which to query the data source. + If omitted, the provider-level region will be used. + +* `workspace_id` - (Required, String) Specifies the ID of workspace where the APIs are located. + +* `dlm_type` - (Optional, String) Specifies the type of DLM engine. + The valid values are as follows: + + **SHARED**: The shared data service. + + **EXCLUSIVE**: The exclusive data service. + + Defaults to **SHARED**. + +* `catalog_id` - (Required, String) Specifies the ID of the catalog to which the APIs belong. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The data source ID. + +* `apis` - All API summaries that under the specified catalog. + The [apis](#dataservice_api_summaries_under_catalog) structure is documented below. + + +The `apis` block supports: + +* `id` - The API ID, in UUID format. + +* `name` - The API name. + +* `description` - The description of the API. + +* `group_id` - The ID of the group to which the shared API belongs. + +* `status` - The status of the shared API. + + **API_STATUS_CREATED**: API has been created. + + **API_STATUS_PUBLISH_WAIT_REVIEW**: Release review status. + + **API_STATUS_PUBLISH_REJECT**: Rejection status. + + **API_STATUS_PUBLISHED**: Released status. + + **API_STATUS_WAITING_STOP**: Disable review status. + + **API_STATUS_STOPPED**: Disabled status. + + **API_STATUS_RECOVER_WAIT_REVIEW**: Recover review status. + + **API_STATUS_WAITING_OFFLINE**: Offline review status. + + **API_STATUS_OFFLINE**: Already offline. + + **API_STATUS_OFFLINE_WAIT_REVIEW**: Offline pending review status. + +* `debug_status` - The debug status of the shared API. + + **API_DEBUG_WAITING**: Waiting for debugging. + + **API_DEBUG_FAILED**: Debugging failed. + + **API_DEBUG_SUCCESS**: Debugging successful. + +* `publish_messages` - All publish messages of the exclusive API. + The [publish_messages](#datasource_api_publish_messages_under_catalog) structure is documented below. + +* `type` - The API type. + + **API_SPECIFIC_TYPE_CONFIGURATION**: Configuration API + + **API_SPECIFIC_TYPE_SCRIPT**: Script API + + **API_SPECIFIC_TYPE_REGISTER**: Registration API + +* `manager` - The API reviewer. + +* `created_at` - The creation time of the API, in RFC3339 format. + +* `authorization_status` - The authorization status of the API. + + **NO_AUTHORIZATION_REQUIRED**: No authorization required. + + **UNAUTHORIZED**: Unauthorized. + + **AUTHORIZED**: Authorized. + + +The `publish_messages` block supports: + +* `id` - The publish ID, in UUID format. + +* `instance_id` - The ID of the instance used to publish the exclusive API. + +* `instance_name` - The name of the instance used to publish the exclusive API. + +* `api_status` - The publish status of the exclusive API. + + **API_STATUS_CREATED**: API has been created. + + **API_STATUS_PUBLISH_WAIT_REVIEW**: Release review status. + + **API_STATUS_PUBLISH_REJECT**: Rejection status. + + **API_STATUS_PUBLISHED**: Released status. + + **API_STATUS_WAITING_STOP**: Disable review status. + + **API_STATUS_STOPPED**: Disabled status. + + **API_STATUS_RECOVER_WAIT_REVIEW**: Recover review status. + + **API_STATUS_WAITING_OFFLINE**: Offline review status. + + **API_STATUS_OFFLINE**: Already offline. + + **API_STATUS_OFFLINE_WAIT_REVIEW**: Offline pending review status. + +* `api_debug` - The debug status of the exclusive API. + + **API_DEBUG_WAITING**: Waiting for debugging. + + **API_DEBUG_FAILED**: Debugging failed. + + **API_DEBUG_SUCCESS**: Debugging successful. diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go index 07157fd793..7a329f09d6 100644 --- a/huaweicloud/provider.go +++ b/huaweicloud/provider.go @@ -590,6 +590,7 @@ func Provider() *schema.Provider { "huaweicloud_dataarts_dataservice_apis": dataarts.DataSourceDataServiceApis(), "huaweicloud_dataarts_dataservice_apps": dataarts.DataSourceDataServiceApps(), "huaweicloud_dataarts_dataservice_authorized_apps": dataarts.DataSourceDataServiceAuthorizedApps(), + "huaweicloud_dataarts_dataservice_catalog_apis": dataarts.DataSourceDataServiceCatalogApis(), "huaweicloud_dataarts_dataservice_instances": dataarts.DataSourceDataServiceInstances(), "huaweicloud_dataarts_dataservice_messages": dataarts.DataSourceDataServiceMessages(), // DataArts Quality diff --git a/huaweicloud/services/acceptance/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis_test.go b/huaweicloud/services/acceptance/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis_test.go new file mode 100644 index 0000000000..e6807449b0 --- /dev/null +++ b/huaweicloud/services/acceptance/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis_test.go @@ -0,0 +1,123 @@ +package dataarts + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" +) + +// Query exclusive API that they are not published. +func TestAccDataSourceDataServiceCatalogApis_basic(t *testing.T) { + var ( + rName = "data.huaweicloud_dataarts_dataservice_catalog_apis.test" + dc = acceptance.InitDataSourceCheck(rName) + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acceptance.TestAccPreCheck(t) + acceptance.TestAccPreCheckDataArtsWorkSpaceID(t) + acceptance.TestAccPreCheckDataArtsReviewerName(t) + acceptance.TestAccPreCheckDataArtsConnectionID(t) + acceptance.TestAccPreCheckDataArtsRelatedDliQueueName(t) + }, + ProviderFactories: acceptance.TestAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceDataServiceCatalogApis_basic(), + Check: resource.ComposeTestCheckFunc( + dc.CheckResourceExists(), + resource.TestMatchResourceAttr(rName, "apis.#", regexp.MustCompile(`^[1-9]([0-9]*)?$`)), + resource.TestCheckResourceAttrSet(rName, "apis.0.id"), + resource.TestCheckResourceAttrSet(rName, "apis.0.name"), + resource.TestCheckResourceAttrSet(rName, "apis.0.description"), + resource.TestCheckResourceAttrSet(rName, "apis.0.type"), + resource.TestCheckResourceAttrSet(rName, "apis.0.manager"), + resource.TestMatchResourceAttr(rName, "apis.0.created_at", + regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}?(Z|([+-]\d{2}:\d{2}))$`)), + ), + }, + }, + }) +} + +func testAccDataSourceDataServiceCatalogApis_basic() string { + name := acceptance.RandomAccResourceName() + + return fmt.Sprintf(` +resource "huaweicloud_dli_database" "test" { + name = "%[1]s" +} + +resource "huaweicloud_dli_table" "test" { + database_name = huaweicloud_dli_database.test.name + name = "%[1]s" + data_location = "DLI" + + columns { + name = "configuration" + type = "string" + description = "The configuration for automatic creation, in JSON format" + } +} + +// Under root path. +resource "huaweicloud_dataarts_dataservice_catalog" "test" { + workspace_id = "%[2]s" + dlm_type = "EXCLUSIVE" + + name = "%[1]s" +} + +resource "huaweicloud_dataarts_dataservice_api" "test" { + count = 2 + + workspace_id = "%[2]s" + dlm_type = "EXCLUSIVE" + + type = "API_SPECIFIC_TYPE_CONFIGURATION" + catalog_id = huaweicloud_dataarts_dataservice_catalog.test.id + name = format("%[1]s_%%d", count.index) + description = "Created by terraform script" + auth_type = "NONE" + manager = "%[3]s" + path = format("/%[1]s/%%d", count.index) + protocol = "PROTOCOL_TYPE_HTTPS" + request_type = "REQUEST_TYPE_GET" + visibility = "PROJECT" + + datasource_config { + type = "DLI" + connection_id = "%[4]s" + database = huaweicloud_dli_database.test.name + datatable = huaweicloud_dli_table.test.name + queue = "%[5]s" + + response_params { + name = "configuration" + type = "REQUEST_PARAMETER_TYPE_STRING" + field = "configuration" + } + } +} + +data "huaweicloud_dataarts_dataservice_catalog_apis" "test" { + depends_on = [ + huaweicloud_dataarts_dataservice_api.test + ] + + workspace_id = "%[2]s" + dlm_type = "EXCLUSIVE" + + catalog_id = huaweicloud_dataarts_dataservice_catalog.test.id +} +`, name, + acceptance.HW_DATAARTS_WORKSPACE_ID, + acceptance.HW_DATAARTS_REVIEWER_NAME, + acceptance.HW_DATAARTS_CONNECTION_ID, + acceptance.HW_DATAARTS_DLI_QUEUE_NAME) +} diff --git a/huaweicloud/services/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis.go b/huaweicloud/services/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis.go new file mode 100644 index 0000000000..a224daf46f --- /dev/null +++ b/huaweicloud/services/dataarts/data_source_huaweicloud_dataarts_dataservice_catalog_apis.go @@ -0,0 +1,264 @@ +package dataarts + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/chnsz/golangsdk" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils" +) + +// @API DataArtsStudio GET /v1/{project_id}/service/servicecatalogs/{catalog_id}/apis +func DataSourceDataServiceCatalogApis() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceDataServiceCatalogApisRead, + + Schema: map[string]*schema.Schema{ + "region": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The region where the catalog and APIs are located.`, + }, + + // Parameters in request header + "workspace_id": { + Type: schema.TypeString, + Required: true, + Description: `The ID of the workspace to which the catalog and APIs belong.`, + }, + "dlm_type": { + Type: schema.TypeString, + Optional: true, + Description: `The type of DLM engine.`, + }, + + // Query argument + "catalog_id": { + Type: schema.TypeString, + Required: true, + Description: `The ID of the catalog to which the APIs belong.`, + }, + + // Attribute + "apis": { + Type: schema.TypeList, + Elem: dataserviceCatelogApiSummarySchema(), + Computed: true, + Description: `All API summaries that under the specified catalog.`, + }, + }, + } +} + +func dataserviceCatelogApiSummarySchema() *schema.Resource { + sc := schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: `The API ID, in UUID format.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The API name.`, + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: `The description of the API.`, + }, + "group_id": { + Type: schema.TypeString, + Computed: true, + Description: `The ID of the group to which the shared API belongs.`, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: `The status of the shared API.`, + }, + "debug_status": { + Type: schema.TypeString, + Computed: true, + Description: `The debug status of the shared API.`, + }, + "publish_messages": { + Type: schema.TypeList, + Elem: dataserviceCatelogApiPublishInfoSchema(), + Computed: true, + Description: `All publish messages of the exclusive API.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The API type.`, + }, + "manager": { + Type: schema.TypeString, + Computed: true, + Description: `The API reviewer.`, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: `The creation time of the API, in RFC3339 format.`, + }, + "authorization_status": { + Type: schema.TypeString, + Computed: true, + Description: `The authorization status of the API.`, + }, + }, + } + return &sc +} + +func dataserviceCatelogApiPublishInfoSchema() *schema.Resource { + sc := schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: `The publish ID, in UUID format.`, + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: `The ID of the instance used to publish the exclusive API.`, + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the instance used to publish the exclusive API.`, + }, + "api_status": { + Type: schema.TypeString, + Computed: true, + Description: `The publish status of the exclusive API.`, + }, + "api_debug": { + Type: schema.TypeString, + Computed: true, + Description: `The debug status of the exclusive API.`, + }, + }, + } + return &sc +} + +func queryDataServiceApisUnderCatalog(client *golangsdk.ServiceClient, d *schema.ResourceData) ([]interface{}, error) { + var ( + httpUrl = "v1/{project_id}/service/servicecatalogs/{catalog_id}/apis?limit=100" + offset = 0 + result = make([]interface{}, 0) + ) + listPath := client.Endpoint + httpUrl + listPath = strings.ReplaceAll(listPath, "{project_id}", client.ProjectID) + listPath = strings.ReplaceAll(listPath, "{catalog_id}", d.Get("catalog_id").(string)) + + opt := golangsdk.RequestOpts{ + KeepResponseBody: true, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + "workspace": d.Get("workspace_id").(string), + "dlm-type": d.Get("dlm_type").(string), + }, + } + + for { + listPathWithOffset := listPath + fmt.Sprintf("&offset=%d", offset) + requestResp, err := client.Request("GET", listPathWithOffset, &opt) + if err != nil { + return nil, err + } + respBody, err := utils.FlattenResponse(requestResp) + if err != nil { + return nil, err + } + apiRecords := utils.PathSearch("apis", respBody, make([]interface{}, 0)).([]interface{}) + if len(apiRecords) < 1 { + break + } + result = append(result, apiRecords...) + offset += len(apiRecords) + } + + return result, nil +} + +func flattenDataServiceCatalogApiPublishMessages(messages []interface{}) []interface{} { + result := make([]interface{}, 0, len(messages)) + for _, message := range messages { + result = append(result, map[string]interface{}{ + "id": utils.PathSearch("id", message, nil), + "instance_id": utils.PathSearch("instance_id", message, nil), + "instance_name": utils.PathSearch("instance_name", message, nil), + "api_status": utils.PathSearch("api_status", message, nil), + "api_debug": utils.PathSearch("api_debug", message, nil), + }) + } + return result +} + +func flattenDataServiceCatalogApis(apiRecords []interface{}) []interface{} { + result := make([]interface{}, 0, len(apiRecords)) + + for _, apiRecord := range apiRecords { + result = append(result, map[string]interface{}{ + "id": utils.PathSearch("id", apiRecord, nil), + "name": utils.PathSearch("name", apiRecord, nil), + "description": utils.PathSearch("description", apiRecord, nil), + "group_id": utils.PathSearch("group_id", apiRecord, nil), + "status": utils.PathSearch("status", apiRecord, nil), + "debug_status": utils.PathSearch("debug_status", apiRecord, nil), + "type": utils.PathSearch("type", apiRecord, nil), + "manager": utils.PathSearch("manager", apiRecord, nil), + "authorization_status": utils.PathSearch("authorization_status", apiRecord, nil), + "publish_messages": flattenDataServiceCatalogApiPublishMessages(utils.PathSearch("publish_messages", + apiRecord, make([]interface{}, 0)).([]interface{})), + "created_at": utils.FormatTimeStampRFC3339(int64(utils.PathSearch("create_time", + apiRecord, float64(0)).(float64))/1000, false), + }) + } + + return result +} + +func dataSourceDataServiceCatalogApisRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var ( + cfg = meta.(*config.Config) + region = cfg.GetRegion(d) + ) + + client, err := cfg.NewServiceClient("dataarts", region) + if err != nil { + return diag.Errorf("error creating DataArts Studio client: %s", err) + } + + apiRecords, err := queryDataServiceApisUnderCatalog(client, d) + if err != nil { + return diag.FromErr(err) + } + + dataSourceId, err := uuid.GenerateUUID() + if err != nil { + return diag.Errorf("unable to generate ID: %s", err) + } + d.SetId(dataSourceId) + + mErr := multierror.Append(nil, + d.Set("region", region), + d.Set("apis", flattenDataServiceCatalogApis(apiRecords)), + ) + return diag.FromErr(mErr.ErrorOrNil()) +}