-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(AS): add datasource AS lifecycle hooks (#4002)
- Loading branch information
1 parent
ca60824
commit 8dc602e
Showing
4 changed files
with
355 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
--- | ||
subcategory: "Auto Scaling" | ||
--- | ||
|
||
# huaweicloud_as_lifecycle_hooks | ||
|
||
Use this data source to get a list of AS scaling lifecycle hooks within HuaweiCloud. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
variable "scaling_group_id" {} | ||
data "huaweicloud_as_lifecycle_hooks" "test" { | ||
scaling_group_id = var.scaling_group_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. | ||
|
||
* `scaling_group_id` - (Required, String) Specifies the AS scaling group ID. | ||
|
||
* `name` - (Optional, String) Specifies the lifecycle hook name. | ||
|
||
* `type` - (Optional, String) Specifies the lifecycle hook type. The valid values are as follows: | ||
+ **ADD**: The hook suspends the instance when the instance is started. | ||
+ **REMOVE**: The hook suspends the instance when the instance is terminated. | ||
|
||
* `default_result` - (Optional, String) Specifies the default lifecycle hook callback action. This action is | ||
performed when the timeout duration expires. The valid values are **ABANDON** and **CONTINUE**, defaults to **ABANDON**. | ||
|
||
## Attribute Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
* `id` - The data source ID. | ||
|
||
* `lifecycle_hooks` - All AS scaling lifecycle hooks that match the filter parameters. | ||
The [lifecycle_hooks](#attrblock_lifecycle_hooks) structure is documented below. | ||
|
||
<a name="attrblock_lifecycle_hooks"></a> | ||
The `lifecycle_hooks` block supports: | ||
|
||
* `name` - The lifecycle hook name. | ||
|
||
* `type` - The lifecycle hook type. | ||
|
||
* `default_result` - The default lifecycle hook callback action. | ||
|
||
* `timeout` - The lifecycle hook timeout duration in the unit of second. | ||
|
||
* `notification_topic_urn` - The unique URN of the notification topic in SMN. | ||
|
||
* `notification_topic_name` - The topic name of notification topic in SMN. | ||
|
||
* `notification_message` - The customized notification. After a notification object is configured, | ||
the SMN service sends your customized notification to the object. | ||
|
||
* `created_at` - The creation time of the lifecycle hooks. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
huaweicloud/services/acceptance/as/data_source_huaweicloud_as_lifecycle_hooks_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package as | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
|
||
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" | ||
) | ||
|
||
func TestAccDataSourceLifecycleHooks_basic(t *testing.T) { | ||
var ( | ||
dataSourceName = "data.huaweicloud_as_lifecycle_hooks.test" | ||
dc = acceptance.InitDataSourceCheck(dataSourceName) | ||
) | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { | ||
acceptance.TestAccPreCheck(t) | ||
acceptance.TestAccPreCheckASScalingGroupID(t) | ||
}, | ||
ProviderFactories: acceptance.TestAccProviderFactories, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccLifecycleHooks_basic(), | ||
Check: resource.ComposeTestCheckFunc( | ||
dc.CheckResourceExists(), | ||
resource.TestCheckResourceAttrSet(dataSourceName, "scaling_group_id"), | ||
resource.TestCheckOutput("name_filter_is_useful", "true"), | ||
resource.TestCheckOutput("type_filter_is_useful", "true"), | ||
resource.TestCheckOutput("default_result_filter_is_useful", "true"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccLifecycleHooks_basic() string { | ||
rName := acceptance.RandomAccResourceName() | ||
return fmt.Sprintf(` | ||
%[1]s | ||
resource "huaweicloud_as_lifecycle_hook" "test1" { | ||
name = "%[2]s1" | ||
type = "ADD" | ||
default_result = "ABANDON" | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
notification_topic_urn = huaweicloud_smn_topic.test.topic_urn | ||
notification_message = "This is a test message" | ||
} | ||
resource "huaweicloud_as_lifecycle_hook" "test2" { | ||
name = "%[2]s2" | ||
type = "REMOVE" | ||
default_result = "CONTINUE" | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
notification_topic_urn = huaweicloud_smn_topic.test.topic_urn | ||
notification_message = "This is a test message" | ||
} | ||
resource "huaweicloud_as_lifecycle_hook" "test3" { | ||
name = "%[2]s3" | ||
type = "ADD" | ||
default_result = "CONTINUE" | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
notification_topic_urn = huaweicloud_smn_topic.test.topic_urn | ||
notification_message = "This is a test message" | ||
} | ||
data "huaweicloud_as_lifecycle_hooks" "test" { | ||
depends_on = [ | ||
huaweicloud_as_lifecycle_hook.test1, | ||
huaweicloud_as_lifecycle_hook.test2, | ||
huaweicloud_as_lifecycle_hook.test3, | ||
] | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
} | ||
locals { | ||
name = data.huaweicloud_as_lifecycle_hooks.test.lifecycle_hooks[0].name | ||
} | ||
data "huaweicloud_as_lifecycle_hooks" "filter_by_name" { | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
name = local.name | ||
} | ||
output "name_filter_is_useful" { | ||
value = length(data.huaweicloud_as_lifecycle_hooks.filter_by_name.lifecycle_hooks) > 0 && alltrue( | ||
[for v in data.huaweicloud_as_lifecycle_hooks.filter_by_name.lifecycle_hooks[*].name : v == local.name] | ||
) | ||
} | ||
locals { | ||
type = data.huaweicloud_as_lifecycle_hooks.test.lifecycle_hooks[0].type | ||
} | ||
data "huaweicloud_as_lifecycle_hooks" "filter_by_type" { | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
type = local.type | ||
} | ||
output "type_filter_is_useful" { | ||
value = length(data.huaweicloud_as_lifecycle_hooks.filter_by_type.lifecycle_hooks) >= 0 && alltrue( | ||
[for v in data.huaweicloud_as_lifecycle_hooks.filter_by_type.lifecycle_hooks[*].type : v == local.type] | ||
) | ||
} | ||
locals { | ||
default_result = data.huaweicloud_as_lifecycle_hooks.test.lifecycle_hooks[0].default_result | ||
} | ||
data "huaweicloud_as_lifecycle_hooks" "filter_by_default_result" { | ||
scaling_group_id = huaweicloud_as_group.acc_as_group.id | ||
default_result = local.default_result | ||
} | ||
output "default_result_filter_is_useful" { | ||
value = length(data.huaweicloud_as_lifecycle_hooks.filter_by_default_result.lifecycle_hooks) > 0 && alltrue( | ||
[for v in data.huaweicloud_as_lifecycle_hooks.filter_by_default_result.lifecycle_hooks[*].default_result : v == local.default_result] | ||
) | ||
} | ||
`, testASLifecycleHook_base(rName), rName) | ||
} |
160 changes: 160 additions & 0 deletions
160
huaweicloud/services/as/data_source_huaweicloud_as_lifecycle_hooks.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package as | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"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/openstack/autoscaling/v1/lifecyclehooks" | ||
|
||
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/common" | ||
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" | ||
) | ||
|
||
var convertHookTypeMap = map[string]string{ | ||
"INSTANCE_LAUNCHING": "ADD", | ||
"INSTANCE_TERMINATING": "REMOVE", | ||
} | ||
|
||
// API: AS GET /autoscaling-api/v1/{project_id}/scaling_lifecycle_hook/{scaling_group_id}/list | ||
func DataSourceLifeCycleHooks() *schema.Resource { | ||
return &schema.Resource{ | ||
ReadContext: dataSourceLifeCycleHooksRead, | ||
Schema: map[string]*schema.Schema{ | ||
"region": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"scaling_group_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"name": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"type": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"default_result": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"lifecycle_hooks": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"default_result": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"timeout": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"notification_topic_urn": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"notification_topic_name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"notification_message": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"created_at": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceLifeCycleHooksRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
cfg := meta.(*config.Config) | ||
region := cfg.GetRegion(d) | ||
|
||
client, err := cfg.AutoscalingV1Client(region) | ||
if err != nil { | ||
return diag.Errorf("error creating AS v1 client: %s", err) | ||
} | ||
|
||
groupID := d.Get("scaling_group_id").(string) | ||
|
||
lifecycleHookList, err := lifecyclehooks.List(client, groupID).Extract() | ||
if err != nil { | ||
return common.CheckDeletedDiag(d, err, "AS lifecycle hooks") | ||
} | ||
|
||
lifecycleHooks, err := flattenLifecycleHooks(d, lifecycleHookList) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
randUUID, err := uuid.GenerateUUID() | ||
if err != nil { | ||
return diag.Errorf("unable to generate ID: %s", err) | ||
} | ||
d.SetId(randUUID) | ||
|
||
mErr := multierror.Append(nil, | ||
d.Set("region", region), | ||
d.Set("lifecycle_hooks", lifecycleHooks), | ||
) | ||
if mErr.ErrorOrNil() != nil { | ||
return diag.Errorf("error saving lifecycle hooks data source fields: %s", mErr) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func flattenLifecycleHooks(d *schema.ResourceData, hooks *[]lifecyclehooks.Hook) ([]map[string]interface{}, error) { | ||
rst := make([]map[string]interface{}, 0, len(*hooks)) | ||
for _, hook := range *hooks { | ||
if val, ok := d.GetOk("name"); ok && val.(string) != hook.Name { | ||
continue | ||
} | ||
if val, ok := d.GetOk("type"); ok && val.(string) != hook.Type { | ||
continue | ||
} | ||
if val, ok := d.GetOk("default_result"); ok && val.(string) != hook.DefaultResult { | ||
continue | ||
} | ||
|
||
hookType, ok := convertHookTypeMap[hook.Type] | ||
if !ok { | ||
return nil, fmt.Errorf("lifecycle hook type (%s) is not in the map (%#v)", hook.Type, convertHookTypeMap) | ||
} | ||
lifecycleHookMap := map[string]interface{}{ | ||
"name": hook.Name, | ||
"type": hookType, | ||
"default_result": hook.DefaultResult, | ||
"timeout": hook.Timeout, | ||
"notification_topic_urn": hook.NotificationTopicURN, | ||
"notification_topic_name": hook.NotificationTopicName, | ||
"notification_message": hook.NotificationMetadata, | ||
"created_at": hook.CreateTime, | ||
} | ||
rst = append(rst, lifecycleHookMap) | ||
} | ||
return rst, nil | ||
} |