Feature: CDN custom domain resource and data source (#801)
* Feature: CDN custom domain resource and data source * stabilize acceptance tests * add guide * review changes --------- Co-authored-by: Malte Ehrlen <malte.ehrlen@freiheit.com>
This commit is contained in:
parent
0a86417cbb
commit
2d757a93fd
13 changed files with 914 additions and 19 deletions
150
stackit/internal/services/cdn/customdomain/datasource.go
Normal file
150
stackit/internal/services/cdn/customdomain/datasource.go
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
package cdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"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/core/oapierror"
|
||||
"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/validate"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
var (
|
||||
_ datasource.DataSource = &customDomainDataSource{}
|
||||
_ datasource.DataSourceWithConfigure = &customDomainDataSource{}
|
||||
)
|
||||
|
||||
type customDomainDataSource struct {
|
||||
client *cdn.APIClient
|
||||
}
|
||||
|
||||
func NewCustomDomainDataSource() datasource.DataSource {
|
||||
return &customDomainDataSource{}
|
||||
}
|
||||
|
||||
func (d *customDomainDataSource) 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_custom_domain", "datasource")
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
var apiClient *cdn.APIClient
|
||||
var err error
|
||||
if providerData.CdnCustomEndpoint != "" {
|
||||
ctx = tflog.SetField(ctx, "cdn_custom_endpoint", 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, "CDN client configured")
|
||||
}
|
||||
|
||||
func (r *customDomainDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_cdn_custom_domain"
|
||||
}
|
||||
|
||||
func (r *customDomainDataSource) 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: customDomainSchemaDescriptions["id"],
|
||||
Computed: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["name"],
|
||||
Required: true,
|
||||
},
|
||||
"distribution_id": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["distribution_id"],
|
||||
Required: true,
|
||||
Validators: []validator.String{validate.UUID()},
|
||||
},
|
||||
"project_id": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["project_id"],
|
||||
Required: true,
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: customDomainSchemaDescriptions["status"],
|
||||
},
|
||||
"errors": schema.ListAttribute{
|
||||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
Description: customDomainSchemaDescriptions["errors"],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *customDomainDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
var model CustomDomainModel
|
||||
diags := req.Config.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
distributionId := model.DistributionId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||
name := model.Name.ValueString()
|
||||
ctx = tflog.SetField(ctx, "name", name)
|
||||
|
||||
customDomainResp, err := r.client.GetCustomDomain(ctx, projectId, distributionId, name).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 custom domain", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
err = mapCustomDomainFields(customDomainResp.CustomDomain, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", 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 custom domain read")
|
||||
}
|
||||
310
stackit/internal/services/cdn/customdomain/resource.go
Normal file
310
stackit/internal/services/cdn/customdomain/resource.go
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
package cdn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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-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 = &customDomainResource{}
|
||||
_ resource.ResourceWithConfigure = &customDomainResource{}
|
||||
_ resource.ResourceWithImportState = &customDomainResource{}
|
||||
)
|
||||
|
||||
var customDomainSchemaDescriptions = 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",
|
||||
"errors": "List of distribution errors",
|
||||
}
|
||||
|
||||
type CustomDomainModel 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
|
||||
Name types.String `tfsdk:"name"` // The custom domain
|
||||
Status types.String `tfsdk:"status"` // The status of the cdn distribution
|
||||
Errors types.List `tfsdk:"errors"` // Any errors that the distribution has
|
||||
}
|
||||
|
||||
type customDomainResource struct {
|
||||
client *cdn.APIClient
|
||||
providerData core.ProviderData
|
||||
}
|
||||
|
||||
func NewCustomDomainResource() resource.Resource {
|
||||
return &customDomainResource{}
|
||||
}
|
||||
|
||||
func (r *customDomainResource) 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_custom_domain", "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 *customDomainResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_cdn_custom_domain"
|
||||
}
|
||||
|
||||
func (r *customDomainResource) 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: customDomainSchemaDescriptions["id"],
|
||||
Computed: true,
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["name"],
|
||||
Required: true,
|
||||
Optional: false,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"distribution_id": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["distribution_id"],
|
||||
Required: true,
|
||||
Optional: false,
|
||||
Validators: []validator.String{validate.UUID()},
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"project_id": schema.StringAttribute{
|
||||
Description: customDomainSchemaDescriptions["project_id"],
|
||||
Required: true,
|
||||
Optional: false,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: customDomainSchemaDescriptions["status"],
|
||||
},
|
||||
"errors": schema.ListAttribute{
|
||||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
Description: customDomainSchemaDescriptions["errors"],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *customDomainResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
var model CustomDomainModel
|
||||
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)
|
||||
distributionId := model.DistributionId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||
name := model.Name.ValueString()
|
||||
ctx = tflog.SetField(ctx, "name", name)
|
||||
|
||||
payload := cdn.PutCustomDomainPayload{IntentId: cdn.PtrString(uuid.NewString())}
|
||||
|
||||
_, err := r.client.PutCustomDomain(ctx, projectId, distributionId, name).PutCustomDomainPayload(payload).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN custom domain", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
waitResp, err := wait.CreateCDNCustomDomainWaitHandler(ctx, r.client, projectId, distributionId, name).SetTimeout(5 * time.Minute).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN custom domain", fmt.Sprintf("Waiting for create: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = mapCustomDomainFields(waitResp, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN custom domain", 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 custom domain created")
|
||||
}
|
||||
|
||||
func (r *customDomainResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
var model CustomDomainModel
|
||||
diags := req.State.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
distributionId := model.DistributionId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||
name := model.Name.ValueString()
|
||||
ctx = tflog.SetField(ctx, "name", name)
|
||||
|
||||
customDomainResp, err := r.client.GetCustomDomain(ctx, projectId, distributionId, name).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 custom domain", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
err = mapCustomDomainFields(customDomainResp.CustomDomain, &model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", 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 custom domain read")
|
||||
}
|
||||
|
||||
func (r *customDomainResource) Update(ctx context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
// Update shouldn't be called; custom domains have only computed fields and fields that require replacement when changed
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating CDN custom domain", "Custom domain cannot be updated")
|
||||
}
|
||||
|
||||
func (r *customDomainResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
var model CustomDomainModel
|
||||
diags := req.State.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
distributionId := model.DistributionId.ValueString()
|
||||
ctx = tflog.SetField(ctx, "distribution_id", distributionId)
|
||||
name := model.Name.ValueString()
|
||||
ctx = tflog.SetField(ctx, "name", name)
|
||||
|
||||
_, err := r.client.DeleteCustomDomain(ctx, projectId, distributionId, name).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN custom domain", fmt.Sprintf("Delete custom domain: %v", err))
|
||||
}
|
||||
_, err = wait.DeleteCDNCustomDomainWaitHandler(ctx, r.client, projectId, distributionId, name).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN custom domain", fmt.Sprintf("Waiting for deletion: %v", err))
|
||||
return
|
||||
}
|
||||
tflog.Info(ctx, "CDN custom domain deleted")
|
||||
}
|
||||
|
||||
func (r *customDomainResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
idParts := strings.Split(req.ID, core.Separator)
|
||||
|
||||
if len(idParts) != 3 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error importing CDN custom domain", fmt.Sprintf("Expected import identifier on the format: [project_id]%q[distribution_id]%q[custom_domain_name], got %q", core.Separator, 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])...)
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("name"), idParts[2])...)
|
||||
tflog.Info(ctx, "CDN custom domain state imported")
|
||||
}
|
||||
|
||||
func mapCustomDomainFields(customDomain *cdn.CustomDomain, model *CustomDomainModel) error {
|
||||
if customDomain == nil {
|
||||
return fmt.Errorf("response input is nil")
|
||||
}
|
||||
if model == nil {
|
||||
return fmt.Errorf("model input is nil")
|
||||
}
|
||||
|
||||
if customDomain.Name == nil {
|
||||
return fmt.Errorf("Name is missing in response")
|
||||
}
|
||||
|
||||
if customDomain.Status == nil {
|
||||
return fmt.Errorf("Status missing in response")
|
||||
}
|
||||
|
||||
id := model.ProjectId.ValueString() + core.Separator + model.DistributionId.ValueString() + core.Separator + *customDomain.Name
|
||||
|
||||
model.ID = types.StringValue(id)
|
||||
model.Status = types.StringValue(string(*customDomain.Status))
|
||||
|
||||
customDomainErrors := []attr.Value{}
|
||||
if customDomain.Errors != nil {
|
||||
for _, e := range *customDomain.Errors {
|
||||
if e.En == nil {
|
||||
return fmt.Errorf("Error description missing")
|
||||
}
|
||||
customDomainErrors = append(customDomainErrors, types.StringValue(*e.En))
|
||||
}
|
||||
}
|
||||
modelErrors, diags := types.ListValue(types.StringType, customDomainErrors)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
model.Errors = modelErrors
|
||||
|
||||
return nil
|
||||
}
|
||||
90
stackit/internal/services/cdn/customdomain/resource_test.go
Normal file
90
stackit/internal/services/cdn/customdomain/resource_test.go
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package cdn
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"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 TestMapFields(t *testing.T) {
|
||||
emtpyErrorsList := types.ListValueMust(types.StringType, []attr.Value{})
|
||||
expectedModel := func(mods ...func(*CustomDomainModel)) *CustomDomainModel {
|
||||
model := &CustomDomainModel{
|
||||
ID: types.StringValue("test-project-id,test-distribution-id,https://testdomain.com"),
|
||||
DistributionId: types.StringValue("test-distribution-id"),
|
||||
ProjectId: types.StringValue("test-project-id"),
|
||||
Status: types.StringValue("ACTIVE"),
|
||||
Errors: emtpyErrorsList,
|
||||
}
|
||||
for _, mod := range mods {
|
||||
mod(model)
|
||||
}
|
||||
return model
|
||||
}
|
||||
customDomainFixture := func(mods ...func(*cdn.CustomDomain)) *cdn.CustomDomain {
|
||||
distribution := &cdn.CustomDomain{
|
||||
Errors: &[]cdn.StatusError{},
|
||||
Name: cdn.PtrString("https://testdomain.com"),
|
||||
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
||||
}
|
||||
for _, mod := range mods {
|
||||
mod(distribution)
|
||||
}
|
||||
return distribution
|
||||
}
|
||||
tests := map[string]struct {
|
||||
Input *cdn.CustomDomain
|
||||
Expected *CustomDomainModel
|
||||
IsValid bool
|
||||
}{
|
||||
"happy_path": {
|
||||
Expected: expectedModel(),
|
||||
Input: customDomainFixture(),
|
||||
IsValid: true,
|
||||
},
|
||||
"happy_path_status_error": {
|
||||
Expected: expectedModel(func(m *CustomDomainModel) {
|
||||
m.Status = types.StringValue("ERROR")
|
||||
}),
|
||||
Input: customDomainFixture(func(d *cdn.CustomDomain) {
|
||||
d.Status = cdn.DOMAINSTATUS_ERROR.Ptr()
|
||||
}),
|
||||
IsValid: true,
|
||||
},
|
||||
"sad_path_custom_domain_nil": {
|
||||
Expected: expectedModel(),
|
||||
Input: nil,
|
||||
IsValid: false,
|
||||
},
|
||||
"sad_path_name_missing": {
|
||||
Expected: expectedModel(),
|
||||
Input: customDomainFixture(func(d *cdn.CustomDomain) {
|
||||
d.Name = nil
|
||||
}),
|
||||
IsValid: false,
|
||||
},
|
||||
}
|
||||
for tn, tc := range tests {
|
||||
t.Run(tn, func(t *testing.T) {
|
||||
model := &CustomDomainModel{}
|
||||
model.DistributionId = tc.Expected.DistributionId
|
||||
model.ProjectId = tc.Expected.ProjectId
|
||||
err := mapCustomDomainFields(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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue