Skip to content

Commit 2eb6163

Browse files
committed
feat: add cidr_list attribute to stackit_public_ip_ranges datasource
Signed-off-by: Mauritz Uphoff <[email protected]>
1 parent f0438e8 commit 2eb6163

File tree

4 files changed

+165
-3
lines changed

4 files changed

+165
-3
lines changed

docs/data-sources/public_ip_ranges.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,30 @@ A list of all public IP ranges that STACKIT uses.
1414

1515
```terraform
1616
data "stackit_public_ip_ranges" "example" {}
17+
18+
locals {
19+
vpn_cidrs = ["X.X.X.X/32", "X.X.X.X/24"]
20+
}
21+
22+
# example usage: allow stackit services and customer vpn cidr to access observability apis
23+
resource "stackit_observability_instance" "example" {
24+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
25+
name = "example-instance"
26+
plan_name = "Observability-Monitoring-Medium-EU01"
27+
# Allow all stackit services and customer vpn cidr to access observability apis
28+
acl = concat(data.stackit_public_ip_ranges.example.cidr_list, local.vpn_cidrs)
29+
metrics_retention_days = 90
30+
metrics_retention_days_5m_downsampling = 90
31+
metrics_retention_days_1h_downsampling = 90
32+
}
1733
```
1834

1935
<!-- schema generated by tfplugindocs -->
2036
## Schema
2137

2238
### Read-Only
2339

40+
- `cidr_list` (List of String) A list of IP range strings (CIDRs) extracted from the public_ip_ranges for easy consumption.
2441
- `id` (String) Terraform's internal resource ID. It takes the values of "`public_ip_ranges.*.cidr`".
2542
- `public_ip_ranges` (Attributes List) A list of all public IP ranges. (see [below for nested schema](#nestedatt--public_ip_ranges))
2643

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
data "stackit_public_ip_ranges" "example" {}
1+
data "stackit_public_ip_ranges" "example" {}
2+
3+
locals {
4+
vpn_cidrs = ["X.X.X.X/32", "X.X.X.X/24"]
5+
}
6+
7+
# example usage: allow stackit services and customer vpn cidr to access observability apis
8+
resource "stackit_observability_instance" "example" {
9+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
10+
name = "example-instance"
11+
plan_name = "Observability-Monitoring-Medium-EU01"
12+
# Allow all stackit services and customer vpn cidr to access observability apis
13+
acl = concat(data.stackit_public_ip_ranges.example.cidr_list, local.vpn_cidrs)
14+
metrics_retention_days = 90
15+
metrics_retention_days_5m_downsampling = 90
16+
metrics_retention_days_1h_downsampling = 90
17+
}

stackit/internal/services/iaas/publicipranges/datasource.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type publicIpRangesDataSource struct {
4141
type Model struct {
4242
Id types.String `tfsdk:"id"` // needed by TF
4343
PublicIpRanges types.List `tfsdk:"public_ip_ranges"`
44+
CidrList types.List `tfsdk:"cidr_list"`
4445
}
4546

4647
var publicIpRangesTypes = map[string]attr.Type{
@@ -97,6 +98,11 @@ func (d *publicIpRangesDataSource) Schema(_ context.Context, _ datasource.Schema
9798
},
9899
},
99100
},
101+
"cidr_list": schema.ListAttribute{
102+
Description: "A list of IP range strings (CIDRs) extracted from the public_ip_ranges for easy consumption.",
103+
ElementType: types.StringType,
104+
Computed: true,
105+
},
100106
},
101107
}
102108
}
@@ -155,18 +161,19 @@ func mapFields(ctx context.Context, publicIpRangeResp *iaas.PublicNetworkListRes
155161
}
156162

