Skip to content

Commit ba55f16

Browse files
committed
feat(apps): handle more read attrs
1 parent 2882a27 commit ba55f16

File tree

25 files changed

+134
-26
lines changed

25 files changed

+134
-26
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module go.clever-cloud.com/terraform-provider
22

3-
go 1.23.7
3+
go 1.24.0
44

55
toolchain go1.24.5
66

@@ -93,6 +93,7 @@ require (
9393
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
9494
github.com/mitchellh/mapstructure v1.5.0 // indirect
9595
github.com/mitchellh/reflectwalk v1.0.2 // indirect
96+
github.com/miton18/helper v0.0.2-0.20251007125855-ab20836f278e
9697
github.com/mtibben/percent v0.2.1 // indirect
9798
github.com/oklog/run v1.0.0 // indirect
9899
github.com/philhofer/fwd v1.2.0 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,10 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
425425
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
426426
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
427427
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
428+
github.com/miton18/helper v0.0.2-0.20251001163320-ee4c86a86792 h1:XeA098d0RWNJacxHe2zs7nQxVb8Ls67bv161EMsUu/g=
429+
github.com/miton18/helper v0.0.2-0.20251001163320-ee4c86a86792/go.mod h1:BpVJIypihdfdxycOj7PqtgCvyhNppV97AlmDrGgOjec=
430+
github.com/miton18/helper v0.0.2-0.20251007125855-ab20836f278e h1:9eeF2wEKZG9pd46AdAOCo6wnE6OdEgf3TL9ZSlMvEpM=
431+
github.com/miton18/helper v0.0.2-0.20251007125855-ab20836f278e/go.mod h1:BpVJIypihdfdxycOj7PqtgCvyhNppV97AlmDrGgOjec=
428432
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
429433
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
430434
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=

pkg/attributes/addon.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package attributes
22

33
import (
4+
"context"
5+
"regexp"
6+
47
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
58
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
69
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
710
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
811
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
12+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
913
"github.com/hashicorp/terraform-plugin-framework/types"
1014
"go.clever-cloud.com/terraform-provider/pkg"
1115
)
@@ -21,7 +25,11 @@ type Addon struct {
2125
var addonCommon = map[string]schema.Attribute{
2226
"id": schema.StringAttribute{Computed: true, MarkdownDescription: "Generated unique identifier", PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}},
2327
"name": schema.StringAttribute{Required: true, MarkdownDescription: "Name of the service"},
24-
"plan": schema.StringAttribute{Required: true, MarkdownDescription: "Database size and spec"},
28+
"plan": schema.StringAttribute{
29+
Required: true,
30+
MarkdownDescription: "Database size and spec",
31+
Validators: []validator.String{slugValidator},
32+
},
2533
"region": schema.StringAttribute{
2634
Optional: true,
2735
Computed: true,
@@ -34,3 +42,17 @@ var addonCommon = map[string]schema.Attribute{
3442
func WithAddonCommons(runtimeSpecifics map[string]schema.Attribute) map[string]schema.Attribute {
3543
return pkg.Merge(addonCommon, runtimeSpecifics)
3644
}
45+
46+
// https://regex101.com/r/bMOotf/1
47+
var slugRegex = regexp.MustCompile(`^[a-z1-9_]*$`)
48+
var slugValidator = pkg.NewStringValidator(
49+
"expect slug value",
50+
func(ctx context.Context, req validator.StringRequest, res *validator.StringResponse) {
51+
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
52+
return
53+
}
54+
55+
if !slugRegex.MatchString(req.ConfigValue.ValueString()) {
56+
res.Diagnostics.AddAttributeError(req.Path, "expect lowercase and underscore characters only", "Invalid slug, expect something like `xs_tny`")
57+
}
58+
})

pkg/attributes/blocks.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
99
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1010
"github.com/hashicorp/terraform-plugin-framework/types"
11+
"github.com/miton18/helper/maps"
1112
"go.clever-cloud.com/terraform-provider/pkg"
1213
)
1314

@@ -26,6 +27,14 @@ type Hooks struct {
2627
RunFailed types.String `tfsdk:"run_failed"`
2728
}
2829

30+
const (
31+
CC_PRE_BUILD_HOOK = "CC_PRE_BUILD_HOOK"
32+
CC_POST_BUILD_HOOK = "CC_POST_BUILD_HOOK"
33+
CC_PRE_RUN_HOOK = "CC_PRE_RUN_HOOK"
34+
CC_RUN_FAILED_HOOK = "CC_RUN_FAILED_HOOK"
35+
CC_RUN_SUCCEEDED_HOOK = "CC_RUN_SUCCEEDED_HOOK"
36+
)
37+
2938
var blocks = map[string]schema.Block{
3039
"deployment": schema.SingleNestedBlock{
3140
Attributes: map[string]schema.Attribute{
@@ -111,11 +120,33 @@ func (hooks *Hooks) ToEnv() map[string]string {
111120
return m
112121
}
113122

114-
pkg.IfIsSetStr(hooks.PreBuild, func(script string) { m["CC_PRE_BUILD_HOOK"] = script })
115-
pkg.IfIsSetStr(hooks.PostBuild, func(script string) { m["CC_POST_BUILD_HOOK"] = script })
116-
pkg.IfIsSetStr(hooks.PreRun, func(script string) { m["CC_PRE_RUN_HOOK"] = script })
117-
pkg.IfIsSetStr(hooks.RunFailed, func(script string) { m["CC_RUN_FAILED_HOOK"] = script })
118-
pkg.IfIsSetStr(hooks.RunSucceed, func(script string) { m["CC_RUN_SUCCEEDED_HOOK"] = script })
123+
pkg.IfIsSetStr(hooks.PreBuild, func(script string) { m[CC_PRE_BUILD_HOOK] = script })
124+
pkg.IfIsSetStr(hooks.PostBuild, func(script string) { m[CC_POST_BUILD_HOOK] = script })
125+
pkg.IfIsSetStr(hooks.PreRun, func(script string) { m[CC_PRE_RUN_HOOK] = script })
126+
pkg.IfIsSetStr(hooks.RunFailed, func(script string) { m[CC_RUN_FAILED_HOOK] = script })
127+
pkg.IfIsSetStr(hooks.RunSucceed, func(script string) { m[CC_RUN_SUCCEEDED_HOOK] = script })
119128

120129
return m
121130
}
131+
132+
func (hooks *Hooks) FromEnv(env *maps.Map[string, string]) {
133+
if script := env.Pop(CC_PRE_BUILD_HOOK); script != "" {
134+
hooks.PreBuild = pkg.FromStr(script)
135+
}
136+
137+
if script := env.Pop(CC_POST_BUILD_HOOK); script != "" {
138+
hooks.PostBuild = pkg.FromStr(script)
139+
}
140+
141+
if script := env.Pop(CC_PRE_RUN_HOOK); script != "" {
142+
hooks.PreRun = pkg.FromStr(script)
143+
}
144+
145+
if script := env.Pop(CC_RUN_SUCCEEDED_HOOK); script != "" {
146+
hooks.RunSucceed = pkg.FromStr(script)
147+
}
148+
149+
if script := env.Pop(CC_RUN_FAILED_HOOK); script != "" {
150+
hooks.RunFailed = pkg.FromStr(script)
151+
}
152+
}

pkg/attributes/runtime.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/hashicorp/terraform-plugin-framework/attr"
89
"github.com/hashicorp/terraform-plugin-framework/diag"
910
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1011
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
12+
"github.com/miton18/helper/maps"
1113

1214
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
1315
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
@@ -24,6 +26,8 @@ type VHost struct {
2426
PathBegin types.String `tfsdk:"path_begin"`
2527
}
2628

29+
const APP_FOLDER = "APP_FOLDER"
30+
2731
func (vh VHost) String() *string {
2832
if vh.FQDN.IsNull() || vh.FQDN.IsUnknown() {
2933
return nil
@@ -61,6 +65,24 @@ type Runtime struct {
6165
Environment types.Map `tfsdk:"environment"`
6266
}
6367

68+
func (r *Runtime) FromEnvironment(ctx context.Context, env *maps.Map[string, string]) {
69+
r.Hooks.FromEnv(env)
70+
71+
if appFolder := env.Pop(APP_FOLDER); appFolder != "" {
72+
r.AppFolder = pkg.FromStr(appFolder)
73+
}
74+
75+
if env.Size() == 0 {
76+
return
77+
}
78+
79+
m := map[string]attr.Value{}
80+
for k, v := range env.All {
81+
m[k] = pkg.FromStr(v)
82+
}
83+
r.Environment = types.MapValueMust(types.StringType, m)
84+
}
85+
6486
type RuntimeV0 struct {
6587
ID types.String `tfsdk:"id"`
6688
Name types.String `tfsdk:"name"`

pkg/resources/addon/crud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (r *ResourceAddon) Read(ctx context.Context, req resource.ReadRequest, resp
105105

106106
a := addonRes.Payload()
107107
ad.Name = pkg.FromStr(a.Name)
108-
ad.Plan = pkg.FromStr(a.Plan.Slug)
108+
ad.Plan = pkg.FromStr(strings.ToLower(a.Plan.Slug))
109109
ad.Region = pkg.FromStr(a.Region)
110110
ad.ThirdPartyProvider = pkg.FromStr(a.Provider.ID)
111111
ad.CreationDate = pkg.FromI(a.CreationDate)

pkg/resources/docker/crud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (r *ResourceDocker) Read(ctx context.Context, req resource.ReadRequest, res
110110
state.Region = pkg.FromStr(app.App.Zone)
111111
state.DeployURL = pkg.FromStr(app.App.DeployURL)
112112
state.BuildFlavor = app.GetBuildFlavor()
113-
113+
//state.fromEnv(ctx, appFrankenPHP.EnvAsMap()) // TODO
114114
state.VHosts = helper.VHostsFromAPIHosts(ctx, app.App.Vhosts.AsString(), state.VHosts, &resp.Diagnostics)
115115

116116
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)

pkg/resources/frankenphp/crud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (r *ResourceFrankenPHP) Read(ctx context.Context, req resource.ReadRequest,
106106
state.BiggestFlavor = pkg.FromStr(appFrankenPHP.App.Instance.MaxFlavor.Name)
107107
state.Region = pkg.FromStr(appFrankenPHP.App.Zone)
108108
state.DeployURL = pkg.FromStr(appFrankenPHP.App.DeployURL)
109-
109+
state.fromEnv(ctx, appFrankenPHP.EnvAsMap())
110110
state.VHosts = helper.VHostsFromAPIHosts(ctx, appFrankenPHP.App.Vhosts.AsString(), state.VHosts, &resp.Diagnostics)
111111

112112
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)

pkg/resources/frankenphp/frankenphp.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ type ResourceFrankenPHP struct {
1111
helper.Configurer
1212
}
1313

14+
const CC_PHP_DEV_DEPENDENCIES = "CC_PHP_DEV_DEPENDENCIES"
15+
1416
func NewResourceFrankenPHP() resource.Resource {
1517
return &ResourceFrankenPHP{}
1618
}

pkg/resources/frankenphp/schema.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
_ "embed"
66

7+
"github.com/miton18/helper/maps"
8+
79
"github.com/go-git/go-git/v5/plumbing/transport/http"
810
"github.com/hashicorp/terraform-plugin-framework/diag"
911
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -53,14 +55,26 @@ func (fp *FrankenPHP) toEnv(ctx context.Context, diags *diag.Diagnostics) map[st
5355

5456
pkg.IfIsSetB(fp.DevDependencies, func(devDeps bool) {
5557
if devDeps {
56-
env["CC_PHP_DEV_DEPENDENCIES"] = "install"
58+
env[CC_PHP_DEV_DEPENDENCIES] = "install"
5759
}
5860
})
5961
env = pkg.Merge(env, fp.Hooks.ToEnv())
6062

6163
return env
6264
}
6365

66+
// fromEnv iter on environment set on the clever application and
67+
// handle language specific env vars
68+
// put the others on Environment field
69+
func (fp *FrankenPHP) fromEnv(ctx context.Context, env map[string]string) diag.Diagnostics {
70+
diags := diag.Diagnostics{}
71+
m := maps.NewMap(env)
72+
73+
fp.DevDependencies = pkg.FromBool(m.Pop(CC_PHP_DEV_DEPENDENCIES) == "install")
74+
fp.FromEnvironment(ctx, m)
75+
return diags
76+
}
77+
6478
func (fp *FrankenPHP) toDeployment(gitAuth *http.BasicAuth) *application.Deployment {
6579
if fp.Deployment == nil || fp.Deployment.Repository.IsNull() {
6680
return nil

0 commit comments

Comments
 (0)