Skip to content

Commit 855d304

Browse files
Feature: CDN distribution resource and data source (#786)
* add datasource * finish data source * implement resource * add unit tests * add examples * acceptance test * review comments * review comments 2 --------- Co-authored-by: Malte Ehrlen <[email protected]>
1 parent 3c20b77 commit 855d304

File tree

14 files changed

+1520
-0
lines changed

14 files changed

+1520
-0
lines changed

docs/data-sources/cdn_distribution.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_cdn_distribution Data Source - stackit"
4+
subcategory: ""
5+
description: |-
6+
CDN distribution data source schema.
7+
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
8+
---
9+
10+
# stackit_cdn_distribution (Data Source)
11+
12+
CDN distribution data source schema.
13+
14+
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
15+
16+
## Example Usage
17+
18+
```terraform
19+
data "stackit_cdn_distribution" "example" {
20+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
21+
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
22+
}
23+
```
24+
25+
<!-- schema generated by tfplugindocs -->
26+
## Schema
27+
28+
### Required
29+
30+
- `distribution_id` (String) STACKIT project ID associated with the distribution
31+
- `project_id` (String) STACKIT project ID associated with the distribution
32+
33+
### Read-Only
34+
35+
- `config` (Attributes) The distribution configuration (see [below for nested schema](#nestedatt--config))
36+
- `created_at` (String) Time when the distribution was created
37+
- `domains` (Attributes List) List of configured domains for the distribution (see [below for nested schema](#nestedatt--domains))
38+
- `errors` (List of String) List of distribution errors
39+
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
40+
- `status` (String) Status of the distribution
41+
- `updated_at` (String) Time when the distribution was last updated
42+
43+
<a id="nestedatt--config"></a>
44+
### Nested Schema for `config`
45+
46+
Read-Only:
47+
48+
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
49+
- `regions` (List of String) The configured regions where content will be hosted
50+
51+
<a id="nestedatt--config--backend"></a>
52+
### Nested Schema for `config.backend`
53+
54+
Read-Only:
55+
56+
- `origin_request_headers` (Map of String) The configured origin request headers for the backend
57+
- `origin_url` (String) The configured backend type for the distribution
58+
- `type` (String) The configured backend type
59+
60+
61+
62+
<a id="nestedatt--domains"></a>
63+
### Nested Schema for `domains`
64+
65+
Read-Only:
66+
67+
- `errors` (List of String) List of domain errors
68+
- `name` (String) The name of the domain
69+
- `status` (String) The status of the domain
70+
- `type` (String) The type of the domain. Each distribution has one domain of type "managed", and domains of type "custom" may be additionally created by the user

docs/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
153153

154154
- `argus_custom_endpoint` (String, Deprecated) Custom endpoint for the Argus service
155155
- `authorization_custom_endpoint` (String) Custom endpoint for the Membership service
156+
- `cdn_custom_endpoint` (String) Custom endpoint for the CDN service
156157
- `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`.
157158
- `default_region` (String) Region will be used as the default location for regional services. Not all services require a region, some are global
158159
- `dns_custom_endpoint` (String) Custom endpoint for the DNS service

docs/resources/cdn_distribution.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_cdn_distribution Resource - stackit"
4+
subcategory: ""
5+
description: |-
6+
CDN distribution data source schema.
7+
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
8+
---
9+
10+
# stackit_cdn_distribution (Resource)
11+
12+
CDN distribution data source schema.
13+
14+
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
15+
16+
## Example Usage
17+
18+
```terraform
19+
# Create a CDN distribution
20+
resource "stackit_cdn_distribution" "example_distribution" {
21+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
22+
config = {
23+
backend = {
24+
type = "http"
25+
origin_url = "mybackend.onstackit.cloud"
26+
}
27+
regions = ["EN", "US", "ASIA", "AF", "SA"]
28+
}
29+
}
30+
```
31+
32+
<!-- schema generated by tfplugindocs -->
33+
## Schema
34+
35+
### Required
36+
37+
- `config` (Attributes) The distribution configuration (see [below for nested schema](#nestedatt--config))
38+
- `project_id` (String) STACKIT project ID associated with the distribution
39+
40+
### Read-Only
41+
42+
- `created_at` (String) Time when the distribution was created
43+
- `distribution_id` (String) STACKIT project ID associated with the distribution
44+
- `domains` (Attributes List) List of configured domains for the distribution (see [below for nested schema](#nestedatt--domains))
45+
- `errors` (List of String) List of distribution errors
46+
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
47+
- `status` (String) Status of the distribution
48+
- `updated_at` (String) Time when the distribution was last updated
49+
50+
<a id="nestedatt--config"></a>
51+
### Nested Schema for `config`
52+
53+
Required:
54+
55+
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
56+
- `regions` (List of String) The configured regions where content will be hosted
57+
58+
<a id="nestedatt--config--backend"></a>
59+
### Nested Schema for `config.backend`
60+
61+
Required:
62+
63+
- `origin_url` (String) The configured backend type for the distribution
64+
- `type` (String) The configured backend type
65+
66+
Optional:
67+
68+
- `origin_request_headers` (Map of String) The configured origin request headers for the backend
69+
70+
71+
72+
<a id="nestedatt--domains"></a>
73+
### Nested Schema for `domains`
74+
75+
Read-Only:
76+
77+
- `errors` (List of String) List of domain errors
78+
- `name` (String) The name of the domain
79+
- `status` (String) The status of the domain
80+
- `type` (String) The type of the domain. Each distribution has one domain of type "managed", and domains of type "custom" may be additionally created by the user
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
data "stackit_cdn_distribution" "example" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
4+
}
5+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Create a CDN distribution
2+
resource "stackit_cdn_distribution" "example_distribution" {
3+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
4+
config = {
5+
backend = {
6+
type = "http"
7+
origin_url = "mybackend.onstackit.cloud"
8+
}
9+
regions = ["EN", "US", "ASIA", "AF", "SA"]
10+
}
11+
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/hashicorp/terraform-plugin-log v0.9.0
1313
github.com/hashicorp/terraform-plugin-testing v1.12.0
1414
github.com/stackitcloud/stackit-sdk-go/core v0.17.1
15+
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0
1516
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1
1617
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0
1718
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJS
154154
github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0=
155155
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I=
156156
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA=
157+
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0 h1:l3COE8uny+AVkHW7MElzEGdriy+QzhpRhYgLkYJlnLU=
158+
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0/go.mod h1:O5esCqh35n0ERX7/Sqpf09ZRDWckhHUuflJFbUvx9QM=
157159
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo=
158160
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1/go.mod h1:+i7jQpfgj/OuZNVZ9A9aUHdVUR/j2SfICLeHbtNn+5c=
159161
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJnBfPP1cERc+ERqjebxmEmEOvRHU=

stackit/internal/core/core.go

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type ProviderData struct {
2121
DefaultRegion string
2222
ArgusCustomEndpoint string
2323
AuthorizationCustomEndpoint string
24+
CdnCustomEndpoint string
2425
DnsCustomEndpoint string
2526
IaaSCustomEndpoint string
2627
LoadBalancerCustomEndpoint string
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package cdn_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-testing/terraform"
11+
"github.com/stackitcloud/stackit-sdk-go/core/config"
12+
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
13+
"github.com/stackitcloud/stackit-sdk-go/services/cdn/wait"
14+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
15+
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
16+
)
17+
18+
var instanceResource = map[string]string{
19+
"project_id": testutil.ProjectId,
20+
"config_backend_type": "http",
21+
"config_backend_origin_url": "https://test-backend-1.cdn-dev.runs.onstackit.cloud",
22+
"config_regions": "\"EU\", \"US\"",
23+
"config_regions_updated": "\"EU\", \"US\", \"ASIA\"",
24+
}
25+
26+
func configResources(regions string) string {
27+
return fmt.Sprintf(`
28+
%s
29+
30+
resource "stackit_cdn_distribution" "distribution" {
31+
project_id = "%s"
32+
config = {
33+
backend = {
34+
type = "http"
35+
origin_url = "%s"
36+
}
37+
regions = [%s]
38+
}
39+
}
40+
`, testutil.CdnProviderConfig(), testutil.ProjectId, instanceResource["config_backend_origin_url"], regions)
41+
}
42+
43+
func configDatasources(regions string) string {
44+
return fmt.Sprintf(`
45+
%s
46+
47+
data "stackit_cdn_distribution" "distribution" {
48+
project_id = stackit_cdn_distribution.distribution.project_id
49+
distribution_id = stackit_cdn_distribution.distribution.distribution_id
50+
}
51+
`, configResources(regions))
52+
}
53+
54+
func TestAccCDNDistributionResource(t *testing.T) {
55+
resource.Test(t, resource.TestCase{
56+
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
57+
CheckDestroy: testAccCheckCDNDistributionDestroy,
58+
Steps: []resource.TestStep{
59+
// Create
60+
{
61+
Config: configResources(instanceResource["config_regions"]),
62+
Check: resource.ComposeAggregateTestCheckFunc(
63+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
64+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
65+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
66+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
67+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
68+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
69+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
70+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
71+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
72+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
73+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
74+
),
75+
},
76+
// Import
77+
{
78+
ResourceName: "stackit_cdn_distribution.distribution",
79+
ImportStateIdFunc: func(s *terraform.State) (string, error) {
80+
r, ok := s.RootModule().Resources["stackit_cdn_distribution.distribution"]
81+
if !ok {
82+
return "", fmt.Errorf("couldn't find resource stackit_cdn_distribution.distribution")
83+
}
84+
distributionId, ok := r.Primary.Attributes["distribution_id"]
85+
if !ok {
86+
return "", fmt.Errorf("couldn't find attribute distribution_id")
87+
}
88+
89+
return fmt.Sprintf("%s,%s", testutil.ProjectId, distributionId), nil
90+
},
91+
ImportState: true,
92+
ImportStateVerify: true,
93+
},
94+
// Data Source
95+
{
96+
Config: configDatasources(instanceResource["config_regions"]),
97+
Check: resource.ComposeAggregateTestCheckFunc(
98+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
99+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
100+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
101+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
102+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
103+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
104+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
105+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
106+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
107+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
108+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
109+
),
110+
},
111+
// Update
112+
{
113+
Config: configResources(instanceResource["config_regions_updated"]),
114+
Check: resource.ComposeAggregateTestCheckFunc(
115+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
116+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
117+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
118+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
119+
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
120+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
121+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "3"),
122+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
123+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
124+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.2", "ASIA"),
125+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
126+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
127+
),
128+
},
129+
},
130+
})
131+
}
132+
func testAccCheckCDNDistributionDestroy(s *terraform.State) error {
133+
ctx := context.Background()
134+
var client *cdn.APIClient
135+
var err error
136+
if testutil.MongoDBFlexCustomEndpoint == "" {
137+
client, err = cdn.NewAPIClient()
138+
} else {
139+
client, err = cdn.NewAPIClient(
140+
config.WithEndpoint(testutil.MongoDBFlexCustomEndpoint),
141+
)
142+
}
143+
if err != nil {
144+
return fmt.Errorf("creating client: %w", err)
145+
}
146+
147+
distributionsToDestroy := []string{}
148+
for _, rs := range s.RootModule().Resources {
149+
if rs.Type != "stackit_mongodbflex_instance" {
150+
continue
151+
}
152+
distributionId := strings.Split(rs.Primary.ID, core.Separator)[1]
153+
distributionsToDestroy = append(distributionsToDestroy, distributionId)
154+
}
155+
156+
for _, dist := range distributionsToDestroy {
157+
_, err := client.DeleteDistribution(ctx, testutil.ProjectId, dist).Execute()
158+
if err != nil {
159+
return fmt.Errorf("destroying CDN distribution %s during CheckDestroy: %w", dist, err)
160+
}
161+
_, err = wait.DeleteDistributionWaitHandler(ctx, client, testutil.ProjectId, dist).WaitWithContext(ctx)
162+
if err != nil {
163+
return fmt.Errorf("destroying CDN distribution %s during CheckDestroy: waiting for deletion %w", dist, err)
164+
}
165+
}
166+
return nil
167+
}

0 commit comments

Comments
 (0)