From 6756e457cb2df401afd94d417b66715d8e41b46b Mon Sep 17 00:00:00 2001 From: Wilson de Carvalho <796900+wcmjunior@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:42:30 -0700 Subject: [PATCH] Refactor cyral_policy --- cyral/internal/policy/constants.go | 5 + cyral/internal/policy/model.go | 111 ++++++++++++ cyral/internal/policy/model_policy.go | 28 --- .../{resource_cyral_policy.go => resource.go} | 161 ++---------------- ..._cyral_policy_test.go => resource_test.go} | 0 cyral/internal/policy/schema_loader.go | 26 +++ cyral/provider/provider.go | 2 - cyral/provider/schema_loader.go | 2 + 8 files changed, 160 insertions(+), 175 deletions(-) create mode 100644 cyral/internal/policy/constants.go create mode 100644 cyral/internal/policy/model.go delete mode 100644 cyral/internal/policy/model_policy.go rename cyral/internal/policy/{resource_cyral_policy.go => resource.go} (52%) rename cyral/internal/policy/{resource_cyral_policy_test.go => resource_test.go} (100%) create mode 100644 cyral/internal/policy/schema_loader.go diff --git a/cyral/internal/policy/constants.go b/cyral/internal/policy/constants.go new file mode 100644 index 00000000..57486e47 --- /dev/null +++ b/cyral/internal/policy/constants.go @@ -0,0 +1,5 @@ +package policy + +const ( + resourceName = "cyral_policy" +) diff --git a/cyral/internal/policy/model.go b/cyral/internal/policy/model.go new file mode 100644 index 00000000..c523723a --- /dev/null +++ b/cyral/internal/policy/model.go @@ -0,0 +1,111 @@ +package policy + +import ( + "fmt" + "time" + + "github.com/cyralinc/terraform-provider-cyral/cyral/utils" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type PolicyMetadata struct { + ID string `json:"id"` + Name string `json:"name"` + Version string `json:"version"` + Created time.Time `json:"created"` + LastUpdated time.Time `json:"lastUpdated"` + Type string `json:"type"` + Tags []string `json:"tags"` + Enabled bool `json:"enabled"` + Description string `json:"description"` +} + +type PolicyListResponse struct { + // Policies is a list of policy identifiers. + Policies []string `json:"Policies,omitempty"` +} + +type Policy struct { + Meta *PolicyMetadata `json:"meta"` + Data []string `json:"data,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +func (r Policy) WriteToSchema(d *schema.ResourceData) error { + if err := d.Set("created", r.Meta.Created.String()); err != nil { + return fmt.Errorf("error setting 'created' field: %w", err) + } + if err := d.Set("data", r.Data); err != nil { + return fmt.Errorf("error setting 'data' field: %w", err) + } + if err := d.Set("data_label_tags", r.Tags); err != nil { + return fmt.Errorf("error setting 'data_label_tags' field: %w", err) + } + if err := d.Set("description", r.Meta.Description); err != nil { + return fmt.Errorf("error setting 'description' field: %w", err) + } + if err := d.Set("enabled", r.Meta.Enabled); err != nil { + return fmt.Errorf("error setting 'enabled' field: %w", err) + } + if err := d.Set("last_updated", r.Meta.LastUpdated.String()); err != nil { + return fmt.Errorf("error setting 'last_updated' field: %w", err) + } + if err := d.Set("name", r.Meta.Name); err != nil { + return fmt.Errorf("error setting 'name' field: %w", err) + } + if err := d.Set("type", r.Meta.Type); err != nil { + return fmt.Errorf("error setting 'type' field: %w", err) + } + if err := d.Set("version", r.Meta.Version); err != nil { + return fmt.Errorf("error setting 'version' field: %w", err) + } + // Once the `tags` field is removed, this conditional logic should also be + // removed and only the `metadata_tags` should be set. + _, isDeprecatedFieldSet := d.GetOk("tags") + if isDeprecatedFieldSet { + if err := d.Set("tags", r.Meta.Tags); err != nil { + return fmt.Errorf("error setting 'tags' field: %w", err) + } + } else { + if err := d.Set("metadata_tags", r.Meta.Tags); err != nil { + return fmt.Errorf("error setting 'metadata_tags' field: %w", err) + } + + } + + return nil +} + +func (r *Policy) ReadFromSchema(d *schema.ResourceData) error { + r.Data = utils.GetStrListFromSchemaField(d, "data") + r.Tags = utils.GetStrListFromSchemaField(d, "data_label_tags") + metadataTags := utils.GetStrListFromSchemaField(d, "metadata_tags") + if len(metadataTags) == 0 { + metadataTags = utils.GetStrListFromSchemaField(d, "tags") + } + r.Meta = &PolicyMetadata{ + Tags: metadataTags, + } + + if v, ok := d.Get("name").(string); ok { + r.Meta.Name = v + } + + if v, ok := d.Get("version").(string); ok { + r.Meta.Version = v + } + + if v, ok := d.Get("type").(string); ok { + r.Meta.Type = v + } + + if v, ok := d.Get("enabled").(bool); ok { + r.Meta.Enabled = v + } + + if v, ok := d.Get("description").(string); ok { + r.Meta.Description = v + } + + return nil +} diff --git a/cyral/internal/policy/model_policy.go b/cyral/internal/policy/model_policy.go deleted file mode 100644 index 500dda8f..00000000 --- a/cyral/internal/policy/model_policy.go +++ /dev/null @@ -1,28 +0,0 @@ -package policy - -import ( - "time" -) - -type Policy struct { - Meta *PolicyMetadata `json:"meta"` - Data []string `json:"data,omitempty"` - Tags []string `json:"tags,omitempty"` -} - -type PolicyMetadata struct { - ID string `json:"id"` - Name string `json:"name"` - Version string `json:"version"` - Created time.Time `json:"created"` - LastUpdated time.Time `json:"lastUpdated"` - Type string `json:"type"` - Tags []string `json:"tags"` - Enabled bool `json:"enabled"` - Description string `json:"description"` -} - -type PolicyListResponse struct { - // Policies is a list of policy identifiers. - Policies []string `json:"Policies,omitempty"` -} diff --git a/cyral/internal/policy/resource_cyral_policy.go b/cyral/internal/policy/resource.go similarity index 52% rename from cyral/internal/policy/resource_cyral_policy.go rename to cyral/internal/policy/resource.go index dd39ab60..f53250bc 100644 --- a/cyral/internal/policy/resource_cyral_policy.go +++ b/cyral/internal/policy/resource.go @@ -8,21 +8,31 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/client" "github.com/cyralinc/terraform-provider-cyral/cyral/core" + "github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" "github.com/cyralinc/terraform-provider-cyral/cyral/utils" "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourcePolicy() *schema.Resource { +var resourceContextHandler = core.DefaultContextHandler{ + ResourceName: resourceName, + ResourceType: resourcetype.Resource, + SchemaReaderFactory: func() core.SchemaReader { return &Policy{} }, + SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &Policy{} }, + BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string { + return fmt.Sprintf("https://%s/v1/policies", c.ControlPlane) + }, +} + +func resourceSchema() *schema.Resource { return &schema.Resource{ Description: "Manages [policies](https://cyral.com/docs/reference/policy). See also: " + "[Policy Rule](./policy_rule.md). For more information, see the " + "[Policy Guide](https://cyral.com/docs/policy/overview).", - CreateContext: resourcePolicyCreate, - ReadContext: resourcePolicyRead, - UpdateContext: resourcePolicyUpdate, - DeleteContext: resourcePolicyDelete, + CreateContext: resourceContextHandler.CreateContext(), + ReadContext: resourceContextHandler.ReadContext(), + UpdateContext: resourceContextHandler.UpdateContext(), + DeleteContext: resourceContextHandler.DeleteContext(), Schema: map[string]*schema.Schema{ "created": { Description: "Timestamp for the policy creation.", @@ -116,145 +126,6 @@ func ResourcePolicy() *schema.Resource { } } -func resourcePolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourcePolicyCreate") - c := m.(*client.Client) - - d.Set("type", "terraform") - policy := getPolicyInfoFromResource(d) - - url := fmt.Sprintf("https://%s/v1/policies", c.ControlPlane) - - body, err := c.DoRequest(ctx, url, http.MethodPost, policy) - if err != nil { - return utils.CreateError("Unable to create policy", fmt.Sprintf("%v", err)) - } - - response := core.IDBasedResponse{} - if err := json.Unmarshal(body, &response); err != nil { - return utils.CreateError("Unable to unmarshall JSON", fmt.Sprintf("%v", err)) - } - tflog.Debug(ctx, fmt.Sprintf("Response body (unmarshalled): %#v", response)) - - d.SetId(response.ID) - - tflog.Debug(ctx, "End resourcePolicyCreate") - - return resourcePolicyRead(ctx, d, m) -} - -func resourcePolicyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourcePolicyRead") - c := m.(*client.Client) - - url := fmt.Sprintf("https://%s/v1/policies/%s", c.ControlPlane, d.Id()) - - body, err := c.DoRequest(ctx, url, http.MethodGet, nil) - if err != nil { - return utils.CreateError("Unable to read policy", fmt.Sprintf("%v", err)) - } - - response := Policy{} - if err := json.Unmarshal(body, &response); err != nil { - return utils.CreateError("Unable to unmarshall JSON", fmt.Sprintf("%v", err)) - } - tflog.Debug(ctx, fmt.Sprintf("Response body (unmarshalled): %#v", response)) - - d.Set("created", response.Meta.Created.String()) - d.Set("data", response.Data) - d.Set("data_label_tags", response.Tags) - d.Set("description", response.Meta.Description) - d.Set("enabled", response.Meta.Enabled) - d.Set("last_updated", response.Meta.LastUpdated.String()) - d.Set("name", response.Meta.Name) - d.Set("type", response.Meta.Type) - d.Set("version", response.Meta.Version) - // Once the `tags` field is removed, this conditional logic should also be - // removed and only the `metadata_tags` should be set. - _, isDeprecatedFieldSet := d.GetOk("tags") - if isDeprecatedFieldSet { - d.Set("tags", response.Meta.Tags) - } else { - d.Set("metadata_tags", response.Meta.Tags) - } - - tflog.Debug(ctx, "End resourcePolicyRead") - return diag.Diagnostics{} -} - -func resourcePolicyUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourcePolicyUpdate") - c := m.(*client.Client) - - d.Set("type", "terraform") - policy := getPolicyInfoFromResource(d) - - url := fmt.Sprintf("https://%s/v1/policies/%s", c.ControlPlane, d.Id()) - - _, err := c.DoRequest(ctx, url, http.MethodPut, policy) - if err != nil { - return utils.CreateError("Unable to update policy", fmt.Sprintf("%v", err)) - } - - tflog.Debug(ctx, "End resourcePolicyUpdate") - - return resourcePolicyRead(ctx, d, m) -} - -func resourcePolicyDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Debug(ctx, "Init resourcePolicyDelete") - c := m.(*client.Client) - - url := fmt.Sprintf("https://%s/v1/policies/%s", c.ControlPlane, d.Id()) - - if _, err := c.DoRequest(ctx, url, http.MethodDelete, nil); err != nil { - return utils.CreateError("Unable to delete policy", fmt.Sprintf("%v", err)) - } - - tflog.Debug(ctx, "End resourcePolicyDelete") - - return diag.Diagnostics{} -} - -func getPolicyInfoFromResource(d *schema.ResourceData) Policy { - data := utils.GetStrListFromSchemaField(d, "data") - dataTags := utils.GetStrListFromSchemaField(d, "data_label_tags") - metadataTags := utils.GetStrListFromSchemaField(d, "metadata_tags") - if len(metadataTags) == 0 { - metadataTags = utils.GetStrListFromSchemaField(d, "tags") - } - - policy := Policy{ - Data: data, - Tags: dataTags, - Meta: &PolicyMetadata{ - Tags: metadataTags, - }, - } - - if v, ok := d.Get("name").(string); ok { - policy.Meta.Name = v - } - - if v, ok := d.Get("version").(string); ok { - policy.Meta.Version = v - } - - if v, ok := d.Get("type").(string); ok { - policy.Meta.Type = v - } - - if v, ok := d.Get("enabled").(bool); ok { - policy.Meta.Enabled = v - } - - if v, ok := d.Get("description").(string); ok { - policy.Meta.Description = v - } - - return policy -} - func ListPolicies(c *client.Client) ([]Policy, error) { ctx := context.Background() tflog.Debug(ctx, "Init ListPolicies") diff --git a/cyral/internal/policy/resource_cyral_policy_test.go b/cyral/internal/policy/resource_test.go similarity index 100% rename from cyral/internal/policy/resource_cyral_policy_test.go rename to cyral/internal/policy/resource_test.go diff --git a/cyral/internal/policy/schema_loader.go b/cyral/internal/policy/schema_loader.go new file mode 100644 index 00000000..3d4fbfda --- /dev/null +++ b/cyral/internal/policy/schema_loader.go @@ -0,0 +1,26 @@ +package policy + +import ( + "github.com/cyralinc/terraform-provider-cyral/cyral/core" +) + +type packageSchema struct { +} + +func (p *packageSchema) Name() string { + return "policy" +} + +func (p *packageSchema) Schemas() []*core.SchemaDescriptor { + return []*core.SchemaDescriptor{ + { + Name: resourceName, + Type: core.ResourceSchemaType, + Schema: resourceSchema, + }, + } +} + +func PackageSchema() core.PackageSchema { + return &packageSchema{} +} diff --git a/cyral/provider/provider.go b/cyral/provider/provider.go index 146cebae..24a07aed 100644 --- a/cyral/provider/provider.go +++ b/cyral/provider/provider.go @@ -13,7 +13,6 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/core" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/deprecated" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/permission" - "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy/rule" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/regopolicy" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/role" @@ -141,7 +140,6 @@ func getResourceMap(ps []core.PackageSchema) map[string]*schema.Resource { schemaMap["cyral_integration_idp_okta"] = deprecated.ResourceIntegrationIdP("okta", idpDeprecationMessage) schemaMap["cyral_integration_idp_ping_one"] = deprecated.ResourceIntegrationIdP("pingone", idpDeprecationMessage) schemaMap["cyral_integration_sumo_logic"] = deprecated.ResourceIntegrationSumoLogic() - schemaMap["cyral_policy"] = policy.ResourcePolicy() schemaMap["cyral_policy_rule"] = rule.ResourcePolicyRule() schemaMap["cyral_rego_policy_instance"] = regopolicy.ResourceRegoPolicyInstance() schemaMap["cyral_role"] = role.ResourceRole() diff --git a/cyral/provider/schema_loader.go b/cyral/provider/schema_loader.go index 6115efba..62188a32 100644 --- a/cyral/provider/schema_loader.go +++ b/cyral/provider/schema_loader.go @@ -12,6 +12,7 @@ import ( "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/logging" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/slack" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/integration/teams" + "github.com/cyralinc/terraform-provider-cyral/cyral/internal/policy" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository/accessgateway" "github.com/cyralinc/terraform-provider-cyral/cyral/internal/repository/accessrules" @@ -47,6 +48,7 @@ func packagesSchemas() []core.PackageSchema { mfaduo.PackageSchema(), network.PackageSchema(), pagerduty.PackageSchema(), + policy.PackageSchema(), repository.PackageSchema(), samlcertificate.PackageSchema(), sidecar.PackageSchema(),