Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CBR] include exclude disks support #1802

Merged
merged 8 commits into from Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 29 additions & 4 deletions docs/resources/cbr_vault_v3.md
Expand Up @@ -25,7 +25,32 @@ resource "opentelekomcloud_cbr_vault_v3" "vault" {
}
```

### Vault with associated resource
### Vault with associated resource (server)

```hcl
resource "opentelekomcloud_cbr_vault_v3" "vault" {
name = "cbr-vault-test"

description = "CBR vault for terraform provider test"

billing {
size = 100
object_type = "disk"
protect_type = "backup"
charging_mode = "post_paid"
}

resource {
id = opentelekomcloud_ecs_instance_v1.instance.id
type = "OS::Nova::Server"

exclude_volumes = [
opentelekomcloud_ecs_instance_v1.instance_1.data_disks.1.id
]
}
}
```
### Vault with associated resource (volume)

```hcl
resource "opentelekomcloud_blockstorage_volume_v2" "volume" {
Expand All @@ -50,8 +75,6 @@ resource "opentelekomcloud_cbr_vault_v3" "vault" {
resource {
id = opentelekomcloud_blockstorage_volume_v2.volume.id
type = "OS::Cinder::Volume"

extra_info = {}
}
}
```
Expand Down Expand Up @@ -139,7 +162,9 @@ The following arguments are supported:

* `name` - (Optional) Resource name.

* `extra_info` - (Optional) Map of extra info.
* `exclude_volumes` - (Optional) List of excluded volumes.

* `include_volumes` - (Optional) List of included volumes.

* `backup_policy_id` - (Optional) Backup policy ID. If the value of this parameter is empty, automatic backup is not
performed.
Expand Down
Expand Up @@ -5,8 +5,11 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/cbr/v3/vaults"
"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/common/quotas"
"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/env"
"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg"

"github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/common"
)
Expand Down Expand Up @@ -159,6 +162,57 @@ resource "opentelekomcloud_cbr_vault_v3" "vault" {
`, common.DataSourceImage, common.DataSourceSubnet, env.OsFlavorID)
)

func TestAccCBRVaultV3_extraInfo(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
common.TestAccPreCheck(t)
qts := quotas.MultipleQuotas{
{Q: quotas.Volume, Count: 2},
{Q: quotas.VolumeSize, Count: 20},
{Q: quotas.CBRPolicy, Count: 1},
}
quotas.BookMany(t, qts)
},
ProviderFactories: common.TestAccProviderFactories,
CheckDestroy: testAccCheckCBRVaultV3Destroy,
Steps: []resource.TestStep{
{
Config: testAccCBRVaultV3BasicExtraInfo,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceVaultName, "backup_policy_id"),
),
},
{
Config: testAccCBRVaultV3BasicExtraInfoUpdate,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceVaultName, "resource.#", "1"),
),
},
},
})
}

func testAccCheckCBRVaultV3Destroy(s *terraform.State) error {
config := common.TestAccProvider.Meta().(*cfg.Config)
client, err := config.CbrV3Client(env.OS_REGION_NAME)
if err != nil {
return fmt.Errorf("error creating OpenTelekomCloud CBRv3 client: %s", err)
}

for _, rs := range s.RootModule().Resources {
if rs.Type != "opentelekomcloud_cbr_vault_v3" {
continue
}

_, err := vaults.Get(client, rs.Primary.ID).Extract()
if err == nil {
return fmt.Errorf("CBRv3 vault still exists")
}
}

return nil
}

const (
testAccCBRVaultV3BasicVolumes = `
resource "opentelekomcloud_blockstorage_volume_v2" "volume" {
Expand Down Expand Up @@ -343,5 +397,109 @@ resource "opentelekomcloud_cbr_vault_v3" "vault" {
charging_mode = "post_paid"
}
}
`
testAccCBRVaultV3BasicExtraInfo = `
resource "opentelekomcloud_cbr_policy_v3" "default_policy" {
name = "cbr-policy"
operation_type = "backup"

trigger_pattern = [
"FREQ=DAILY;INTERVAL=1;BYHOUR=23;BYMINUTE=00"
]
operation_definition {
max_backups = 5
timezone = "UTC+01:00"
}

enabled = "true"
}

resource "opentelekomcloud_cbr_vault_v3" "vault" {
name = "cbr-vault-test"

description = "CBR vault for default backup policy"

backup_policy_id = opentelekomcloud_cbr_policy_v3.default_policy.id

auto_bind = true
auto_expand = true

billing {
size = 10000
object_type = "server"
protect_type = "backup"
charging_mode = "post_paid"
}

}
`
)

