Skip to content

Commit 62a7df7

Browse files
authored
Port 4981 terraform fix update resources issue when changing identifier (#87)
1 parent fc0c203 commit 62a7df7

File tree

11 files changed

+411
-6
lines changed

11 files changed

+411
-6
lines changed

internal/cli/entity.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ func (c *PortClient) CreateEntity(ctx context.Context, e *Entity, runID string)
4747
return &pb.Entity, nil
4848
}
4949

50+
func (c *PortClient) UpdateEntity(ctx context.Context, id string, blueprint string, e *Entity, runID string) (*Entity, error) {
51+
url := "v1/blueprints/{blueprint}/entities/{identifier}"
52+
pb := &PortBody{}
53+
resp, err := c.Client.R().
54+
SetBody(e).
55+
SetPathParam(("blueprint"), e.Blueprint).
56+
SetPathParam("identifier", id).
57+
SetQueryParam("run_id", runID).
58+
SetResult(&pb).
59+
Put(url)
60+
if err != nil {
61+
return nil, err
62+
}
63+
if !pb.OK {
64+
return nil, fmt.Errorf("failed to update entity, got: %s", resp.Body())
65+
}
66+
return &pb.Entity, nil
67+
}
68+
5069
func (c *PortClient) DeleteEntity(ctx context.Context, id string, blueprint string) error {
5170
url := "v1/blueprints/{blueprint}/entities/{identifier}"
5271
pb := &PortBody{}

port/action/resource.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ func (r *ActionResource) ImportState(ctx context.Context, req resource.ImportSta
4444

4545
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("blueprint"), idParts[0])...)
4646
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("identifier"), idParts[1])...)
47+
4748
}
4849

4950
func (r *ActionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
@@ -126,7 +127,10 @@ func (r *ActionResource) Create(ctx context.Context, req resource.CreateRequest,
126127

127128
func (r *ActionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
128129
var state *ActionModel
130+
var previousState *ActionModel
131+
129132
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
133+
resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...)
130134

131135
if resp.Diagnostics.HasError() {
132136
return
@@ -144,7 +148,12 @@ func (r *ActionResource) Update(ctx context.Context, req resource.UpdateRequest,
144148
return
145149
}
146150

147-
a, err := r.portClient.UpdateAction(ctx, bp.Identifier, action.Identifier, action)
151+
var a *cli.Action
152+
if previousState.Identifier.IsNull() {
153+
a, err = r.portClient.CreateAction(ctx, bp.Identifier, action)
154+
} else {
155+
a, err = r.portClient.UpdateAction(ctx, bp.Identifier, previousState.Identifier.ValueString(), action)
156+
}
148157
if err != nil {
149158
resp.Diagnostics.AddError("failed to create action", err.Error())
150159
return

port/action/resource_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,3 +854,82 @@ func TestAccPortActionEncryption(t *testing.T) {
854854
},
855855
})
856856
}
857+
858+
func TestAccPortActionUpdateIdentifier(t *testing.T) {
859+
identifier := utils.GenID()
860+
actionIdentifier := utils.GenID()
861+
actionUpdatedIdentifier := utils.GenID()
862+
var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
863+
resource "port_action" "create_microservice" {
864+
title = "TF Provider Test"
865+
identifier = "%s"
866+
icon = "Terraform"
867+
blueprint = port_blueprint.microservice.id
868+
trigger = "DAY-2"
869+
webhook_method = {
870+
url = "https://getport.io"
871+
}
872+
user_properties = {
873+
"string_props" = {
874+
"myStringIdentifier" = {
875+
"title" = "My String Identifier"
876+
"required" = true
877+
}
878+
}
879+
}
880+
}`, actionIdentifier)
881+
882+
var testAccActionConfigUpdate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
883+
resource "port_action" "create_microservice" {
884+
title = "TF Provider Test"
885+
identifier = "%s"
886+
icon = "Terraform"
887+
blueprint = port_blueprint.microservice.id
888+
trigger = "DAY-2"
889+
webhook_method = {
890+
url = "https://getport.io"
891+
}
892+
user_properties = {
893+
"string_props" = {
894+
"myStringIdentifier" = {
895+
"title" = "My String Identifier"
896+
"required" = true
897+
}
898+
}
899+
}
900+
}`, actionUpdatedIdentifier)
901+
902+
resource.Test(t, resource.TestCase{
903+
PreCheck: func() { acctest.TestAccPreCheck(t) },
904+
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
905+
906+
Steps: []resource.TestStep{
907+
{
908+
Config: acctest.ProviderConfig + testAccActionConfigCreate,
909+
Check: resource.ComposeTestCheckFunc(
910+
resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
911+
resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
912+
resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
913+
resource.TestCheckResourceAttr("port_action.create_microservice", "blueprint", identifier),
914+
resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"),
915+
resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.url", "https://getport.io"),
916+
resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"),
917+
resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"),
918+
),
919+
},
920+
{
921+
Config: acctest.ProviderConfig + testAccActionConfigUpdate,
922+
Check: resource.ComposeTestCheckFunc(
923+
resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
924+
resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionUpdatedIdentifier),
925+
resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
926+
resource.TestCheckResourceAttr("port_action.create_microservice", "blueprint", identifier),
927+
resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"),
928+
resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.url", "https://getport.io"),
929+
resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"),
930+
resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"),
931+
),
932+
},
933+
},
934+
})
935+
}

