From a86ea40fce2319cc03e3888e3d9dabcaef4236ee Mon Sep 17 00:00:00 2001 From: MatanGevaPort Date: Thu, 20 Jun 2024 11:35:40 +0300 Subject: [PATCH 1/4] Changed model and schema to support level property --- internal/cli/models.go | 10 ++++++++-- port/scorecard/schema.go | 24 +++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/internal/cli/models.go b/internal/cli/models.go index 202442dc..bf8494f1 100644 --- a/internal/cli/models.go +++ b/internal/cli/models.go @@ -26,9 +26,15 @@ type ( Level string `tfsdk:"level"` } + ScorecardLevelModel struct { + Title string `tfsdk:"title"` + Color string `tfsdk:"color"` + } + ScorecardModel struct { - Rules []ScorecardRulesModel `tfsdk:"rules"` - Level string `tfsdk:"level"` + Rules []ScorecardRulesModel `tfsdk:"rules"` + Levels []ScorecardLevelModel `tfsdk:"levels"` + Level string `tfsdk:"level"` } Entity struct { diff --git a/port/scorecard/schema.go b/port/scorecard/schema.go index 8e49f284..0e6f3855 100644 --- a/port/scorecard/schema.go +++ b/port/scorecard/schema.go @@ -13,6 +13,19 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) +func LevelSchema() map[string]schema.Attribute { + return map[string]schema.Attribute{ + "color": schema.StringAttribute{ + MarkdownDescription: "The color of the level", + Required: true, + }, + "title": schema.StringAttribute{ + MarkdownDescription: "The title of the level", + Required: true, + }, + } +} + func RuleSchema() map[string]schema.Attribute { return map[string]schema.Attribute{ "identifier": schema.StringAttribute{ @@ -26,9 +39,6 @@ func RuleSchema() map[string]schema.Attribute { "level": schema.StringAttribute{ MarkdownDescription: "The level of the rule", Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("Bronze", "Silver", "Gold"), - }, }, "query": schema.SingleNestedAttribute{ MarkdownDescription: "The query of the rule", @@ -70,6 +80,14 @@ func ScorecardSchema() map[string]schema.Attribute { MarkdownDescription: "The title of the scorecard", Required: true, }, + "levels": schema.ListNestedAttribute{ + MarkdownDescription: "The Levels of the scorecard", + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: LevelSchema(), + }, + }, "rules": schema.ListNestedAttribute{ MarkdownDescription: "The rules of the scorecard", Required: true, From 63e455ed86b652fba249056bcdbe731918666b20 Mon Sep 17 00:00:00 2001 From: MatanGevaPort Date: Thu, 20 Jun 2024 14:42:48 +0300 Subject: [PATCH 2/4] Added more models --- internal/cli/models.go | 30 ++++++++++++++++++------------ port/scorecard/model.go | 6 ++++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/internal/cli/models.go b/internal/cli/models.go index bf8494f1..79680edb 100644 --- a/internal/cli/models.go +++ b/internal/cli/models.go @@ -21,20 +21,20 @@ type ( } ScorecardRulesModel struct { - Identifier string `tfsdk:"identifier"` - Status string `tfsdk:"status"` - Level string `tfsdk:"level"` + Identifier string `json:"identifier"` + Status string `json:"status"` + Level string `json:"level"` } ScorecardLevelModel struct { - Title string `tfsdk:"title"` - Color string `tfsdk:"color"` + Title string `json:"title"` + Color string `json:"color"` } ScorecardModel struct { - Rules []ScorecardRulesModel `tfsdk:"rules"` - Levels []ScorecardLevelModel `tfsdk:"levels"` - Level string `tfsdk:"level"` + Rules []ScorecardRulesModel `json:"rules"` + Levels []ScorecardLevelModel `json:"levels,omitempty"` + Level string `json:"level"` } Entity struct { @@ -332,10 +332,11 @@ type ( Scorecard struct { Meta - Identifier string `json:"identifier,omitempty"` - Title string `json:"title,omitempty"` - Blueprint string `json:"blueprint,omitempty"` - Rules []Rule `json:"rules,omitempty"` + Identifier string `json:"identifier,omitempty"` + Title string `json:"title,omitempty"` + Blueprint string `json:"blueprint,omitempty"` + Levels []Level `json:"levels,omitempty"` + Rules []Rule `json:"rules,omitempty"` } Rule struct { @@ -345,6 +346,11 @@ type ( Query Query `json:"query,omitempty"` } + Level struct { + Title string `json:"title"` + Color string `json:"color"` + } + Query struct { Combinator string `json:"combinator,omitempty"` Conditions []any `json:"conditions,omitempty"` diff --git a/port/scorecard/model.go b/port/scorecard/model.go index e518ae20..fbf860ce 100644 --- a/port/scorecard/model.go +++ b/port/scorecard/model.go @@ -16,11 +16,17 @@ type Rule struct { Query *Query `tfsdk:"query"` } +type Level struct { + Title types.String `tfsdk:"title"` + Color types.String `tfsdk:"color"` +} + type ScorecardModel struct { ID types.String `tfsdk:"id"` Identifier types.String `tfsdk:"identifier"` Blueprint types.String `tfsdk:"blueprint"` Title types.String `tfsdk:"title"` + Levels []Level `tfsdk:"levels"` Rules []Rule `tfsdk:"rules"` CreatedAt types.String `tfsdk:"created_at"` CreatedBy types.String `tfsdk:"created_by"` From d60533dbb43b195e724c2bf5e14bcbb685e0a69d Mon Sep 17 00:00:00 2001 From: MatanGevaPort Date: Mon, 8 Jul 2024 19:06:38 +0300 Subject: [PATCH 3/4] Changed models and cli conversion --- internal/cli/models.go | 6 +-- port/scorecard/model.go | 2 +- port/scorecard/refreshScorecardState.go | 17 +++++++++ port/scorecard/resource.go | 15 ++++++-- port/scorecard/resource_test.go | 21 +++++++++++ port/scorecard/schema.go | 1 - port/scorecard/scorecardResourceToPortBody.go | 37 ++++++++++++++++++- 7 files changed, 90 insertions(+), 9 deletions(-) diff --git a/internal/cli/models.go b/internal/cli/models.go index 79680edb..a317688c 100644 --- a/internal/cli/models.go +++ b/internal/cli/models.go @@ -33,7 +33,7 @@ type ( ScorecardModel struct { Rules []ScorecardRulesModel `json:"rules"` - Levels []ScorecardLevelModel `json:"levels,omitempty"` + Levels []ScorecardLevelModel `json:"levels"` Level string `json:"level"` } @@ -347,8 +347,8 @@ type ( } Level struct { - Title string `json:"title"` - Color string `json:"color"` + Title string `json:"title,omitempty"` + Color string `json:"color,omitempty"` } Query struct { diff --git a/port/scorecard/model.go b/port/scorecard/model.go index fbf860ce..da330c64 100644 --- a/port/scorecard/model.go +++ b/port/scorecard/model.go @@ -26,7 +26,7 @@ type ScorecardModel struct { Identifier types.String `tfsdk:"identifier"` Blueprint types.String `tfsdk:"blueprint"` Title types.String `tfsdk:"title"` - Levels []Level `tfsdk:"levels"` + Levels []Level `tfsdk:"levels"` Rules []Rule `tfsdk:"rules"` CreatedAt types.String `tfsdk:"created_at"` CreatedBy types.String `tfsdk:"created_by"` diff --git a/port/scorecard/refreshScorecardState.go b/port/scorecard/refreshScorecardState.go index a263ce15..f4819e9e 100644 --- a/port/scorecard/refreshScorecardState.go +++ b/port/scorecard/refreshScorecardState.go @@ -43,4 +43,21 @@ func refreshScorecardState(ctx context.Context, state *ScorecardModel, s *cli.Sc state.Rules = stateRules + var cliLevels []cli.Level + if len(s.Levels) == 0 { + cliLevels = DefaultLevels() + } else { + cliLevels = s.Levels + } + + stateLevels := []Level{} + for _, cliLevel := range cliLevels { + level := &Level{ + Color: types.StringValue(cliLevel.Color), + Title: types.StringValue(cliLevel.Title), + } + stateLevels = append(stateLevels, *level) + } + fmt.Sprintf("============================================================================================================================ %s", stateLevels) + state.Levels = stateLevels } diff --git a/port/scorecard/resource.go b/port/scorecard/resource.go index cbad0c9b..f90a8cf7 100644 --- a/port/scorecard/resource.go +++ b/port/scorecard/resource.go @@ -57,7 +57,6 @@ func (r *ScorecardResource) Read(ctx context.Context, req resource.ReadRequest, } refreshScorecardState(ctx, state, s, blueprintIdentifier) - resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -81,7 +80,7 @@ func (r *ScorecardResource) Create(ctx context.Context, req resource.CreateReque return } - writeScorecardComputedFieldsToState(state, sp) + refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString()) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -93,6 +92,16 @@ func writeScorecardComputedFieldsToState(state *ScorecardModel, wp *cli.Scorecar state.CreatedBy = types.StringValue(wp.CreatedBy) state.UpdatedAt = types.StringValue(wp.UpdatedAt.String()) state.UpdatedBy = types.StringValue(wp.UpdatedBy) + stateLevels := []Level{} + cliLevels := wp.Levels + for _, cliLevel := range cliLevels { + level := &Level{ + Color: types.StringValue(cliLevel.Color), + Title: types.StringValue(cliLevel.Title), + } + stateLevels = append(stateLevels, *level) + } + state.Levels = stateLevels } func (r *ScorecardResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { @@ -125,7 +134,7 @@ func (r *ScorecardResource) Update(ctx context.Context, req resource.UpdateReque return } - writeScorecardComputedFieldsToState(state, sp) + refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString()) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } diff --git a/port/scorecard/resource_test.go b/port/scorecard/resource_test.go index 8ab1657f..477899dc 100644 --- a/port/scorecard/resource_test.go +++ b/port/scorecard/resource_test.go @@ -5,10 +5,25 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/port-labs/terraform-provider-port-labs/v2/internal/acctest" "github.com/port-labs/terraform-provider-port-labs/v2/internal/utils" ) +func printResourceAttributes(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + for key, value := range rs.Primary.Attributes { + fmt.Printf("%s: %s\n", key, value) + } + return nil + } +} + func testAccCreateBlueprintConfig(identifier string) string { return fmt.Sprintf(` resource "port_blueprint" "microservice" { @@ -71,6 +86,7 @@ func TestAccPortScorecardBasic(t *testing.T) { { Config: acctest.ProviderConfig + testAccActionConfigCreate, Check: resource.ComposeTestCheckFunc( + printResourceAttributes("port_scorecard.test"), resource.TestCheckResourceAttr("port_scorecard.test", "title", "Scorecard 1"), resource.TestCheckResourceAttr("port_scorecard.test", "blueprint", blueprintIdentifier), resource.TestCheckResourceAttr("port_scorecard.test", "rules.#", "1"), @@ -80,6 +96,11 @@ func TestAccPortScorecardBasic(t *testing.T) { resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.combinator", "and"), resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.conditions.#", "1"), resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.conditions.0", "{\"operator\":\"isNotEmpty\",\"property\":\"$team\"}"), + resource.TestCheckResourceAttr("port_scorecard.test", "levels.#", "4"), + resource.TestCheckResourceAttr("port_scorecard.test", "levels.0", "{\"color\":\"paleBlue\",\"title\":\"Basic\"}"), + resource.TestCheckResourceAttr("port_scorecard.test", "levels.1", "{\"color\":\"bronze\",\"title\":\"Bronze\"}"), + resource.TestCheckResourceAttr("port_scorecard.test", "levels.2", "{\"color\":\"silver\",\"title\":\"Silver\"}"), + resource.TestCheckResourceAttr("port_scorecard.test", "levels.3", "{\"color\":\"gold\",\"title\":\"Gold\"}"), ), }, }, diff --git a/port/scorecard/schema.go b/port/scorecard/schema.go index 0e6f3855..82dbd106 100644 --- a/port/scorecard/schema.go +++ b/port/scorecard/schema.go @@ -83,7 +83,6 @@ func ScorecardSchema() map[string]schema.Attribute { "levels": schema.ListNestedAttribute{ MarkdownDescription: "The Levels of the scorecard", Optional: true, - Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: LevelSchema(), }, diff --git a/port/scorecard/scorecardResourceToPortBody.go b/port/scorecard/scorecardResourceToPortBody.go index 3c78abe7..2a3ce252 100644 --- a/port/scorecard/scorecardResourceToPortBody.go +++ b/port/scorecard/scorecardResourceToPortBody.go @@ -6,6 +6,28 @@ import ( "github.com/port-labs/terraform-provider-port-labs/v2/internal/cli" ) + +func DefaultLevels() []cli.Level { + return []cli.Level{ + { + Color: "paleBlue", + Title: "Basic", + }, + { + Color: "bronze", + Title: "Bronze", + }, + { + Color: "silver", + Title: "Silver", + }, + { + Color: "gold", + Title: "Gold", + }, + } +} + func scorecardResourceToPortBody(ctx context.Context, state *ScorecardModel) (*cli.Scorecard, error) { s := &cli.Scorecard{ Identifier: state.Identifier.ValueString(), @@ -42,6 +64,19 @@ func scorecardResourceToPortBody(ctx context.Context, state *ScorecardModel) (*c } s.Rules = rules - + + if len(state.Levels) == 0 { + s.Levels = DefaultLevels() + } else { + var levels []cli.Level + for _, stateLevel := range state.Levels { + level := &cli.Level{ + Color: stateLevel.Color.ValueString(), + Title: stateLevel.Title.ValueString(), + } + levels = append(levels, *level) + } + s.Levels = levels + } return s, nil } From 0b42329c1d12af176a1095894e44696ed45bb0e7 Mon Sep 17 00:00:00 2001 From: tankilevitch Date: Mon, 8 Jul 2024 19:38:36 +0300 Subject: [PATCH 4/4] don't trust it --- port/scorecard/refreshScorecardState.go | 6 +++++- port/scorecard/resource.go | 10 +++++++--- port/scorecard/scorecardResourceToPortBody.go | 7 ++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/port/scorecard/refreshScorecardState.go b/port/scorecard/refreshScorecardState.go index f4819e9e..b2364173 100644 --- a/port/scorecard/refreshScorecardState.go +++ b/port/scorecard/refreshScorecardState.go @@ -9,7 +9,7 @@ import ( "github.com/port-labs/terraform-provider-port-labs/v2/internal/cli" ) -func refreshScorecardState(ctx context.Context, state *ScorecardModel, s *cli.Scorecard, blueprintIdentifier string) { +func refreshScorecardState(ctx context.Context, state *ScorecardModel, s *cli.Scorecard, blueprintIdentifier string, expectLevels *bool) { state.ID = types.StringValue(fmt.Sprintf("%s:%s", blueprintIdentifier, s.Identifier)) state.Identifier = types.StringValue(s.Identifier) state.Blueprint = types.StringValue(blueprintIdentifier) @@ -43,6 +43,10 @@ func refreshScorecardState(ctx context.Context, state *ScorecardModel, s *cli.Sc state.Rules = stateRules + if expectLevels != nil && !*expectLevels { + return + } + var cliLevels []cli.Level if len(s.Levels) == 0 { cliLevels = DefaultLevels() diff --git a/port/scorecard/resource.go b/port/scorecard/resource.go index f90a8cf7..c045ad31 100644 --- a/port/scorecard/resource.go +++ b/port/scorecard/resource.go @@ -56,7 +56,7 @@ func (r *ScorecardResource) Read(ctx context.Context, req resource.ReadRequest, return } - refreshScorecardState(ctx, state, s, blueprintIdentifier) + refreshScorecardState(ctx, state, s, blueprintIdentifier, nil) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -80,7 +80,11 @@ func (r *ScorecardResource) Create(ctx context.Context, req resource.CreateReque return } - refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString()) + expectLevels := false + if len(s.Levels) > 0 { + expectLevels = true + } + refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString(), &expectLevels) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -134,7 +138,7 @@ func (r *ScorecardResource) Update(ctx context.Context, req resource.UpdateReque return } - refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString()) + refreshScorecardState(ctx, state, sp, state.Blueprint.ValueString(), nil) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } diff --git a/port/scorecard/scorecardResourceToPortBody.go b/port/scorecard/scorecardResourceToPortBody.go index 2a3ce252..c3f2133b 100644 --- a/port/scorecard/scorecardResourceToPortBody.go +++ b/port/scorecard/scorecardResourceToPortBody.go @@ -6,7 +6,6 @@ import ( "github.com/port-labs/terraform-provider-port-labs/v2/internal/cli" ) - func DefaultLevels() []cli.Level { return []cli.Level{ { @@ -64,10 +63,8 @@ func scorecardResourceToPortBody(ctx context.Context, state *ScorecardModel) (*c } s.Rules = rules - - if len(state.Levels) == 0 { - s.Levels = DefaultLevels() - } else { + + if len(state.Levels) > 0 { var levels []cli.Level for _, stateLevel := range state.Levels { level := &cli.Level{