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 <malte.ehrlen@freiheit.com>
This commit is contained in:
parent
3c20b7743f
commit
855d3040ef
14 changed files with 1520 additions and 0 deletions
70
docs/data-sources/cdn_distribution.md
Normal file
70
docs/data-sources/cdn_distribution.md
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "stackit_cdn_distribution Data Source - stackit"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
CDN distribution data source schema.
|
||||||
|
~> 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.
|
||||||
|
---
|
||||||
|
|
||||||
|
# stackit_cdn_distribution (Data Source)
|
||||||
|
|
||||||
|
CDN distribution data source schema.
|
||||||
|
|
||||||
|
~> 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.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
data "stackit_cdn_distribution" "example" {
|
||||||
|
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `distribution_id` (String) STACKIT project ID associated with the distribution
|
||||||
|
- `project_id` (String) STACKIT project ID associated with the distribution
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `config` (Attributes) The distribution configuration (see [below for nested schema](#nestedatt--config))
|
||||||
|
- `created_at` (String) Time when the distribution was created
|
||||||
|
- `domains` (Attributes List) List of configured domains for the distribution (see [below for nested schema](#nestedatt--domains))
|
||||||
|
- `errors` (List of String) List of distribution errors
|
||||||
|
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
|
||||||
|
- `status` (String) Status of the distribution
|
||||||
|
- `updated_at` (String) Time when the distribution was last updated
|
||||||
|
|
||||||
|
<a id="nestedatt--config"></a>
|
||||||
|
### Nested Schema for `config`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
|
||||||
|
- `regions` (List of String) The configured regions where content will be hosted
|
||||||
|
|
||||||
|
<a id="nestedatt--config--backend"></a>
|
||||||
|
### Nested Schema for `config.backend`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `origin_request_headers` (Map of String) The configured origin request headers for the backend
|
||||||
|
- `origin_url` (String) The configured backend type for the distribution
|
||||||
|
- `type` (String) The configured backend type
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--domains"></a>
|
||||||
|
### Nested Schema for `domains`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `errors` (List of String) List of domain errors
|
||||||
|
- `name` (String) The name of the domain
|
||||||
|
- `status` (String) The status of the domain
|
||||||
|
- `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
|
||||||
|
|
@ -153,6 +153,7 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
|
||||||
|
|
||||||
- `argus_custom_endpoint` (String, Deprecated) Custom endpoint for the Argus service
|
- `argus_custom_endpoint` (String, Deprecated) Custom endpoint for the Argus service
|
||||||
- `authorization_custom_endpoint` (String) Custom endpoint for the Membership service
|
- `authorization_custom_endpoint` (String) Custom endpoint for the Membership service
|
||||||
|
- `cdn_custom_endpoint` (String) Custom endpoint for the CDN service
|
||||||
- `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`.
|
- `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`.
|
||||||
- `default_region` (String) Region will be used as the default location for regional services. Not all services require a region, some are global
|
- `default_region` (String) Region will be used as the default location for regional services. Not all services require a region, some are global
|
||||||
- `dns_custom_endpoint` (String) Custom endpoint for the DNS service
|
- `dns_custom_endpoint` (String) Custom endpoint for the DNS service
|
||||||
|
|
|
||||||
80
docs/resources/cdn_distribution.md
Normal file
80
docs/resources/cdn_distribution.md
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "stackit_cdn_distribution Resource - stackit"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
CDN distribution data source schema.
|
||||||
|
~> 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.
|
||||||
|
---
|
||||||
|
|
||||||
|
# stackit_cdn_distribution (Resource)
|
||||||
|
|
||||||
|
CDN distribution data source schema.
|
||||||
|
|
||||||
|
~> 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.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
# Create a CDN distribution
|
||||||
|
resource "stackit_cdn_distribution" "example_distribution" {
|
||||||
|
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
config = {
|
||||||
|
backend = {
|
||||||
|
type = "http"
|
||||||
|
origin_url = "mybackend.onstackit.cloud"
|
||||||
|
}
|
||||||
|
regions = ["EN", "US", "ASIA", "AF", "SA"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `config` (Attributes) The distribution configuration (see [below for nested schema](#nestedatt--config))
|
||||||
|
- `project_id` (String) STACKIT project ID associated with the distribution
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `created_at` (String) Time when the distribution was created
|
||||||
|
- `distribution_id` (String) STACKIT project ID associated with the distribution
|
||||||
|
- `domains` (Attributes List) List of configured domains for the distribution (see [below for nested schema](#nestedatt--domains))
|
||||||
|
- `errors` (List of String) List of distribution errors
|
||||||
|
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
|
||||||
|
- `status` (String) Status of the distribution
|
||||||
|
- `updated_at` (String) Time when the distribution was last updated
|
||||||
|
|
||||||
|
<a id="nestedatt--config"></a>
|
||||||
|
### Nested Schema for `config`
|
||||||
|
|
||||||
|
Required:
|
||||||
|
|
||||||
|
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
|
||||||
|
- `regions` (List of String) The configured regions where content will be hosted
|
||||||
|
|
||||||
|
<a id="nestedatt--config--backend"></a>
|
||||||
|
### Nested Schema for `config.backend`
|
||||||
|
|
||||||
|
Required:
|
||||||
|
|
||||||
|
- `origin_url` (String) The configured backend type for the distribution
|
||||||
|
- `type` (String) The configured backend type
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
|
- `origin_request_headers` (Map of String) The configured origin request headers for the backend
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--domains"></a>
|
||||||
|
### Nested Schema for `domains`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `errors` (List of String) List of domain errors
|
||||||
|
- `name` (String) The name of the domain
|
||||||
|
- `status` (String) The status of the domain
|
||||||
|
- `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
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
data "stackit_cdn_distribution" "example" {
|
||||||
|
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
}
|
||||||
|
|
||||||
11
examples/resources/stackit_cdn_distribution/resource.tf
Normal file
11
examples/resources/stackit_cdn_distribution/resource.tf
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Create a CDN distribution
|
||||||
|
resource "stackit_cdn_distribution" "example_distribution" {
|
||||||
|
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
|
config = {
|
||||||
|
backend = {
|
||||||
|
type = "http"
|
||||||
|
origin_url = "mybackend.onstackit.cloud"
|
||||||
|
}
|
||||||
|
regions = ["EN", "US", "ASIA", "AF", "SA"]
|
||||||
|
}
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
|
|
@ -12,6 +12,7 @@ require (
|
||||||
github.com/hashicorp/terraform-plugin-log v0.9.0
|
github.com/hashicorp/terraform-plugin-log v0.9.0
|
||||||
github.com/hashicorp/terraform-plugin-testing v1.12.0
|
github.com/hashicorp/terraform-plugin-testing v1.12.0
|
||||||
github.com/stackitcloud/stackit-sdk-go/core v0.17.1
|
github.com/stackitcloud/stackit-sdk-go/core v0.17.1
|
||||||
|
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1
|
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0
|
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1
|
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.1
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -154,6 +154,8 @@ github.com/stackitcloud/stackit-sdk-go/core v0.17.1 h1:TTrVoB1lERd/qfWzpe6HpwCJS
|
||||||
github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0=
|
github.com/stackitcloud/stackit-sdk-go/core v0.17.1/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0=
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I=
|
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I=
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA=
|
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA=
|
||||||
|
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0 h1:l3COE8uny+AVkHW7MElzEGdriy+QzhpRhYgLkYJlnLU=
|
||||||
|
github.com/stackitcloud/stackit-sdk-go/services/cdn v0.3.0/go.mod h1:O5esCqh35n0ERX7/Sqpf09ZRDWckhHUuflJFbUvx9QM=
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo=
|
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo=
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1/go.mod h1:+i7jQpfgj/OuZNVZ9A9aUHdVUR/j2SfICLeHbtNn+5c=
|
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1/go.mod h1:+i7jQpfgj/OuZNVZ9A9aUHdVUR/j2SfICLeHbtNn+5c=
|
||||||
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJnBfPP1cERc+ERqjebxmEmEOvRHU=
|
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.0 h1:xaNory8kBIsBG7PJnBfPP1cERc+ERqjebxmEmEOvRHU=
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ type ProviderData struct {
|
||||||
DefaultRegion string
|
DefaultRegion string
|
||||||
ArgusCustomEndpoint string
|
ArgusCustomEndpoint string
|
||||||
AuthorizationCustomEndpoint string
|
AuthorizationCustomEndpoint string
|
||||||
|
CdnCustomEndpoint string
|
||||||
DnsCustomEndpoint string
|
DnsCustomEndpoint string
|
||||||
IaaSCustomEndpoint string
|
IaaSCustomEndpoint string
|
||||||
LoadBalancerCustomEndpoint string
|
LoadBalancerCustomEndpoint string
|
||||||
|
|
|
||||||
167
stackit/internal/services/cdn/cdn_acc_test.go
Normal file
167
stackit/internal/services/cdn/cdn_acc_test.go
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
package cdn_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn/wait"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var instanceResource = map[string]string{
|
||||||
|
"project_id": testutil.ProjectId,
|
||||||
|
"config_backend_type": "http",
|
||||||
|
"config_backend_origin_url": "https://test-backend-1.cdn-dev.runs.onstackit.cloud",
|
||||||
|
"config_regions": "\"EU\", \"US\"",
|
||||||
|
"config_regions_updated": "\"EU\", \"US\", \"ASIA\"",
|
||||||
|
}
|
||||||
|
|
||||||
|
func configResources(regions string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
%s
|
||||||
|
|
||||||
|
resource "stackit_cdn_distribution" "distribution" {
|
||||||
|
project_id = "%s"
|
||||||
|
config = {
|
||||||
|
backend = {
|
||||||
|
type = "http"
|
||||||
|
origin_url = "%s"
|
||||||
|
}
|
||||||
|
regions = [%s]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, testutil.CdnProviderConfig(), testutil.ProjectId, instanceResource["config_backend_origin_url"], regions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func configDatasources(regions string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
%s
|
||||||
|
|
||||||
|
data "stackit_cdn_distribution" "distribution" {
|
||||||
|
project_id = stackit_cdn_distribution.distribution.project_id
|
||||||
|
distribution_id = stackit_cdn_distribution.distribution.distribution_id
|
||||||
|
}
|
||||||
|
`, configResources(regions))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCDNDistributionResource(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||||
|
CheckDestroy: testAccCheckCDNDistributionDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
// Create
|
||||||
|
{
|
||||||
|
Config: configResources(instanceResource["config_regions"]),
|
||||||
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// Import
|
||||||
|
{
|
||||||
|
ResourceName: "stackit_cdn_distribution.distribution",
|
||||||
|
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||||
|
r, ok := s.RootModule().Resources["stackit_cdn_distribution.distribution"]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("couldn't find resource stackit_cdn_distribution.distribution")
|
||||||
|
}
|
||||||
|
distributionId, ok := r.Primary.Attributes["distribution_id"]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("couldn't find attribute distribution_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s,%s", testutil.ProjectId, distributionId), nil
|
||||||
|
},
|
||||||
|
ImportState: true,
|
||||||
|
ImportStateVerify: true,
|
||||||
|
},
|
||||||
|
// Data Source
|
||||||
|
{
|
||||||
|
Config: configDatasources(instanceResource["config_regions"]),
|
||||||
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// Update
|
||||||
|
{
|
||||||
|
Config: configResources(instanceResource["config_regions_updated"]),
|
||||||
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "1"),
|
||||||
|
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "3"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.2", "ASIA"),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
|
||||||
|
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func testAccCheckCDNDistributionDestroy(s *terraform.State) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
var client *cdn.APIClient
|
||||||
|
var err error
|
||||||
|
if testutil.MongoDBFlexCustomEndpoint == "" {
|
||||||
|
client, err = cdn.NewAPIClient()
|
||||||
|
} else {
|
||||||
|
client, err = cdn.NewAPIClient(
|
||||||
|
config.WithEndpoint(testutil.MongoDBFlexCustomEndpoint),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("creating client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
distributionsToDestroy := []string{}
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "stackit_mongodbflex_instance" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
distributionId := strings.Split(rs.Primary.ID, core.Separator)[1]
|
||||||
|
distributionsToDestroy = append(distributionsToDestroy, distributionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dist := range distributionsToDestroy {
|
||||||
|
_, err := client.DeleteDistribution(ctx, testutil.ProjectId, dist).Execute()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("destroying CDN distribution %s during CheckDestroy: %w", dist, err)
|
||||||
|
}
|
||||||
|
_, err = wait.DeleteDistributionWaitHandler(ctx, client, testutil.ProjectId, dist).WaitWithContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("destroying CDN distribution %s during CheckDestroy: waiting for deletion %w", dist, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
203
stackit/internal/services/cdn/distribution/datasource.go
Normal file
203
stackit/internal/services/cdn/distribution/datasource.go
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
package cdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type distributionDataSource struct {
|
||||||
|
client *cdn.APIClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the implementation satisfies the expected interfaces.
|
||||||
|
var (
|
||||||
|
_ datasource.DataSource = &distributionDataSource{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewDistributionDataSource() datasource.DataSource {
|
||||||
|
return &distributionDataSource{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *distributionDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||||
|
if req.ProviderData == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
providerData, ok := req.ProviderData.(core.ProviderData)
|
||||||
|
if !ok {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
features.CheckBetaResourcesEnabled(ctx, &providerData, &resp.Diagnostics, "stackit_cdn_distribution", "datasource")
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiClient *cdn.APIClient
|
||||||
|
var err error
|
||||||
|
if providerData.CdnCustomEndpoint != "" {
|
||||||
|
apiClient, err = cdn.NewAPIClient(
|
||||||
|
config.WithCustomAuth(providerData.RoundTripper),
|
||||||
|
config.WithEndpoint(providerData.CdnCustomEndpoint),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
apiClient, err = cdn.NewAPIClient(
|
||||||
|
config.WithCustomAuth(providerData.RoundTripper),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.client = apiClient
|
||||||
|
tflog.Info(ctx, "Service Account client configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||||
|
resp.TypeName = req.ProviderTypeName + "_cdn_distribution"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||||
|
resp.Schema = schema.Schema{
|
||||||
|
MarkdownDescription: features.AddBetaDescription("CDN distribution data source schema."),
|
||||||
|
Description: "CDN distribution data source schema.",
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["id"],
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"distribution_id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["project_id"],
|
||||||
|
Required: true,
|
||||||
|
Validators: []validator.String{
|
||||||
|
validate.UUID(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"project_id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["project_id"],
|
||||||
|
Required: true,
|
||||||
|
Validators: []validator.String{
|
||||||
|
validate.UUID(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"status": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["status"],
|
||||||
|
},
|
||||||
|
"created_at": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["created_at"],
|
||||||
|
},
|
||||||
|
"updated_at": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["updated_at"],
|
||||||
|
},
|
||||||
|
"errors": schema.ListAttribute{
|
||||||
|
ElementType: types.StringType,
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["errors"],
|
||||||
|
},
|
||||||
|
"domains": schema.ListNestedAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domains"],
|
||||||
|
NestedObject: schema.NestedAttributeObject{
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"name": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_name"],
|
||||||
|
},
|
||||||
|
"status": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_status"],
|
||||||
|
},
|
||||||
|
"type": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_type"],
|
||||||
|
},
|
||||||
|
"errors": schema.ListAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_errors"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"config": schema.SingleNestedAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config"],
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"backend": schema.SingleNestedAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config_backend"],
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"type": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config_backend_type"],
|
||||||
|
},
|
||||||
|
"origin_url": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config_backend_origin_url"],
|
||||||
|
},
|
||||||
|
"origin_request_headers": schema.MapAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config_backend_origin_request_headers"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"regions": schema.ListAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["config_regions"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model Model
|
||||||
|
diags := req.Config.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
distributionId := model.DistributionId.ValueString()
|
||||||
|
distributionResp, err := r.client.GetDistributionExecute(ctx, projectId, distributionId)
|
||||||
|
if err != nil {
|
||||||
|
utils.LogError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
err,
|
||||||
|
"Reading CDN distribution",
|
||||||
|
fmt.Sprintf("Unable to access CDN distribution %q.", distributionId),
|
||||||
|
map[int]string{},
|
||||||
|
)
|
||||||
|
resp.State.RemoveResource(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = mapFields(distributionResp.Distribution, &model)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN distribution", fmt.Sprintf("Error processing API response: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diags = resp.State.Set(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
}
|
||||||
613
stackit/internal/services/cdn/distribution/resource.go
Normal file
613
stackit/internal/services/cdn/distribution/resource.go
Normal file
|
|
@ -0,0 +1,613 @@
|
||||||
|
package cdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||||
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn/wait"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
|
||||||
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ensure the implementation satisfies the expected interfaces.
|
||||||
|
var (
|
||||||
|
_ resource.Resource = &distributionResource{}
|
||||||
|
_ resource.ResourceWithConfigure = &distributionResource{}
|
||||||
|
_ resource.ResourceWithImportState = &distributionResource{}
|
||||||
|
)
|
||||||
|
|
||||||
|
var schemaDescriptions = map[string]string{
|
||||||
|
"id": "Terraform's internal resource identifier. It is structured as \"`project_id`,`distribution_id`\".",
|
||||||
|
"distribution_id": "CDN distribution ID",
|
||||||
|
"project_id": "STACKIT project ID associated with the distribution",
|
||||||
|
"status": "Status of the distribution",
|
||||||
|
"created_at": "Time when the distribution was created",
|
||||||
|
"updated_at": "Time when the distribution was last updated",
|
||||||
|
"errors": "List of distribution errors",
|
||||||
|
"domains": "List of configured domains for the distribution",
|
||||||
|
"config": "The distribution configuration",
|
||||||
|
"config_backend": "The configured backend for the distribution",
|
||||||
|
"config_regions": "The configured regions where content will be hosted",
|
||||||
|
"config_backend_type": "The configured backend type",
|
||||||
|
"config_backend_origin_url": "The configured backend type for the distribution",
|
||||||
|
"config_backend_origin_request_headers": "The configured origin request headers for the backend",
|
||||||
|
"domain_name": "The name of the domain",
|
||||||
|
"domain_status": "The status of the domain",
|
||||||
|
"domain_type": "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",
|
||||||
|
"domain_errors": "List of domain errors",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Model struct {
|
||||||
|
ID types.String `tfsdk:"id"` // Required by Terraform
|
||||||
|
DistributionId types.String `tfsdk:"distribution_id"` // DistributionID associated with the cdn distribution
|
||||||
|
ProjectId types.String `tfsdk:"project_id"` // ProjectId associated with the cdn distribution
|
||||||
|
Status types.String `tfsdk:"status"` // The status of the cdn distribution
|
||||||
|
CreatedAt types.String `tfsdk:"created_at"` // When the distribution was created
|
||||||
|
UpdatedAt types.String `tfsdk:"updated_at"` // When the distribution was last updated
|
||||||
|
Errors types.List `tfsdk:"errors"` // Any errors that the distribution has
|
||||||
|
Domains types.List `tfsdk:"domains"` // The domains associated with the distribution
|
||||||
|
Config types.Object `tfsdk:"config"` // the configuration of the distribution
|
||||||
|
}
|
||||||
|
|
||||||
|
type distributionConfig struct {
|
||||||
|
Backend backend `tfsdk:"backend"` // The backend associated with the distribution
|
||||||
|
Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached
|
||||||
|
}
|
||||||
|
|
||||||
|
type backend struct {
|
||||||
|
Type string `tfsdk:"type"` // The type of the backend. Currently, only "http" backend is supported
|
||||||
|
OriginURL string `tfsdk:"origin_url"` // The origin URL of the backend
|
||||||
|
OriginRequestHeaders *map[string]string `tfsdk:"origin_request_headers"` // Request headers that should be added by the CDN distribution to incoming requests
|
||||||
|
}
|
||||||
|
|
||||||
|
var configTypes = map[string]attr.Type{
|
||||||
|
"backend": types.ObjectType{AttrTypes: backendTypes},
|
||||||
|
"regions": types.ListType{ElemType: types.StringType},
|
||||||
|
}
|
||||||
|
|
||||||
|
var backendTypes = map[string]attr.Type{
|
||||||
|
"type": types.StringType,
|
||||||
|
"origin_url": types.StringType,
|
||||||
|
"origin_request_headers": types.MapType{ElemType: types.StringType},
|
||||||
|
}
|
||||||
|
|
||||||
|
var domainTypes = map[string]attr.Type{
|
||||||
|
"name": types.StringType,
|
||||||
|
"status": types.StringType,
|
||||||
|
"type": types.StringType,
|
||||||
|
"errors": types.ListType{ElemType: types.StringType},
|
||||||
|
}
|
||||||
|
|
||||||
|
type distributionResource struct {
|
||||||
|
client *cdn.APIClient
|
||||||
|
providerData core.ProviderData
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDistributionResource() resource.Resource {
|
||||||
|
return &distributionResource{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||||
|
if req.ProviderData == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ok bool
|
||||||
|
if r.providerData, ok = req.ProviderData.(core.ProviderData); !ok {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
features.CheckBetaResourcesEnabled(ctx, &r.providerData, &resp.Diagnostics, "stackit_cdn_distribution", "resource")
|
||||||
|
|
||||||
|
var apiClient *cdn.APIClient
|
||||||
|
var err error
|
||||||
|
if r.providerData.CdnCustomEndpoint != "" {
|
||||||
|
ctx = tflog.SetField(ctx, "cdn_custom_endpoint", r.providerData.CdnCustomEndpoint)
|
||||||
|
apiClient, err = cdn.NewAPIClient(
|
||||||
|
config.WithCustomAuth(r.providerData.RoundTripper),
|
||||||
|
config.WithEndpoint(r.providerData.CdnCustomEndpoint),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
apiClient, err = cdn.NewAPIClient(
|
||||||
|
config.WithCustomAuth(r.providerData.RoundTripper),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.client = apiClient
|
||||||
|
tflog.Info(ctx, "CDN client configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||||
|
resp.TypeName = req.ProviderTypeName + "_cdn_distribution"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||||
|
resp.Schema = schema.Schema{
|
||||||
|
MarkdownDescription: features.AddBetaDescription("CDN distribution data source schema."),
|
||||||
|
Description: "CDN distribution data source schema.",
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["id"],
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"distribution_id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["project_id"],
|
||||||
|
Computed: true,
|
||||||
|
Validators: []validator.String{validate.UUID()},
|
||||||
|
PlanModifiers: []planmodifier.String{
|
||||||
|
stringplanmodifier.UseStateForUnknown(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"project_id": schema.StringAttribute{
|
||||||
|
Description: schemaDescriptions["project_id"],
|
||||||
|
Required: true,
|
||||||
|
Optional: false,
|
||||||
|
PlanModifiers: []planmodifier.String{
|
||||||
|
stringplanmodifier.RequiresReplace(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"status": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["status"],
|
||||||
|
},
|
||||||
|
"created_at": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["created_at"],
|
||||||
|
},
|
||||||
|
"updated_at": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["updated_at"],
|
||||||
|
},
|
||||||
|
"errors": schema.ListAttribute{
|
||||||
|
ElementType: types.StringType,
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["errors"],
|
||||||
|
},
|
||||||
|
"domains": schema.ListNestedAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domains"],
|
||||||
|
NestedObject: schema.NestedAttributeObject{
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"name": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_name"],
|
||||||
|
},
|
||||||
|
"status": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_status"],
|
||||||
|
},
|
||||||
|
"type": schema.StringAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_type"],
|
||||||
|
},
|
||||||
|
"errors": schema.ListAttribute{
|
||||||
|
Computed: true,
|
||||||
|
Description: schemaDescriptions["domain_errors"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"config": schema.SingleNestedAttribute{
|
||||||
|
Required: true,
|
||||||
|
Description: schemaDescriptions["config"],
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"backend": schema.SingleNestedAttribute{
|
||||||
|
Required: true,
|
||||||
|
Description: schemaDescriptions["config_backend"],
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"type": schema.StringAttribute{
|
||||||
|
Required: true,
|
||||||
|
Description: schemaDescriptions["config_backend_type"],
|
||||||
|
},
|
||||||
|
"origin_url": schema.StringAttribute{
|
||||||
|
Required: true,
|
||||||
|
Description: schemaDescriptions["config_backend_origin_url"],
|
||||||
|
},
|
||||||
|
"origin_request_headers": schema.MapAttribute{
|
||||||
|
Optional: true,
|
||||||
|
Description: schemaDescriptions["config_backend_origin_request_headers"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"regions": schema.ListAttribute{
|
||||||
|
Required: true,
|
||||||
|
Description: schemaDescriptions["config_regions"],
|
||||||
|
ElementType: types.StringType,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model Model
|
||||||
|
diags := req.Plan.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
|
||||||
|
payload, err := toCreatePayload(ctx, &model)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Creating API payload: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createResp, err := r.client.CreateDistribution(ctx, projectId).CreateDistributionPayload(*payload).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
waitResp, err := wait.CreateDistributionPoolWaitHandler(ctx, r.client, projectId, *createResp.Distribution.Id).WaitWithContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Waiting for create: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mapFields(waitResp.Distribution, &model)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Processing API payload: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "CDN distribution created")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model Model
|
||||||
|
diags := req.State.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
distributionId := model.DistributionId.ValueString()
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||||
|
|
||||||
|
cdnResp, err := r.client.GetDistribution(ctx, projectId, distributionId).Execute()
|
||||||
|
if err != nil {
|
||||||
|
var oapiErr *oapierror.GenericOpenAPIError
|
||||||
|
// n.b. err is caught here if of type *oapierror.GenericOpenAPIError, which the stackit SDK client returns
|
||||||
|
if errors.As(err, &oapiErr) {
|
||||||
|
if oapiErr.StatusCode == http.StatusNotFound {
|
||||||
|
resp.State.RemoveResource(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN distribution", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = mapFields(cdnResp.Distribution, &model)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN ditribution", fmt.Sprintf("Processing API payload: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Set refreshed state
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "CDN distribution read")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model Model
|
||||||
|
diags := req.Plan.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
distributionId := model.DistributionId.ValueString()
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||||
|
|
||||||
|
configModel := distributionConfig{}
|
||||||
|
diags = model.Config.As(ctx, &configModel, basetypes.ObjectAsOptions{
|
||||||
|
UnhandledNullAsEmpty: false,
|
||||||
|
UnhandledUnknownAsEmpty: false,
|
||||||
|
})
|
||||||
|
if diags.HasError() {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", "Error mapping config")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
regions := []cdn.Region{}
|
||||||
|
for _, r := range *configModel.Regions {
|
||||||
|
regionEnum, err := cdn.NewRegionFromValue(r)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Map regions: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
regions = append(regions, *regionEnum)
|
||||||
|
}
|
||||||
|
_, err := r.client.PatchDistribution(ctx, projectId, distributionId).PatchDistributionPayload(cdn.PatchDistributionPayload{
|
||||||
|
Config: &cdn.ConfigPatch{
|
||||||
|
Backend: &cdn.ConfigPatchBackend{
|
||||||
|
HttpBackendPatch: &cdn.HttpBackendPatch{
|
||||||
|
OriginRequestHeaders: configModel.Backend.OriginRequestHeaders,
|
||||||
|
OriginUrl: &configModel.Backend.OriginURL,
|
||||||
|
Type: &configModel.Backend.Type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Regions: ®ions,
|
||||||
|
},
|
||||||
|
IntentId: cdn.PtrString(uuid.NewString()),
|
||||||
|
}).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Patch distribution: %v", err))
|
||||||
|
}
|
||||||
|
waitResp, err := wait.UpdateDistributionWaitHandler(ctx, r.client, projectId, distributionId).WaitWithContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Waiting for update: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mapFields(waitResp.Distribution, &model)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Processing API payload: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "CDN distribution updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model Model
|
||||||
|
diags := req.State.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
distributionId := model.DistributionId.ValueString()
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||||
|
|
||||||
|
_, err := r.client.DeleteDistribution(ctx, projectId, distributionId).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN distribution", fmt.Sprintf("Delete distribution: %v", err))
|
||||||
|
}
|
||||||
|
_, err = wait.DeleteDistributionWaitHandler(ctx, r.client, projectId, distributionId).WaitWithContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN distribution", fmt.Sprintf("Waiting for deletion: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "CDN distribution deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *distributionResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||||
|
idParts := strings.Split(req.ID, core.Separator)
|
||||||
|
|
||||||
|
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error importing CDN distribution", fmt.Sprintf("Expected import identifier on the format: [project_id]%q[distribution_id], got %q", core.Separator, req.ID))
|
||||||
|
}
|
||||||
|
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...)
|
||||||
|
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("distribution_id"), idParts[1])...)
|
||||||
|
tflog.Info(ctx, "CDN distribution state imported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapFields(distribution *cdn.Distribution, model *Model) error {
|
||||||
|
if distribution == nil {
|
||||||
|
return fmt.Errorf("response input is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if distribution.ProjectId == nil {
|
||||||
|
return fmt.Errorf("Project ID not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
if distribution.Id == nil {
|
||||||
|
return fmt.Errorf("CDN distribution ID not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
if distribution.CreatedAt == nil {
|
||||||
|
return fmt.Errorf("CreatedAt missing in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if distribution.UpdatedAt == nil {
|
||||||
|
return fmt.Errorf("UpdatedAt missing in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if distribution.Status == nil {
|
||||||
|
return fmt.Errorf("Status missing in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
id := *distribution.ProjectId + core.Separator + *distribution.Id
|
||||||
|
|
||||||
|
model.ID = types.StringValue(id)
|
||||||
|
model.DistributionId = types.StringValue(*distribution.Id)
|
||||||
|
model.ProjectId = types.StringValue(*distribution.ProjectId)
|
||||||
|
model.Status = types.StringValue(*distribution.Status)
|
||||||
|
model.CreatedAt = types.StringValue(distribution.CreatedAt.String())
|
||||||
|
model.UpdatedAt = types.StringValue(distribution.UpdatedAt.String())
|
||||||
|
|
||||||
|
distributionErrors := []attr.Value{}
|
||||||
|
if distribution.Errors != nil {
|
||||||
|
for _, e := range *distribution.Errors {
|
||||||
|
distributionErrors = append(distributionErrors, types.StringValue(*e.En))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modelErrors, diags := types.ListValue(types.StringType, distributionErrors)
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
model.Errors = modelErrors
|
||||||
|
|
||||||
|
regions := []attr.Value{}
|
||||||
|
for _, r := range *distribution.Config.Regions {
|
||||||
|
regions = append(regions, types.StringValue(string(r)))
|
||||||
|
}
|
||||||
|
modelRegions, diags := types.ListValue(types.StringType, regions)
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
originRequestHeaders := types.MapNull(types.StringType)
|
||||||
|
if origHeaders := distribution.Config.Backend.HttpBackend.OriginRequestHeaders; origHeaders != nil && len(*origHeaders) > 0 {
|
||||||
|
headers := map[string]attr.Value{}
|
||||||
|
for k, v := range *origHeaders {
|
||||||
|
headers[k] = types.StringValue(v)
|
||||||
|
}
|
||||||
|
mappedHeaders, diags := types.MapValue(types.StringType, headers)
|
||||||
|
originRequestHeaders = mappedHeaders
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// note that httpbackend is hardcoded here as long as it is the only available backend
|
||||||
|
backend, diags := types.ObjectValue(backendTypes, map[string]attr.Value{
|
||||||
|
"type": types.StringValue(*distribution.Config.Backend.HttpBackend.Type),
|
||||||
|
"origin_url": types.StringValue(*distribution.Config.Backend.HttpBackend.OriginUrl),
|
||||||
|
"origin_request_headers": originRequestHeaders,
|
||||||
|
})
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
cfg, diags := types.ObjectValue(configTypes, map[string]attr.Value{
|
||||||
|
"backend": backend,
|
||||||
|
"regions": modelRegions,
|
||||||
|
})
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
model.Config = cfg
|
||||||
|
|
||||||
|
domains := []attr.Value{}
|
||||||
|
if distribution.Domains != nil {
|
||||||
|
for _, d := range *distribution.Domains {
|
||||||
|
domainErrors := []attr.Value{}
|
||||||
|
if d.Errors != nil {
|
||||||
|
for _, e := range *d.Errors {
|
||||||
|
if e.En == nil {
|
||||||
|
return fmt.Errorf("error description missing")
|
||||||
|
}
|
||||||
|
domainErrors = append(domainErrors, types.StringValue(*e.En))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modelDomainErrors, diags := types.ListValue(types.StringType, domainErrors)
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
if d.Name == nil || d.Status == nil || d.Type == nil {
|
||||||
|
return fmt.Errorf("domain entry incomplete")
|
||||||
|
}
|
||||||
|
modelDomain, diags := types.ObjectValue(domainTypes, map[string]attr.Value{
|
||||||
|
"name": types.StringValue(*d.Name),
|
||||||
|
"status": types.StringValue(string(*d.Status)),
|
||||||
|
"type": types.StringValue(*d.Type),
|
||||||
|
"errors": modelDomainErrors,
|
||||||
|
})
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
|
||||||
|
domains = append(domains, modelDomain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modelDomains, diags := types.ListValue(types.ObjectType{AttrTypes: domainTypes}, domains)
|
||||||
|
if diags.HasError() {
|
||||||
|
return core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
model.Domains = modelDomains
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toCreatePayload(ctx context.Context, model *Model) (*cdn.CreateDistributionPayload, error) {
|
||||||
|
if model == nil {
|
||||||
|
return nil, fmt.Errorf("missing model")
|
||||||
|
}
|
||||||
|
cfg, err := convertConfig(ctx, model)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload := &cdn.CreateDistributionPayload{
|
||||||
|
IntentId: cdn.PtrString(uuid.NewString()),
|
||||||
|
OriginUrl: cfg.Backend.HttpBackend.OriginUrl,
|
||||||
|
Regions: cfg.Regions,
|
||||||
|
OriginRequestHeaders: cfg.Backend.HttpBackend.OriginRequestHeaders,
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
|
||||||
|
if model == nil {
|
||||||
|
return nil, errors.New("model cannot be nil")
|
||||||
|
}
|
||||||
|
if model.Config.IsNull() || model.Config.IsUnknown() {
|
||||||
|
return nil, errors.New("config cannot be nil or unknown")
|
||||||
|
}
|
||||||
|
configModel := distributionConfig{}
|
||||||
|
diags := model.Config.As(ctx, &configModel, basetypes.ObjectAsOptions{
|
||||||
|
UnhandledNullAsEmpty: false,
|
||||||
|
UnhandledUnknownAsEmpty: false,
|
||||||
|
})
|
||||||
|
if diags.HasError() {
|
||||||
|
return nil, core.DiagsToError(diags)
|
||||||
|
}
|
||||||
|
regions := []cdn.Region{}
|
||||||
|
for _, r := range *configModel.Regions {
|
||||||
|
regionEnum, err := cdn.NewRegionFromValue(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
regions = append(regions, *regionEnum)
|
||||||
|
}
|
||||||
|
|
||||||
|
originRequestHeaders := map[string]string{}
|
||||||
|
if configModel.Backend.OriginRequestHeaders != nil {
|
||||||
|
for k, v := range *configModel.Backend.OriginRequestHeaders {
|
||||||
|
originRequestHeaders[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &cdn.Config{
|
||||||
|
Backend: &cdn.ConfigBackend{
|
||||||
|
HttpBackend: &cdn.HttpBackend{
|
||||||
|
OriginRequestHeaders: &originRequestHeaders,
|
||||||
|
OriginUrl: &configModel.Backend.OriginURL,
|
||||||
|
Type: &configModel.Backend.Type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Regions: ®ions,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
342
stackit/internal/services/cdn/distribution/resource_test.go
Normal file
342
stackit/internal/services/cdn/distribution/resource_test.go
Normal file
|
|
@ -0,0 +1,342 @@
|
||||||
|
package cdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToCreatePayload(t *testing.T) {
|
||||||
|
headers := map[string]attr.Value{
|
||||||
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
||||||
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
||||||
|
}
|
||||||
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
||||||
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
||||||
|
"type": types.StringValue("http"),
|
||||||
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
||||||
|
"origin_request_headers": originRequestHeaders,
|
||||||
|
})
|
||||||
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
||||||
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
||||||
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
||||||
|
"backend": backend,
|
||||||
|
"regions": regionsFixture,
|
||||||
|
})
|
||||||
|
modelFixture := func(mods ...func(*Model)) *Model {
|
||||||
|
model := &Model{
|
||||||
|
DistributionId: types.StringValue("test-distribution-id"),
|
||||||
|
ProjectId: types.StringValue("test-project-id"),
|
||||||
|
Config: config,
|
||||||
|
}
|
||||||
|
for _, mod := range mods {
|
||||||
|
mod(model)
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
tests := map[string]struct {
|
||||||
|
Input *Model
|
||||||
|
Expected *cdn.CreateDistributionPayload
|
||||||
|
IsValid bool
|
||||||
|
}{
|
||||||
|
"happy_path": {
|
||||||
|
Input: modelFixture(),
|
||||||
|
Expected: &cdn.CreateDistributionPayload{
|
||||||
|
OriginRequestHeaders: &map[string]string{
|
||||||
|
"testHeader0": "testHeaderValue0",
|
||||||
|
"testHeader1": "testHeaderValue1",
|
||||||
|
},
|
||||||
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
||||||
|
Regions: &[]cdn.Region{"EU", "US"},
|
||||||
|
},
|
||||||
|
IsValid: true,
|
||||||
|
},
|
||||||
|
"sad_path_model_nil": {
|
||||||
|
Input: nil,
|
||||||
|
Expected: nil,
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
"sad_path_config_error": {
|
||||||
|
Input: modelFixture(func(m *Model) {
|
||||||
|
m.Config = types.ObjectNull(configTypes)
|
||||||
|
}),
|
||||||
|
Expected: nil,
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for tn, tc := range tests {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
res, err := toCreatePayload(context.Background(), tc.Input)
|
||||||
|
if err != nil && tc.IsValid {
|
||||||
|
t.Fatalf("Error converting model to create payload: %v", err)
|
||||||
|
}
|
||||||
|
if err == nil && !tc.IsValid {
|
||||||
|
t.Fatalf("Should have failed")
|
||||||
|
}
|
||||||
|
if tc.IsValid {
|
||||||
|
// set generated ID before diffing
|
||||||
|
tc.Expected.IntentId = res.IntentId
|
||||||
|
|
||||||
|
diff := cmp.Diff(res, tc.Expected)
|
||||||
|
if diff != "" {
|
||||||
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertConfig(t *testing.T) {
|
||||||
|
headers := map[string]attr.Value{
|
||||||
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
||||||
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
||||||
|
}
|
||||||
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
||||||
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
||||||
|
"type": types.StringValue("http"),
|
||||||
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
||||||
|
"origin_request_headers": originRequestHeaders,
|
||||||
|
})
|
||||||
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
||||||
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
||||||
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
||||||
|
"backend": backend,
|
||||||
|
"regions": regionsFixture,
|
||||||
|
})
|
||||||
|
modelFixture := func(mods ...func(*Model)) *Model {
|
||||||
|
model := &Model{
|
||||||
|
DistributionId: types.StringValue("test-distribution-id"),
|
||||||
|
ProjectId: types.StringValue("test-project-id"),
|
||||||
|
Config: config,
|
||||||
|
}
|
||||||
|
for _, mod := range mods {
|
||||||
|
mod(model)
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
tests := map[string]struct {
|
||||||
|
Input *Model
|
||||||
|
Expected *cdn.Config
|
||||||
|
IsValid bool
|
||||||
|
}{
|
||||||
|
"happy_path": {
|
||||||
|
Input: modelFixture(),
|
||||||
|
Expected: &cdn.Config{
|
||||||
|
Backend: &cdn.ConfigBackend{
|
||||||
|
HttpBackend: &cdn.HttpBackend{
|
||||||
|
OriginRequestHeaders: &map[string]string{
|
||||||
|
"testHeader0": "testHeaderValue0",
|
||||||
|
"testHeader1": "testHeaderValue1",
|
||||||
|
},
|
||||||
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
||||||
|
Type: cdn.PtrString("http"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Regions: &[]cdn.Region{"EU", "US"},
|
||||||
|
},
|
||||||
|
IsValid: true,
|
||||||
|
},
|
||||||
|
"sad_path_model_nil": {
|
||||||
|
Input: nil,
|
||||||
|
Expected: nil,
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
"sad_path_config_error": {
|
||||||
|
Input: modelFixture(func(m *Model) {
|
||||||
|
m.Config = types.ObjectNull(configTypes)
|
||||||
|
}),
|
||||||
|
Expected: nil,
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for tn, tc := range tests {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
res, err := convertConfig(context.Background(), tc.Input)
|
||||||
|
if err != nil && tc.IsValid {
|
||||||
|
t.Fatalf("Error converting model to create payload: %v", err)
|
||||||
|
}
|
||||||
|
if err == nil && !tc.IsValid {
|
||||||
|
t.Fatalf("Should have failed")
|
||||||
|
}
|
||||||
|
if tc.IsValid {
|
||||||
|
diff := cmp.Diff(res, tc.Expected)
|
||||||
|
if diff != "" {
|
||||||
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFields(t *testing.T) {
|
||||||
|
createdAt := time.Now()
|
||||||
|
updatedAt := time.Now()
|
||||||
|
headers := map[string]attr.Value{
|
||||||
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
||||||
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
||||||
|
}
|
||||||
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
||||||
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
||||||
|
"type": types.StringValue("http"),
|
||||||
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
||||||
|
"origin_request_headers": originRequestHeaders,
|
||||||
|
})
|
||||||
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
||||||
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
||||||
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
||||||
|
"backend": backend,
|
||||||
|
"regions": regionsFixture,
|
||||||
|
})
|
||||||
|
emtpyErrorsList := types.ListValueMust(types.StringType, []attr.Value{})
|
||||||
|
managedDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
||||||
|
"name": types.StringValue("test.stackit-cdn.com"),
|
||||||
|
"status": types.StringValue("ACTIVE"),
|
||||||
|
"type": types.StringValue("managed"),
|
||||||
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
||||||
|
})
|
||||||
|
domains := types.ListValueMust(types.ObjectType{AttrTypes: domainTypes}, []attr.Value{managedDomain})
|
||||||
|
expectedModel := func(mods ...func(*Model)) *Model {
|
||||||
|
model := &Model{
|
||||||
|
ID: types.StringValue("test-project-id,test-distribution-id"),
|
||||||
|
DistributionId: types.StringValue("test-distribution-id"),
|
||||||
|
ProjectId: types.StringValue("test-project-id"),
|
||||||
|
Config: config,
|
||||||
|
Status: types.StringValue("ACTIVE"),
|
||||||
|
CreatedAt: types.StringValue(createdAt.String()),
|
||||||
|
UpdatedAt: types.StringValue(updatedAt.String()),
|
||||||
|
Errors: emtpyErrorsList,
|
||||||
|
Domains: domains,
|
||||||
|
}
|
||||||
|
for _, mod := range mods {
|
||||||
|
mod(model)
|
||||||
|
}
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
distributionFixture := func(mods ...func(*cdn.Distribution)) *cdn.Distribution {
|
||||||
|
distribution := &cdn.Distribution{
|
||||||
|
Config: &cdn.Config{Backend: &cdn.ConfigBackend{
|
||||||
|
HttpBackend: &cdn.HttpBackend{
|
||||||
|
OriginRequestHeaders: &map[string]string{
|
||||||
|
"testHeader0": "testHeaderValue0",
|
||||||
|
"testHeader1": "testHeaderValue1",
|
||||||
|
},
|
||||||
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
||||||
|
Type: cdn.PtrString("http"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Regions: &[]cdn.Region{"EU", "US"},
|
||||||
|
},
|
||||||
|
CreatedAt: &createdAt,
|
||||||
|
Domains: &[]cdn.Domain{
|
||||||
|
{
|
||||||
|
Name: cdn.PtrString("test.stackit-cdn.com"),
|
||||||
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
||||||
|
Type: cdn.PtrString("managed"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Id: cdn.PtrString("test-distribution-id"),
|
||||||
|
ProjectId: cdn.PtrString("test-project-id"),
|
||||||
|
Status: cdn.PtrString("ACTIVE"),
|
||||||
|
UpdatedAt: &updatedAt,
|
||||||
|
}
|
||||||
|
for _, mod := range mods {
|
||||||
|
mod(distribution)
|
||||||
|
}
|
||||||
|
return distribution
|
||||||
|
}
|
||||||
|
tests := map[string]struct {
|
||||||
|
Input *cdn.Distribution
|
||||||
|
Expected *Model
|
||||||
|
IsValid bool
|
||||||
|
}{
|
||||||
|
"happy_path": {
|
||||||
|
Expected: expectedModel(),
|
||||||
|
Input: distributionFixture(),
|
||||||
|
IsValid: true,
|
||||||
|
},
|
||||||
|
"happy_path_status_error": {
|
||||||
|
Expected: expectedModel(func(m *Model) {
|
||||||
|
m.Status = types.StringValue("ERROR")
|
||||||
|
}),
|
||||||
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
||||||
|
d.Status = cdn.PtrString("ERROR")
|
||||||
|
}),
|
||||||
|
IsValid: true,
|
||||||
|
},
|
||||||
|
"happy_path_custom_domain": {
|
||||||
|
Expected: expectedModel(func(m *Model) {
|
||||||
|
managedDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
||||||
|
"name": types.StringValue("test.stackit-cdn.com"),
|
||||||
|
"status": types.StringValue("ACTIVE"),
|
||||||
|
"type": types.StringValue("managed"),
|
||||||
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
||||||
|
})
|
||||||
|
customDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
||||||
|
"name": types.StringValue("mycoolapp.info"),
|
||||||
|
"status": types.StringValue("ACTIVE"),
|
||||||
|
"type": types.StringValue("custom"),
|
||||||
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
||||||
|
})
|
||||||
|
domains := types.ListValueMust(types.ObjectType{AttrTypes: domainTypes}, []attr.Value{managedDomain, customDomain})
|
||||||
|
m.Domains = domains
|
||||||
|
}),
|
||||||
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
||||||
|
d.Domains = &[]cdn.Domain{
|
||||||
|
{
|
||||||
|
Name: cdn.PtrString("test.stackit-cdn.com"),
|
||||||
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
||||||
|
Type: cdn.PtrString("managed"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: cdn.PtrString("mycoolapp.info"),
|
||||||
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
||||||
|
Type: cdn.PtrString("custom"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
IsValid: true,
|
||||||
|
},
|
||||||
|
"sad_path_distribution_nil": {
|
||||||
|
Expected: nil,
|
||||||
|
Input: nil,
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
"sad_path_project_id_missing": {
|
||||||
|
Expected: expectedModel(),
|
||||||
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
||||||
|
d.ProjectId = nil
|
||||||
|
}),
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
"sad_path_distribution_id_missing": {
|
||||||
|
Expected: expectedModel(),
|
||||||
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
||||||
|
d.Id = nil
|
||||||
|
}),
|
||||||
|
IsValid: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for tn, tc := range tests {
|
||||||
|
t.Run(tn, func(t *testing.T) {
|
||||||
|
model := &Model{}
|
||||||
|
err := mapFields(tc.Input, model)
|
||||||
|
if err != nil && tc.IsValid {
|
||||||
|
t.Fatalf("Error mapping fields: %v", err)
|
||||||
|
}
|
||||||
|
if err == nil && !tc.IsValid {
|
||||||
|
t.Fatalf("Should have failed")
|
||||||
|
}
|
||||||
|
if tc.IsValid {
|
||||||
|
diff := cmp.Diff(model, tc.Expected)
|
||||||
|
if diff != "" {
|
||||||
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,6 +51,7 @@ var (
|
||||||
TestImageLocalFilePath = getenv("TF_ACC_TEST_IMAGE_LOCAL_FILE_PATH", "default")
|
TestImageLocalFilePath = getenv("TF_ACC_TEST_IMAGE_LOCAL_FILE_PATH", "default")
|
||||||
|
|
||||||
ArgusCustomEndpoint = os.Getenv("TF_ACC_ARGUS_CUSTOM_ENDPOINT")
|
ArgusCustomEndpoint = os.Getenv("TF_ACC_ARGUS_CUSTOM_ENDPOINT")
|
||||||
|
CdnCustomEndpoint = os.Getenv("TF_ACC_CDN_CUSTOM_ENDPOINT")
|
||||||
DnsCustomEndpoint = os.Getenv("TF_ACC_DNS_CUSTOM_ENDPOINT")
|
DnsCustomEndpoint = os.Getenv("TF_ACC_DNS_CUSTOM_ENDPOINT")
|
||||||
IaaSCustomEndpoint = os.Getenv("TF_ACC_IAAS_CUSTOM_ENDPOINT")
|
IaaSCustomEndpoint = os.Getenv("TF_ACC_IAAS_CUSTOM_ENDPOINT")
|
||||||
LoadBalancerCustomEndpoint = os.Getenv("TF_ACC_LOADBALANCER_CUSTOM_ENDPOINT")
|
LoadBalancerCustomEndpoint = os.Getenv("TF_ACC_LOADBALANCER_CUSTOM_ENDPOINT")
|
||||||
|
|
@ -105,6 +106,17 @@ func ObservabilityProviderConfig() string {
|
||||||
ObservabilityCustomEndpoint,
|
ObservabilityCustomEndpoint,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
func CdnProviderConfig() string {
|
||||||
|
if CdnCustomEndpoint == "" {
|
||||||
|
return `provider "stackit" {}`
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
provider "stackit" {
|
||||||
|
cdn_custom_endpoint = "%s"
|
||||||
|
}`,
|
||||||
|
CdnCustomEndpoint,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func DnsProviderConfig() string {
|
func DnsProviderConfig() string {
|
||||||
if DnsCustomEndpoint == "" {
|
if DnsCustomEndpoint == "" {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
|
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
|
||||||
roleAssignements "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/authorization/roleassignments"
|
roleAssignements "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/authorization/roleassignments"
|
||||||
|
cdn "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/cdn/distribution"
|
||||||
dnsRecordSet "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/recordset"
|
dnsRecordSet "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/recordset"
|
||||||
dnsZone "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/zone"
|
dnsZone "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/zone"
|
||||||
iaasAffinityGroup "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/affinitygroup"
|
iaasAffinityGroup "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/affinitygroup"
|
||||||
|
|
@ -114,6 +115,7 @@ type providerModel struct {
|
||||||
Region types.String `tfsdk:"region"`
|
Region types.String `tfsdk:"region"`
|
||||||
DefaultRegion types.String `tfsdk:"default_region"`
|
DefaultRegion types.String `tfsdk:"default_region"`
|
||||||
ArgusCustomEndpoint types.String `tfsdk:"argus_custom_endpoint"`
|
ArgusCustomEndpoint types.String `tfsdk:"argus_custom_endpoint"`
|
||||||
|
CdnCustomEndpoint types.String `tfsdk:"cdn_custom_endpoint"`
|
||||||
DNSCustomEndpoint types.String `tfsdk:"dns_custom_endpoint"`
|
DNSCustomEndpoint types.String `tfsdk:"dns_custom_endpoint"`
|
||||||
IaaSCustomEndpoint types.String `tfsdk:"iaas_custom_endpoint"`
|
IaaSCustomEndpoint types.String `tfsdk:"iaas_custom_endpoint"`
|
||||||
PostgresFlexCustomEndpoint types.String `tfsdk:"postgresflex_custom_endpoint"`
|
PostgresFlexCustomEndpoint types.String `tfsdk:"postgresflex_custom_endpoint"`
|
||||||
|
|
@ -154,6 +156,7 @@ func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *pro
|
||||||
"region": "Region will be used as the default location for regional services. Not all services require a region, some are global",
|
"region": "Region will be used as the default location for regional services. Not all services require a region, some are global",
|
||||||
"default_region": "Region will be used as the default location for regional services. Not all services require a region, some are global",
|
"default_region": "Region will be used as the default location for regional services. Not all services require a region, some are global",
|
||||||
"argus_custom_endpoint": "Custom endpoint for the Argus service",
|
"argus_custom_endpoint": "Custom endpoint for the Argus service",
|
||||||
|
"cdn_custom_endpoint": "Custom endpoint for the CDN service",
|
||||||
"dns_custom_endpoint": "Custom endpoint for the DNS service",
|
"dns_custom_endpoint": "Custom endpoint for the DNS service",
|
||||||
"iaas_custom_endpoint": "Custom endpoint for the IaaS service",
|
"iaas_custom_endpoint": "Custom endpoint for the IaaS service",
|
||||||
"mongodbflex_custom_endpoint": "Custom endpoint for the MongoDB Flex service",
|
"mongodbflex_custom_endpoint": "Custom endpoint for the MongoDB Flex service",
|
||||||
|
|
@ -232,6 +235,10 @@ func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *pro
|
||||||
Description: descriptions["argus_custom_endpoint"],
|
Description: descriptions["argus_custom_endpoint"],
|
||||||
DeprecationMessage: "Argus service has been deprecated and integration will be removed after February 26th 2025. Please use `observability_custom_endpoint` and `observability` resources instead, which offer the exact same functionality.",
|
DeprecationMessage: "Argus service has been deprecated and integration will be removed after February 26th 2025. Please use `observability_custom_endpoint` and `observability` resources instead, which offer the exact same functionality.",
|
||||||
},
|
},
|
||||||
|
"cdn_custom_endpoint": schema.StringAttribute{
|
||||||
|
Optional: true,
|
||||||
|
Description: descriptions["cdn_custom_endpoint"],
|
||||||
|
},
|
||||||
"dns_custom_endpoint": schema.StringAttribute{
|
"dns_custom_endpoint": schema.StringAttribute{
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: descriptions["dns_custom_endpoint"],
|
Description: descriptions["dns_custom_endpoint"],
|
||||||
|
|
@ -373,6 +380,9 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
|
||||||
} else if !(providerConfig.Region.IsUnknown() || providerConfig.Region.IsNull()) { // nolint:staticcheck // preliminary handling of deprecated attribute
|
} else if !(providerConfig.Region.IsUnknown() || providerConfig.Region.IsNull()) { // nolint:staticcheck // preliminary handling of deprecated attribute
|
||||||
providerData.Region = providerConfig.Region.ValueString() // nolint:staticcheck // preliminary handling of deprecated attribute
|
providerData.Region = providerConfig.Region.ValueString() // nolint:staticcheck // preliminary handling of deprecated attribute
|
||||||
}
|
}
|
||||||
|
if !(providerConfig.CdnCustomEndpoint.IsUnknown() || providerConfig.CdnCustomEndpoint.IsNull()) {
|
||||||
|
providerData.CdnCustomEndpoint = providerConfig.CdnCustomEndpoint.ValueString()
|
||||||
|
}
|
||||||
if !(providerConfig.DNSCustomEndpoint.IsUnknown() || providerConfig.DNSCustomEndpoint.IsNull()) {
|
if !(providerConfig.DNSCustomEndpoint.IsUnknown() || providerConfig.DNSCustomEndpoint.IsNull()) {
|
||||||
providerData.DnsCustomEndpoint = providerConfig.DNSCustomEndpoint.ValueString()
|
providerData.DnsCustomEndpoint = providerConfig.DNSCustomEndpoint.ValueString()
|
||||||
}
|
}
|
||||||
|
|
@ -465,6 +475,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
|
||||||
func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource {
|
func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource {
|
||||||
return []func() datasource.DataSource{
|
return []func() datasource.DataSource{
|
||||||
alertGroup.NewAlertGroupDataSource,
|
alertGroup.NewAlertGroupDataSource,
|
||||||
|
cdn.NewDistributionDataSource,
|
||||||
dnsZone.NewZoneDataSource,
|
dnsZone.NewZoneDataSource,
|
||||||
dnsRecordSet.NewRecordSetDataSource,
|
dnsRecordSet.NewRecordSetDataSource,
|
||||||
iaasAffinityGroup.NewAffinityGroupDatasource,
|
iaasAffinityGroup.NewAffinityGroupDatasource,
|
||||||
|
|
@ -520,6 +531,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
|
||||||
func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
|
func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
|
||||||
resources := []func() resource.Resource{
|
resources := []func() resource.Resource{
|
||||||
alertGroup.NewAlertGroupResource,
|
alertGroup.NewAlertGroupResource,
|
||||||
|
cdn.NewDistributionResource,
|
||||||
dnsZone.NewZoneResource,
|
dnsZone.NewZoneResource,
|
||||||
dnsRecordSet.NewRecordSetResource,
|
dnsRecordSet.NewRecordSetResource,
|
||||||
iaasAffinityGroup.NewAffinityGroupResource,
|
iaasAffinityGroup.NewAffinityGroupResource,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue