Skip to content

Commit bcb1750

Browse files
authored
Merge pull request #16 from port-labs/PORT-1843-terraform-provider-provider-assumes-that-default-of-a-property-is-always-string
Port 1843 terraform provider support multiple types of default of a property
2 parents ad96656 + d6d570e commit bcb1750

7 files changed

+182
-14
lines changed

docs/resources/action.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Required:
5757
Optional:
5858

5959
- `blueprint` (String) When selecting format 'entity', the identifier of the target blueprint
60+
- `default_items` (List of String) The list of default items, in case the type of this property is a list
6061
- `default` (String) A default value for this property in case an entity is created without explicitly providing a value.
6162
- `description` (String) A description of the property. This value is visible to users when hovering on the info icon in the UI. It provides detailed information about the use of a specific property.
6263
- `enum` (List of String) A list of allowed values for the property

docs/resources/blueprint.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Required:
5050

5151
Optional:
5252

53+
- `default_items` (List of String) The list of default items, in case the type of this property is a list
5354
- `default` (String) The default value of the property
5455
- `description` (String) The description of the property
5556
- `enum` (List of String) A list of allowed values for the property

port/cli/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type (
3232
Type string `json:"type,omitempty"`
3333
Title string `json:"title,omitempty"`
3434
Identifier string `json:"identifier,omitempty"`
35-
Default string `json:"default,omitempty"`
35+
Default interface{} `json:"default,omitempty"`
3636
Icon string `json:"icon,omitempty"`
3737
Format string `json:"format,omitempty"`
3838
Description string `json:"description,omitempty"`

port/resource_port_action.go

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package port
22

33
import (
44
"context"
5+
"encoding/json"
6+
"strconv"
57

68
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -74,6 +76,14 @@ func newActionResource() *schema.Resource {
7476
Optional: true,
7577
Description: "A default value for this property in case an entity is created without explicitly providing a value.",
7678
},
79+
"default_items": {
80+
Type: schema.TypeList,
81+
Optional: true,
82+
Description: "The list of items, in case the type of default property is a list",
83+
Elem: &schema.Schema{
84+
Type: schema.TypeString,
85+
},
86+
},
7787
"format": {
7888
Type: schema.TypeString,
7989
Optional: true,
@@ -170,7 +180,6 @@ func writeActionFieldsToResource(d *schema.ResourceData, action *cli.Action) {
170180
p["title"] = v.Title
171181
p["type"] = v.Type
172182
p["description"] = v.Description
173-
p["default"] = v.Default
174183
p["format"] = v.Format
175184
p["pattern"] = v.Pattern
176185
p["blueprint"] = v.Blueprint
@@ -180,6 +189,27 @@ func writeActionFieldsToResource(d *schema.ResourceData, action *cli.Action) {
180189
} else {
181190
p["required"] = false
182191
}
192+
if v.Default != nil {
193+
switch t := v.Default.(type) {
194+
case map[string]interface{}:
195+
js, _ := json.Marshal(&t)
196+
p["default"] = string(js)
197+
case []interface{}:
198+
p["default_items"] = t
199+
case float64:
200+
p["default"] = strconv.FormatFloat(t, 'f', -1, 64)
201+
case int:
202+
p["default"] = strconv.Itoa(t)
203+
case string:
204+
p["default"] = t
205+
case bool:
206+
p["default"] = "false"
207+
if t {
208+
p["default"] = "true"
209+
}
210+
}
211+
}
212+
183213
properties.Add(p)
184214
}
185215
d.Set("user_properties", &properties)
@@ -220,8 +250,40 @@ func actionResourceToBody(d *schema.ResourceData) (*cli.Action, error) {
220250
if d, ok := p["description"]; ok && d != "" {
221251
propFields.Description = d.(string)
222252
}
223-
if d, ok := p["default"]; ok && d != "" {
224-
propFields.Default = d.(string)
253+
switch propFields.Type {
254+
case "string":
255+
if d, ok := p["default"]; ok && d.(string) != "" {
256+
propFields.Default = d.(string)
257+
}
258+
case "number":
259+
if d, ok := p["default"]; ok && d.(string) != "" {
260+
defaultNum, err := strconv.ParseInt(d.(string), 10, 0)
261+
if err != nil {
262+
return nil, err
263+
}
264+
propFields.Default = defaultNum
265+
}
266+
case "boolean":
267+
if d, ok := p["default"]; ok && d.(string) != "" {
268+
defaultBool, err := strconv.ParseBool(d.(string))
269+
if err != nil {
270+
return nil, err
271+
}
272+
propFields.Default = defaultBool
273+
}
274+
case "array":
275+
if d, ok := p["default_items"]; ok && d != nil {
276+
propFields.Default = d
277+
}
278+
case "object":
279+
if d, ok := p["default"]; ok && d.(string) != "" {
280+
defaultObj := make(map[string]interface{})
281+
err := json.Unmarshal([]byte(d.(string)), &defaultObj)
282+
if err != nil {
283+
return nil, err
284+
}
285+
propFields.Default = defaultObj
286+
}
225287
}
226288
if f, ok := p["format"]; ok && f != "" {
227289
propFields.Format = f.(string)

port/resource_port_action_test.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,35 @@ func TestAccPortAction(t *testing.T) {
3131
invocation_method {
3232
type = "KAFKA"
3333
}
34+
user_properties {
35+
identifier = "reason"
36+
type = "string"
37+
title = "Reason"
38+
default = "test"
39+
}
40+
user_properties {
41+
identifier = "delay"
42+
type = "number"
43+
title = "Delay"
44+
default = 3
45+
}
3446
user_properties {
3547
identifier = "clear_cache"
3648
type = "boolean"
3749
title = "Clear cache"
50+
default = true
51+
}
52+
user_properties {
53+
identifier = "services"
54+
type = "array"
55+
title = "Services"
56+
default_items = ["api", "frontend"]
57+
}
58+
user_properties {
59+
identifier = "config"
60+
type = "object"
61+
title = "Config"
62+
default = jsonencode({"when":"immediate"})
3863
}
3964
}
4065
`, identifier, actionIdentifier)
@@ -87,10 +112,16 @@ func TestAccPortAction(t *testing.T) {
87112
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "blueprint_identifier", identifier),
88113
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "invocation_method.0.type", "KAFKA"),
89114
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "trigger", "DAY-2"),
90-
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.#", "1"),
91-
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.0.identifier", "clear_cache"),
92-
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.0.type", "boolean"),
93-
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.0.title", "Clear cache"),
115+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.#", "5"),
116+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.0.default_items.0", "api"),
117+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.0.default_items.#", "2"),
118+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.1.default", "3"),
119+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.2.default", "test"),
120+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.3.identifier", "clear_cache"),
121+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.3.type", "boolean"),
122+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.3.title", "Clear cache"),
123+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.3.default", "true"),
124+
resource.TestCheckResourceAttr("port-labs_action.restart_microservice", "user_properties.4.default", "{\"when\":\"immediate\"}"),
94125
),
95126
},
96127
{

port/resource_port_blueprint.go

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package port
22

33
import (
44
"context"
5+
"encoding/json"
6+
"strconv"
57

68
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -118,6 +120,14 @@ func newBlueprintResource() *schema.Resource {
118120
Optional: true,
119121
Description: "The default value of the property",
120122
},
123+
"default_items": {
124+
Type: schema.TypeList,
125+
Optional: true,
126+
Description: "The list of items, in case the type of default property is a list",
127+
Elem: &schema.Schema{
128+
Type: schema.TypeString,
129+
},
130+
},
121131
"format": {
122132
Type: schema.TypeString,
123133
Optional: true,
@@ -283,7 +293,6 @@ func writeBlueprintFieldsToResource(d *schema.ResourceData, b *cli.Blueprint) {
283293
p["title"] = v.Title
284294
p["type"] = v.Type
285295
p["description"] = v.Description
286-
p["default"] = v.Default
287296
p["format"] = v.Format
288297
p["icon"] = v.Icon
289298
p["enum"] = v.Enum
@@ -293,6 +302,27 @@ func writeBlueprintFieldsToResource(d *schema.ResourceData, b *cli.Blueprint) {
293302
} else {
294303
p["required"] = false
295304
}
305+
if v.Default != nil {
306+
switch t := v.Default.(type) {
307+
case map[string]interface{}:
308+
js, _ := json.Marshal(&t)
309+
p["default"] = string(js)
310+
case []interface{}:
311+
p["default_items"] = t
312+
case float64:
313+
p["default"] = strconv.FormatFloat(t, 'f', -1, 64)
314+
case int:
315+
p["default"] = strconv.Itoa(t)
316+
case string:
317+
p["default"] = t
318+
case bool:
319+
p["default"] = "false"
320+
if t {
321+
p["default"] = "true"
322+
}
323+
}
324+
}
325+
296326
properties.Add(p)
297327
}
298328

@@ -356,8 +386,40 @@ func blueprintResourceToBody(d *schema.ResourceData) (*cli.Blueprint, error) {
356386
if d, ok := p["description"]; ok && d != "" {
357387
propFields.Description = d.(string)
358388
}
359-
if d, ok := p["default"]; ok && d != "" {
360-
propFields.Default = d.(string)
389+
switch propFields.Type {
390+
case "string":
391+
if d, ok := p["default"]; ok && d.(string) != "" {
392+
propFields.Default = d.(string)
393+
}
394+
case "number":
395+
if d, ok := p["default"]; ok && d.(string) != "" {
396+
defaultNum, err := strconv.ParseInt(d.(string), 10, 0)
397+
if err != nil {
398+
return nil, err
399+
}
400+
propFields.Default = defaultNum
401+
}
402+
case "boolean":
403+
if d, ok := p["default"]; ok && d.(string) != "" {
404+
defaultBool, err := strconv.ParseBool(d.(string))
405+
if err != nil {
406+
return nil, err
407+
}
408+
propFields.Default = defaultBool
409+
}
410+
case "array":
411+
if d, ok := p["default_items"]; ok && d != nil {
412+
propFields.Default = d
413+
}
414+
case "object":
415+
if d, ok := p["default"]; ok && d.(string) != "" {
416+
defaultObj := make(map[string]interface{})
417+
err := json.Unmarshal([]byte(d.(string)), &defaultObj)
418+
if err != nil {
419+
return nil, err
420+
}
421+
propFields.Default = defaultObj
422+
}
361423
}
362424
if f, ok := p["format"]; ok && f != "" {
363425
propFields.Format = f.(string)

port/resource_port_blueprint_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,25 @@ func TestAccPortBlueprint(t *testing.T) {
2828
identifier = "bool"
2929
type = "boolean"
3030
title = "boolean"
31+
default = true
3132
}
3233
properties {
3334
identifier = "number"
3435
type = "number"
3536
title = "number"
37+
default = 1
3638
}
3739
properties {
3840
identifier = "obj"
3941
type = "object"
4042
title = "object"
43+
default = jsonencode({"a":"b"})
4144
}
4245
properties {
4346
identifier = "array"
4447
type = "array"
4548
title = "array"
49+
default_items = [1, 2, 3]
4650
}
4751
properties {
4852
identifier = "text"
@@ -54,6 +58,7 @@ func TestAccPortBlueprint(t *testing.T) {
5458
a = "red"
5559
b = "blue"
5660
}
61+
default = "a"
5762
}
5863
}
5964
`, identifier)
@@ -65,9 +70,15 @@ func TestAccPortBlueprint(t *testing.T) {
6570
{
6671
Config: testAccActionConfigCreate,
6772
Check: resource.ComposeTestCheckFunc(
68-
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.0.identifier", "text"),
69-
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.0.enum.0", "a"),
70-
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.0.enum_colors.a", "red"),
73+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.0.default_items.0", "1"),
74+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.0.default_items.#", "3"),
75+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.1.default", "1"),
76+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.2.identifier", "text"),
77+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.2.enum.0", "a"),
78+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.2.enum_colors.a", "red"),
79+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.2.default", "a"),
80+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.3.default", "true"),
81+
resource.TestCheckResourceAttr("port-labs_blueprint.microservice", "properties.4.default", "{\"a\":\"b\"}"),
7182
),
7283
},
7384
},

0 commit comments

Comments
 (0)