parent
6f33262e8c
commit
bf9b225cb9
9 changed files with 287 additions and 44 deletions
|
|
@ -57,6 +57,7 @@ var schemaDescriptions = map[string]string{
|
|||
"config_optimizer": "Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience.",
|
||||
"config_backend_origin_url": "The configured backend type for the distribution",
|
||||
"config_backend_origin_request_headers": "The configured origin request headers for the backend",
|
||||
"config_blocked_countries": "The configured countries where distribution of content is blocked",
|
||||
"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",
|
||||
|
|
@ -76,13 +77,16 @@ type Model struct {
|
|||
}
|
||||
|
||||
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
|
||||
Optimizer types.Object `tfsdk:"optimizer"` // The optimizer configuration
|
||||
Backend backend `tfsdk:"backend"` // The backend associated with the distribution
|
||||
Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached
|
||||
BlockedCountries *[]string `tfsdk:"blocked_countries"` // The countries for which content will be blocked
|
||||
Optimizer types.Object `tfsdk:"optimizer"` // The optimizer configuration
|
||||
}
|
||||
|
||||
type optimizerConfig struct {
|
||||
Enabled types.Bool `tfsdk:"enabled"`
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -90,8 +94,9 @@ type backend struct {
|
|||
}
|
||||
|
||||
var configTypes = map[string]attr.Type{
|
||||
"backend": types.ObjectType{AttrTypes: backendTypes},
|
||||
"regions": types.ListType{ElemType: types.StringType},
|
||||
"backend": types.ObjectType{AttrTypes: backendTypes},
|
||||
"regions": types.ListType{ElemType: types.StringType},
|
||||
"blocked_countries": types.ListType{ElemType: types.StringType},
|
||||
"optimizer": types.ObjectType{
|
||||
AttrTypes: optimizerTypes,
|
||||
},
|
||||
|
|
@ -258,6 +263,11 @@ func (r *distributionResource) Schema(_ context.Context, _ resource.SchemaReques
|
|||
Description: schemaDescriptions["config_regions"],
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"blocked_countries": schema.ListAttribute{
|
||||
Optional: true,
|
||||
Description: schemaDescriptions["config_blocked_countries"],
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -378,6 +388,26 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
|
|||
regions = append(regions, *regionEnum)
|
||||
}
|
||||
|
||||
// blockedCountries
|
||||
// Use a pointer to a slice to distinguish between an empty list (unblock all) and nil (no change).
|
||||
var blockedCountries *[]string
|
||||
if configModel.BlockedCountries != nil {
|
||||
// Use a temporary slice
|
||||
tempBlockedCountries := []string{}
|
||||
|
||||
for _, blockedCountry := range *configModel.BlockedCountries {
|
||||
validatedBlockedCountry, err := validateCountryCode(blockedCountry)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Blocked countries: %v", err))
|
||||
return
|
||||
}
|
||||
tempBlockedCountries = append(tempBlockedCountries, validatedBlockedCountry)
|
||||
}
|
||||
|
||||
// Point to the populated slice
|
||||
blockedCountries = &tempBlockedCountries
|
||||
}
|
||||
|
||||
configPatch := &cdn.ConfigPatch{
|
||||
Backend: &cdn.ConfigPatchBackend{
|
||||
HttpBackendPatch: &cdn.HttpBackendPatch{
|
||||
|
|
@ -386,7 +416,8 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
|
|||
Type: &configModel.Backend.Type,
|
||||
},
|
||||
},
|
||||
Regions: ®ions,
|
||||
Regions: ®ions,
|
||||
BlockedCountries: blockedCountries,
|
||||
}
|
||||
|
||||
if !utils.IsUndefined(configModel.Optimizer) {
|
||||
|
|
@ -411,7 +442,9 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
|
|||
}).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Patch distribution: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
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))
|
||||
|
|
@ -423,6 +456,7 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
|
|||
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() {
|
||||
|
|
@ -501,6 +535,7 @@ func mapFields(distribution *cdn.Distribution, model *Model) error {
|
|||
model.CreatedAt = types.StringValue(distribution.CreatedAt.String())
|
||||
model.UpdatedAt = types.StringValue(distribution.UpdatedAt.String())
|
||||
|
||||
// distributionErrors
|
||||
distributionErrors := []attr.Value{}
|
||||
if distribution.Errors != nil {
|
||||
for _, e := range *distribution.Errors {
|
||||
|
|
@ -513,6 +548,7 @@ func mapFields(distribution *cdn.Distribution, model *Model) error {
|
|||
}
|
||||
model.Errors = modelErrors
|
||||
|
||||
// regions
|
||||
regions := []attr.Value{}
|
||||
for _, r := range *distribution.Config.Regions {
|
||||
regions = append(regions, types.StringValue(string(r)))
|
||||
|
|
@ -521,6 +557,21 @@ func mapFields(distribution *cdn.Distribution, model *Model) error {
|
|||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
// blockedCountries
|
||||
var blockedCountries []attr.Value
|
||||
if distribution.Config != nil && distribution.Config.BlockedCountries != nil {
|
||||
for _, c := range *distribution.Config.BlockedCountries {
|
||||
blockedCountries = append(blockedCountries, types.StringValue(string(c)))
|
||||
}
|
||||
}
|
||||
|
||||
modelBlockedCountries, diags := types.ListValue(types.StringType, blockedCountries)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
// originRequestHeaders
|
||||
originRequestHeaders := types.MapNull(types.StringType)
|
||||
if origHeaders := distribution.Config.Backend.HttpBackend.OriginRequestHeaders; origHeaders != nil && len(*origHeaders) > 0 {
|
||||
headers := map[string]attr.Value{}
|
||||
|
|
@ -557,9 +608,10 @@ func mapFields(distribution *cdn.Distribution, model *Model) error {
|
|||
}
|
||||
}
|
||||
cfg, diags := types.ObjectValue(configTypes, map[string]attr.Value{
|
||||
"backend": backend,
|
||||
"regions": modelRegions,
|
||||
"optimizer": optimizerVal,
|
||||
"backend": backend,
|
||||
"regions": modelRegions,
|
||||
"blocked_countries": modelBlockedCountries,
|
||||
"optimizer": optimizerVal,
|
||||
})
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
|
|
@ -624,6 +676,7 @@ func toCreatePayload(ctx context.Context, model *Model) (*cdn.CreateDistribution
|
|||
IntentId: cdn.PtrString(uuid.NewString()),
|
||||
OriginUrl: cfg.Backend.HttpBackend.OriginUrl,
|
||||
Regions: cfg.Regions,
|
||||
BlockedCountries: cfg.BlockedCountries,
|
||||
OriginRequestHeaders: cfg.Backend.HttpBackend.OriginRequestHeaders,
|
||||
Optimizer: optimizer,
|
||||
}
|
||||
|
|
@ -646,6 +699,8 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
|
|||
if diags.HasError() {
|
||||
return nil, core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
// regions
|
||||
regions := []cdn.Region{}
|
||||
for _, r := range *configModel.Regions {
|
||||
regionEnum, err := cdn.NewRegionFromValue(r)
|
||||
|
|
@ -655,6 +710,19 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
|
|||
regions = append(regions, *regionEnum)
|
||||
}
|
||||
|
||||
// blockedCountries
|
||||
var blockedCountries []string
|
||||
if configModel.BlockedCountries != nil {
|
||||
for _, blockedCountry := range *configModel.BlockedCountries {
|
||||
validatedBlockedCountry, err := validateCountryCode(blockedCountry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockedCountries = append(blockedCountries, validatedBlockedCountry)
|
||||
}
|
||||
}
|
||||
|
||||
// originRequestHeaders
|
||||
originRequestHeaders := map[string]string{}
|
||||
if configModel.Backend.OriginRequestHeaders != nil {
|
||||
for k, v := range *configModel.Backend.OriginRequestHeaders {
|
||||
|
|
@ -670,7 +738,8 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
|
|||
Type: &configModel.Backend.Type,
|
||||
},
|
||||
},
|
||||
Regions: ®ions,
|
||||
Regions: ®ions,
|
||||
BlockedCountries: &blockedCountries,
|
||||
}
|
||||
|
||||
if !utils.IsUndefined(configModel.Optimizer) {
|
||||
|
|
@ -687,3 +756,25 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
|
|||
|
||||
return cdnConfig, nil
|
||||
}
|
||||
|
||||
// validateCountryCode checks for a valid country user input. This is just a quick check
|
||||
// since the API already does a more thorough check.
|
||||
func validateCountryCode(country string) (string, error) {
|
||||
if len(country) != 2 {
|
||||
return "", errors.New("country code must be exactly 2 characters long")
|
||||
}
|
||||
|
||||
upperCountry := strings.ToUpper(country)
|
||||
|
||||
// Check if both characters are alphabetical letters within the ASCII range A-Z.
|
||||
// Yes, we could use the unicode package, but we are only targeting ASCII letters specifically, so
|
||||
// let's omit this dependency.
|
||||
char1 := upperCountry[0]
|
||||
char2 := upperCountry[1]
|
||||
|
||||
if !((char1 >= 'A' && char1 <= 'Z') && (char2 >= 'A' && char2 <= 'Z')) {
|
||||
return "", fmt.Errorf("country code '%s' must consist of two alphabetical letters (A-Z or a-z)", country)
|
||||
}
|
||||
|
||||
return upperCountry, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue