Skip to content

Commit

Permalink
feat(iotda): add resource to manage device asynchronous command deliver
Browse files Browse the repository at this point in the history
  • Loading branch information
ruwenqiang123 committed Nov 4, 2024
1 parent 453ca67 commit 3f582bf
Show file tree
Hide file tree
Showing 4 changed files with 457 additions and 12 deletions.
114 changes: 114 additions & 0 deletions docs/resources/iotda_device_async_command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
subcategory: "IoT Device Access (IoTDA)"
layout: "huaweicloud"
page_title: "HuaweiCloud: huaweicloud_iotda_device_async_command"
description: |-
Manages a device asynchronous command delivery resource within HuaweiCloud.
---

# huaweicloud_iotda_device_async_command

Manages a device asynchronous command delivery resource within HuaweiCloud.

-> 1.This resource is only a one-time action resource for doing API action. Deleting this resource will not clear
the corresponding request record, but will only remove the resource information from the tfstate file.
<br>2.Currently, this resource is only supported deliver commands asynchronously to NB-IoT devices.
<br>3.After the resource is created, please pay attention to the command executed result through `status`,
you can execute the **terraform plan** command at regular intervals to monitor `status` changes.

-> When accessing an IoTDA **standard** or **enterprise** edition instance, you need to specify the IoTDA service
endpoint in `provider` block.
You can login to the IoTDA console, choose the instance **Overview** and click **Access Details**
to view the HTTPS application access address. An example of the access address might be
**9bc34xxxxx.st1.iotda-app.ap-southeast-1.myhuaweicloud.com**, then you need to configure the
`provider` block as follows:

```hcl
provider "huaweicloud" {
endpoints = {
iotda = "https://9bc34xxxxx.st1.iotda-app.ap-southeast-1.myhuaweicloud.com"
}
}
```

## Example Usage

