-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement PolicyV2 resource using gRPC. (#584)
* bump dependencies * Implement generic context handler * implement policy v2 resource using gRPC * minor changes * use generated protobuf code from label main on buf * address review comments * rename GenericContextHandler to ContextHandler * rename DefaultContextHandler as HTTPContextHandler
- Loading branch information
1 parent
39635f2
commit b8d78a0
Showing
37 changed files
with
494 additions
and
230 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package core | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
|
||
"github.com/cyralinc/terraform-provider-cyral/cyral/client" | ||
"github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" | ||
"github.com/cyralinc/terraform-provider-cyral/cyral/utils" | ||
) | ||
|
||
type ResourceMethod func(context.Context, *client.Client, *schema.ResourceData) error | ||
|
||
// ContextHandler can be used by resource implementations to ensure that | ||
// the recommended best practices are consistently followed (e.g., handling of | ||
// 404 errors, following a create/update with a get etc). The resource implementation | ||
// needs to supply functions that implement the basic CRUD operations on the resource | ||
// using gRPC or whatever else. Note that if REST APIs are used, it is recommended | ||
// to use the HTTPContextHandler instead. | ||
type ContextHandler struct { | ||
ResourceName string | ||
ResourceType resourcetype.ResourceType | ||
Create ResourceMethod | ||
Read ResourceMethod | ||
Update ResourceMethod | ||
Delete ResourceMethod | ||
} | ||
|
||
type method struct { | ||
method ResourceMethod | ||
name string | ||
errorHandler func(context.Context, *schema.ResourceData, error) error | ||
} | ||
|
||
func (gch *ContextHandler) handleResourceNotFoundError( | ||
ctx context.Context, rd *schema.ResourceData, err error, | ||
) error { | ||
var isNotFoundError bool | ||
if status.Code(err) == codes.NotFound { | ||
isNotFoundError = true | ||
} else if httpError, ok := err.(*client.HttpError); ok && | ||
httpError.StatusCode == http.StatusNotFound { | ||
isNotFoundError = true | ||
} | ||
if isNotFoundError { | ||
tflog.Debug( | ||
ctx, | ||
fmt.Sprintf( | ||
"==> Resource %s not found, marking for recreation or deletion.", | ||
gch.ResourceName, | ||
), | ||
) | ||
rd.SetId("") | ||
return nil | ||
} | ||
return err | ||
} | ||
|
||
// CreateContext is used to create a resource instance. | ||
func (gch *ContextHandler) CreateContext( | ||
ctx context.Context, | ||
rd *schema.ResourceData, | ||
pd any, | ||
) diag.Diagnostics { | ||
c := pd.(*client.Client) | ||
return gch.executeMethods( | ||
ctx, c, rd, []method{ | ||
{ | ||
method: gch.Create, | ||
name: "create", | ||
}, | ||
{ | ||
method: gch.Read, | ||
name: "read", | ||
errorHandler: gch.handleResourceNotFoundError, | ||
}, | ||
}, | ||
) | ||
} | ||
|
||
// UpdateContext is used to update a resource instance. | ||
func (gch *ContextHandler) UpdateContext( | ||
ctx context.Context, | ||
rd *schema.ResourceData, | ||
pd any, | ||
) diag.Diagnostics { | ||
c := pd.(*client.Client) | ||
return gch.executeMethods( | ||
ctx, c, rd, []method{ | ||
{ | ||
method: gch.Update, | ||
name: "update", | ||
}, | ||
{ | ||
method: gch.Read, | ||
name: "read", | ||
errorHandler: gch.handleResourceNotFoundError, | ||
}, | ||
}, | ||
) | ||
} | ||
|
||
// ReadContext is used to read a resource instance. | ||
func (gch *ContextHandler) ReadContext( | ||
ctx context.Context, | ||
rd *schema.ResourceData, | ||
pd any, | ||
) diag.Diagnostics { | ||
c := pd.(*client.Client) | ||
return gch.executeMethods( | ||
ctx, c, rd, []method{ | ||
{ | ||
method: gch.Read, | ||
name: "read", | ||
errorHandler: gch.handleResourceNotFoundError, | ||
}, | ||
}, | ||
) | ||
} | ||
|
||
// DeleteContext is used to delete a resource instance. | ||
func (gch *ContextHandler) DeleteContext( | ||
ctx context.Context, | ||
rd *schema.ResourceData, | ||
pd any, | ||
) diag.Diagnostics { | ||
c := pd.(*client.Client) | ||
return gch.executeMethods( | ||
ctx, c, rd, []method{ | ||
{ | ||
method: gch.Delete, | ||
name: "delete", | ||
errorHandler: gch.handleResourceNotFoundError, | ||
}, | ||
}, | ||
) | ||
} | ||
|
||
func (gch *ContextHandler) executeMethods( | ||
ctx context.Context, c *client.Client, rd *schema.ResourceData, methods []method, | ||
) diag.Diagnostics { | ||
for _, m := range methods { | ||
tflog.Debug(ctx, fmt.Sprintf("resource %s: operation %s", gch.ResourceName, m.name)) | ||
err := m.method(ctx, c, rd) | ||
if err != nil { | ||
tflog.Debug( | ||
ctx, | ||
fmt.Sprintf("resource %s: operation %s - error: %v", gch.ResourceName, m.name, err), | ||
) | ||
if m.errorHandler != nil { | ||
err = m.errorHandler(ctx, rd, err) | ||
} | ||
} | ||
if err != nil { | ||
return utils.CreateError( | ||
fmt.Sprintf("error in operation %s on resource %s", m.name, gch.ResourceName), | ||
err.Error(), | ||
) | ||
} | ||
tflog.Debug( | ||
ctx, | ||
fmt.Sprintf("resource %s: operation %s - success", gch.ResourceName, m.name), | ||
) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.