Skip to content

Commit

Permalink
Refactor cyral_repository_binding
Browse files Browse the repository at this point in the history
  • Loading branch information
wcmjunior committed Apr 1, 2024
1 parent f11c32a commit ab89d44
Show file tree
Hide file tree
Showing 31 changed files with 351 additions and 343 deletions.
79 changes: 50 additions & 29 deletions cyral/core/default_context_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Implementation of a default context handler that can be used by all resources
// which API follows these principles:
// 1. The resource is backed by an ID coming from the API.
// 2. The creation is a POST that returns a JSON with an `id` field, meaning
// it can be used with the `IDBasedResponse` struct.
// 3. The endpoint to perform GET, PUT and DELETE calls are composed by the
// POST endpoint plus the ID specification like the following:
// Implementation of a default context handler that can be used by all resources.
//
// 1. `SchemaWriterFactoryGetMethod“ must be provided.
// 2. In case `SchemaWriterFactoryPostMethod“ is not provided,
// it will assume that a call to POST returns a JSON with
// an `id` field, meaning it will use the
// `IDBasedResponse` struct in such cases.
// 3. `BaseURLFactory` must be provided. It will be used to
// create the POST endpoint and others in case `IdBasedURLFactory`
// is not provided.
// 4. If `IdBasedURLFactory` is NOT provided, the endpoint to
// perform GET, PUT and DELETE calls are composed by the
// `BaseURLFactory` endpoint plus the ID specification as follows:
// - POST: https://<CP>/<apiVersion>/<featureName>
// - GET: https://<CP>/<apiVersion>/<featureName>/<id>
// - PUT: https://<CP>/<apiVersion>/<featureName>/<id>
Expand All @@ -27,45 +33,55 @@ type DefaultContextHandler struct {
ResourceName string
ResourceType rt.ResourceType
SchemaReaderFactory SchemaReaderFactoryFunc
SchemaWriterFactory SchemaWriterFactoryFunc
BaseURLFactory URLFactoryFunc
// SchemaWriterFactoryGetMethod defines how the schema will be
// written in GET operations.
SchemaWriterFactoryGetMethod SchemaWriterFactoryFunc
// SchemaWriterFactoryPostMethod defines how the schema will be
// written in POST operations.
SchemaWriterFactoryPostMethod SchemaWriterFactoryFunc
// BaseURLFactory provides the base URL used for POSTs and that
// will also be used to compose the ID URL in case the later
// is not provided.
BaseURLFactory URLFactoryFunc
IdBasedURLFactory URLFactoryFunc
}

