Skip to content

Commit 633ba77

Browse files
committed
Add support for cloudstack_physicalnetwork data source and resource
- Implement data source for cloudstack_physicalnetwork to retrieve physical network details. - Create resource for managing cloudstack_physicalnetwork, including CRUD operations. - Add tests for both data source and resource functionalities. - Update documentation for cloudstack_physicalnetwork data source and resource.
1 parent edb0901 commit 633ba77

7 files changed

+644
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package cloudstack
21+
22+
import (
23+
"encoding/json"
24+
"fmt"
25+
"log"
26+
"regexp"
27+
"strings"
28+
29+
"github.com/apache/cloudstack-go/v2/cloudstack"
30+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
31+
)
32+
33+
func dataSourceCloudStackPhysicalNetwork() *schema.Resource {
34+
return &schema.Resource{
35+
Read: dataSourceCloudStackPhysicalNetworkRead,
36+
Schema: map[string]*schema.Schema{
37+
"filter": dataSourceFiltersSchema(),
38+
39+
//Computed values
40+
"name": {
41+
Type: schema.TypeString,
42+
Computed: true,
43+
},
44+
"zone": {
45+
Type: schema.TypeString,
46+
Computed: true,
47+
},
48+
"broadcast_domain_range": {
49+
Type: schema.TypeString,
50+
Computed: true,
51+
},
52+
"isolation_methods": {
53+
Type: schema.TypeList,
54+
Computed: true,
55+
Elem: &schema.Schema{Type: schema.TypeString},
56+
},
57+
"network_speed": {
58+
Type: schema.TypeString,
59+
Computed: true,
60+
},
61+
"vlan": {
62+
Type: schema.TypeString,
63+
Computed: true,
64+
},
65+
},
66+
}
67+
}
68+
69+
func dataSourceCloudStackPhysicalNetworkRead(d *schema.ResourceData, meta interface{}) error {
70+
cs := meta.(*cloudstack.CloudStackClient)
71+
p := cs.Network.NewListPhysicalNetworksParams()
72+
physicalNetworks, err := cs.Network.ListPhysicalNetworks(p)
73+
74+
if err != nil {
75+
return fmt.Errorf("Failed to list physical networks: %s", err)
76+
}
77+
filters := d.Get("filter")
78+
var physicalNetwork *cloudstack.PhysicalNetwork
79+
80+
for _, pn := range physicalNetworks.PhysicalNetworks {
81+
match, err := applyPhysicalNetworkFilters(pn, filters.(*schema.Set))
82+
if err != nil {
83+
return err
84+
}
85+
if match {
86+
physicalNetwork = pn
87+
}
88+
}
89+
90+
if physicalNetwork == nil {
91+
return fmt.Errorf("No physical network is matching with the specified regex")
92+
}
93+
log.Printf("[DEBUG] Selected physical network: %s\n", physicalNetwork.Name)
94+
95+
return physicalNetworkDescriptionAttributes(d, physicalNetwork)
96+
}
97+
98+
func physicalNetworkDescriptionAttributes(d *schema.ResourceData, physicalNetwork *cloudstack.PhysicalNetwork) error {
99+
d.SetId(physicalNetwork.Id)
100+
d.Set("name", physicalNetwork.Name)
101+
d.Set("broadcast_domain_range", physicalNetwork.Broadcastdomainrange)
102+
d.Set("network_speed", physicalNetwork.Networkspeed)
103+
d.Set("vlan", physicalNetwork.Vlan)
104+
105+
// Set isolation methods
106+
if physicalNetwork.Isolationmethods != "" {
107+
methods := strings.Split(physicalNetwork.Isolationmethods, ",")
108+
d.Set("isolation_methods", methods)
109+
}
110+
111+
// Set the zone
112+
d.Set("zone", physicalNetwork.Zonename)
113+
114+
// Physical networks don't support tags in CloudStack API
115+
116+
return nil
117+
}
118+
119+
func applyPhysicalNetworkFilters(physicalNetwork *cloudstack.PhysicalNetwork, filters *schema.Set) (bool, error) {
120+
var physicalNetworkJSON map[string]interface{}
121+
k, _ := json.Marshal(physicalNetwork)
122+
err := json.Unmarshal(k, &physicalNetworkJSON)
123+
if err != nil {
124+
return false, err
125+
}
126+
127+
for _, f := range filters.List() {
128+
m := f.(map[string]interface{})
129+
r, err := regexp.Compile(m["value"].(string))
130+
if err != nil {
131+
return false, fmt.Errorf("Invalid regex: %s", err)
132+
}
133+
updatedName := strings.ReplaceAll(m["name"].(string), "_", "")
134+
physicalNetworkField := physicalNetworkJSON[updatedName].(string)
135+
if !r.MatchString(physicalNetworkField) {
136+
return false, nil
137+
}
138+
}
139+
return true, nil
140+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package cloudstack
21+
22+
import (
23+
"testing"
24+
25+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
26+
)
27+
28+
func TestAccDataSourceCloudStackPhysicalNetwork_basic(t *testing.T) {
29+
resource.Test(t, resource.TestCase{
30+
PreCheck: func() { testAccPreCheck(t) },
31+
Providers: testAccProviders,
32+
Steps: []resource.TestStep{
33+
{
34+
Config: testAccDataSourceCloudStackPhysicalNetwork_basic,
35+
Check: resource.ComposeTestCheckFunc(
36+
resource.TestCheckResourceAttr(
37+
"data.cloudstack_physicalnetwork.foo", "name", "terraform-physical-network"),
38+
resource.TestCheckResourceAttr(
39+
"data.cloudstack_physicalnetwork.foo", "broadcast_domain_range", "ZONE"),
40+
),
41+
},
42+
},
43+
})
44+
}
45+
46+
const testAccDataSourceCloudStackPhysicalNetwork_basic = `
47+
resource "cloudstack_zone" "foo" {
48+
name = "terraform-zone-ds"
49+
dns1 = "8.8.8.8"
50+
internal_dns1 = "8.8.4.4"
51+
network_type = "Advanced"
52+
}
53+
54+
resource "cloudstack_physicalnetwork" "foo" {
55+
name = "terraform-physical-network"
56+
zone = cloudstack_zone.foo.name
57+
broadcast_domain_range = "ZONE"
58+
isolation_methods = ["VLAN"]
59+
}
60+
61+
data "cloudstack_physicalnetwork" "foo" {
62+
filter {
63+
name = "name"
64+
value = "terraform-physical-network"
65+
}
66+
depends_on = [cloudstack_physicalnetwork.foo]
67+
}`

cloudstack/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ func Provider() *schema.Provider {
9090
"cloudstack_user": dataSourceCloudstackUser(),
9191
"cloudstack_vpn_connection": dataSourceCloudstackVPNConnection(),
9292
"cloudstack_pod": dataSourceCloudstackPod(),
93+
"cloudstack_physicalnetwork": dataSourceCloudStackPhysicalNetwork(),
9394
},
9495

9596
ResourcesMap: map[string]*schema.Resource{
@@ -131,6 +132,7 @@ func Provider() *schema.Provider {
131132
"cloudstack_account": resourceCloudStackAccount(),
132133
"cloudstack_user": resourceCloudStackUser(),
133134
"cloudstack_domain": resourceCloudStackDomain(),
135+
"cloudstack_physicalnetwork": resourceCloudStackPhysicalNetwork(),
134136
},
135137

136138
ConfigureFunc: providerConfigure,

0 commit comments

Comments
 (0)