var testAccCBRVaultV3BasicExtraInfoUpdate = fmt.Sprintf(`
data "opentelekomcloud_vpc_subnet_v1" "shared_subnet" {
name = "%s"
}

resource "opentelekomcloud_ecs_instance_v1" "instance_1" {
name = "server_1"
image_id = "c0b36460-7aa6-44d2-990d-cc300f3a7e43"
flavor = "s2.medium.1"
vpc_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.vpc_id

nics {
network_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.network_id
}

data_disks {
type = "SATA"
size = "10"
}
data_disks {
type = "SAS"
size = "10"
}

password = "Password@123"
availability_zone = "%s"
auto_recovery = true
delete_disks_on_termination = true
}

resource "opentelekomcloud_cbr_policy_v3" "default_policy" {
name = "cbr-policy"
operation_type = "backup"

trigger_pattern = [
"FREQ=DAILY;INTERVAL=1;BYHOUR=23;BYMINUTE=00"
]
operation_definition {
max_backups = 5
timezone = "UTC+01:00"
}

enabled = "true"
}

resource "opentelekomcloud_cbr_vault_v3" "vault" {
name = "cbr-vault-test"

description = "CBR vault for default backup policy"

billing {
size = 10000
object_type = "server"
protect_type = "backup"
charging_mode = "post_paid"
}

resource {
id = opentelekomcloud_ecs_instance_v1.instance_1.id
type = "OS::Nova::Server"

exclude_volumes = [
opentelekomcloud_ecs_instance_v1.instance_1.data_disks.1.id
]

}
}
`, env.OsSubnetName, env.OS_AVAILABILITY_ZONE)
Expand Up @@ -2,7 +2,6 @@ package cbr

