Skip to content

Commit 76b8e56

Browse files
authored
Implement new stackit_network resource and datasource (#366)
* Copy file from DNS zone resource * Implement resource * Implement datasource * Add examples * Implement acceptance test; Some fixes * Add docs * Fix linter * Fixes after review
1 parent 940b15e commit 76b8e56

14 files changed

Lines changed: 1216 additions & 4 deletions

File tree

docs/data-sources/network.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_network Data Source - stackit"
4+
subcategory: ""
5+
description: |-
6+
Network resource schema. Must have a region specified in the provider configuration.
7+
---
8+
9+
# stackit_network (Data Source)
10+
11+
Network resource schema. Must have a `region` specified in the provider configuration.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "stackit_network" "example" {
17+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
18+
network_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
19+
}
20+
```
21+
22+
<!-- schema generated by tfplugindocs -->
23+
## Schema
24+
25+
### Required
26+
27+
- `network_id` (String) The network ID.
28+
- `project_id` (String) STACKIT project ID to which the network is associated.
29+
30+
### Read-Only
31+
32+
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`network_id`".
33+
- `ipv4_prefix_length` (Number) The IPv4 prefix length of the network.
34+
- `name` (String) The name of the network.
35+
- `nameservers` (List of String) The nameservers of the network.
36+
- `prefixes` (List of String) The prefixes of the network.
37+
- `public_ip` (String) The public IP of the network.

docs/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
143143
- `argus_custom_endpoint` (String) Custom endpoint for the Argus service
144144
- `credentials_path` (String) Path of JSON from where the credentials are read. Takes precedence over the env var `STACKIT_CREDENTIALS_PATH`. Default value is `~/.stackit/credentials.json`.
145145
- `dns_custom_endpoint` (String) Custom endpoint for the DNS service
146+
- `iaas_custom_endpoint` (String) Custom endpoint for the IaaS service
146147
- `jwks_custom_endpoint` (String, Deprecated) Custom endpoint for the jwks API, which is used to get the json web key sets (jwks) to validate tokens when using the key flow
147148
- `loadbalancer_custom_endpoint` (String) Custom endpoint for the Load Balancer service
148149
- `logme_custom_endpoint` (String) Custom endpoint for the LogMe service
@@ -155,7 +156,7 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
155156
- `private_key` (String) Private RSA key used for authentication, relevant for the key flow. It takes precedence over the private key that is included in the service account key.
156157
- `private_key_path` (String) Path for the private RSA key used for authentication, relevant for the key flow. It takes precedence over the private key that is included in the service account key.
157158
- `rabbitmq_custom_endpoint` (String) Custom endpoint for the RabbitMQ service
158-
- `redis_custom_endpoint` (String)
159+
- `redis_custom_endpoint` (String) Custom endpoint for the Redis service
159160
- `region` (String) Region will be used as the default location for regional services. Not all services require a region, some are global
160161
- `resourcemanager_custom_endpoint` (String) Custom endpoint for the Resource Manager service
161162
- `secretsmanager_custom_endpoint` (String) Custom endpoint for the Secrets Manager service

docs/resources/network.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_network Resource - stackit"
4+
subcategory: ""
5+
description: |-
6+
Network resource schema. Must have a region specified in the provider configuration.
7+
---
8+
9+
# stackit_network (Resource)
10+
11+
Network resource schema. Must have a `region` specified in the provider configuration.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "stackit_network" "example" {
17+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
18+
name = "example-network"
19+
nameservers = ["1.2.3.4", "5.6.7.8"]
20+
ipv4_prefix_length = 24
21+
}
22+
```
23+
24+
<!-- schema generated by tfplugindocs -->
25+
## Schema
26+
27+
### Required
28+
29+
- `name` (String) The name of the network.
30+
- `nameservers` (List of String) The nameservers of the network.
31+
- `project_id` (String) STACKIT project ID to which the network is associated.
32+
33+
### Optional
34+
35+
- `ipv4_prefix_length` (Number) The IPv4 prefix length of the network.
36+
37+
### Read-Only
38+
39+
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`network_id`".
40+
- `network_id` (String) The network ID.
41+
- `prefixes` (List of String) The prefixes of the network.
42+
- `public_ip` (String) The public IP of the network.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data "stackit_network" "example" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
network_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
4+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resource "stackit_network" "example" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
name = "example-network"
4+
nameservers = ["1.2.3.4", "5.6.7.8"]
5+
ipv4_prefix_length = 24
6+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/stackitcloud/stackit-sdk-go/core v0.12.0
1515
github.com/stackitcloud/stackit-sdk-go/services/argus v0.10.0
1616
github.com/stackitcloud/stackit-sdk-go/services/dns v0.9.1
17+
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.3.0
1718
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.12.0
1819
github.com/stackitcloud/stackit-sdk-go/services/logme v0.14.0
1920
github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.14.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ github.com/stackitcloud/stackit-sdk-go/services/argus v0.10.0 h1:FAYOt6UBy/F2jPH
152152
github.com/stackitcloud/stackit-sdk-go/services/argus v0.10.0/go.mod h1:nVllQfYODhX1q3bgwVTLO7wHOp+8NMLiKbn3u/Dg5nU=
153153
github.com/stackitcloud/stackit-sdk-go/services/dns v0.9.1 h1:pj2nAJvgzFSckA56rCPdi7StXGrr06go8qejI1weNJ8=
154154
github.com/stackitcloud/stackit-sdk-go/services/dns v0.9.1/go.mod h1:MdZcRbs19s2NLeJmSLSoqTzm9IPIQhE1ZEMpo9gePq0=
155+
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.3.0 h1:0Nb7CruTyM/HxhZQjntQUHJqwCoKjFUC9KZcBBj+c5c=
156+
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.3.0/go.mod h1:XtJA9FMK/yJ0dj4HtRAogmZPRUsZiFcuwUSfHYNASjo=
155157
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.12.0 h1:LAteZO46XmqTsmPw0QV8n8WiGM205pxrcqHqWznNmyY=
156158
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.12.0/go.mod h1:wsO3+vXe1XiKLeCIctWAptaHQZ07Un7kmLTQ+drbj7w=
157159
github.com/stackitcloud/stackit-sdk-go/services/logme v0.14.0 h1:vvQFCN5sKZA9tdzrbDnAVMsaTijX8lvTYnPaKQHmkoI=

stackit/internal/core/core.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type ProviderData struct {
1919
Region string
2020
ArgusCustomEndpoint string
2121
DnsCustomEndpoint string
22+
IaaSCustomEndpoint string
2223
LoadBalancerCustomEndpoint string
2324
LogMeCustomEndpoint string
2425
MariaDBCustomEndpoint string
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package iaas_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-testing/terraform"
12+
"github.com/stackitcloud/stackit-sdk-go/core/config"
13+
"github.com/stackitcloud/stackit-sdk-go/core/utils"
14+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
15+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
16+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
17+
)
18+
19+
// Network resource data
20+
var networkResource = map[string]string{
21+
"project_id": testutil.ProjectId,
22+
"name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)),
23+
"ipv4_prefix_length": "24",
24+
"nameserver0": "1.2.3.4",
25+
"nameserver1": "5.6.7.8",
26+
}
27+
28+
func resourceConfig(name, nameservers string) string {
29+
return fmt.Sprintf(`
30+
%s
31+
32+
resource "stackit_network" "network" {
33+
project_id = "%s"
34+
name = "%s"
35+
ipv4_prefix_length = "%s"
36+
nameservers = %s
37+
}
38+
`,
39+
testutil.IaaSProviderConfig(),
40+
networkResource["project_id"],
41+
name,
42+
networkResource["ipv4_prefix_length"],
43+
nameservers,
44+
)
45+
}
46+
47+
func TestAccIaaS(t *testing.T) {
48+
resource.Test(t, resource.TestCase{
49+
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
50+
CheckDestroy: testAccCheckIaaSDestroy,
51+
Steps: []resource.TestStep{
52+
53+
// Creation
54+
{
55+
Config: resourceConfig(
56+
networkResource["name"],
57+
fmt.Sprintf(
58+
"[%q]",
59+
networkResource["nameserver0"],
60+
),
61+
),
62+
Check: resource.ComposeAggregateTestCheckFunc(
63+
// Instance
64+
resource.TestCheckResourceAttr("stackit_network.network", "project_id", networkResource["project_id"]),
65+
resource.TestCheckResourceAttrSet("stackit_network.network", "network_id"),
66+
resource.TestCheckResourceAttr("stackit_network.network", "name", networkResource["name"]),
67+
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.#", "1"),
68+
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
69+
),
70+
},
71+
// Data source
72+
{
73+
Config: fmt.Sprintf(`
74+
%s
75+
76+
data "stackit_network" "network" {
77+
project_id = stackit_network.network.project_id
78+
network_id = stackit_network.network.network_id
79+
}`,
80+
resourceConfig(
81+
networkResource["name"],
82+
fmt.Sprintf(
83+
"[%q]",
84+
networkResource["nameserver0"],
85+
),
86+
),
87+
),
88+
Check: resource.ComposeAggregateTestCheckFunc(
89+
// Instance
90+
resource.TestCheckResourceAttr("data.stackit_network.network", "project_id", networkResource["project_id"]),
91+
resource.TestCheckResourceAttrPair(
92+
"stackit_network.network", "network_id",
93+
"data.stackit_network.network", "network_id",
94+
),
95+
resource.TestCheckResourceAttr("data.stackit_network.network", "name", networkResource["name"]),
96+
resource.TestCheckResourceAttr("data.stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
97+
),
98+
},
99+
// Import
100+
{
101+
ResourceName: "stackit_network.network",
102+
ImportStateIdFunc: func(s *terraform.State) (string, error) {
103+
r, ok := s.RootModule().Resources["stackit_network.network"]
104+
if !ok {
105+
return "", fmt.Errorf("couldn't find resource stackit_network.network")
106+
}
107+
networkId, ok := r.Primary.Attributes["network_id"]
108+
if !ok {
109+
return "", fmt.Errorf("couldn't find attribute network_id")
110+
}
111+
return fmt.Sprintf("%s,%s", testutil.ProjectId, networkId), nil
112+
},
113+
ImportState: true,
114+
ImportStateVerify: true,
115+
ImportStateVerifyIgnore: []string{"ipv4_prefix_length"}, // Field is not returned by the API
116+
},
117+
// Update
118+
{
119+
Config: resourceConfig(
120+
fmt.Sprintf("%s-updated", networkResource["name"]),
121+
fmt.Sprintf(
122+
"[%q, %q]",
123+
networkResource["nameserver0"],
124+
networkResource["nameserver1"],
125+
),
126+
),
127+
Check: resource.ComposeAggregateTestCheckFunc(
128+
// Instance
129+
resource.TestCheckResourceAttr("stackit_network.network", "project_id", networkResource["project_id"]),
130+
resource.TestCheckResourceAttrSet("stackit_network.network", "network_id"),
131+
resource.TestCheckResourceAttr("stackit_network.network", "name", fmt.Sprintf("%s-updated", networkResource["name"])),
132+
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.#", "2"),
133+
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
134+
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.1", networkResource["nameserver1"]),
135+
),
136+
},
137+
// Deletion is done by the framework implicitly
138+
},
139+
})
140+
}
141+
142+
func testAccCheckIaaSDestroy(s *terraform.State) error {
143+
ctx := context.Background()
144+
var client *iaas.APIClient
145+
var err error
146+
if testutil.IaaSCustomEndpoint == "" {
147+
client, err = iaas.NewAPIClient(
148+
config.WithRegion("eu01"),
149+
)
150+
} else {
151+
client, err = iaas.NewAPIClient(
152+
config.WithEndpoint(testutil.IaaSCustomEndpoint),
153+
)
154+
}
155+
if err != nil {
156+
return fmt.Errorf("creating client: %w", err)
157+
}
158+
159+
networksToDestroy := []string{}
160+
for _, rs := range s.RootModule().Resources {
161+
if rs.Type != "stackit_network" {
162+
continue
163+
}
164+
// network terraform ID: "[project_id],[network_id]"
165+
networkId := strings.Split(rs.Primary.ID, core.Separator)[1]
166+
networksToDestroy = append(networksToDestroy, networkId)
167+
}
168+
169+
networksResp, err := client.ListNetworksExecute(ctx, testutil.ProjectId)
170+
if err != nil {
171+
return fmt.Errorf("getting networksResp: %w", err)
172+
}
173+
174+
networks := *networksResp.Items
175+
for i := range networks {
176+
if networks[i].NetworkId == nil {
177+
continue
178+
}
179+
if utils.Contains(networksToDestroy, *networks[i].NetworkId) {
180+
err := client.DeleteNetworkExecute(ctx, testutil.ProjectId, *networks[i].NetworkId)
181+
if err != nil {
182+
return fmt.Errorf("destroying network %s during CheckDestroy: %w", *networks[i].NetworkId, err)
183+
}
184+
}
185+
}
186+
return nil
187+
}

0 commit comments

Comments
 (0)