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

make subnet_id be optional and name be updatable for vip #648

Merged
merged 1 commit into from
Nov 10, 2020
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions docs/resources/networking_vip.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ subcategory: "Virtual Private Cloud (VPC)"
# huaweicloud\_networking\_vip

Manages a Vip resource within HuaweiCloud.
This is an alternative to `huaweicloud_networking_vip`
This is an alternative to `huaweicloud_networking_vip_v2`

## Example Usage

Expand All @@ -16,37 +16,36 @@ data "huaweicloud_vpc_subnet" "mynet" {

resource "huaweicloud_networking_vip" "myvip" {
network_id = data.huaweicloud_vpc_subnet.mynet.id
subnet_id = data.huaweicloud_vpc_subnet.mynet.subnet_id
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional) The region in which to obtain the vip resource. If omitted, the provider-level region will work as default. Changing this creates a new vip resource.
* `region` - (Optional, ForceNew) The region in which to obtain the vip resource.
If omitted, the provider-level region will work as default.

* `network_id` - (Required) The Network ID of the VPC subnet to attach the vip to.
Changing this creates a new vip.
* `network_id` - (Required, ForceNew) Specifies the ID of the network to which the vip belongs.

* `subnet_id` - (Required) Subnet in which to allocate IP address for this vip.
Changing this creates a new vip.
* `subnet_id` - (Optional, ForceNew) Specifies the subnet in which to allocate IP address for this vip.

* `ip_address` - (Optional) IP address desired in the subnet for this vip.
* `ip_address` - (Optional, ForceNew) Specifies the IP address desired in the subnet for this vip.
If you don't specify `ip_address`, an available IP address from
the specified subnet will be allocated to this vip.

* `name` - (Optional) A unique name for the vip.
* `name` - (Optional) Specifies a unique name for the vip.

## Attributes Reference

The following attributes are exported:

* `id` - The ID of the vip.
* `name` - See Argument Reference above.
* `network_id` - See Argument Reference above.
* `subnet_id` - See Argument Reference above.
* `ip_address` - See Argument Reference above.
* `name` - See Argument Reference above.
* `mac_address` - The MAC address of the vip.
* `status` - The status of vip.
* `id` - The ID of the vip.
* `tenant_id` - The tenant ID of the vip.
* `device_owner` - The device owner of the vip.
1 change: 0 additions & 1 deletion examples/vpc/vip/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ data "huaweicloud_networking_port" "port_1" {

resource "huaweicloud_networking_vip" "vip_1" {
network_id = huaweicloud_vpc_subnet.subnet_1.id
subnet_id = huaweicloud_vpc_subnet.subnet_1.subnet_id
}

# associate ports to the vip
Expand Down
75 changes: 64 additions & 11 deletions huaweicloud/resource_huaweicloud_networking_vip_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/openstack/networking/v1/subnets"
"github.com/huaweicloud/golangsdk/openstack/networking/v2/ports"
)

func resourceNetworkingVIPV2() *schema.Resource {
return &schema.Resource{
Create: resourceNetworkingVIPV2Create,
Read: resourceNetworkingVIPV2Read,
Update: resourceNetworkingVIPV2Update,
Delete: resourceNetworkingVIPV2Delete,

Schema: map[string]*schema.Schema{
Expand All @@ -31,12 +33,14 @@ func resourceNetworkingVIPV2() *schema.Resource {
},
"subnet_id": {
Type: schema.TypeString,
Required: true,
Optional: true,
ForceNew: true,
Computed: true,
},
"ip_address": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"name": {
Expand All @@ -56,30 +60,55 @@ func resourceNetworkingVIPV2() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceNetworkingVIPV2Create(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
networkingClient, err := config.NetworkingV2Client(GetRegion(d, config))
region := GetRegion(d, config)
networkingClient, err := config.NetworkingV2Client(region)
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud networking client: %s", err)
}

// Contruct CreateOpts
fixip := make([]ports.IP, 1)
fixip[0] = ports.IP{
SubnetID: d.Get("subnet_id").(string),
IPAddress: d.Get("ip_address").(string),
}
networkID := d.Get("network_id").(string)
createOpts := ports.CreateOpts{
Name: d.Get("name").(string),
NetworkID: d.Get("network_id").(string),
FixedIPs: fixip,
NetworkID: networkID,
DeviceOwner: "neutron:VIP_PORT",
}

// Contruct fixed ip
subnetID := d.Get("subnet_id").(string)
fixedIP := d.Get("ip_address").(string)
if subnetID != "" || fixedIP != "" {
vpcClient, err := config.NetworkingV1Client(region)
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC client: %s", err)
}

n, err := subnets.Get(vpcClient, networkID).Extract()
if err != nil {
return fmt.Errorf("Error retrieving Huaweicloud Subnet %s: %s", networkID, err)
}

if subnetID != "" && subnetID != n.SubnetId {
return fmt.Errorf("Error invalid value of subnet_id %s, expect to %s", subnetID, n.SubnetId)
}

fixip := make([]ports.IP, 1)
fixip[0] = ports.IP{
SubnetID: n.SubnetId,
IPAddress: fixedIP,
}
createOpts.FixedIPs = fixip
}

log.Printf("[DEBUG] Create Options: %#v", createOpts)
vip, err := ports.Create(networkingClient, createOpts).Extract()
if err != nil {
Expand Down Expand Up @@ -116,6 +145,7 @@ func resourceNetworkingVIPV2Read(d *schema.ResourceData, meta interface{}) error

log.Printf("[DEBUG] Retrieved VIP %s: %+v", d.Id(), vip)

d.SetId(vip.ID)
// Computed values
d.Set("network_id", vip.NetworkID)
if len(vip.FixedIPs) > 0 {
Expand All @@ -125,15 +155,38 @@ func resourceNetworkingVIPV2Read(d *schema.ResourceData, meta interface{}) error
d.Set("subnet_id", "")
d.Set("ip_address", "")
}

d.Set("name", vip.Name)
d.Set("status", vip.Status)
d.SetId(vip.ID)
d.Set("tenant_id", vip.TenantID)
d.Set("device_owner", vip.DeviceOwner)
d.Set("mac_address", vip.MACAddress)

return nil
}

func resourceNetworkingVIPV2Update(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
networkingClient, err := config.NetworkingV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud networking client: %s", err)
}

if d.HasChange("name") {
updateOpts := ports.UpdateOpts{
Name: d.Get("name").(string),
}
log.Printf("[DEBUG] Updating networking vip %s with options: %#v", d.Id(), updateOpts)

_, err = ports.Update(networkingClient, d.Id(), updateOpts).Extract()
if err != nil {
return fmt.Errorf("Error updating HuaweiCloud networking vip: %s", err)
}
}

return resourceNetworkingVIPV2Read(d, meta)
}

func resourceNetworkingVIPV2Delete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
networkingClient, err := config.NetworkingV2Client(GetRegion(d, config))
Expand Down
67 changes: 45 additions & 22 deletions huaweicloud/resource_huaweicloud_networking_vip_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"log"
"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/networking/v2/ports"
)

func TestAccNetworkingV2VIP_basic(t *testing.T) {
rand := acctest.RandString(5)
resourceName := "huaweicloud_networking_vip.vip_1"
var vip ports.Port

resource.Test(t, resource.TestCase{
Expand All @@ -19,9 +22,16 @@ func TestAccNetworkingV2VIP_basic(t *testing.T) {
CheckDestroy: testAccCheckNetworkingV2VIPDestroy,
Steps: []resource.TestStep{
{
Config: TestAccNetworkingV2VIPConfig_basic,
Config: testAccNetworkingV2VIPConfig_basic(rand),
Check: resource.ComposeTestCheckFunc(
testAccCheckNetworkingV2VIPExists("huaweicloud_networking_vip_v2.vip_1", &vip),
testAccCheckNetworkingV2VIPExists(resourceName, &vip),
resource.TestCheckResourceAttr(resourceName, "name", "acc-test-vip"),
),
},
{
Config: testAccNetworkingV2VIPConfig_update(rand),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "acc-test-vip-updated"),
),
},
},
Expand All @@ -36,7 +46,7 @@ func testAccCheckNetworkingV2VIPDestroy(s *terraform.State) error {
}

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

Expand Down Expand Up @@ -83,31 +93,44 @@ func testAccCheckNetworkingV2VIPExists(n string, vip *ports.Port) resource.TestC
}
}

var TestAccNetworkingV2VIPConfig_basic = fmt.Sprintf(`
resource "huaweicloud_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
func testAccNetworkingV2VIPConfig_basic(rand string) string {
return fmt.Sprintf(`
resource "huaweicloud_vpc" "vpc_1" {
name = "acc-test-vpc-%s"
cidr = "192.168.0.0/16"
}

resource "huaweicloud_networking_subnet_v2" "subnet_1" {
name = "subnet_1"
cidr = "192.168.199.0/24"
ip_version = 4
network_id = "${huaweicloud_networking_network_v2.network_1.id}"
resource "huaweicloud_vpc_subnet" "subnet_1" {
vpc_id = huaweicloud_vpc.vpc_1.id
name = "acc-test-subnet-%s"
cidr = "192.168.0.0/24"
gateway_ip = "192.168.0.1"
}

resource "huaweicloud_networking_router_interface_v2" "router_interface_1" {
router_id = "${huaweicloud_networking_router_v2.router_1.id}"
subnet_id = "${huaweicloud_networking_subnet_v2.subnet_1.id}"
resource "huaweicloud_networking_vip" "vip_1" {
name = "acc-test-vip"
network_id = huaweicloud_vpc_subnet.subnet_1.id
}
`, rand, rand)
}

func testAccNetworkingV2VIPConfig_update(rand string) string {
return fmt.Sprintf(`
resource "huaweicloud_vpc" "vpc_1" {
name = "acc-test-vpc-%s"
cidr = "192.168.0.0/16"
}

resource "huaweicloud_networking_router_v2" "router_1" {
name = "router_1"
external_network_id = "%s"
resource "huaweicloud_vpc_subnet" "subnet_1" {
vpc_id = huaweicloud_vpc.vpc_1.id
name = "acc-test-subnet-%s"
cidr = "192.168.0.0/24"
gateway_ip = "192.168.0.1"
}

resource "huaweicloud_networking_vip_v2" "vip_1" {
network_id = "${huaweicloud_networking_network_v2.network_1.id}"
subnet_id = "${huaweicloud_networking_subnet_v2.subnet_1.id}"
resource "huaweicloud_networking_vip" "vip_1" {
name = "acc-test-vip-updated"
network_id = huaweicloud_vpc_subnet.subnet_1.id
}
`, rand, rand)
}
`, OS_EXTGW_ID)