Skip to content

Commit 6f33262

Browse files
matheuspolitanoMatheus Politanomarceljk
authored
feat: implement image optimizer in cdn service (#895)
* implement image optimizer in cdn service * add documentation * add optimizer in cdn acc test * add example --------- Co-authored-by: Matheus Politano <matheus.correia_politano@mail.schwarz> Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com>
1 parent 126b7a2 commit 6f33262

7 files changed

Lines changed: 230 additions & 33 deletions

File tree

docs/data-sources/cdn_distribution.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ data "stackit_cdn_distribution" "example" {
4646
Read-Only:
4747

4848
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
49+
- `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer))
4950
- `regions` (List of String) The configured regions where content will be hosted
5051

5152
<a id="nestedatt--config--backend"></a>
@@ -58,6 +59,14 @@ Read-Only:
5859
- `type` (String) The configured backend type. Supported values are: `http`.
5960

6061

62+
<a id="nestedatt--config--optimizer"></a>
63+
### Nested Schema for `config.optimizer`
64+
65+
Read-Only:
66+
67+
- `enabled` (Boolean)
68+
69+
6170

6271
<a id="nestedatt--domains"></a>
6372
### Nested Schema for `domains`

docs/resources/cdn_distribution.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ resource "stackit_cdn_distribution" "example_distribution" {
2424
origin_url = "mybackend.onstackit.cloud"
2525
}
2626
regions = ["EU", "US", "ASIA", "AF", "SA"]
27+
optimizer = {
28+
enabled = true
29+
}
2730
}
2831
}
2932
```
@@ -54,6 +57,10 @@ Required:
5457
- `backend` (Attributes) The configured backend for the distribution (see [below for nested schema](#nestedatt--config--backend))
5558
- `regions` (List of String) The configured regions where content will be hosted
5659

60+
Optional:
61+
62+
- `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer))
63+
5764
<a id="nestedatt--config--backend"></a>
5865
### Nested Schema for `config.backend`
5966

@@ -67,6 +74,14 @@ Optional:
6774
- `origin_request_headers` (Map of String) The configured origin request headers for the backend
6875

6976

77+
<a id="nestedatt--config--optimizer"></a>
78+
### Nested Schema for `config.optimizer`
79+
80+
Optional:
81+
82+
- `enabled` (Boolean)
83+
84+
7085

7186
<a id="nestedatt--domains"></a>
7287
### Nested Schema for `domains`

examples/resources/stackit_cdn_distribution/resource.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@ resource "stackit_cdn_distribution" "example_distribution" {
66
origin_url = "mybackend.onstackit.cloud"
77
}
88
regions = ["EU", "US", "ASIA", "AF", "SA"]
9+
optimizer = {
10+
enabled = true
11+
}
912
}
1013
}

stackit/internal/services/cdn/cdn_acc_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ func configResources(regions string) string {
3939
origin_url = "%s"
4040
}
4141
regions = [%s]
42+
optimizer = {
43+
enabled = true
44+
}
4245
}
4346
}
4447
@@ -108,6 +111,7 @@ func TestAccCDNDistributionResource(t *testing.T) {
108111
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.#", "2"),
109112
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
110113
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
114+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.optimizer.enabled", "true"),
111115
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
112116
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
113117
),
@@ -187,6 +191,7 @@ func TestAccCDNDistributionResource(t *testing.T) {
187191
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.regions.#", "2"),
188192
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
189193
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.regions.1", "US"),
194+
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.optimizer.enabled", "true"),
190195
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
191196
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "status", "ACTIVE"),
192197
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
@@ -212,6 +217,7 @@ func TestAccCDNDistributionResource(t *testing.T) {
212217
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.0", "EU"),
213218
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.1", "US"),
214219
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.regions.2", "ASIA"),
220+
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.optimizer.enabled", "true"),
215221
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
216222
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
217223
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),

stackit/internal/services/cdn/distribution/datasource.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,17 @@ func (r *distributionDataSource) Schema(_ context.Context, _ datasource.SchemaRe
148148
Computed: true,
149149
Description: schemaDescriptions["config_regions"],
150150
ElementType: types.StringType,
151-
}},
151+
},
152+
"optimizer": schema.SingleNestedAttribute{
153+
Description: schemaDescriptions["config_optimizer"],
154+
Computed: true,
155+
Attributes: map[string]schema.Attribute{
156+
"enabled": schema.BoolAttribute{
157+
Computed: true,
158+
},
159+
},
160+
},
161+
},
152162
},
153163
},
154164
}

stackit/internal/services/cdn/distribution/resource.go

Lines changed: 100 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import (
1212
cdnUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/cdn/utils"
1313

1414
"github.com/google/uuid"
15+
"github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator"
1516
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1617
"github.com/hashicorp/terraform-plugin-framework/attr"
18+
"github.com/hashicorp/terraform-plugin-framework/diag"
1719
"github.com/hashicorp/terraform-plugin-framework/path"
1820
"github.com/hashicorp/terraform-plugin-framework/resource"
1921
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
@@ -52,6 +54,7 @@ var schemaDescriptions = map[string]string{
5254
"config_backend": "The configured backend for the distribution",
5355
"config_regions": "The configured regions where content will be hosted",
5456
"config_backend_type": "The configured backend type. ",
57+
"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.",
5558
"config_backend_origin_url": "The configured backend type for the distribution",
5659
"config_backend_origin_request_headers": "The configured origin request headers for the backend",
5760
"domain_name": "The name of the domain",
@@ -73,10 +76,13 @@ type Model struct {
7376
}
7477

7578
type distributionConfig struct {
76-
Backend backend `tfsdk:"backend"` // The backend associated with the distribution
77-
Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached
79+
Backend backend `tfsdk:"backend"` // The backend associated with the distribution
80+
Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached
81+
Optimizer types.Object `tfsdk:"optimizer"` // The optimizer configuration
82+
}
83+
type optimizerConfig struct {
84+
Enabled types.Bool `tfsdk:"enabled"`
7885
}
79-
8086
type backend struct {
8187
Type string `tfsdk:"type"` // The type of the backend. Currently, only "http" backend is supported
8288
OriginURL string `tfsdk:"origin_url"` // The origin URL of the backend
@@ -86,6 +92,13 @@ type backend struct {
8692
var configTypes = map[string]attr.Type{
8793
"backend": types.ObjectType{AttrTypes: backendTypes},
8894
"regions": types.ListType{ElemType: types.StringType},
95+
"optimizer": types.ObjectType{
96+
AttrTypes: optimizerTypes,
97+
},
98+
}
99+
100+
var optimizerTypes = map[string]attr.Type{
101+
"enabled": types.BoolType,
89102
}
90103

91104
var backendTypes = map[string]attr.Type{
@@ -206,6 +219,20 @@ func (r *distributionResource) Schema(_ context.Context, _ resource.SchemaReques
206219
Required: true,
207220
Description: schemaDescriptions["config"],
208221
Attributes: map[string]schema.Attribute{
222+
"optimizer": schema.SingleNestedAttribute{
223+
Description: schemaDescriptions["config_optimizer"],
224+
Optional: true,
225+
Computed: true,
226+
Attributes: map[string]schema.Attribute{
227+
"enabled": schema.BoolAttribute{
228+
Optional: true,
229+
Computed: true,
230+
},
231+
},
232+
Validators: []validator.Object{
233+
objectvalidator.AlsoRequires(path.MatchRelative().AtName("enabled")),
234+
},
235+
},
209236
"backend": schema.SingleNestedAttribute{
210237
Required: true,
211238
Description: schemaDescriptions["config_backend"],
@@ -230,7 +257,8 @@ func (r *distributionResource) Schema(_ context.Context, _ resource.SchemaReques
230257
Required: true,
231258
Description: schemaDescriptions["config_regions"],
232259
ElementType: types.StringType,
233-
}},
260+
},
261+
},
234262
},
235263
},
236264
}
@@ -349,17 +377,36 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
349377
}
350378
regions = append(regions, *regionEnum)
351379
}
352-
_, err := r.client.PatchDistribution(ctx, projectId, distributionId).PatchDistributionPayload(cdn.PatchDistributionPayload{
353-
Config: &cdn.ConfigPatch{
354-
Backend: &cdn.ConfigPatchBackend{
355-
HttpBackendPatch: &cdn.HttpBackendPatch{
356-
OriginRequestHeaders: configModel.Backend.OriginRequestHeaders,
357-
OriginUrl: &configModel.Backend.OriginURL,
358-
Type: &configModel.Backend.Type,
359-
},
380+
381+
configPatch := &cdn.ConfigPatch{
382+
Backend: &cdn.ConfigPatchBackend{
383+
HttpBackendPatch: &cdn.HttpBackendPatch{
384+
OriginRequestHeaders: configModel.Backend.OriginRequestHeaders,
385+
OriginUrl: &configModel.Backend.OriginURL,
386+
Type: &configModel.Backend.Type,
360387
},
361-
Regions: &regions,
362388
},
389+
Regions: &regions,
390+
}
391+
392+
if !utils.IsUndefined(configModel.Optimizer) {
393+
var optimizerModel optimizerConfig
394+
395+
diags = configModel.Optimizer.As(ctx, &optimizerModel, basetypes.ObjectAsOptions{})
396+
if diags.HasError() {
397+
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", "Error mapping optimizer config")
398+
return
399+
}
400+
401+
optimizer := cdn.NewOptimizerPatch()
402+
if !utils.IsUndefined(optimizerModel.Enabled) {
403+
optimizer.SetEnabled(optimizerModel.Enabled.ValueBool())
404+
}
405+
configPatch.Optimizer = optimizer
406+
}
407+
408+
_, err := r.client.PatchDistribution(ctx, projectId, distributionId).PatchDistributionPayload(cdn.PatchDistributionPayload{
409+
Config: configPatch,
363410
IntentId: cdn.PtrString(uuid.NewString()),
364411
}).Execute()
365412
if err != nil {
@@ -495,9 +542,24 @@ func mapFields(distribution *cdn.Distribution, model *Model) error {
495542
if diags.HasError() {
496543
return core.DiagsToError(diags)
497544
}
545+
546+
optimizerVal := types.ObjectNull(optimizerTypes)
547+
if o := distribution.Config.Optimizer; o != nil {
548+
optimizerEnabled, ok := o.GetEnabledOk()
549+
if ok {
550+
var diags diag.Diagnostics
551+
optimizerVal, diags = types.ObjectValue(optimizerTypes, map[string]attr.Value{
552+
"enabled": types.BoolValue(optimizerEnabled),
553+
})
554+
if diags.HasError() {
555+
return core.DiagsToError(diags)
556+
}
557+
}
558+
}
498559
cfg, diags := types.ObjectValue(configTypes, map[string]attr.Value{
499-
"backend": backend,
500-
"regions": modelRegions,
560+
"backend": backend,
561+
"regions": modelRegions,
562+
"optimizer": optimizerVal,
501563
})
502564
if diags.HasError() {
503565
return core.DiagsToError(diags)
@@ -553,11 +615,17 @@ func toCreatePayload(ctx context.Context, model *Model) (*cdn.CreateDistribution
553615
if err != nil {
554616
return nil, err
555617
}
618+
var optimizer *cdn.Optimizer
619+
if cfg.Optimizer != nil {
620+
optimizer = cdn.NewOptimizer(cfg.Optimizer.GetEnabled())
621+
}
622+
556623
payload := &cdn.CreateDistributionPayload{
557624
IntentId: cdn.PtrString(uuid.NewString()),
558625
OriginUrl: cfg.Backend.HttpBackend.OriginUrl,
559626
Regions: cfg.Regions,
560627
OriginRequestHeaders: cfg.Backend.HttpBackend.OriginRequestHeaders,
628+
Optimizer: optimizer,
561629
}
562630

563631
return payload, nil
@@ -593,7 +661,8 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
593661
originRequestHeaders[k] = v
594662
}
595663
}
596-
return &cdn.Config{
664+
665+
cdnConfig := &cdn.Config{
597666
Backend: &cdn.ConfigBackend{
598667
HttpBackend: &cdn.HttpBackend{
599668
OriginRequestHeaders: &originRequestHeaders,
@@ -602,5 +671,19 @@ func convertConfig(ctx context.Context, model *Model) (*cdn.Config, error) {
602671
},
603672
},
604673
Regions: &regions,
605-
}, nil
674+
}
675+
676+
if !utils.IsUndefined(configModel.Optimizer) {
677+
var optimizerModel optimizerConfig
678+
diags := configModel.Optimizer.As(ctx, &optimizerModel, basetypes.ObjectAsOptions{})
679+
if diags.HasError() {
680+
return nil, core.DiagsToError(diags)
681+
}
682+
683+
if !utils.IsUndefined(optimizerModel.Enabled) {
684+
cdnConfig.Optimizer = cdn.NewOptimizer(optimizerModel.Enabled.ValueBool())
685+
}
686+
}
687+
688+
return cdnConfig, nil
606689
}

0 commit comments

Comments
 (0)