Skip to content

Commit

Permalink
Merge pull request #152 from niuzhenguo/add-port-data-source
Browse files Browse the repository at this point in the history
Add networking_port data source
  • Loading branch information
niuzhenguo authored Jun 19, 2019
2 parents 4f6fbee + cfb1917 commit 63fe163
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 0 deletions.
237 changes: 237 additions & 0 deletions huaweicloud/data_source_huaweicloud_networking_port_v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package huaweicloud

import (
"fmt"
"log"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"

"github.com/huaweicloud/golangsdk/openstack/networking/v2/ports"
)

func dataSourceNetworkingPortV2() *schema.Resource {
return &schema.Resource{
Read: dataSourceNetworkingPortV2Read,

Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
},

"port_id": {
Type: schema.TypeString,
Optional: true,
},

"name": {
Type: schema.TypeString,
Optional: true,
},

"admin_state_up": {
Type: schema.TypeBool,
Optional: true,
},

"network_id": {
Type: schema.TypeString,
Optional: true,
},

"tenant_id": {
Type: schema.TypeString,
Optional: true,
},

"project_id": {
Type: schema.TypeString,
Optional: true,
},

"device_owner": {
Type: schema.TypeString,
Optional: true,
},

"mac_address": {
Type: schema.TypeString,
Optional: true,
},

"device_id": {
Type: schema.TypeString,
Optional: true,
},

"fixed_ip": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.SingleIP(),
},

"status": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"all_fixed_ips": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"all_security_group_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}

func dataSourceNetworkingPortV2Read(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)
}

listOpts := ports.ListOpts{}

if v, ok := d.GetOk("port_id"); ok {
listOpts.ID = v.(string)
}

if v, ok := d.GetOk("name"); ok {
listOpts.Name = v.(string)
}

if v, ok := d.GetOkExists("admin_state_up"); ok {
asu := v.(bool)
listOpts.AdminStateUp = &asu
}

if v, ok := d.GetOk("network_id"); ok {
listOpts.NetworkID = v.(string)
}

if v, ok := d.GetOk("status"); ok {
listOpts.Status = v.(string)
}

if v, ok := d.GetOk("tenant_id"); ok {
listOpts.TenantID = v.(string)
}

if v, ok := d.GetOk("project_id"); ok {
listOpts.ProjectID = v.(string)
}

if v, ok := d.GetOk("device_owner"); ok {
listOpts.DeviceOwner = v.(string)
}

if v, ok := d.GetOk("mac_address"); ok {
listOpts.MACAddress = v.(string)
}

if v, ok := d.GetOk("device_id"); ok {
listOpts.DeviceID = v.(string)
}

allPages, err := ports.List(networkingClient, listOpts).AllPages()
if err != nil {
return fmt.Errorf("Unable to list huaweicloud_networking_ports_v2: %s", err)
}

var allPorts []ports.Port

err = ports.ExtractPortsInto(allPages, &allPorts)
if err != nil {
return fmt.Errorf("Unable to retrieve huaweicloud_networking_ports_v2: %s", err)
}

if len(allPorts) == 0 {
return fmt.Errorf("No huaweicloud_networking_port_v2 found")
}

var portsList []ports.Port

// Filter returned Fixed IPs by a "fixed_ip".
if v, ok := d.GetOk("fixed_ip"); ok {
for _, p := range allPorts {
for _, ipObject := range p.FixedIPs {
if v.(string) == ipObject.IPAddress {
portsList = append(portsList, p)
}
}
}
if len(portsList) == 0 {
log.Printf("No huaweicloud_networking_port_v2 found after the 'fixed_ip' filter")
return fmt.Errorf("No huaweicloud_networking_port_v2 found")
}
} else {
portsList = allPorts
}

securityGroups := expandToStringSlice(d.Get("security_group_ids").(*schema.Set).List())
if len(securityGroups) > 0 {
var sgPorts []ports.Port
for _, p := range portsList {
for _, sg := range p.SecurityGroups {
if strSliceContains(securityGroups, sg) {
sgPorts = append(sgPorts, p)
}
}
}
if len(sgPorts) == 0 {
log.Printf("[DEBUG] No huaweicloud_networking_port_v2 found after the 'security_group_ids' filter")
return fmt.Errorf("No huaweicloud_networking_port_v2 found")
}
portsList = sgPorts
}

if len(portsList) > 1 {
return fmt.Errorf("More than one huaweicloud_networking_port_v2 found (%d)", len(portsList))
}

port := portsList[0]

log.Printf("[DEBUG] Retrieved huaweicloud_networking_port_v2 %s: %+v", port.ID, port)
d.SetId(port.ID)

d.Set("port_id", port.ID)
d.Set("name", port.Name)
d.Set("admin_state_up", port.AdminStateUp)
d.Set("network_id", port.NetworkID)
d.Set("tenant_id", port.TenantID)
d.Set("project_id", port.ProjectID)
d.Set("device_owner", port.DeviceOwner)
d.Set("mac_address", port.MACAddress)
d.Set("device_id", port.DeviceID)
d.Set("region", GetRegion(d, config))
d.Set("all_security_group_ids", port.SecurityGroups)
d.Set("all_fixed_ips", expandNetworkingPortFixedIPToStringSlice(port.FixedIPs))

return nil
}

func expandNetworkingPortFixedIPToStringSlice(fixedIPs []ports.IP) []string {
s := make([]string, len(fixedIPs))
for i, fixedIP := range fixedIPs {
s[i] = fixedIP.IPAddress
}

return s
}
93 changes: 93 additions & 0 deletions huaweicloud/data_source_huaweicloud_networking_port_v2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package huaweicloud

import (
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccNetworkingV2PortDataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckNetworkingV2PortDestroy,
Steps: []resource.TestStep{
{
Config: testAccNetworkingV2PortDataSource_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(
"data.huaweicloud_networking_port_v2.port_1", "id",
"huaweicloud_networking_port_v2.port_1", "id"),
resource.TestCheckResourceAttrPair(
"data.huaweicloud_networking_port_v2.port_2", "id",
"huaweicloud_networking_port_v2.port_2", "id"),
resource.TestCheckResourceAttrPair(
"data.huaweicloud_networking_port_v2.port_3", "id",
"huaweicloud_networking_port_v2.port_1", "id"),
resource.TestCheckResourceAttr(
"data.huaweicloud_networking_port_v2.port_3", "all_fixed_ips.#", "1"),
),
},
},
})
}

const testAccNetworkingV2PortDataSource_basic = `
resource "huaweicloud_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
}
resource "huaweicloud_networking_subnet_v2" "subnet_1" {
name = "subnet_1"
network_id = "${huaweicloud_networking_network_v2.network_1.id}"
cidr = "10.0.0.0/24"
ip_version = 4
}
data "huaweicloud_networking_secgroup_v2" "default" {
name = "default"
}
resource "huaweicloud_networking_port_v2" "port_1" {
name = "port_1"
network_id = "${huaweicloud_networking_network_v2.network_1.id}"
admin_state_up = "true"
security_group_ids = [
"${data.huaweicloud_networking_secgroup_v2.default.id}",
]
fixed_ip {
subnet_id = "${huaweicloud_networking_subnet_v2.subnet_1.id}"
}
}
resource "huaweicloud_networking_port_v2" "port_2" {
name = "port_2"
network_id = "${huaweicloud_networking_network_v2.network_1.id}"
admin_state_up = "true"
security_group_ids = [
"${data.huaweicloud_networking_secgroup_v2.default.id}",
]
}
data "huaweicloud_networking_port_v2" "port_1" {
name = "${huaweicloud_networking_port_v2.port_1.name}"
admin_state_up = "${huaweicloud_networking_port_v2.port_1.admin_state_up}"
security_group_ids = [
"${data.huaweicloud_networking_secgroup_v2.default.id}",
]
}
data "huaweicloud_networking_port_v2" "port_2" {
name = "${huaweicloud_networking_port_v2.port_2.name}"
admin_state_up = "${huaweicloud_networking_port_v2.port_2.admin_state_up}"
}
data "huaweicloud_networking_port_v2" "port_3" {
fixed_ip = "${huaweicloud_networking_port_v2.port_1.all_fixed_ips.0}"
}
`
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ func Provider() terraform.ResourceProvider {
"huaweicloud_images_image_v2": dataSourceImagesImageV2(),
"huaweicloud_networking_network_v2": dataSourceNetworkingNetworkV2(),
"huaweicloud_networking_subnet_v2": dataSourceNetworkingSubnetV2(),
"huaweicloud_networking_port_v2": dataSourceNetworkingPortV2(),
"huaweicloud_networking_secgroup_v2": dataSourceNetworkingSecGroupV2(),
"huaweicloud_s3_bucket_object": dataSourceS3BucketObject(),
"huaweicloud_kms_key_v1": dataSourceKmsKeyV1(),
Expand Down
11 changes: 11 additions & 0 deletions huaweicloud/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ func resourceNetworkingAvailabilityZoneHintsV2(d *schema.ResourceData) []string
return azh
}

func expandToStringSlice(v []interface{}) []string {
s := make([]string, len(v))
for i, val := range v {
if strVal, ok := val.(string); ok {
s[i] = strVal
}
}

return s
}

// strSliceContains checks if a given string is contained in a slice
// When anybody asks why Go needs generics, here you go.
func strSliceContains(haystack []string, needle string) bool {
Expand Down
Loading

0 comments on commit 63fe163

Please sign in to comment.