Skip to content

Commit

Permalink
Merge pull request #201 from port-labs/scorecard_description
Browse files Browse the repository at this point in the history
added rule description support:
  • Loading branch information
OmriGez authored Jan 22, 2025
2 parents f8b450f + 16e667c commit e5a27ed
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 13 deletions.
4 changes: 4 additions & 0 deletions docs/resources/port_scorecard.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ Required:
- `query` (Attributes) The query of the rule (see [below for nested schema](#nestedatt--rules--query))
- `title` (String) The title of the rule

Optional:

- `description` (String) The description of the rule

<a id="nestedatt--rules--query"></a>
### Nested Schema for `rules.query`

Expand Down
11 changes: 6 additions & 5 deletions internal/cli/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ type (
ChangelogDestination *ChangelogDestination `json:"changelogDestination,omitempty"`
TeamInheritance *TeamInheritance `json:"teamInheritance,omitempty"`
Relations map[string]Relation `json:"relations"`
Ownership *Ownership `json:"ownership,omitempty"`
Ownership *Ownership `json:"ownership,omitempty"`
}

Action struct {
Expand Down Expand Up @@ -354,10 +354,11 @@ type (
}

Rule struct {
Identifier string `json:"identifier,omitempty"`
Title string `json:"title,omitempty"`
Level string `json:"level,omitempty"`
Query Query `json:"query,omitempty"`
Identifier string `json:"identifier,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Level string `json:"level,omitempty"`
Query Query `json:"query,omitempty"`
}

Level struct {
Expand Down
9 changes: 5 additions & 4 deletions port/scorecard/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ type Query struct {
}

type Rule struct {
Identifier types.String `tfsdk:"identifier"`
Title types.String `tfsdk:"title"`
Level types.String `tfsdk:"level"`
Query *Query `tfsdk:"query"`
Identifier types.String `tfsdk:"identifier"`
Title types.String `tfsdk:"title"`
Description types.String `tfsdk:"description"`
Level types.String `tfsdk:"level"`
Query *Query `tfsdk:"query"`
}

type Level struct {
Expand Down
17 changes: 13 additions & 4 deletions port/scorecard/refreshScorecardState.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ package scorecard
import (
"context"
"fmt"

"github.com/port-labs/terraform-provider-port-labs/v2/internal/utils"

"reflect"

"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/port-labs/terraform-provider-port-labs/v2/internal/cli"
"reflect"
)

func shouldRefreshLevels(stateLevels []Level, cliLevels []cli.Level) bool {
// When you create a scorecard in Port, the scorecard gets created with default levels.
// When you create a scorecard in Port, the scorecard gets created with default levels.
// If your scorecard doesn't have the "levels" attribute, it means the scorecard is created with default levels behind the scenes.
//
// If the TF state has no levels and the Port existing levels are the default levels, This means both are considered
// If the TF state has no levels and the Port existing levels are the default levels, This means both are considered
// to have default levels, And so we don't need to update them.
if len(stateLevels) == 0 && reflect.DeepEqual(cliLevels, DefaultCliLevels()) {
return false
}
// If the TF state has defined levels, we have to make sure that Port's existing levels are the same as the TF state levels.
// also,
// If TF state doesn't have levels and the Port existing levels are not the default ones,
// this means we have to make sure that Port's defined levels are the default levels,
// this means we have to make sure that Port's defined levels are the default levels,
// as the state without levels is considered to have default levels.
if len(stateLevels) > 0 || (len(stateLevels) == 0 && !reflect.DeepEqual(cliLevels, DefaultCliLevels())) {
return true
Expand Down Expand Up @@ -81,6 +83,13 @@ func refreshScorecardState(ctx context.Context, state *ScorecardModel, s *cli.Sc
Level: types.StringValue(rule.Level),
Identifier: types.StringValue(rule.Identifier),
}

if rule.Description != "" {
stateRule.Description = types.StringValue(rule.Description)
} else {
stateRule.Description = types.StringNull()
}

stateQuery := &Query{
Combinator: types.StringValue(rule.Query.Combinator),
}
Expand Down
4 changes: 4 additions & 0 deletions port/scorecard/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func TestAccPortScorecardUpdate(t *testing.T) {
rules = [{
identifier = "hasTeam"
title = "Has Team"
description = "Checks if the entity has a team assigned"
level = "Gold"
query = {
combinator = "and"
Expand All @@ -218,6 +219,7 @@ func TestAccPortScorecardUpdate(t *testing.T) {
rules = [{
identifier = "hasTeam"
title = "Has Team"
description = "Updated: Verifies team assignment"
level = "Bronze"
query = {
combinator = "or"
Expand Down Expand Up @@ -245,6 +247,7 @@ func TestAccPortScorecardUpdate(t *testing.T) {
resource.TestCheckResourceAttr("port_scorecard.test", "rules.#", "1"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.identifier", "hasTeam"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.title", "Has Team"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.description", "Checks if the entity has a team assigned"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.level", "Gold"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.combinator", "and"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.conditions.#", "1"),
Expand All @@ -259,6 +262,7 @@ func TestAccPortScorecardUpdate(t *testing.T) {
resource.TestCheckResourceAttr("port_scorecard.test", "rules.#", "1"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.identifier", "hasTeam"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.title", "Has Team"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.description", "Updated: Verifies team assignment"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.level", "Bronze"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.combinator", "or"),
resource.TestCheckResourceAttr("port_scorecard.test", "rules.0.query.conditions.#", "1"),
Expand Down
5 changes: 5 additions & 0 deletions port/scorecard/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scorecard

import (
"context"

"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"github.com/hashicorp/terraform-plugin-framework/types"

Expand Down Expand Up @@ -36,6 +37,10 @@ func RuleSchema() map[string]schema.Attribute {
MarkdownDescription: "The title of the rule",
Required: true,
},
"description": schema.StringAttribute{
MarkdownDescription: "The description of the rule",
Optional: true,
},
"level": schema.StringAttribute{
MarkdownDescription: "The level of the rule",
Required: true,
Expand Down
6 changes: 6 additions & 0 deletions port/scorecard/scorecardResourceToPortBody.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scorecard
import (
"context"
"encoding/json"

"github.com/port-labs/terraform-provider-port-labs/v2/internal/cli"
)

Expand Down Expand Up @@ -32,6 +33,11 @@ func scorecardResourceToPortBody(ctx context.Context, state *ScorecardModel) (*c
Identifier: stateRule.Identifier.ValueString(),
Title: stateRule.Title.ValueString(),
}

if !stateRule.Description.IsNull() {
rule.Description = stateRule.Description.ValueString()
}

query := &cli.Query{
Combinator: stateRule.Query.Combinator.ValueString(),
}
Expand Down

0 comments on commit e5a27ed

Please sign in to comment.