diff --git a/docs/resources/apig_api_group.md b/docs/resources/apig_api_group.md new file mode 100644 index 0000000000..28410c7573 --- /dev/null +++ b/docs/resources/apig_api_group.md @@ -0,0 +1,93 @@ +--- +subcategory: "API Gateway (APIG)" +--- + +# huaweicloud_apig_group + +Manages an APIG (API) group resource within HuaweiCloud. + +## Example Usage + +```hcl +variable "instance_id" {} +variable "group_name" {} +variable "description" {} +variable "environment_id" {} + +resource "huaweicloud_apig_group" "test" { + instance_id = var.instance_id + name = var.group_name + description = var.description + + environment { + variable { + name = "TERRAFORM" + value = "/stage/terraform" + } + environment_id = var.environment_id + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String, ForceNew) Specifies the region in which to create the API group resource. + If omitted, the provider-level region will be used. + Changing this will create a new API group resource. + +* `instance_id` - (Required, String, ForceNew) Specifies an ID of the APIG dedicated instance to which the + API group belongs to. + Changing this will create a new API group resource. + +* `name` - (Required, String) Specifies the name of the API group. + The API group name consists of 3 to 64 characters, starting with a letter. + Only letters, digits and underscores (_) are allowed. + Chinese characters must be in UTF-8 or Unicode format. + +* `description` - (Optional, String) Specifies the description about the API group. + The description contain a maximum of 255 characters and the angle brackets (< and >) are not allowed. + Chinese characters must be in UTF-8 or Unicode format. + +* `environment` - (Optional, List) Specifies an array of one or more APIG environments of the associated APIG group. + The object structure is documented below. + +The `environment` block supports: + +* `variable` - (Required, List) Specifies an array of one or more APIG environment variables. + The object structure is documented below. + The environment variables of different groups are isolated in the same environment. + +* `environment_id` - (Required, String) Specifies the APIG environment ID of the associated APIG group. + +The `variable` block supports: + +* `name` - (Required, String) Specifies the variable name, which can contains of 3 to 32 characters, + starting with a letter. + Only letters, digits, hyphens (-), and underscores (_) are allowed. + In the definition of an API, `name` (case-sensitive) indicates a variable, such as #Name#. + It is replaced by the actual value when the API is published in an environment. + The variable names are not allowed to be repeated for an API group. + +* `value` - (Required, String) Specifies the environment ariable value, which can contains of 1 to 255 characters. + Only letters, digits and special characters (_-/.:) are allowed. + + -> **NOTE:** The variable value will be displayed in plain text on the console. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the API group. +* `registraion_time` - Registration time, in RFC-3339 format. +* `update_time` - Time when the API group was last modified, in RFC-3339 format. +* `environment/variable/variable_id` - ID of the environment variable. + +## Import + +API groups of the APIG can be imported using their `id` and the ID of the APIG instance to which the group belongs, +separated by a slash, e.g. +``` +$ terraform import huaweicloud_apig_group.test / +``` diff --git a/go.sum b/go.sum index de95295869..b99356b159 100644 --- a/go.sum +++ b/go.sum @@ -206,6 +206,8 @@ github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596/go.mod github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/huaweicloud/golangsdk v0.0.0-20210706092920-c12079d6a740 h1:RCAJI5jVLah5GJkr1lk9I0g6+PdTjUMCwzY5pUUd7fA= +github.com/huaweicloud/golangsdk v0.0.0-20210706092920-c12079d6a740/go.mod h1:fcOI5u+0f62JtJd7zkCch/Z57BNC6bhqb32TKuiF4r0= github.com/huaweicloud/golangsdk v0.0.0-20210714031135-2f101c51a35d h1:GJFDZ3hxptdDs10RjT1+Tq4oDsWXu+e2yNoHzLRgJ38= github.com/huaweicloud/golangsdk v0.0.0-20210714031135-2f101c51a35d/go.mod h1:fcOI5u+0f62JtJd7zkCch/Z57BNC6bhqb32TKuiF4r0= github.com/huaweicloud/golangsdk v0.0.0-20210715061636-f0d85a483f0b h1:s3ZJgf61mC4EaZp3OEMrC7hbZixXMr9JbFL5cgATB/o= diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go index a81fdb95ac..e48a6364dd 100644 --- a/huaweicloud/provider.go +++ b/huaweicloud/provider.go @@ -370,6 +370,7 @@ func Provider() terraform.ResourceProvider { "huaweicloud_apig_instance": apig.ResourceApigInstanceV2(), "huaweicloud_apig_application": apig.ResourceApigApplicationV2(), "huaweicloud_apig_environment": apig.ResourceApigEnvironmentV2(), + "huaweicloud_apig_group": apig.ResourceApigGroupV2(), "huaweicloud_apig_vpc_channel": apig.ResourceApigVpcChannelV2(), "huaweicloud_as_configuration": ResourceASConfiguration(), "huaweicloud_as_group": ResourceASGroup(), diff --git a/huaweicloud/services/acceptance/apig/resource_huaweicloud_apig_group_test.go b/huaweicloud/services/acceptance/apig/resource_huaweicloud_apig_group_test.go new file mode 100644 index 0000000000..f4024ca8a0 --- /dev/null +++ b/huaweicloud/services/acceptance/apig/resource_huaweicloud_apig_group_test.go @@ -0,0 +1,260 @@ +package apig + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" +) + +func TestAccApigGroupV2_basic(t *testing.T) { + var ( + // Only letters, digits and underscores (_) are allowed in the name. + rName = fmt.Sprintf("tf_acc_test_%s", acctest.RandString(5)) + resourceName = "huaweicloud_apig_group.test" + group apigroups.Group + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acceptance.TestAccPreCheck(t) + acceptance.TestAccPreCheckEpsID(t) // Method testAccApigApplication_base needs HW_ENTERPRISE_PROJECT_ID. + }, + Providers: acceptance.TestAccProviders, + CheckDestroy: testAccCheckApigGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccApigGroup_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApigGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "Created by script"), + ), + }, + { + Config: testAccApigGroup_update(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApigGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "name", rName+"_update"), + resource.TestCheckResourceAttr(resourceName, "description", "Updated by script"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccApigInstanceSubResourceImportStateIdFunc(resourceName), + }, + }, + }) +} + +func TestAccApigGroupV2_variables(t *testing.T) { + var ( + // Only letters, digits and underscores (_) are allowed in the name. + rName = fmt.Sprintf("tf_acc_test_%s", acctest.RandString(5)) + resourceName = "huaweicloud_apig_group.test" + group apigroups.Group + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acceptance.TestAccPreCheck(t) + acceptance.TestAccPreCheckEpsID(t) // Method testAccApigApplication_base needs HW_ENTERPRISE_PROJECT_ID. + }, + Providers: acceptance.TestAccProviders, + CheckDestroy: testAccCheckApigGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccApigGroup_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApigGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + // Bind two environment to group, and create some variables. + Config: testAccApigGroup_variables(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApigGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "environment.#", "2"), + ), + }, + { + // Update the variables for two environments. + Config: testAccApigGroup_variablesUpdate(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckApigGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "environment.#", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccApigInstanceSubResourceImportStateIdFunc(resourceName), + }, + }, + }) +} + +func testAccCheckApigGroupDestroy(s *terraform.State) error { + config := acceptance.TestAccProvider.Meta().(*config.Config) + client, err := config.ApigV2Client(acceptance.HW_REGION_NAME) + if err != nil { + return fmt.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "huaweicloud_apig_group" { + continue + } + _, err := apigroups.Get(client, rs.Primary.Attributes["instance_id"], rs.Primary.ID).Extract() + if err == nil { + return fmt.Errorf("APIG v2 API group (%s) is still exists", rs.Primary.ID) + } + } + return nil +} + +func testAccCheckApigGroupExists(groupName string, app *apigroups.Group) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[groupName] + if !ok { + return fmt.Errorf("Resource %s not found", groupName) + } + if rs.Primary.ID == "" { + return fmt.Errorf("No APIG V2 API group Id") + } + + config := acceptance.TestAccProvider.Meta().(*config.Config) + client, err := config.ApigV2Client(acceptance.HW_REGION_NAME) + if err != nil { + return fmt.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + found, err := apigroups.Get(client, rs.Primary.Attributes["instance_id"], rs.Primary.ID).Extract() + if err != nil { + return fmt.Errorf("APIG v2 API group not exist: %s", err) + } + *app = *found + return nil + } +} + +func testAccApigGroup_basic(rName string) string { + return fmt.Sprintf(` +%s + +resource "huaweicloud_apig_group" "test" { + name = "%s" + instance_id = huaweicloud_apig_instance.test.id + description = "Created by script" +} +`, testAccApigApplication_base(rName), rName) +} + +func testAccApigGroup_update(rName string) string { + return fmt.Sprintf(` +%s + +resource "huaweicloud_apig_group" "test" { + name = "%s_update" + instance_id = huaweicloud_apig_instance.test.id + description = "Updated by script" +} +`, testAccApigApplication_base(rName), rName) +} + +func testAccApigGroup_variablesBase(rName string) string { + return fmt.Sprintf(` +resource "huaweicloud_apig_environment" "test1" { + name = "%s_1" + instance_id = huaweicloud_apig_instance.test.id + description = "Created by script" +} + +resource "huaweicloud_apig_environment" "test2" { + name = "%s_2" + instance_id = huaweicloud_apig_instance.test.id + description = "Created by script" +} +`, rName, rName) +} + +// Create two environments for the group, and add a total of three variables to the two environments. +// Each of the two environments has a variable with the same name and different value. +func testAccApigGroup_variables(rName string) string { + return fmt.Sprintf(` +%s + +%s + +resource "huaweicloud_apig_group" "test" { + name = "%s" + instance_id = huaweicloud_apig_instance.test.id + description = "Created by script" + + environment { + environment_id = huaweicloud_apig_environment.test1.id + + variable { + name = "TERRAFORM" + value = "/stage/terraform" + } + } + environment { + environment_id = huaweicloud_apig_environment.test2.id + + variable { + name = "TERRAFORM" + value = "/res/terraform" + } + variable { + name = "DEMO" + value = "/stage/demo" + } + } +} +`, testAccApigApplication_base(rName), testAccApigGroup_variablesBase(rName), rName) +} + +func testAccApigGroup_variablesUpdate(rName string) string { + return fmt.Sprintf(` +%s + +%s + +resource "huaweicloud_apig_group" "test" { + name = "%s" + instance_id = huaweicloud_apig_instance.test.id + description = "Created by script" + + environment { + environment_id = huaweicloud_apig_environment.test1.id + + variable { + name = "TERRAFORM" + value = "/stage/terraform" + } + variable { + name = "TEST" + value = "/stage/test" + } + } + environment { + environment_id = huaweicloud_apig_environment.test2.id + + variable { + name = "TERRAFORM" + value = "/stage/terraform" + } + } +} +`, testAccApigApplication_base(rName), testAccApigGroup_variablesBase(rName), rName) +} diff --git a/huaweicloud/services/apig/resource_huaweicloud_apig_group.go b/huaweicloud/services/apig/resource_huaweicloud_apig_group.go new file mode 100644 index 0000000000..6725be4e3e --- /dev/null +++ b/huaweicloud/services/apig/resource_huaweicloud_apig_group.go @@ -0,0 +1,319 @@ +package apig + +import ( + "regexp" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups" + "github.com/huaweicloud/golangsdk/openstack/apigw/v2/environments" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils/fmtp" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils/logp" +) + +func ResourceApigGroupV2() *schema.Resource { + return &schema.Resource{ + Create: resourceApigGroupV2Create, + Read: resourceApigGroupV2Read, + Update: resourceApigGroupV2Update, + Delete: resourceApigGroupV2Delete, + Importer: &schema.ResourceImporter{ + State: resourceApigInstanceSubResourceImportState, + }, + + Schema: map[string]*schema.Schema{ + "region": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile("^[\u4e00-\u9fa5A-Za-z][\u4e00-\u9fa5A-Za-z_0-9]{2,63}$"), + "The name consists of 3 to 64 characters, starting with a letter. "+ + "Only letters, digits and underscores (_) are allowed. "+ + "Chinese characters must be in UTF-8 or Unicode format."), + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile("^[^<>]{1,255}$"), + "The description contain a maximum of 255 characters, "+ + "and the angle brackets (< and >) are not allowed."), + }, + "environment": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "variable": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile("^[A-Za-z][\\w_-]{2,31}$"), + "The name consists of 3 to 32 characters, starting with a letter. "+ + "Only letters, digits, hyphens (-) and underscores (_) are allowed."), + }, + "value": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile("^[\\w:/.-]{1,255}$"), + "The value consists of 1 to 255 characters, only letters, digit and "+ + "following special characters are allowed: _-/.:"), + }, + "variable_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "environment_id": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "registraion_time": { + Type: schema.TypeString, + Computed: true, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func createApigGroupEnvironmentVariables(client *golangsdk.ServiceClient, instanceId, groupId string, + environmentSet *schema.Set) error { + for _, env := range environmentSet.List() { + envMap := env.(map[string]interface{}) + envId := envMap["environment_id"].(string) + for _, v := range envMap["variable"].(*schema.Set).List() { + variable := v.(map[string]interface{}) + opt := environments.CreateVariableOpts{ + Name: variable["name"].(string), + Value: variable["value"].(string), + GroupId: groupId, + EnvId: envId, + } + if _, err := environments.CreateVariable(client, instanceId, opt).Extract(); err != nil { + return err + } + } + } + return nil +} + +func removeApigGroupEnvironmentVariables(client *golangsdk.ServiceClient, instanceId string, + environmentSet *schema.Set) error { + for _, env := range environmentSet.List() { + envMap := env.(map[string]interface{}) + for _, v := range envMap["variable"].(*schema.Set).List() { + variable := v.(map[string]interface{}) + err := environments.DeleteVariable(client, instanceId, variable["variable_id"].(string)).ExtractErr() + if err != nil { + return err + } + } + } + return nil +} + +func resourceApigGroupV2Create(d *schema.ResourceData, meta interface{}) error { + config := meta.(*config.Config) + client, err := config.ApigV2Client(config.GetRegion(d)) + if err != nil { + return fmtp.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + desc := d.Get("description").(string) + opt := apigroups.GroupOpts{ + Name: d.Get("name").(string), + Description: &desc, + } + logp.Printf("[DEBUG] Create Option: %#v", opt) + instanceId := d.Get("instance_id").(string) + resp, err := apigroups.Create(client, instanceId, opt).Extract() + if err != nil { + return fmtp.Errorf("Error creating HuaweiCloud APIG group: %s", err) + } + d.SetId(resp.Id) + if environments, ok := d.GetOk("environment"); ok { + err = createApigGroupEnvironmentVariables(client, instanceId, d.Id(), environments.(*schema.Set)) + if err != nil { + return fmtp.Errorf("Binding environment variables failed: %s", err) + } + } + return resourceApigGroupV2Read(d, meta) +} + +// Classify all environment variables belonging to the API group according to the APIG environment. +func setApigGroupEnvironmentVariables(d *schema.ResourceData, variables []environments.Variable) error { + // Store all variables of the same environment in the corresponding list, + // and generate a map with the environment ID as the key name. + environmentMap := make(map[string]interface{}) + for _, variable := range variables { + varMap := map[string]interface{}{ + "name": variable.Name, + "value": variable.Value, + "variable_id": variable.Id, + } + if val, ok := environmentMap[variable.EnvId]; !ok { + environmentMap[variable.EnvId] = []map[string]interface{}{ + varMap, + } + } else { + environmentMap[variable.EnvId] = append(val.([]map[string]interface{}), varMap) + } + } + // Generate a schema set according to the key value of the map. + result := make([]map[string]interface{}, 0, len(environmentMap)) + for k, v := range environmentMap { + envMap := map[string]interface{}{ + "variable": v, + "environment_id": k, + } + result = append(result, envMap) + } + + if len(result) == 0 { + return d.Set("environment", nil) + } + return d.Set("environment", result) +} + +func setApigGroupParamters(d *schema.ResourceData, config *config.Config, resp *apigroups.Group) error { + mErr := multierror.Append(nil, + d.Set("region", config.GetRegion(d)), + d.Set("name", resp.Name), + d.Set("description", resp.Description), + d.Set("registraion_time", resp.RegistraionTime), + d.Set("update_time", resp.UpdateTime), + ) + if mErr.ErrorOrNil() != nil { + return mErr + } + return nil +} + +func getApigGroupEnvironmentVariables(d *schema.ResourceData, + client *golangsdk.ServiceClient) ([]environments.Variable, error) { + instanceId := d.Get("instance_id").(string) + listOpt := environments.ListVariablesOpts{ + GroupId: d.Id(), + } + pages, err := environments.ListVariables(client, instanceId, listOpt).AllPages() + if err != nil { + return []environments.Variable{}, fmtp.Errorf("Error getting environment variable list from server: %s", err) + } + result, err := environments.ExtractVariables(pages) + if err != nil { + return []environments.Variable{}, fmtp.Errorf("Error extract environment variables: %s", err) + } + return result, nil +} + +func resourceApigGroupV2Read(d *schema.ResourceData, meta interface{}) error { + config := meta.(*config.Config) + client, err := config.ApigV2Client(config.GetRegion(d)) + if err != nil { + return fmtp.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + instanceId := d.Get("instance_id").(string) + resp, err := apigroups.Get(client, instanceId, d.Id()).Extract() + if err != nil { + return fmtp.Errorf("Error getting APIG v2 group: %s", err) + } + if err = setApigGroupParamters(d, config, resp); err != nil { + return fmtp.Errorf("Error saving group to state: %s", err) + } + // Saving environment variables to state file. + variables, err := getApigGroupEnvironmentVariables(d, client) + if err != nil { + return err + } + if err = setApigGroupEnvironmentVariables(d, variables); err != nil { + return fmtp.Errorf("Error saving variables to state: %s", err) + } + return nil +} + +func updateApigGroupEnvironmentVariables(d *schema.ResourceData, client *golangsdk.ServiceClient) error { + oldRaws, newRaws := d.GetChange("environment") + addRaws := newRaws.(*schema.Set).Difference(oldRaws.(*schema.Set)) + removeRaws := oldRaws.(*schema.Set).Difference(newRaws.(*schema.Set)) + instanceId := d.Get("instance_id").(string) + if err := removeApigGroupEnvironmentVariables(client, instanceId, removeRaws); err != nil { + return err + } + if err := createApigGroupEnvironmentVariables(client, instanceId, d.Id(), addRaws); err != nil { + return err + } + return nil +} + +func resourceApigGroupV2Update(d *schema.ResourceData, meta interface{}) error { + config := meta.(*config.Config) + client, err := config.ApigV2Client(config.GetRegion(d)) + if err != nil { + return fmtp.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + opt := apigroups.GroupOpts{} + if d.HasChange("name") { + opt.Name = d.Get("name").(string) + } + if d.HasChange("description") { + desc := d.Get("description").(string) + opt.Description = &desc + } + if opt != (apigroups.GroupOpts{}) { + logp.Printf("[DEBUG] Update Option: %#v", opt) + instanceId := d.Get("instance_id").(string) + _, err = apigroups.Update(client, instanceId, d.Id(), opt).Extract() + if err != nil { + return fmtp.Errorf("Error updating HuaweiCloud APIG group (%s): %s", d.Id(), err) + } + } + if d.HasChange("environment") { + if err := updateApigGroupEnvironmentVariables(d, client); err != nil { + return fmtp.Errorf("Error updating HuaweiCloud APIG environment variables for the group (%s): %s", + d.Id(), err) + } + } + return resourceApigGroupV2Read(d, meta) +} + +func resourceApigGroupV2Delete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*config.Config) + client, err := config.ApigV2Client(config.GetRegion(d)) + if err != nil { + return fmtp.Errorf("Error creating HuaweiCloud APIG v2 client: %s", err) + } + instanceId := d.Get("instance_id").(string) + err = apigroups.Delete(client, instanceId, d.Id()).ExtractErr() + if err != nil { + return fmtp.Errorf("Error deleting HuaweiCloud APIG group from the instance (%s): %s", instanceId, err) + } + d.SetId("") + return nil +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/requests.go b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/requests.go new file mode 100644 index 0000000000..4d12ba604d --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/requests.go @@ -0,0 +1,105 @@ +package apigroups + +import ( + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/pagination" +) + +// GroupOpts allows to create a group or update a existing group using given parameters. +type GroupOpts struct { + // API group name, which can contain 3 to 64 characters, starting with a letter. + // Only letters, digits and underscores (_) are allowed. + // Chinese characters must be in UTF-8 or Unicode format. + Name string `json:"name" required:"true"` + // Description of the API group, which can contain a maximum of 255 characters, + // and the angle brackets (< and >) are not allowed. + // Chinese characters must be in UTF-8 or Unicode format. + Description *string `json:"remark,omitempty"` +} + +type CreateOptsBuilder interface { + ToCreateOptsMap() (map[string]interface{}, error) +} + +func (opts GroupOpts) ToCreateOptsMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "") +} + +// Create is a method by which to create function that create a new group. +func Create(client *golangsdk.ServiceClient, instanceId string, opts CreateOptsBuilder) (r CreateResult) { + reqBody, err := opts.ToCreateOptsMap() + if err != nil { + r.Err = err + return + } + _, r.Err = client.Post(rootURL(client, instanceId), reqBody, &r.Body, nil) + return +} + +// Update is a method by which to create function that udpate a existing group. +func Update(client *golangsdk.ServiceClient, instanceId, groupId string, opts CreateOptsBuilder) (r UpdateResult) { + reqBody, err := opts.ToCreateOptsMap() + if err != nil { + r.Err = err + return + } + _, r.Err = client.Put(resourceURL(client, instanceId, groupId), reqBody, &r.Body, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + return +} + +// Get is a method to obtain the specified group according to the instanceId and appId. +func Get(client *golangsdk.ServiceClient, instanceId, groupId string) (r GetResult) { + _, r.Err = client.Get(resourceURL(client, instanceId, groupId), &r.Body, nil) + return +} + +// ListOpts allows to filter list data using given parameters. +type ListOpts struct { + // API group ID. + Id string `q:"id"` + // API group name. + Name string `q:"name"` + // Offset from which the query starts. + // If the offset is less than 0, the value is automatically converted to 0. Default to 0. + Offset int `q:"offset"` + // Number of items displayed on each page. The valid values are range form 1 to 500, default to 20. + Limit int `q:"limit"` + // Parameter name for exact matching. Only API group names are supported. + PreciseSearch string `q:"precise_search"` +} + +type ListOptsBuilder interface { + ToListQuery() (string, error) +} + +func (opts ListOpts) ToListQuery() (string, error) { + q, err := golangsdk.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), err +} + +// List is a method to obtain an array of one or more groups according to the query parameters. +func List(client *golangsdk.ServiceClient, instanceId string, opts ListOptsBuilder) pagination.Pager { + url := rootURL(client, instanceId) + if opts != nil { + query, err := opts.ToListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return GroupPage{pagination.SinglePageBase(r)} + }) +} + +// Delete is a method to delete an existing group. +func Delete(client *golangsdk.ServiceClient, instanceId, groupId string) (r DeleteResult) { + _, r.Err = client.Delete(resourceURL(client, instanceId, groupId), nil) + return +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/results.go b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/results.go new file mode 100644 index 0000000000..5c5b7e87fe --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/results.go @@ -0,0 +1,98 @@ +package apigroups + +import ( + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/pagination" +) + +type commonResult struct { + golangsdk.Result +} + +// CreateResult represents a result of the Create method. +type CreateResult struct { + commonResult +} + +// GetResult represents a result of the Get operation. +type GetResult struct { + commonResult +} + +// UpdateResult represents a result of the Update operation. +type UpdateResult struct { + commonResult +} + +type Group struct { + // List of independent domain names bound to the API group. + UrlDomians []UrlDomian `json:"url_domains"` + // Time when the API group was last modified. + UpdateTime string `json:"update_time"` + // API group name. + Name string `json:"name"` + // Indicates whether the API group has been listed on the marketplace. + // 1: listed + // 2: not listed + // 3: under review. + OnSellStatus int `json:"on_sell_status"` + // Description. + Description string `json:"remark"` + // Subdomain name that API Gateway automatically allocates to the API group. + Subdomain string `json:"sl_domain"` + // Subdomain names that API Gateway automatically allocates to the API group. + Subdomains []string `json:"sl_domains"` + // ID. + Id string `json:"id"` + // Registraion time. + RegistraionTime string `json:"register_time"` + // group status. + // 1: valid + Status int `json:"status"` + // Indicates whether the API group is the default group. + IsDefault int `json:"is_default"` +} + +type UrlDomian struct { + // Domain ID. + Id string `json:"id"` + // Domain ID. + DomainName string `json:"domain"` + // CNAME resolution status of the domain name. + // 1: not resolved + // 2: resolving + // 3: resolved + // 4: resolving failed + ResolutionStatus int `json:"cname_status"` + // SSL certificate ID. + SSLId string `json:"ssl_id"` + // SSL certificate name. + SSLName string `json:"ssl_name"` + // Minimum SSL version. TLS 1.1 and TLS 1.2 are supported. + // Enumeration values: + // TLSv1.1 + // TLSv1.2 + MinSSLVersion string `json:"min_ssl_version"` +} + +func (r commonResult) Extract() (*Group, error) { + var s Group + err := r.ExtractInto(&s) + return &s, err +} + +// GroupPage represents the response pages of the List operation. +type GroupPage struct { + pagination.SinglePageBase +} + +func ExtractGroups(r pagination.Page) ([]Group, error) { + var s []Group + err := r.(GroupPage).Result.ExtractIntoSlicePtr(&s, "groups") + return s, err +} + +// DeleteResult represents a result of the Delete method. +type DeleteResult struct { + golangsdk.ErrResult +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/urls.go b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/urls.go new file mode 100644 index 0000000000..20a34b500b --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups/urls.go @@ -0,0 +1,13 @@ +package apigroups + +import "github.com/huaweicloud/golangsdk" + +const rootPath = "instances" + +func rootURL(c *golangsdk.ServiceClient, instanceId string) string { + return c.ServiceURL(rootPath, instanceId, "api-groups") +} + +func resourceURL(c *golangsdk.ServiceClient, instanceId, groupId string) string { + return c.ServiceURL(rootPath, instanceId, "api-groups", groupId) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 8ff61e5d77..64a6dd0750 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -276,6 +276,7 @@ github.com/huaweicloud/golangsdk/openstack/antiddos/v1/antiddos github.com/huaweicloud/golangsdk/openstack/aom/v1/icagents github.com/huaweicloud/golangsdk/openstack/apigw/apis github.com/huaweicloud/golangsdk/openstack/apigw/groups +github.com/huaweicloud/golangsdk/openstack/apigw/v2/apigroups github.com/huaweicloud/golangsdk/openstack/apigw/v2/applications github.com/huaweicloud/golangsdk/openstack/apigw/v2/channels github.com/huaweicloud/golangsdk/openstack/apigw/v2/environments