Skip to content

Commit

Permalink
feat(dws): add new resource to copy automated snapshot (#5596)
Browse files Browse the repository at this point in the history
* chore(dws/snapshot): extract query and delete  methods as common method

* feat(dws): add new resource to copy automated snapshot
  • Loading branch information
wuzhuanhong authored Sep 26, 2024
1 parent 7f672a0 commit 6811712
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 105 deletions.
63 changes: 63 additions & 0 deletions docs/resources/dws_snapshot_copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
subcategory: "GaussDB(DWS)"
layout: "huaweicloud"
page_title: "HuaweiCloud: huaweicloud_dws_snapshot_copy"
description: |-
Use this resource to copy an automated snapshot to a manual snapshot within HuaweiCloud.
---

# huaweicloud_dws_snapshot_copy

Use this resource to copy an automated snapshot to a manual snapshot within HuaweiCloud.

-> 1. An automated snapshot can only correspond to one `huaweicloud_dws_snapshot_copy` resource.
<br>2. Deleting this resource will delete the corresponding copied snapshot.

## Example Usage

```hcl
variable "automated_snapshot_id" {}
variable "snapshot_name" {}
variable "description" {}
resource "huaweicloud_dws_snapshot_copy" "test" {
snapshot_id = var.automated_snapshot_id
name = var.snapshot_name
description = var.description
}
```

## Argument Reference

The following arguments are supported:

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

* `snapshot_id` - (Required, String, ForceNew) Specifies the ID of the automated snapshot to be copied.
Changing this creates a new resource.

* `name` - (Required, String, ForceNew) Specifies the name of the copy snapshot.
Changing this creates a new resource.
The valid length is limited from `4` to `64`, only English letters, digits, underscores (_) and hyphens (-) are allowed,
and must start with a letter.
The snapshot name must be unique.

* `description` - (Optional, String, ForceNew) Specifies the description of the copy snapshot.
Changing this creates a new resource.
The maximum length is limited to `256` characters, and special characters (`!<>'=&"`) are not allowed.

## Attribute Reference

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

* `id` - The resource ID, also the ID of the copied snapshot.

## Import

The resource can be imported using the related `snapshot_id` and `id`, separated by a slash, e.g.

```bash
$ terraform import huaweicloud_dws_snapshot_copy.test <snapshot_id>/<id>
```
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,7 @@ func Provider() *schema.Provider {
"huaweicloud_dws_logical_cluster": dws.ResourceLogicalCluster(),
"huaweicloud_dws_om_account_action": dws.ResourceOmAccountAction(),
"huaweicloud_dws_public_domain_associate": dws.ResourcePublicDomainAssociate(),
"huaweicloud_dws_snapshot_copy": dws.ResourceSnapshotCopy(),
"huaweicloud_dws_snapshot_policy": dws.ResourceDwsSnapshotPolicy(),
"huaweicloud_dws_snapshot": dws.ResourceDwsSnapshot(),
"huaweicloud_dws_workload_configuration": dws.ResourceWorkLoadConfiguration(),
Expand Down
13 changes: 10 additions & 3 deletions huaweicloud/services/acceptance/acceptance.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,10 @@ var (
HW_DWS_CLUSTER_ID = os.Getenv("HW_DWS_CLUSTER_ID")
HW_DWS_LOGICAL_MODE_CLUSTER_ID = os.Getenv("HW_DWS_LOGICAL_MODE_CLUSTER_ID")
HW_DWS_LOGICAL_CLUSTER_NAME = os.Getenv("HW_DWS_LOGICAL_CLUSTER_NAME")

HW_DWS_SNAPSHOT_POLICY_NAME = os.Getenv("HW_DWS_SNAPSHOT_POLICY_NAME")
HW_DWS_SNAPSHOT_POLICY_NAME = os.Getenv("HW_DWS_SNAPSHOT_POLICY_NAME")
// The list of the user names under specified DWS cluster. Using commas (,) to separate multiple names.
HW_DWS_ASSOCIATE_USER_NAMES = os.Getenv("HW_DWS_ASSOCIATE_USER_NAMES")
HW_DWS_ASSOCIATE_USER_NAMES = os.Getenv("HW_DWS_ASSOCIATE_USER_NAMES")
HW_DWS_AUTOMATED_SNAPSHOT_ID = os.Getenv("HW_DWS_AUTOMATED_SNAPSHOT_ID")

HW_DCS_ACCOUNT_WHITELIST = os.Getenv("HW_DCS_ACCOUNT_WHITELIST")

Expand Down Expand Up @@ -2089,6 +2089,13 @@ func TestAccPreCheckDwsClusterUserNames(t *testing.T) {
}
}

// lintignore:AT003
func TestAccPreCheckDwsAutomatedSnapshot(t *testing.T) {
if HW_DWS_AUTOMATED_SNAPSHOT_ID == "" {
t.Skip("HW_DWS_AUTOMATED_SNAPSHOT_ID must be set for the acceptance test")
}
}

// lintignore:AT003
func TestAccPreCheckDCSAccountWhitelist(t *testing.T) {
if HW_DCS_ACCOUNT_WHITELIST == "" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package dws

import (
"fmt"
"testing"

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

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

func getCopiedSnapshotFunc(cfg *config.Config, state *terraform.ResourceState) (interface{}, error) {
region := acceptance.HW_REGION_NAME
client, err := cfg.NewServiceClient("dws", region)
if err != nil {
return nil, fmt.Errorf("error creating DWS client: %s", err)
}

return dws.GetSnapshotById(client, state.Primary.ID)
}

func TestAccSnapshotCopy_basic(t *testing.T) {
var (
obj interface{}
rName = "huaweicloud_dws_snapshot_copy.test"
name = acceptance.RandomAccResourceNameWithDash()

rc = acceptance.InitResourceCheck(
rName,
&obj,
getCopiedSnapshotFunc,
)
)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acceptance.TestAccPreCheck(t)
acceptance.TestAccPreCheckDwsAutomatedSnapshot(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
CheckDestroy: rc.CheckResourceDestroy(),
Steps: []resource.TestStep{
{
Config: testSnapshotCopy_basic_step1(name),
Check: resource.ComposeTestCheckFunc(
rc.CheckResourceExists(),
resource.TestCheckResourceAttr(rName, "name", name),
resource.TestCheckResourceAttr(rName, "snapshot_id", acceptance.HW_DWS_AUTOMATED_SNAPSHOT_ID),
resource.TestCheckResourceAttr(rName, "description", "Copying a snapshot by terraform script"),
),
},
{
ResourceName: rName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testAccSnapshotCopyImportStateFunc(rName),
},
},
})
}

func testAccSnapshotCopyImportStateFunc(rName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[rName]
if !ok {
return "", fmt.Errorf("resource (%s) not found: %s", rName, rs)
}

if rs.Primary.Attributes["snapshot_id"] == "" {
return "", fmt.Errorf("invalid format specified for import ID, want '<snapshot_id>/<id>', but got '%s/%s'",
rs.Primary.Attributes["snapshot_id"], rs.Primary.ID)
}
return fmt.Sprintf("%s/%s", rs.Primary.Attributes["snapshot_id"], rs.Primary.ID), nil
}
}

func testSnapshotCopy_basic_step1(name string) string {
return fmt.Sprintf(`
resource "huaweicloud_dws_snapshot_copy" "test" {
snapshot_id = "%[1]s"
name = "%[2]s"
description = "Copying a snapshot by terraform script"
}
`, acceptance.HW_DWS_AUTOMATED_SNAPSHOT_ID, name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,24 @@ package dws

import (
"fmt"
"strings"
"testing"

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

"github.com/chnsz/golangsdk"
"github.com/chnsz/golangsdk/openstack/dws/v1/cluster"

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

func getDwsSnapshotResourceFunc(cfg *config.Config, state *terraform.ResourceState) (interface{}, error) {
region := acceptance.HW_REGION_NAME
// getDwsSnapshot: Query the DWS snapshot.
var (
getDwsSnapshotHttpUrl = "v1.0/{project_id}/snapshots/{snapshot_id}"
getDwsSnapshotProduct = "dws"
)
getDwsSnapshotClient, err := cfg.NewServiceClient(getDwsSnapshotProduct, region)
getDwsSnapshotClient, err := cfg.NewServiceClient("dws", region)
if err != nil {
return nil, fmt.Errorf("error creating DWS Client: %s", err)
return nil, fmt.Errorf("error creating DWS client: %s", err)
}

getDwsSnapshotPath := getDwsSnapshotClient.Endpoint + getDwsSnapshotHttpUrl
getDwsSnapshotPath = strings.ReplaceAll(getDwsSnapshotPath, "{project_id}", getDwsSnapshotClient.ProjectID)
getDwsSnapshotPath = strings.ReplaceAll(getDwsSnapshotPath, "{snapshot_id}", state.Primary.ID)

getDwsSnapshotOpt := golangsdk.RequestOpts{
KeepResponseBody: true,
MoreHeaders: map[string]string{
"Content-Type": "application/json;charset=UTF-8",
},
OkCodes: []int{
200,
},
}
getDwsSnapshotResp, err := getDwsSnapshotClient.Request("GET", getDwsSnapshotPath, &getDwsSnapshotOpt)
if err != nil {
return nil, fmt.Errorf("error retrieving DWS snapshot: %s", err)
}
return utils.FlattenResponse(getDwsSnapshotResp)
return dws.GetSnapshotById(getDwsSnapshotClient, state.Primary.ID)
}

func TestAccDwsSnapshot_basic(t *testing.T) {
Expand All @@ -61,7 +35,10 @@ func TestAccDwsSnapshot_basic(t *testing.T) {
)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheck(t) },
PreCheck: func() {
acceptance.TestAccPreCheck(t)
acceptance.TestAccPreCheckDwsClusterId(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
CheckDestroy: rc.CheckResourceDestroy(),
Steps: []resource.TestStep{
Expand All @@ -72,7 +49,7 @@ func TestAccDwsSnapshot_basic(t *testing.T) {
resource.TestCheckResourceAttr(rName, "name", name),
resource.TestCheckResourceAttr(rName, "status", "AVAILABLE"),
resource.TestCheckResourceAttr(rName, "type", "MANUAL"),
resource.TestCheckResourceAttrPair(rName, "cluster_id", "huaweicloud_dws_cluster.test", "id"),
resource.TestCheckResourceAttr(rName, "cluster_id", acceptance.HW_DWS_CLUSTER_ID),
resource.TestCheckResourceAttrSet(rName, "started_at"),
resource.TestCheckResourceAttrSet(rName, "finished_at"),
resource.TestCheckResourceAttrSet(rName, "size"),
Expand All @@ -89,11 +66,9 @@ func TestAccDwsSnapshot_basic(t *testing.T) {

func testDwsSnapshot_basic(name string) string {
return fmt.Sprintf(`
%s
resource "huaweicloud_dws_snapshot" "test" {
name = "%s"
cluster_id = huaweicloud_dws_cluster.test.id
name = "%[1]s"
cluster_id = "%[2]s"
}
`, testAccDwsCluster_basic_step1(name, 3, cluster.PublicBindTypeNotUse, "cluster123@!"), name)
`, name, acceptance.HW_DWS_CLUSTER_ID)
}
Loading

0 comments on commit 6811712

Please sign in to comment.