Skip to content

Commit

Permalink
feat: [CCM-19504]: Terraform Support for Governance Rules (#1068)
Browse files Browse the repository at this point in the history
* feat: [CCM-19504]: Terraform Support for Governance Rules

* feat: [CCM-19504]: Add TF Docs

* feat: [CCM-19504]: Add TF Docs

* feat: [CCM-19504]: Terraform Support for Governance Rules

* feat: [CCM-19504]: Terraform Support for Governance Rules

* feat: [CCM-19504]: Terraform Support for Governance Rules
  • Loading branch information
rajarshee-harness authored Sep 19, 2024
1 parent c6f296f commit eeb35f8
Show file tree
Hide file tree
Showing 13 changed files with 470 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .changelog/1068.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
harness_governance_rule - Added Governance Rule resource in Harness terraform provider
```
34 changes: 34 additions & 0 deletions docs/data-sources/governance_rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "harness_governance_rule Data Source - terraform-provider-harness"
subcategory: "Next Gen"
description: |-
Datasource for looking up a rule.
---

# harness_governance_rule (Data Source)

Datasource for looking up a rule.

## Example Usage

```terraform
data "harness_governance_rule" "example" {
rule_id = "rule_id"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `rule_id` (String) Id of rule.

### Read-Only

- `cloud_provider` (String) The cloud provider for the rule.
- `description` (String) Description for rule.
- `id` (String) The ID of this resource.
- `name` (String) Name of the rule.
- `rules_yaml` (String) Policy YAML of the rule.
40 changes: 40 additions & 0 deletions docs/resources/governance_rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "harness_governance_rule Resource - terraform-provider-harness"
subcategory: "Next Gen"
description: |-
Resource for creating, updating, and managing rule.
---

# harness_governance_rule (Resource)

Resource for creating, updating, and managing rule.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `cloud_provider` (String) The cloud provider for the rule. It should be either AWS, AZURE or GCP.
- `name` (String) Name of the rule.
- `rules_yaml` (String) The policy YAML of the rule

### Optional

- `description` (String) Description for rule.

### Read-Only

- `id` (String) The ID of this resource.
- `rule_id` (String) Id of the rule.

## Import

Import is supported using the following syntax:

```shell
# Import governance enforcement
terraform import harness_governance_rule.example <rule_id>
```
3 changes: 3 additions & 0 deletions examples/data-sources/harness_governance_rule/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "harness_governance_rule" "example" {
rule_id = "rule_id"
}
2 changes: 2 additions & 0 deletions examples/resources/harness_governance_rule/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Import governance enforcement
terraform import harness_governance_rule.example <rule_id>
7 changes: 7 additions & 0 deletions examples/resources/harness_governance_rule/resources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "harness_governance_rule" "example" {
identifier = "identifier"
name = "name"
cloud_provider = "AWS/AZURE/GCP"
description = "description"
rules_yaml = "policies:\n - name: aws-list-ec2\n resource: aws.ec2"
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/antihax/optional v1.0.0
github.com/aws/aws-sdk-go v1.46.4
github.com/docker/docker v24.0.5+incompatible
github.com/harness/harness-go-sdk v0.4.5
github.com/harness/harness-go-sdk v0.4.8
github.com/harness/harness-openapi-go-client v0.0.21
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/harness/harness-go-sdk v0.4.5 h1:nXcZ5XNP+PFfRgo9A3yuQi5zTQbinWpooZq3VRBTN2E=
github.com/harness/harness-go-sdk v0.4.5/go.mod h1:a/1HYTgVEuNEoh3Z3IsOHZdlUNxl94KcX57ZSNVGll0=
github.com/harness/harness-go-sdk v0.4.8 h1:ufWTQgFKq5xGLGPEm8CMuEHv0v0Gveri2TzDTdPqDMw=
github.com/harness/harness-go-sdk v0.4.8/go.mod h1:a/1HYTgVEuNEoh3Z3IsOHZdlUNxl94KcX57ZSNVGll0=
github.com/harness/harness-openapi-go-client v0.0.21 h1:VtJnpQKZvCAlaCmUPbNR69OT3c5WRdhNN5TOgUwtwZ4=
github.com/harness/harness-openapi-go-client v0.0.21/go.mod h1:u0vqYb994BJGotmEwJevF4L3BNAdU9i8ui2d22gmLPA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
Expand Down
3 changes: 3 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
dbschema "github.com/harness/terraform-provider-harness/internal/service/platform/db_schema"
"github.com/harness/terraform-provider-harness/internal/service/platform/gitx/webhook"
governance_enforcement "github.com/harness/terraform-provider-harness/internal/service/platform/governance/enforcement"
governance_rule "github.com/harness/terraform-provider-harness/internal/service/platform/governance/rule"
"github.com/harness/terraform-provider-harness/internal/service/platform/notification_rule"

"github.com/harness/terraform-provider-harness/internal/service/platform/feature_flag"
Expand Down Expand Up @@ -282,6 +283,7 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_gitops_app_project": gitops_project.DataSourceGitOpsProject(),
"harness_platform_gitx_webhook": webhook.DataSourceWebhook(),
"harness_governance_rule_enforcement": governance_enforcement.DatasourceRuleEnforcement(),
"harness_governance_rule": governance_rule.DatasourceRule(),
},
ResourcesMap: map[string]*schema.Resource{
"harness_platform_template": pl_template.ResourceTemplate(),
Expand Down Expand Up @@ -425,6 +427,7 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_connector_custom_secret_manager": connector.ResourceConnectorCSM(),
"harness_platform_gitx_webhook": webhook.ResourceWebhook(),
"harness_governance_rule_enforcement": governance_enforcement.ResourceRuleEnforcement(),
"harness_governance_rule": governance_rule.ResourceRule(),
},
}

Expand Down
162 changes: 162 additions & 0 deletions internal/service/platform/governance/rule/rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package governance_rule

import (
"context"
"net/http"

"github.com/harness/harness-go-sdk/harness/nextgen"
"github.com/harness/terraform-provider-harness/helpers"
"github.com/harness/terraform-provider-harness/internal"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func ResourceRule() *schema.Resource {
resource := &schema.Resource{
Description: "Resource for creating, updating, and managing rule.",
ReadContext: resourceRuleRead,
CreateContext: resourceRuleCreateOrUpdate,
UpdateContext: resourceRuleCreateOrUpdate,
DeleteContext: resourceRuleDelete,
Importer: helpers.AccountLevelResourceImporter,
Schema: map[string]*schema.Schema{
"name": {
Description: "Name of the rule.",
Type: schema.TypeString,
Required: true,
},
"description": {
Description: "Description for rule.",
Type: schema.TypeString,
Optional: true,
},
"cloud_provider": {
Description: "The cloud provider for the rule. It should be either AWS, AZURE or GCP.",
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"AWS", "GCP", "AZURE"}, false),
},
"rules_yaml": {
Description: "The policy YAML of the rule",
Type: schema.TypeString,
Required: true,
},
"rule_id": {
Description: "Id of the rule.",
Type: schema.TypeString,
Computed: true,
},
},
}

return resource
}

func resourceRuleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)

id := d.Id()
resp, httpResp, err := c.RuleApi.GetPolicies(ctx, readRuleRequest(id), c.AccountId, nil)

if err != nil {
return helpers.HandleReadApiError(err, d, httpResp)
}

if resp.Data != nil {
err := readRuleResponse(d, resp.Data)
if err != nil {
return helpers.HandleReadApiError(err, d, httpResp)
}
}

return nil
}

func readRuleRequest(id string) nextgen.ListDto {
return nextgen.ListDto{
Query: &nextgen.RuleRequest{
PolicyIds: []string{id},
},
}
}

func readRuleResponse(d *schema.ResourceData, ruleList *nextgen.RuleList) error {
rule := ruleList.Rules[0]

d.Set("name", rule.Name)
d.Set("cloud_provider", rule.CloudProvider)
d.Set("description", rule.Description)
d.Set("rules_yaml", rule.RulesYaml)

return nil
}

func resourceRuleCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)

var err error
var resp nextgen.ResponseDtoRule
var httpResp *http.Response

id := d.Id()

if id == "" {
resp, httpResp, err = c.RuleApi.CreateNewRule(ctx, buildRule(d, false), c.AccountId)
} else {
resp, httpResp, err = c.RuleApi.UpdateRule(ctx, buildRule(d, true), c.AccountId)
}

if err != nil {
return helpers.HandleApiError(err, d, httpResp)
}

if resp.Data != nil {
createOrUpdateRuleResponse(d, resp.Data)
}

return nil
}

func buildRule(d *schema.ResourceData, update bool) nextgen.CreateRuleDto {
rule := &nextgen.CcmRule{
Name: d.Get("name").(string),
CloudProvider: d.Get("cloud_provider").(string),
Description: d.Get("description").(string),
RulesYaml: d.Get("rules_yaml").(string),
IsOOTB: false,
}

if update {
rule.Uuid = d.Id()
}

return nextgen.CreateRuleDto{
Rule: rule,
}
}

func createOrUpdateRuleResponse(d *schema.ResourceData, rule *nextgen.CcmRule) error {
d.SetId(rule.Uuid)
d.Set("rule_id", rule.Uuid)
d.Set("name", rule.Name)
d.Set("cloud_provider", rule.CloudProvider)
d.Set("description", rule.Description)
d.Set("rules_yaml", rule.RulesYaml)

return nil
}

func resourceRuleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)

id := d.Id()

_, httpResp, err := c.RuleApi.DeleteRule(ctx, c.AccountId, id)

if err != nil {
return helpers.HandleApiError(err, d, httpResp)
}

return nil
}
68 changes: 68 additions & 0 deletions internal/service/platform/governance/rule/rule_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package governance_rule

import (
"context"

"github.com/harness/terraform-provider-harness/helpers"
"github.com/harness/terraform-provider-harness/internal"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DatasourceRule() *schema.Resource {
return &schema.Resource{
Description: "Datasource for looking up a rule.",

ReadContext: resourceRuleReadDataSource,

Schema: map[string]*schema.Schema{
"rule_id": {
Description: "Id of rule.",
Type: schema.TypeString,
Required: true,
},
"name": {
Description: "Name of the rule.",
Type: schema.TypeString,
Computed: true,
},
"rules_yaml": {
Description: "Policy YAML of the rule.",
Type: schema.TypeString,
Computed: true,
},
"cloud_provider": {
Description: "The cloud provider for the rule.",
Type: schema.TypeString,
Computed: true,
},
"description": {
Description: "Description for rule.",
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceRuleReadDataSource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c, ctx := meta.(*internal.Session).GetPlatformClientWithContext(ctx)

id := d.Get("rule_id").(string)
resp, httpResp, err := c.RuleApi.GetPolicies(ctx, readRuleRequest(id), c.AccountId, nil)

if err != nil {
return helpers.HandleReadApiError(err, d, httpResp)
}

if resp.Data != nil {
err := readRuleResponse(d, resp.Data)
if err != nil {
return helpers.HandleReadApiError(err, d, httpResp)
}
}

d.SetId(id)

return nil
}
Loading

0 comments on commit eeb35f8

Please sign in to comment.