import (
"context"
"encoding/json"
"fmt"

"github.com/hashicorp/go-multierror"
Expand Down Expand Up @@ -64,10 +63,17 @@ func ResourceCBRVaultV3() *schema.Resource {
"OS::Nova::Server", "OS::Cinder::Volume",
}, false),
},
"extra_info": {
Type: schema.TypeMap,
"exclude_volumes": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Set: schema.HashString,
Elem: &schema.Schema{Type: schema.TypeString},
},
"include_volumes": {
Type: schema.TypeSet,
Optional: true,
Set: schema.HashString,
Elem: &schema.Schema{Type: schema.TypeString},
},
"protect_status": {
Type: schema.TypeString,
Expand Down Expand Up @@ -279,16 +285,18 @@ func resourceCBRVaultV3Read(_ context.Context, d *schema.ResourceData, meta inte
return fmterr.Errorf("error getting vault details: %s", err)
}

resourceList := make([]interface{}, len(vault.Resources))
for i, resource := range vault.Resources {
data, _ := json.Marshal(resource)
resMap := make(map[string]interface{})
err = json.Unmarshal(data, &resMap)
if err != nil {
return fmterr.Errorf("error converting resource list: %s", err)
var resourceInfo []map[string]interface{}
for _, resource := range vault.Resources {
resourceMap := map[string]interface{}{
"id": resource.ID,
"name": resource.Name,
"type": resource.Type,
"exclude_volumes": resource.ExtraInfo.ExcludeVolumes,
"include_volumes": resource.ExtraInfo.IncludeVolumes,
}
resourceList[i] = resMap
resourceInfo = append(resourceInfo, resourceMap)
}

tagsMap := make(map[string]string)
for _, tag := range vault.Tags {
tagsMap[tag.Key] = tag.Value
Expand All @@ -307,7 +315,7 @@ func resourceCBRVaultV3Read(_ context.Context, d *schema.ResourceData, meta inte
d.Set("name", vault.Name),
d.Set("project_id", vault.ProjectID),
d.Set("provider_id", vault.ProviderID),
d.Set("resource", resourceList),
d.Set("resource", resourceInfo),
d.Set("tags", tagsMap),
d.Set("enterprise_project_id", vault.EnterpriseProjectID),
d.Set("auto_bind", vault.AutoBind),
Expand Down Expand Up @@ -367,37 +375,48 @@ func resourceCBRVaultV3Create(ctx context.Context, d *schema.ResourceData, meta
}

func resourceExtraMapToExtra(src map[string]interface{}) (*vaults.ResourceExtraInfo, error) {
var resExtra *vaults.ResourceExtraInfo
if src == nil {
return nil, nil
}
data, err := json.Marshal(src)
if err != nil {
return nil, err

rawExclude := src["exclude_volumes"].(*schema.Set).List()
exclude := make([]string, len(rawExclude))
for i, raw := range rawExclude {
exclude[i] = raw.(string)
}
extra := new(vaults.ResourceExtraInfo)
err = json.Unmarshal(data, extra)
if err != nil {
return nil, err

rawInclude := src["include_volumes"].(*schema.Set).List()
include := make([]vaults.ResourceExtraInfoIncludeVolumes, len(rawInclude))
for i, raw := range rawInclude {
include[i] = vaults.ResourceExtraInfoIncludeVolumes{
ID: raw.(string),
}
}
if len(exclude) != 0 || len(include) != 0 {
resExtra = &vaults.ResourceExtraInfo{
ExcludeVolumes: exclude,
IncludeVolumes: include,
}
}
return extra, nil
return resExtra, nil
}

func cbrVaultResourcesCreate(d *schema.ResourceData) (res []vaults.ResourceCreate, err error) {
resources := d.Get("resource").(*schema.Set)
res = make([]vaults.ResourceCreate, resources.Len())
for i, v := range resources.List() {
resource := v.(map[string]interface{})
rawExtra := resource["extra_info"].(map[string]interface{})
resourceID := resource["id"].(string)
extra, err := resourceExtraMapToExtra(rawExtra)
resExtra, err := resourceExtraMapToExtra(resource)
if err != nil {
return nil, fmt.Errorf("error converting \"%s\" resource extra: %v", resourceID, rawExtra)
return nil, err
}
res[i] = vaults.ResourceCreate{
ID: resourceID,
Type: resource["type"].(string),
Name: resource["name"].(string),
ExtraInfo: extra,
ExtraInfo: resExtra,
}
}
return
Expand Down Expand Up @@ -480,7 +499,6 @@ func cbrVaultTags(d *schema.ResourceData) []vaults.Tag {
func vaultAddedResources(d *schema.ResourceData) ([]vaults.ResourceCreate, error) {
oldR, newR := d.GetChange("resource")
addedSet := newR.(*schema.Set).Difference(oldR.(*schema.Set))

res := make([]vaults.ResourceCreate, addedSet.Len())
for i, v := range addedSet.List() {
newMap := v.(map[string]interface{})
Expand All @@ -489,14 +507,13 @@ func vaultAddedResources(d *schema.ResourceData) ([]vaults.ResourceCreate, error
Type: newMap["type"].(string),
Name: newMap["name"].(string),
}
extraMap, ok := newMap["extra"].(map[string]interface{})
if ok {
extra, err := resourceExtraMapToExtra(extraMap)
if err != nil {
return nil, err
}
newResource.ExtraInfo = extra

extra, err := resourceExtraMapToExtra(newMap)
if err != nil {
return nil, err
}

newResource.ExtraInfo = extra
res[i] = newResource
}
return res, nil
Expand Down
4 changes: 4 additions & 0 deletions releasenotes/notes/cbr-extra-bea81a63bd50d47a.yaml
@@ -0,0 +1,4 @@
---
fixes:
- |
**[CBR]** Add support of ``exclude_volumes`` and ``include_volumes`` for ``resource`` in ``resource/opentelekomcloud_cbr_vault_v3`` (`#1802 <https://github.com/opentelekomcloud/terraform-provider-opentelekomcloud/pull/1802>`_)