Skip to content

Commit 1a8dc30

Browse files
feat(cdn): add redirects in distribution resource (#1333)
* add new attribute `redirects` in `stackit_cdn_distribution` resource and datasource
1 parent 945dc15 commit 1a8dc30

9 files changed

Lines changed: 939 additions & 49 deletions

File tree

docs/data-sources/cdn_distribution.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Read-Only:
5151

5252
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
5353
- `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer))
54+
- `redirects` (Attributes) A wrapper for a list of redirect rules that allows for redirect settings on a distribution (see [below for nested schema](#nestedatt--config--redirects))
5455
- `regions` (List of String) The configured regions where content will be hosted
5556

5657
<a id="nestedatt--config--backend"></a>
@@ -74,6 +75,36 @@ Read-Only:
7475
- `enabled` (Boolean)
7576

7677

78+
<a id="nestedatt--config--redirects"></a>
79+
### Nested Schema for `config.redirects`
80+
81+
Read-Only:
82+
83+
- `rules` (Attributes List) A list of redirect rules. The order of rules matters for evaluation (see [below for nested schema](#nestedatt--config--redirects--rules))
84+
85+
<a id="nestedatt--config--redirects--rules"></a>
86+
### Nested Schema for `config.redirects.rules`
87+
88+
Read-Only:
89+
90+
- `description` (String) An optional description for the redirect rule
91+
- `enabled` (Boolean) A toggle to enable or disable the redirect rule. Default to true
92+
- `matchers` (Attributes List) A list of matchers that define when this rule should apply. At least one matcher is required (see [below for nested schema](#nestedatt--config--redirects--rules--matchers))
93+
- `rule_match_condition` (String) Defines how multiple matchers within this rule are combined (ALL, ANY, NONE). Defaults to ANY.
94+
- `status_code` (Number) The HTTP status code for the redirect. Must be one of 301, 302, 303, 307, or 308.
95+
- `target_url` (String) The target URL to redirect to. Must be a valid URI
96+
97+
<a id="nestedatt--config--redirects--rules--matchers"></a>
98+
### Nested Schema for `config.redirects.rules.matchers`
99+
100+
Read-Only:
101+
102+
- `value_match_condition` (String) Defines how multiple matchers within this rule are combined (ALL, ANY, NONE). Defaults to ANY.
103+
- `values` (List of String) A list of glob patterns to match against the request path. At least one value is required. Examples: "/shop/*" or "*/img/*"
104+
105+
106+
107+
77108

78109
<a id="nestedatt--domains"></a>
79110
### Nested Schema for `domains`

docs/resources/cdn_distribution.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ resource "stackit_cdn_distribution" "example_bucket_distribution" {
5656
optimizer = {
5757
enabled = false
5858
}
59+
60+
redirects = {
61+
rules = [
62+
{
63+
description = "test redirect"
64+
enabled = true
65+
rule_match_condition = "ANY"
66+
status_code = 302
67+
target_url = "https://stackit.de/"
68+
matchers = [
69+
{
70+
values = ["*/otherPath/"]
71+
value_match_condition = "ANY"
72+
}
73+
]
74+
}
75+
]
76+
}
5977
}
6078
}
6179
@@ -96,6 +114,7 @@ Optional:
96114

97115
- `blocked_countries` (List of String) The configured countries where distribution of content is blocked
98116
- `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer))
117+
- `redirects` (Attributes) A wrapper for a list of redirect rules that allows for redirect settings on a distribution (see [below for nested schema](#nestedatt--config--redirects))
99118

100119
<a id="nestedatt--config--backend"></a>
101120
### Nested Schema for `config.backend`
@@ -131,6 +150,42 @@ Optional:
131150
- `enabled` (Boolean)
132151

133152

153+
<a id="nestedatt--config--redirects"></a>
154+
### Nested Schema for `config.redirects`
155+
156+
Required:
157+
158+
- `rules` (Attributes List) A list of redirect rules. The order of rules matters for evaluation (see [below for nested schema](#nestedatt--config--redirects--rules))
159+
160+
<a id="nestedatt--config--redirects--rules"></a>
161+
### Nested Schema for `config.redirects.rules`
162+
163+
Required:
164+
165+
- `matchers` (Attributes List) A list of matchers that define when this rule should apply. At least one matcher is required (see [below for nested schema](#nestedatt--config--redirects--rules--matchers))
166+
- `status_code` (Number) The HTTP status code for the redirect. Must be one of 301, 302, 303, 307, or 308.
167+
- `target_url` (String) The target URL to redirect to. Must be a valid URI
168+
169+
Optional:
170+
171+
- `description` (String) An optional description for the redirect rule
172+
- `enabled` (Boolean) A toggle to enable or disable the redirect rule. Default to true
173+
- `rule_match_condition` (String) Defines how multiple matchers within this rule are combined (ALL, ANY, NONE). Defaults to ANY.
174+
175+
<a id="nestedatt--config--redirects--rules--matchers"></a>
176+
### Nested Schema for `config.redirects.rules.matchers`
177+
178+
Required:
179+
180+
- `values` (List of String) A list of glob patterns to match against the request path. At least one value is required. Examples: "/shop/*" or "*/img/*"
181+
182+
Optional:
183+
184+
- `value_match_condition` (String) Defines how multiple matchers within this rule are combined (ALL, ANY, NONE). Defaults to ANY.
185+
186+
187+
188+
134189

135190
<a id="nestedatt--domains"></a>
136191
### Nested Schema for `domains`

examples/resources/stackit_cdn_distribution/resource.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,24 @@ resource "stackit_cdn_distribution" "example_bucket_distribution" {
3838
optimizer = {
3939
enabled = false
4040
}
41+
42+
redirects = {
43+
rules = [
44+
{
45+
description = "test redirect"
46+
enabled = true
47+
rule_match_condition = "ANY"
48+
status_code = 302
49+
target_url = "https://stackit.de/"
50+
matchers = [
51+
{
52+
values = ["*/otherPath/"]
53+
value_match_condition = "ANY"
54+
}
55+
]
56+
}
57+
]
58+
}
4159
}
4260
}
4361

stackit/internal/services/cdn/cdn_acc_test.go

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ import (
2121
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
2222
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
2323
"github.com/hashicorp/terraform-plugin-testing/terraform"
24-
cdnSdk "github.com/stackitcloud/stackit-sdk-go/services/cdn/v1api"
2524
"github.com/stackitcloud/stackit-sdk-go/services/cdn/v1api/wait"
2625

2726
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
2827
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
28+
29+
cdnSdk "github.com/stackitcloud/stackit-sdk-go/services/cdn/v1api"
2930
)
3031

3132
var (
@@ -77,27 +78,34 @@ func configVarsBucketUpdated() config.Variables {
7778
}
7879

7980
var testConfigVarsHttp = config.Variables{
80-
"project_id": config.StringVariable(testutil.ProjectId),
81-
"name": config.StringVariable(httpTestName),
82-
"regions": config.ListVariable(config.StringVariable("EU"), config.StringVariable("US")),
83-
"dns_zone_name": config.StringVariable("acc_cdn_test_zone"),
84-
"dns_name": config.StringVariable(dnsNameHttp),
85-
"dns_record_name": config.StringVariable(dnsRecordNameHttp),
86-
"optimizer": config.BoolVariable(true),
87-
"backend_http_type": config.StringVariable("http"),
88-
"blocked_countries": config.ListVariable(config.StringVariable("CU")),
89-
"backend_origin_url": config.StringVariable("https://test-backend-1.cdn-dev.runs.onstackit.cloud"),
90-
"geofencing_list": config.ListVariable(config.StringVariable("DE")),
91-
"origin_request_headers_name": config.StringVariable("X-Custom-Header"),
92-
"origin_request_headers_value": config.StringVariable("x-custom-value"),
93-
"certificate": config.StringVariable(string(cert)),
94-
"private_key": config.StringVariable(string(key)),
81+
"project_id": config.StringVariable(testutil.ProjectId),
82+
"name": config.StringVariable(httpTestName),
83+
"regions": config.ListVariable(config.StringVariable("EU"), config.StringVariable("US")),
84+
"dns_zone_name": config.StringVariable("acc_cdn_test_zone"),
85+
"dns_name": config.StringVariable(dnsNameHttp),
86+
"dns_record_name": config.StringVariable(dnsRecordNameHttp),
87+
"optimizer": config.BoolVariable(true),
88+
"backend_http_type": config.StringVariable("http"),
89+
"blocked_countries": config.ListVariable(config.StringVariable("CU")),
90+
"backend_origin_url": config.StringVariable("https://test-backend-1.cdn-dev.runs.onstackit.cloud"),
91+
"geofencing_list": config.ListVariable(config.StringVariable("DE")),
92+
"origin_request_headers_name": config.StringVariable("X-Custom-Header"),
93+
"origin_request_headers_value": config.StringVariable("x-custom-value"),
94+
"certificate": config.StringVariable(string(cert)),
95+
"private_key": config.StringVariable(string(key)),
96+
"redirect_target_url": config.StringVariable("https://example.com"),
97+
"redirect_status_code": config.IntegerVariable(301),
98+
"redirect_matcher_value": config.StringVariable("/shop/*"),
99+
"redirect_rule_description": config.StringVariable("Acc test redirect"),
100+
"redirect_rule_enabled": config.BoolVariable(true),
101+
"redirect_rule_match_condition": config.StringVariable("ANY"),
102+
"redirect_matcher_condition": config.StringVariable("ANY"),
95103
}
96104

97105
func configVarsHttpUpdated() config.Variables {
98106
updatedConfig := maps.Clone(testConfigVarsHttp)
99107
updatedConfig["regions"] = config.ListVariable(config.StringVariable("EU"), config.StringVariable("US"), config.StringVariable("ASIA"))
100-
108+
updatedConfig["redirect_target_url"] = config.StringVariable("https://example.com/updated")
101109
return updatedConfig
102110
}
103111

@@ -157,6 +165,15 @@ func TestAccCDNDistributionHttp(t *testing.T) {
157165
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
158166
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.type", "managed"),
159167
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
168+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.#", "1"),
169+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.target_url", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_target_url"])),
170+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.status_code", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_status_code"])),
171+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.description", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_description"])),
172+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_enabled"])),
173+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.rule_match_condition", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_match_condition"])),
174+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.matchers.#", "1"),
175+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.matchers.0.values.0", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_matcher_value"])),
176+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.matchers.0.value_match_condition", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_matcher_condition"])),
160177
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
161178
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
162179
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
@@ -277,6 +294,14 @@ func TestAccCDNDistributionHttp(t *testing.T) {
277294
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.optimizer.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["optimizer"])),
278295
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
279296
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "status", "ACTIVE"),
297+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.#", "1"),
298+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.target_url", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_target_url"])),
299+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.status_code", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_status_code"])),
300+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.description", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_description"])),
301+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_enabled"])),
302+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.rule_match_condition", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_rule_match_condition"])),
303+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.matchers.0.values.0", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_matcher_value"])),
304+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.redirects.rules.0.matchers.0.value_match_condition", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_matcher_condition"])),
280305

281306
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
282307
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "name", fullDomainNameHttp),
@@ -319,6 +344,10 @@ func TestAccCDNDistributionHttp(t *testing.T) {
319344
"DE",
320345
),
321346

347+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.#", "1"),
348+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.target_url", testutil.ConvertConfigVariable(configVarsHttpUpdated()["redirect_target_url"])),
349+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.redirects.rules.0.status_code", testutil.ConvertConfigVariable(testConfigVarsHttp["redirect_status_code"])),
350+
322351
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
323352
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "name", fullDomainNameHttp),
324353
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "certificate.version", "1"),

0 commit comments

Comments
 (0)