func defaultSchemaWriterFactory(d *schema.ResourceData) SchemaWriter {
func DefaultSchemaWriterFactory(d *schema.ResourceData) SchemaWriter {
return &IDBasedResponse{}
}

func defaultOperationHandler(
resourceName string,
resourceType rt.ResourceType,
func (dch DefaultContextHandler) defaultOperationHandler(
operationType ot.OperationType,
baseURLFactory URLFactoryFunc,
httpMethod string,
schemaReaderFactory SchemaReaderFactoryFunc,
schemaWriterFactory SchemaWriterFactoryFunc,
) ResourceOperationConfig {
// POST = https://<CP>/<apiVersion>/<feature>
// GET, PUT and DELETE = https://<CP>/<apiVersion>/<feature>/<id>
endpoint := func(d *schema.ResourceData, c *client.Client) string {
url := baseURLFactory(d, c)
if d.Id() != "" {
url = fmt.Sprintf("%s/%s", baseURLFactory(d, c), d.Id())
var url string
if httpMethod == http.MethodPost {
url = dch.BaseURLFactory(d, c)
} else if dch.IdBasedURLFactory != nil {
url = dch.IdBasedURLFactory(d, c)
} else {
url = fmt.Sprintf("%s/%s", dch.BaseURLFactory(d, c), d.Id())
}
tflog.Debug(context.Background(), fmt.Sprintf("Returning base URL for %s '%s' operation '%s' and httpMethod %s: %s",
resourceType, resourceName, operationType, httpMethod, url))
dch.ResourceType, dch.ResourceName, operationType, httpMethod, url))
return url
}

var errorHandler RequestErrorHandler
if httpMethod == http.MethodGet {
errorHandler = &ReadIgnoreHttpNotFound{ResName: resourceName}
errorHandler = &ReadIgnoreHttpNotFound{ResName: dch.ResourceName}
} else if httpMethod == http.MethodDelete {
errorHandler = &DeleteIgnoreHttpNotFound{ResName: resourceName}
errorHandler = &DeleteIgnoreHttpNotFound{ResName: dch.ResourceName}
}
result := ResourceOperationConfig{
ResourceName: resourceName,
ResourceName: dch.ResourceName,
Type: operationType,
ResourceType: resourceType,
ResourceType: dch.ResourceType,
HttpMethod: httpMethod,
URLFactory: endpoint,
SchemaReaderFactory: schemaReaderFactory,
Expand All @@ -77,26 +93,31 @@ func defaultOperationHandler(
}

func (dch DefaultContextHandler) CreateContext() schema.CreateContextFunc {
// By default, assumes that if no SchemaWriterFactoryPostMethod is provided,
// the POST api will return an ID
schemaWriterPost := DefaultSchemaWriterFactory
if dch.SchemaWriterFactoryPostMethod != nil {
schemaWriterPost = dch.SchemaWriterFactoryPostMethod
}
return CreateResource(
defaultOperationHandler(dch.ResourceName, dch.ResourceType, ot.Create, dch.BaseURLFactory, http.MethodPost, dch.SchemaReaderFactory, nil),
defaultOperationHandler(dch.ResourceName, dch.ResourceType, ot.Create, dch.BaseURLFactory, http.MethodGet, nil, dch.SchemaWriterFactory),
dch.defaultOperationHandler(ot.Create, http.MethodPost, dch.SchemaReaderFactory, schemaWriterPost),
dch.defaultOperationHandler(ot.Create, http.MethodGet, nil, dch.SchemaWriterFactoryGetMethod),
)
}

func (dch DefaultContextHandler) ReadContext() schema.ReadContextFunc {
return ReadResource(dch.ReadResourceOperationConfig())
}
func (dch DefaultContextHandler) ReadResourceOperationConfig() ResourceOperationConfig {
return defaultOperationHandler(dch.ResourceName, dch.ResourceType, ot.Read, dch.BaseURLFactory, http.MethodGet, nil, dch.SchemaWriterFactory)
return dch.defaultOperationHandler(ot.Read, http.MethodGet, nil, dch.SchemaWriterFactoryGetMethod)
}

func (dch DefaultContextHandler) UpdateContext() schema.UpdateContextFunc {
return UpdateResource(
defaultOperationHandler(dch.ResourceName, dch.ResourceType, ot.Update, dch.BaseURLFactory, http.MethodPut, dch.SchemaReaderFactory, nil),
defaultOperationHandler(dch.ResourceName, dch.ResourceType, ot.Update, dch.BaseURLFactory, http.MethodGet, nil, dch.SchemaWriterFactory))
dch.defaultOperationHandler(ot.Update, http.MethodPut, dch.SchemaReaderFactory, nil),
dch.defaultOperationHandler(ot.Update, http.MethodGet, nil, dch.SchemaWriterFactoryGetMethod))
}

func (dch DefaultContextHandler) DeleteContext() schema.DeleteContextFunc {
return DeleteResource(defaultOperationHandler(
dch.ResourceName, dch.ResourceType, ot.Delete, dch.BaseURLFactory, http.MethodDelete, nil, nil))
return DeleteResource(dch.defaultOperationHandler(ot.Delete, http.MethodDelete, nil, nil))
}
18 changes: 4 additions & 14 deletions cyral/core/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,10 @@ func handleRequests(operations []ResourceOperationConfig) func(context.Context,
)
}

// If a `SchemaWriterFactory` implementation is NOT provided and this is a creation operation,
// use the `defaultSchemaWriterFactory`, assuming the response is a JSON with an `id` field.
/// TODO: Remove this feature after refactoring all resources to use the `DefaultContext`.
var responseDataFunc SchemaWriterFactoryFunc
if body != nil {
if operation.SchemaWriterFactory == nil && operation.Type == operationtype.Create {
responseDataFunc = defaultSchemaWriterFactory
tflog.Debug(ctx, "NewResponseData function set to defaultSchemaWriterFactory.")
} else {
responseDataFunc = operation.SchemaWriterFactory
}
}
if responseDataFunc != nil {
if responseData := responseDataFunc(d); responseData != nil {
if operation.SchemaWriterFactory == nil {
tflog.Debug(ctx, fmt.Sprintf("No SchemaWriterFactory found to %s resource %s", operation.Type, operation.ResourceName))
} else {
if responseData := operation.SchemaWriterFactory(d); responseData != nil {
tflog.Debug(ctx, fmt.Sprintf("NewResponseData function call performed. d: %#v", d))
if err := json.Unmarshal(body, responseData); err != nil {
return utils.CreateError("Unable to unmarshall JSON", err.Error())
Expand Down
10 changes: 5 additions & 5 deletions cyral/internal/datalabel/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import (

func resourceSchema() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &DataLabel{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &DataLabel{} },
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &DataLabel{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &DataLabel{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/datalabels",
c.ControlPlane)
Expand Down Expand Up @@ -114,7 +114,7 @@ func resourceSchema() *schema.Resource {
}

var readDataLabelConfig = core.ResourceOperationConfig{
ResourceName: "DataLabelResourceRead",
ResourceName: resourceName,
Type: operationtype.Read,
HttpMethod: http.MethodGet,
URLFactory: func(d *schema.ResourceData, c *client.Client) string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ func (data *DatadogIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationDatadog() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "Datadog Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &DatadogIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &DatadogIntegration{} },
ResourceName: "Datadog Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &DatadogIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &DatadogIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/datadog", c.ControlPlane)
},
Expand Down
8 changes: 4 additions & 4 deletions cyral/internal/deprecated/resource_cyral_integration_elk.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ func (data *ELKIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationELK() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "ELK Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &ELKIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &ELKIntegration{} },
ResourceName: "ELK Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &ELKIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &ELKIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/elk", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ func (data *LogstashIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationLogstash() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "Logstash Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &LogstashIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &LogstashIntegration{} },
ResourceName: "Logstash Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &LogstashIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &LogstashIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/logstash", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ func (data *LookerIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationLooker() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "Looker Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &LookerIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &LookerIntegration{} },
ResourceName: "Looker Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &LookerIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &LookerIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/looker", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ func (data *SplunkIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationSplunk() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "Splunk Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SplunkIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &SplunkIntegration{} },
ResourceName: "Splunk Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SplunkIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &SplunkIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/splunk", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ func (data *SumoLogicIntegration) ReadFromSchema(d *schema.ResourceData) error {

func ResourceIntegrationSumoLogic() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "SumoLogic Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SumoLogicIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &SumoLogicIntegration{} },
ResourceName: "SumoLogic Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SumoLogicIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &SumoLogicIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/sumologic", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ func (wrapper *AWSIAMIntegrationWrapper) ReadFromSchema(d *schema.ResourceData)

func ResourceIntegrationAWSIAM() *schema.Resource {
contextHandler := core.DefaultContextHandler{
ResourceName: "AWS IAM Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &AWSIAMIntegrationWrapper{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &AWSIAMIntegrationWrapper{} },
ResourceName: "AWS IAM Integration",
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &AWSIAMIntegrationWrapper{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &AWSIAMIntegrationWrapper{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/aws/iam", c.ControlPlane)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func ConfExtensionIntegrationCreate(templateType string) core.ResourceOperationC
SchemaReaderFactory: func() core.SchemaReader {
return NewIntegrationConfExtension(templateType)
},
SchemaWriterFactory: core.DefaultSchemaWriterFactory,
}
}

Expand Down
8 changes: 4 additions & 4 deletions cyral/internal/integration/hcvault/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
)

var resourceContextHandler = core.DefaultContextHandler{
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &HCVaultIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &HCVaultIntegration{} },
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &HCVaultIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &HCVaultIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/secretProviders/hcvault", c.ControlPlane)
},
Expand Down
2 changes: 1 addition & 1 deletion cyral/internal/integration/hcvault/schema_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type packageSchema struct {
}

func (p *packageSchema) Name() string {
return "HC Vault Integration"
return "hcvault"
}

func (p *packageSchema) Schemas() []*core.SchemaDescriptor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func CreateLoggingIntegration() core.ResourceOperationConfig {
return fmt.Sprintf("https://%s/v1/integrations/logging", c.ControlPlane)
},
SchemaReaderFactory: func() core.SchemaReader { return &LoggingIntegration{} },
SchemaWriterFactory: core.DefaultSchemaWriterFactory,
}
}

Expand Down
8 changes: 4 additions & 4 deletions cyral/internal/integration/slack/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
)

var resourceContextHandler = core.DefaultContextHandler{
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SlackAlertsIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &SlackAlertsIntegration{} },
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &SlackAlertsIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &SlackAlertsIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/notifications/slack", c.ControlPlane)
},
Expand Down
2 changes: 1 addition & 1 deletion cyral/internal/integration/slack/schema_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type packageSchema struct {
}

func (p *packageSchema) Name() string {
return "Slack Integration"
return "slack"
}

func (p *packageSchema) Schemas() []*core.SchemaDescriptor {
Expand Down
8 changes: 4 additions & 4 deletions cyral/internal/integration/teams/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
)

var resourceContextHandler = core.DefaultContextHandler{
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &MsTeamsIntegration{} },
SchemaWriterFactory: func(_ *schema.ResourceData) core.SchemaWriter { return &MsTeamsIntegration{} },
ResourceName: resourceName,
ResourceType: resourcetype.Resource,
SchemaReaderFactory: func() core.SchemaReader { return &MsTeamsIntegration{} },
SchemaWriterFactoryGetMethod: func(_ *schema.ResourceData) core.SchemaWriter { return &MsTeamsIntegration{} },
BaseURLFactory: func(d *schema.ResourceData, c *client.Client) string {
return fmt.Sprintf("https://%s/v1/integrations/notifications/teams", c.ControlPlane)
},
Expand Down
2 changes: 1 addition & 1 deletion cyral/internal/integration/teams/schema_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type packageSchema struct {
}

func (p *packageSchema) Name() string {
return "Microsoft Teams Integration"
return "teams"
}

func (p *packageSchema) Schemas() []*core.SchemaDescriptor {
Expand Down
2 changes: 1 addition & 1 deletion cyral/internal/repository/accessgateway/schema_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type packageSchema struct {
}

func (p *packageSchema) Name() string {
return "repository_access_gateway"
return "accessgateway"
}

func (p *packageSchema) Schemas() []*core.SchemaDescriptor {
Expand Down
9 changes: 9 additions & 0 deletions cyral/internal/repository/binding/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package binding

const (
resourceName = "cyral_repository_binding"

BindingEnabledKey = "enabled"
ListenerBindingKey = "listener_binding"
NodeIndexKey = "node_index"
)
Loading

0 comments on commit ab89d44

Please sign in to comment.