Skip to content
Open
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
230 changes: 230 additions & 0 deletions cloudstack/data_source_cloudstack_network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//

package cloudstack

import (
"encoding/json"
"fmt"
"log"
"regexp"
"strings"
"time"

"github.com/apache/cloudstack-go/v2/cloudstack"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceCloudstackNetwork() *schema.Resource {
return &schema.Resource{
Read: datasourceCloudStackNetworkRead,
Schema: map[string]*schema.Schema{
"filter": dataSourceFiltersSchema(),

// Computed values
"name": {
Type: schema.TypeString,
Computed: true,
},

"display_text": {
Type: schema.TypeString,
Computed: true,
},

"cidr": {
Type: schema.TypeString,
Computed: true,
},

"gateway": {
Type: schema.TypeString,
Computed: true,
},

"network_domain": {
Type: schema.TypeString,
Computed: true,
},

"network_offering_id": {
Type: schema.TypeString,
Computed: true,
},

"network_offering_name": {
Type: schema.TypeString,
Computed: true,
},

"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

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

"vpc_id": {
Type: schema.TypeString,
Computed: true,
},

"acl_id": {
Type: schema.TypeString,
Computed: true,
},

"zone_id": {
Type: schema.TypeString,
Computed: true,
},

"zone_name": {
Type: schema.TypeString,
Computed: true,
},

"state": {
Type: schema.TypeString,
Computed: true,
},

"type": {
Type: schema.TypeString,
Computed: true,
},

"traffic_type": {
Type: schema.TypeString,
Computed: true,
},

"tags": tagsSchema(),
},
}
}

func datasourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) error {
cs := meta.(*cloudstack.CloudStackClient)
p := cs.Network.NewListNetworksParams()

if err := setProjectid(p, cs, d); err != nil {
return err
}

csNetworks, err := cs.Network.ListNetworks(p)
if err != nil {
return fmt.Errorf("Failed to list networks: %s", err)
}

filters := d.Get("filter")
var networks []*cloudstack.Network

for _, n := range csNetworks.Networks {
match, err := applyNetworkFilters(n, filters.(*schema.Set))
if err != nil {
return err
}
if match {
networks = append(networks, n)
}
}

if len(networks) == 0 {
return fmt.Errorf("No network is matching with the specified regex")
}

network, err := latestNetwork(networks)
if err != nil {
return err
}
log.Printf("[DEBUG] Selected network: %s\n", network.Name)

return networkDescriptionAttributes(d, network)
}

func networkDescriptionAttributes(d *schema.ResourceData, network *cloudstack.Network) error {
d.SetId(network.Id)
d.Set("name", network.Name)
d.Set("display_text", network.Displaytext)
d.Set("cidr", network.Cidr)
d.Set("gateway", network.Gateway)
d.Set("network_domain", network.Networkdomain)
d.Set("network_offering_id", network.Networkofferingid)
d.Set("network_offering_name", network.Networkofferingname)
d.Set("project", network.Project)
d.Set("project_id", network.Projectid)
d.Set("vpc_id", network.Vpcid)
d.Set("acl_id", network.Aclid)
d.Set("zone_id", network.Zoneid)
d.Set("zone_name", network.Zonename)
d.Set("state", network.State)
d.Set("type", network.Type)
d.Set("traffic_type", network.Traffictype)
d.Set("tags", tagsToMap(network.Tags))

return nil
}

func latestNetwork(networks []*cloudstack.Network) (*cloudstack.Network, error) {
var latest time.Time
var network *cloudstack.Network

for _, n := range networks {
created, err := time.Parse("2006-01-02T15:04:05-0700", n.Created)
if err != nil {
return nil, fmt.Errorf("Failed to parse creation date of a network: %s", err)
}

if created.After(latest) {
latest = created
network = n
}
}

return network, nil
}