157163
// mapPublicIpRanges map the response publicIpRanges to the model
158-
func mapPublicIpRanges(_ context.Context, publicIpRanges *[]iaas.PublicNetwork, model *Model) error {
164+
func mapPublicIpRanges(ctx context.Context, publicIpRanges *[]iaas.PublicNetwork, model *Model) error {
159165
if publicIpRanges == nil {
160166
return fmt.Errorf("publicIpRanges input is nil")
161167
}
162168
if len(*publicIpRanges) == 0 {
163169
model.PublicIpRanges = types.ListNull(types.ObjectType{AttrTypes: publicIpRangesTypes})
170+
model.CidrList = types.ListNull(types.StringType)
164171
return nil
165172
}
166173

167174
var apiIpRanges []string
168175
for _, ipRange := range *publicIpRanges {
169-
if ipRange.Cidr != nil || *ipRange.Cidr != "" {
176+
if ipRange.Cidr != nil && *ipRange.Cidr != "" {
170177
apiIpRanges = append(apiIpRanges, *ipRange.Cidr)
171178
}
172179
}
@@ -197,5 +204,12 @@ func mapPublicIpRanges(_ context.Context, publicIpRanges *[]iaas.PublicNetwork,
197204
}
198205

199206
model.PublicIpRanges = ipRangesTF
207+
208+
cidrListTF, diags := types.ListValueFrom(ctx, types.StringType, apiIpRanges)
209+
if diags.HasError() {
210+
return core.DiagsToError(diags)
211+
}
212+
model.CidrList = cidrListTF
213+
200214
return nil
201215
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package publicipranges
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
"github.com/hashicorp/terraform-plugin-framework/attr"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
coreUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
11+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
12+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
13+
)
14+
15+
func TestMapPublicIpRanges(t *testing.T) {
16+
ctx := context.Background()
17+
18+
tests := []struct {
19+
name string
20+
input *[]iaas.PublicNetwork
21+
expected Model
22+
isValid bool
23+
}{
24+
{
25+
name: "nil input should return error",
26+
input: nil,
27+
isValid: false,
28+
},
29+
{
30+
name: "empty input should return nulls",
31+
input: &[]iaas.PublicNetwork{},
32+
expected: Model{
33+
PublicIpRanges: types.ListNull(types.ObjectType{AttrTypes: publicIpRangesTypes}),
34+
CidrList: types.ListNull(types.StringType),
35+
},
36+
isValid: true,
37+
},
38+
{
39+
name: "valid cidr entries",
40+
input: &[]iaas.PublicNetwork{
41+
{Cidr: coreUtils.Ptr("192.168.0.0/24")},
42+
{Cidr: coreUtils.Ptr("192.168.1.0/24")},
43+
},
44+
expected: func() Model {
45+
cidrs := []string{"192.168.0.0/24", "192.168.1.0/24"}
46+
ipRangesList := make([]attr.Value, 0, len(cidrs))
47+
for _, cidr := range cidrs {
48+
ipRange, _ := types.ObjectValue(publicIpRangesTypes, map[string]attr.Value{
49+
"cidr": types.StringValue(cidr),
50+
})
51+
ipRangesList = append(ipRangesList, ipRange)
52+
}
53+
ipRangesVal, _ := types.ListValue(types.ObjectType{AttrTypes: publicIpRangesTypes}, ipRangesList)
54+
cidrListVal, _ := types.ListValueFrom(ctx, types.StringType, cidrs)
55+
56+
return Model{
57+
PublicIpRanges: ipRangesVal,
58+
CidrList: cidrListVal,
59+
Id: utils.BuildInternalTerraformId(cidrs...),
60+
}
61+
}(),
62+
isValid: true,
63+
},
64+
{
65+
name: "filter out empty CIDRs",
66+
input: &[]iaas.PublicNetwork{
67+
{Cidr: coreUtils.Ptr("")},
68+
{Cidr: nil},
69+
{Cidr: coreUtils.Ptr("10.0.0.0/8")},
70+
},
71+
expected: func() Model {
72+
cidrs := []string{"10.0.0.0/8"}
73+
ipRange, _ := types.ObjectValue(publicIpRangesTypes, map[string]attr.Value{
74+
"cidr": types.StringValue("10.0.0.0/8"),
75+
})
76+
ipRangesVal, _ := types.ListValue(types.ObjectType{AttrTypes: publicIpRangesTypes}, []attr.Value{ipRange})
77+
cidrListVal, _ := types.ListValueFrom(ctx, types.StringType, cidrs)
78+
return Model{
79+
PublicIpRanges: ipRangesVal,
80+
CidrList: cidrListVal,
81+
Id: utils.BuildInternalTerraformId(cidrs...),
82+
}
83+
}(),
84+
isValid: true,
85+
},
86+
}
87+
88+
for _, tt := range tests {
89+
t.Run(tt.name, func(t *testing.T) {
90+
var model Model
91+
err := mapPublicIpRanges(ctx, tt.input, &model)
92+
93+
if !tt.isValid {
94+
if err == nil {
95+
t.Fatalf("Expected error but got nil")
96+
}
97+
return
98+
} else if err != nil {
99+
t.Fatalf("Unexpected error: %v", err)
100+
}
101+
102+
if diff := cmp.Diff(tt.expected.Id, model.Id); diff != "" {
103+
t.Errorf("ID does not match:\n%s", diff)
104+
}
105+
106+
if diff := cmp.Diff(tt.expected.CidrList, model.CidrList); diff != "" {
107+
t.Errorf("cidr_list does not match:\n%s", diff)
108+
}
109+
110+
if diff := cmp.Diff(tt.expected.PublicIpRanges, model.PublicIpRanges); diff != "" {
111+
t.Errorf("public_ip_ranges does not match:\n%s", diff)
112+
}
113+
})
114+
}
115+
}

0 commit comments

Comments
 (0)