port/blueprint/resource.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ func writeBlueprintComputedFieldsToState(state *BlueprintModel, bp *cli.Blueprin
150150

151151
func (r *BlueprintResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
152152
var state *BlueprintModel
153+
var previousState *BlueprintModel
154+
153155
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
156+
resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...)
154157

155158
if resp.Diagnostics.HasError() {
156159
return
@@ -164,10 +167,10 @@ func (r *BlueprintResource) Update(ctx context.Context, req resource.UpdateReque
164167

165168
var bp *cli.Blueprint
166169

167-
if state.Identifier.IsNull() {
170+
if previousState.Identifier.IsNull() {
168171
bp, err = r.portClient.CreateBlueprint(ctx, b)
169172
} else {
170-
bp, err = r.portClient.UpdateBlueprint(ctx, b, state.Identifier.ValueString())
173+
bp, err = r.portClient.UpdateBlueprint(ctx, b, previousState.ID.ValueString())
171174
}
172175

173176
if err != nil {
@@ -207,6 +210,10 @@ func (r *BlueprintResource) ImportState(ctx context.Context, req resource.Import
207210
resp.Diagnostics.Append(resp.State.SetAttribute(
208211
ctx, path.Root("identifier"), req.ID,
209212
)...)
213+
214+
resp.Diagnostics.Append(resp.State.SetAttribute(
215+
ctx, path.Root("id"), req.ID,
216+
)...)
210217
}
211218

212219
func blueprintResourceToPortRequest(ctx context.Context, state *BlueprintModel) (*cli.Blueprint, error) {

port/blueprint/resource_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,48 @@ func TestAccPortBlueprintWithCalculationProperty(t *testing.T) {
678678
},
679679
})
680680
}
681+
682+
func TestAccPortUpdateBlueprintIdentifier(t *testing.T) {
683+
identifier := utils.GenID()
684+
updatedIdentifier := utils.GenID()
685+
var testAccActionConfigCreate = fmt.Sprintf(`
686+
resource "port_blueprint" "microservice" {
687+
title = "TF Provider Test"
688+
icon = "Terraform"
689+
identifier = "%s"
690+
description = ""
691+
}
692+
`, identifier)
693+
694+
var testAccActionConfigUpdate = fmt.Sprintf(`
695+
resource "port_blueprint" "microservice" {
696+
title = "TF Provider Test"
697+
icon = "Terraform"
698+
identifier = "%s"
699+
description = ""
700+
}
701+
`, updatedIdentifier)
702+
703+
resource.Test(t, resource.TestCase{
704+
PreCheck: func() { acctest.TestAccPreCheck(t) },
705+
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
706+
Steps: []resource.TestStep{
707+
{
708+
Config: acctest.ProviderConfig + testAccActionConfigCreate,
709+
Check: resource.ComposeTestCheckFunc(
710+
resource.TestCheckResourceAttr("port_blueprint.microservice", "title", "TF Provider Test"),
711+
resource.TestCheckResourceAttr("port_blueprint.microservice", "identifier", identifier),
712+
resource.TestCheckResourceAttr("port_blueprint.microservice", "icon", "Terraform"),
713+
),
714+
},
715+
{
716+
Config: acctest.ProviderConfig + testAccActionConfigUpdate,
717+
Check: resource.ComposeTestCheckFunc(
718+
resource.TestCheckResourceAttr("port_blueprint.microservice", "title", "TF Provider Test"),
719+
resource.TestCheckResourceAttr("port_blueprint.microservice", "identifier", updatedIdentifier),
720+
resource.TestCheckResourceAttr("port_blueprint.microservice", "icon", "Terraform"),
721+
),
722+
},
723+
},
724+
})
725+
}

port/entity/resource.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ func writeEntityComputedFieldsToState(state *EntityModel, e *cli.Entity) {
115115

116116
func (r *EntityResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
117117
var state *EntityModel
118+
var previousState *EntityModel
119+
118120
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
121+
resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...)
119122

120123
if resp.Diagnostics.HasError() {
121124
return
@@ -138,7 +141,14 @@ func (r *EntityResource) Update(ctx context.Context, req resource.UpdateRequest,
138141
runID = state.RunID.ValueString()
139142
}
140143

141-
en, err := r.portClient.CreateEntity(ctx, e, runID)
144+
var en *cli.Entity
145+
146+
if previousState.Identifier.IsNull() {
147+
en, err = r.portClient.CreateEntity(ctx, e, runID)
148+
} else {
149+
en, err = r.portClient.UpdateEntity(ctx, previousState.Identifier.ValueString(), previousState.Blueprint.ValueString(), e, runID)
150+
}
151+
142152
if err != nil {
143153
resp.Diagnostics.AddError("failed to create entity", err.Error())
144154
return

port/entity/resource_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,83 @@ func TestAccPortEntityUpdateProp(t *testing.T) {
419419
},
420420
})
421421
}
422+
423+
func TestAccPortEntityUpdateIdentifier(t *testing.T) {
424+
blueprintIdentifier := utils.GenID()
425+
entityIdentifier := utils.GenID()
426+
entityUpdatedIdentifier := utils.GenID()
427+
var testAccActionConfigCreate = fmt.Sprintf(`
428+
resource "port_blueprint" "microservice" {
429+
title = "TF Provider Test BP0"
430+
icon = "Terraform"
431+
identifier = "%s"
432+
properties = {
433+
"string_props" = {
434+
"myStringIdentifier" = {
435+
"title" = "My String Identifier"
436+
}
437+
}
438+
}
439+
}
440+
resource "port_entity" "microservice" {
441+
title = "TF Provider Test Entity0"
442+
blueprint = port_blueprint.microservice.identifier
443+
identifier = "%s"
444+
properties = {
445+
"string_props" = {
446+
"myStringIdentifier" = "My String Value"
447+
}
448+
}
449+
}`, blueprintIdentifier, entityIdentifier)
450+
451+
var testAccActionConfigUpdate = fmt.Sprintf(`
452+
resource "port_blueprint" "microservice" {
453+
title = "TF Provider Test BP0"
454+
icon = "Terraform"
455+
identifier = "%s"
456+
properties = {
457+
"string_props" = {
458+
"myStringIdentifier" = {
459+
"title" = "My String Identifier"
460+
}
461+
}
462+
}
463+
}
464+
resource "port_entity" "microservice" {
465+
title = "TF Provider Test Entity0"
466+
blueprint = port_blueprint.microservice.identifier
467+
identifier = "%s"
468+
properties = {
469+
"string_props" = {
470+
"myStringIdentifier" = "My String Value2"
471+
}
472+
}
473+
}`, blueprintIdentifier, entityUpdatedIdentifier)
474+
475+
resource.Test(t, resource.TestCase{
476+
PreCheck: func() { acctest.TestAccPreCheck(t) },
477+
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
478+
479+
Steps: []resource.TestStep{
480+
{
481+
Config: acctest.ProviderConfig + testAccActionConfigCreate,
482+
Check: resource.ComposeTestCheckFunc(
483+
resource.TestCheckResourceAttr("port_entity.microservice", "identifier", entityIdentifier),
484+
resource.TestCheckResourceAttr("port_entity.microservice", "title", "TF Provider Test Entity0"),
485+
resource.TestCheckResourceAttr("port_entity.microservice", "blueprint", blueprintIdentifier),
486+
resource.TestCheckResourceAttr("port_entity.microservice", "properties.string_props.myStringIdentifier", "My String Value"),
487+
),
488+
},
489+
{
490+
Config: acctest.ProviderConfig + testAccActionConfigUpdate,
491+
Check: resource.ComposeTestCheckFunc(
492+
resource.TestCheckResourceAttr("port_entity.microservice", "identifier", entityUpdatedIdentifier),
493+
resource.TestCheckResourceAttr("port_entity.microservice", "title", "TF Provider Test Entity0"),
494+
resource.TestCheckResourceAttr("port_entity.microservice", "blueprint", blueprintIdentifier),
495+
resource.TestCheckResourceAttr("port_entity.microservice", "properties.string_props.myStringIdentifier", "My String Value2"),
496+
),
497+
},
498+
},
499+
})
500+
501+
}

port/scorecard/resouce.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ func writeScorecardComputedFieldsToState(state *ScorecardModel, wp *cli.Scorecar
9797

9898
func (r *ScorecardResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
9999
var state *ScorecardModel
100+
var previousState *ScorecardModel
101+
100102
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
103+
resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...)
101104

102105
if resp.Diagnostics.HasError() {
103106
return
@@ -109,7 +112,14 @@ func (r *ScorecardResource) Update(ctx context.Context, req resource.UpdateReque
109112
return
110113
}
111114

112-
sp, err := r.portClient.UpdateScorecard(ctx, state.Blueprint.ValueString(), state.Identifier.ValueString(), s)
115+
var sp *cli.Scorecard
116+
117+
if previousState.Identifier.IsNull() {
118+
sp, err = r.portClient.CreateScorecard(ctx, state.Blueprint.ValueString(), s)
119+
} else {
120+
sp, err = r.portClient.UpdateScorecard(ctx, state.Blueprint.ValueString(), previousState.Identifier.ValueString(), s)
121+
}
122+
113123
if err != nil {
114124
resp.Diagnostics.AddError("failed to update the scorecard", err.Error())
115125
return

0 commit comments

Comments
 (0)