func applyNetworkFilters(network *cloudstack.Network, filters *schema.Set) (bool, error) {
var networkJSON map[string]interface{}
k, _ := json.Marshal(network)
err := json.Unmarshal(k, &networkJSON)
if err != nil {
return false, err
}

for _, f := range filters.List() {
m := f.(map[string]interface{})
r, err := regexp.Compile(m["value"].(string))
if err != nil {
return false, fmt.Errorf("Invalid regex: %s", err)
}
updatedName := strings.ReplaceAll(m["name"].(string), "_", "")
networkField := fmt.Sprintf("%v", networkJSON[updatedName])
if !r.MatchString(networkField) {
return false, nil
}
}

return true, nil
}
77 changes: 77 additions & 0 deletions cloudstack/data_source_cloudstack_network_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//

package cloudstack

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccNetworkDataSource_basic(t *testing.T) {
resourceName := "cloudstack_network.network-resource"
datasourceName := "data.cloudstack_network.network-data-source"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testNetworkDataSourceConfig_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(datasourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(datasourceName, "display_text", resourceName, "display_text"),
resource.TestCheckResourceAttrPair(datasourceName, "cidr", resourceName, "cidr"),
resource.TestCheckResourceAttrPair(datasourceName, "network_offering_name", resourceName, "network_offering"),
),
},
},
})
}

const testNetworkDataSourceConfig_basic = `
resource "cloudstack_network" "network-resource" {
name = "terraform-network"
display_text = "terraform-network"
cidr = "10.1.1.0/24"
network_offering = "DefaultIsolatedNetworkOfferingWithSourceNatService"
zone = "Sandbox-simulator"
}

data "cloudstack_network" "network-data-source" {
filter {
name = "name"
value = "terraform-network"
}

filter {
name = "cidr"
value = "10.1.1.0/24"
}

depends_on = [
cloudstack_network.network-resource
]
}

output "network-output" {
value = data.cloudstack_network.network-data-source
}
`
1 change: 1 addition & 0 deletions cloudstack/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func Provider() *schema.Provider {
"cloudstack_security_group": dataSourceCloudstackSecurityGroup(),
"cloudstack_vgpu_profile": dataSourceCloudstackVgpuProfile(),
"cloudstack_gpu_card": dataSourceCloudstackGpuCard(),
"cloudstack_network": dataSourceCloudstackNetwork(),
},

ResourcesMap: map[string]*schema.Resource{
Expand Down
3 changes: 3 additions & 0 deletions website/cloudstack.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<li<%= sidebar_current("docs-cloudstack-datasource-role") %>>
<a href="/docs/providers/cloudstack/d/role.html">cloudstack_role</a>
</li>
<li<%= sidebar_current("docs-cloudstack-datasource-network") %>>
<a href="/docs/providers/cloudstack/d/network.html">cloudstack_network</a>
</li>
</ul>
</li>

Expand Down
54 changes: 54 additions & 0 deletions website/docs/d/network.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
layout: "cloudstack"
page_title: "Cloudstack: cloudstack_network"
sidebar_current: "docs-cloudstack-datasource-network"
description: |-
Gets information about a CloudStack network.
---

# cloudstack_network

Use this datasource to get information about a network for use in other resources.

### Example Usage

```hcl
data "cloudstack_network" "network-data-source" {
filter {
name = "name"
value = "test-network"
}

filter {
name = "cidr"
value = "10.1.1.0/24"
}
}
```

### Argument Reference

* `filter` - (Required) One or more name/value pairs to filter off of. You can apply filters on any exported attributes.
* `project` - (Optional) The name or ID of the project the network belongs to.

## Attributes Reference

The following attributes are exported:

* `name` - The name of the network.
* `display_text` - An alternate display text of the network.
* `cidr` - The CIDR block of the network.
* `gateway` - The gateway of the network.
* `network_domain` - The network domain of the network.
* `network_offering_id` - The ID of the network offering used by the network.
* `network_offering_name` - The name of the network offering used by the network.
* `project` - The project name of the network.
* `project_id` - The project ID of the network.
* `vpc_id` - The VPC ID the network belongs to.
* `acl_id` - The ACL ID attached to the network.
* `zone_id` - The ID of the zone the network belongs to.
* `zone_name` - The name of the zone the network belongs to.
* `state` - The state of the network.
* `type` - The type of the network.
* `traffic_type` - The traffic type of the network.
* `tags` - The tags assigned to the network.