```hcl
variable "device_id"{}
variable "send_strategy"{}
resource "huaweicloud_iotda_device_async_command" "test" {
device_id = var.device_id
send_strategy = var.send_strategy
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional, String, ForceNew) Specifies the region in which to create the access credential resource.
If omitted, the provider-level region will be used.
Changing this parameter will create a new resource.

* `device_id` - (Required, String, ForceNew) Specifies the ID of the device to which the command is delivered.
Changing this parameter will create a new resource.

* `send_strategy` - (Required, String, ForceNew) Specifies the delivery policy.
The valid values are as follows:
+ **immediately**: The command is delivered immediately.
+ **delay**: The command is cached and delivered after the device reports data or goes online. Default value.

Changing this parameter will create a new resource.

* `service_id` - (Optional, String, ForceNew) Specifies the ID of the device service to which the device command belongs,
which is defined in the product model associated with the device.
This parameter is mandatory if the device requires codecs to parse commands.
Changing this parameter will create a new resource.

* `name` - (Optional, String, ForceNew) Specifies the command name, which is defined in the product model
associated with the device.
This parameter is mandatory if the device requires codecs to parse commands.
Changing this parameter will create a new resource.

* `paras` - (Optional, Map, ForceNew) Specifies the command executed by the device.
If `service_id` is specified, each key is the parameter in commands in the product model.
If `service_id` is left empty, the key can custom.
The maximum size of the request object is `256` KB.
Changing this parameter will create a new resource.

* `expire_time` - (Optional, Int, ForceNew) Specifies the duration of caching commands on the IoT platform.
This parameter is valid only when `send_strategy` is set to **delay**. The unit is second.
If `expire_time` is set to **0** or not specified, the command is cached for 24 hours (`86,400` seconds) by default,
and the maximum cache duration is `2` days.
Changing this parameter will create a new resource.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The resource ID.

* `status` - The status of the command.
The valid values are as follows:
+ **PENDING**: The command is not delivered and is cached on the platform.
+ **EXPIRED**: The command has expired, the cache time exceeds the value of `expire_time`.
+ **SENT**: The command is being delivered.
+ **DELIVERED**: The command has been delivered.
+ **SUCCESSFUL**: The command has been executed.
+ **FAILED**: The command fails to be executed.
+ **TIMEOUT**: After the command is delivered, no response is received from the device or the response times out.

* `result` - The command execution result.

* `sent_time` - The time of the platform sent the command.
The format is **yyyyMMdd'T'HHmmss'Z'**, e.g. **20151212T121212Z**.

* `delivered_time` - The time of the device received the command.
The format is **yyyyMMdd'T'HHmmss'Z'**, e.g. **20151212T121212Z**.

* `response_time` - The time of the device responded to the command.
The format is **yyyyMMdd'T'HHmmss'Z'**, e.g. **20151212T121212Z**.

* `created_at` - The creation time of the device command.
The format is **yyyyMMdd'T'HHmmss'Z'**, e.g. **20151212T121212Z**.
25 changes: 13 additions & 12 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,18 +1685,19 @@ func Provider() *schema.Provider {
"huaweicloud_images_image_share": ims.ResourceImsImageShare(),
"huaweicloud_images_image_share_accepter": ims.ResourceImsImageShareAccepter(),

"huaweicloud_iotda_access_credential": iotda.ResourceAccessCredential(),
"huaweicloud_iotda_amqp": iotda.ResourceAmqp(),
"huaweicloud_iotda_batchtask": iotda.ResourceBatchTask(),
"huaweicloud_iotda_dataforwarding_rule": iotda.ResourceDataForwardingRule(),
"huaweicloud_iotda_device": iotda.ResourceDevice(),
"huaweicloud_iotda_device_certificate": iotda.ResourceDeviceCertificate(),
"huaweicloud_iotda_device_group": iotda.ResourceDeviceGroup(),
"huaweicloud_iotda_device_linkage_rule": iotda.ResourceDeviceLinkageRule(),
"huaweicloud_iotda_device_proxy": iotda.ResourceDeviceProxy(),
"huaweicloud_iotda_product": iotda.ResourceProduct(),
"huaweicloud_iotda_space": iotda.ResourceSpace(),
"huaweicloud_iotda_upgrade_package": iotda.ResourceUpgradePackage(),
"huaweicloud_iotda_access_credential": iotda.ResourceAccessCredential(),
"huaweicloud_iotda_amqp": iotda.ResourceAmqp(),
"huaweicloud_iotda_batchtask": iotda.ResourceBatchTask(),
"huaweicloud_iotda_dataforwarding_rule": iotda.ResourceDataForwardingRule(),
"huaweicloud_iotda_device": iotda.ResourceDevice(),
"huaweicloud_iotda_device_async_command": iotda.ResourceDeviceAsyncCommand(),
"huaweicloud_iotda_device_certificate": iotda.ResourceDeviceCertificate(),
"huaweicloud_iotda_device_group": iotda.ResourceDeviceGroup(),
"huaweicloud_iotda_device_linkage_rule": iotda.ResourceDeviceLinkageRule(),
"huaweicloud_iotda_device_proxy": iotda.ResourceDeviceProxy(),
"huaweicloud_iotda_product": iotda.ResourceProduct(),
"huaweicloud_iotda_space": iotda.ResourceSpace(),
"huaweicloud_iotda_upgrade_package": iotda.ResourceUpgradePackage(),

"huaweicloud_kms_data_encrypt_decrypt": dew.ResourceKmsDataEncryptDecrypt(),
"huaweicloud_kms_key": dew.ResourceKmsKey(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package iotda

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"

"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iotda/v5/model"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
)

func getDeviceAsyncCommandFunc(conf *config.Config, state *terraform.ResourceState) (interface{}, error) {
client, err := conf.HcIoTdaV5Client(acceptance.HW_REGION_NAME, WithDerivedAuth())
if err != nil {
return nil, fmt.Errorf("error creating IoTDA v5 client: %s", err)
}

return client.ShowAsyncDeviceCommand(&model.ShowAsyncDeviceCommandRequest{DeviceId: state.Primary.Attributes["device_id"],
CommandId: state.Primary.ID})
}

func TestAccDeviceAsyncCommand_basic(t *testing.T) {
var obj model.ShowDeviceResponse

name := acceptance.RandomAccResourceName()
rName := "huaweicloud_iotda_device_async_command.test"
rc := acceptance.InitResourceCheck(
rName,
&obj,
getDeviceAsyncCommandFunc,
)

resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheck(t) },
ProviderFactories: acceptance.TestAccProviderFactories,
CheckDestroy: rc.CheckResourceDestroy(),
Steps: []resource.TestStep{
{
Config: testAccDeviceAsyncCommand_basic(name),
Check: resource.ComposeTestCheckFunc(
rc.CheckResourceExists(),
resource.TestCheckResourceAttrPair(rName, "device_id", "huaweicloud_iotda_device.test", "id"),
resource.TestCheckResourceAttrPair(rName, "service_id", "huaweicloud_iotda_product.test", "services.0.id"),
resource.TestCheckResourceAttrPair(rName, "name", "huaweicloud_iotda_product.test", "services.0.commands.0.name"),
resource.TestCheckResourceAttr(rName, "send_strategy", "delay"),
resource.TestCheckResourceAttr(rName, "expire_time", "80000"),
resource.TestCheckResourceAttrSet(rName, "status"),
resource.TestCheckResourceAttrSet(rName, "created_at"),
),
},
},
})
}

func TestAccDeviceAsyncCommand_derived(t *testing.T) {
var obj model.ShowDeviceResponse

name := acceptance.RandomAccResourceName()
rName := "huaweicloud_iotda_device_async_command.test"
rc := acceptance.InitResourceCheck(
rName,
&obj,
getDeviceAsyncCommandFunc,
)

resource.Test(t, resource.TestCase{
PreCheck: func() {
acceptance.TestAccPreCheck(t)
acceptance.TestAccPreCheckHWIOTDAAccessAddress(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
CheckDestroy: rc.CheckResourceDestroy(),
Steps: []resource.TestStep{
{
Config: testAccDeviceAsyncCommand_basic(name),
Check: resource.ComposeTestCheckFunc(
rc.CheckResourceExists(),
resource.TestCheckResourceAttrPair(rName, "device_id", "huaweicloud_iotda_device.test", "id"),
resource.TestCheckResourceAttrPair(rName, "service_id", "huaweicloud_iotda_product.test", "services.0.id"),
resource.TestCheckResourceAttrPair(rName, "name", "huaweicloud_iotda_product.test", "services.0.commands.0.name"),
resource.TestCheckResourceAttr(rName, "send_strategy", "delay"),
resource.TestCheckResourceAttr(rName, "expire_time", "80000"),
resource.TestCheckResourceAttrSet(rName, "status"),
resource.TestCheckResourceAttrSet(rName, "created_at"),
),
},
},
})
}

func testAccDeviceAsyncCommand_base(name string) string {
return fmt.Sprintf(`
resource "huaweicloud_iotda_space" "test" {
name = "%[1]s"
}
resource "huaweicloud_iotda_product" "test" {
name = "%[1]s"
device_type = "AI"
protocol = "CoAP"
space_id = huaweicloud_iotda_space.test.id
data_type = "json"
industry = "smart-home"
services {
id = "001211985996"
type = "001002"
commands {
name = "cmd-test"
paras {
name = "cmd-req"
type = "string"
max_length = 20
}
responses {
name = "cmd-resp"
type = "string"
max_length = 20
}
}
}
}
resource "huaweicloud_iotda_device" "test" {
node_id = "101112026"
name = "%[1]s"
space_id = huaweicloud_iotda_space.test.id
product_id = huaweicloud_iotda_product.test.id
description = "demo"
}
`, name)
}

func testAccDeviceAsyncCommand_basic(name string) string {
return fmt.Sprintf(`
%[1]s
resource "huaweicloud_iotda_device_async_command" "test" {
device_id = huaweicloud_iotda_device.test.id
service_id = huaweicloud_iotda_product.test.services.0.id
name = huaweicloud_iotda_product.test.services.0.commands.0.name
send_strategy = "delay"
expire_time = "80000"
paras = {
(huaweicloud_iotda_product.test.services.0.commands.0.paras.0.name) = "tf-acc"
}
}
`, testAccDeviceAsyncCommand_base(name))
}
Loading

0 comments on commit 3f582bf

Please sign in to comment.