diff --git a/cyral/client/client.go b/cyral/client/client.go index 30f2317f..9bd703c8 100644 --- a/cyral/client/client.go +++ b/cyral/client/client.go @@ -71,23 +71,26 @@ func New(clientID, clientSecret, controlPlane string, tlsSkipVerify bool) (*Clie // DoRequest calls the httpMethod informed and delivers the resourceData as a payload, // filling the response parameter (if not nil) with the response body. func (c *Client) DoRequest(ctx context.Context, url, httpMethod string, resourceData interface{}) ([]byte, error) { - tflog.Debug(ctx, "Init DoRequest") - tflog.Debug(ctx, fmt.Sprintf("Resource info: %#v", resourceData)) - tflog.Debug(ctx, fmt.Sprintf("%s URL: %s", httpMethod, url)) + tflog.Debug(ctx, "=> Init DoRequest") + tflog.Debug(ctx, fmt.Sprintf("==> Resource info: %#v", resourceData)) + tflog.Debug(ctx, fmt.Sprintf("==> %s URL: %s", httpMethod, url)) var req *http.Request var err error if resourceData != nil { payloadBytes, err := json.Marshal(resourceData) if err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, fmt.Errorf("failed to encode payload: %v", err) } payload := string(payloadBytes) tflog.Debug(ctx, fmt.Sprintf("%s payload: %s", httpMethod, payload)) if req, err = http.NewRequest(httpMethod, url, strings.NewReader(payload)); err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, fmt.Errorf("unable to create request; err: %v", err) } } else { if req, err = http.NewRequest(httpMethod, url, nil); err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, fmt.Errorf("unable to create request; err: %v", err) } } @@ -96,24 +99,27 @@ func (c *Client) DoRequest(ctx context.Context, url, httpMethod string, resource token := &oauth2.Token{} if c.TokenSource != nil { if token, err = c.TokenSource.Token(); err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, fmt.Errorf("unable to retrieve authorization token. error: %v", err) } else { - tflog.Debug(ctx, fmt.Sprintf("Token Type: %s", token.Type())) - tflog.Debug(ctx, fmt.Sprintf("Access Token: %s", redactContent(token.AccessToken))) - tflog.Debug(ctx, fmt.Sprintf("Token Expiry: %s", token.Expiry)) + tflog.Debug(ctx, fmt.Sprintf("==> Token Type: %s", token.Type())) + tflog.Debug(ctx, fmt.Sprintf("==> Access Token: %s", redactContent(token.AccessToken))) + tflog.Debug(ctx, fmt.Sprintf("==> Token Expiry: %s", token.Expiry)) req.Header.Add("Authorization", fmt.Sprintf("%s %s", token.Type(), token.AccessToken)) } } - tflog.Debug(ctx, fmt.Sprintf("Executing %s", httpMethod)) + tflog.Debug(ctx, fmt.Sprintf("==> Executing %s", httpMethod)) res, err := c.client.Do(req) if err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, fmt.Errorf("unable to execute request. Check the control plane address; err: %v", err) } defer res.Body.Close() if res.StatusCode == http.StatusConflict || (httpMethod == http.MethodPost && strings.Contains(strings.ToLower(res.Status), "already exists")) { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, NewHttpError( fmt.Sprintf("resource possibly exists in the control plane. Response status: %s", res.Status), res.StatusCode) @@ -121,6 +127,7 @@ func (c *Client) DoRequest(ctx context.Context, url, httpMethod string, resource body, err := ioutil.ReadAll(res.Body) if err != nil { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, NewHttpError( fmt.Sprintf("unable to read data from request body; err: %v", err), res.StatusCode) @@ -129,18 +136,19 @@ func (c *Client) DoRequest(ctx context.Context, url, httpMethod string, resource // Redact token before logging the request req.Header.Set("Authorization", fmt.Sprintf("%s %s", token.Type(), redactContent(token.AccessToken))) - tflog.Debug(ctx, fmt.Sprintf("Request: %#v", req)) - tflog.Debug(ctx, fmt.Sprintf("Response status code: %d", res.StatusCode)) - tflog.Debug(ctx, fmt.Sprintf("Response body: %s", string(body))) + tflog.Debug(ctx, fmt.Sprintf("==> Request: %#v", req)) + tflog.Debug(ctx, fmt.Sprintf("==> Response status code: %d", res.StatusCode)) + tflog.Debug(ctx, fmt.Sprintf("==> Response body: %s", string(body))) if !(res.StatusCode >= 200 && res.StatusCode < 300) { + tflog.Debug(ctx, "=> End DoRequest - Error") return nil, NewHttpError( fmt.Sprintf("error executing %s request; status code: %d; body: %q", httpMethod, res.StatusCode, body), res.StatusCode) } - tflog.Debug(ctx, "End DoRequest") + tflog.Debug(ctx, "=> End DoRequest - Success") return body, nil } diff --git a/cyral/core/resource.go b/cyral/core/resource.go index 8a0e4a59..ac4a121f 100644 --- a/cyral/core/resource.go +++ b/cyral/core/resource.go @@ -109,57 +109,63 @@ func DeleteResource(deleteConfig ResourceOperationConfig) schema.DeleteContextFu func handleRequests(operations []ResourceOperationConfig) func(context.Context, *schema.ResourceData, any) diag.Diagnostics { return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { for _, operation := range operations { - tflog.Debug(ctx, fmt.Sprintf("Init %s - %s", operation.ResourceName, operation.Type)) + tflog.Debug(ctx, fmt.Sprintf("Init handleRequests to %s %s %s", operation.Type, operation.ResourceType, operation.ResourceName)) c := m.(*client.Client) var resourceData SchemaReader if operation.SchemaReaderFactory != nil { + tflog.Debug(ctx, "=> Calling SchemaReaderFactory") if resourceData = operation.SchemaReaderFactory(); resourceData != nil { - tflog.Debug(ctx, fmt.Sprintf("Calling ReadFromSchema. Schema: %#v", d)) + tflog.Debug(ctx, fmt.Sprintf("=> Calling ReadFromSchema. Schema: %#v", d)) if err := resourceData.ReadFromSchema(d); err != nil { + tflog.Debug(ctx, fmt.Sprintf("End handleRequests to %s %s %s - Error: %s", operation.Type, operation.ResourceType, operation.ResourceName, err.Error())) return utils.CreateError( - fmt.Sprintf("Unable to %s resource %s", operation.Type, operation.ResourceName), + fmt.Sprintf("Unable to %s %s %s", operation.Type, operation.ResourceType, operation.ResourceName), err.Error(), ) } - tflog.Debug(ctx, fmt.Sprintf("Succesful call to ReadFromSchema. resourceData: %#v", resourceData)) + tflog.Debug(ctx, fmt.Sprintf("=> Succesful call to ReadFromSchema. resourceData: %#v", resourceData)) } } url := operation.URLFactory(d, c) body, err := c.DoRequest(ctx, url, operation.HttpMethod, resourceData) - if operation.RequestErrorHandler != nil { + if err != nil && operation.RequestErrorHandler != nil { + tflog.Debug(ctx, "=> Calling operation.RequestErrorHandler.HandleError") err = operation.RequestErrorHandler.HandleError(ctx, d, c, err) } if err != nil { + tflog.Debug(ctx, fmt.Sprintf("End handleRequests to %s %s %s - Error: %s", operation.Type, operation.ResourceType, operation.ResourceName, err.Error())) return utils.CreateError( - fmt.Sprintf("Unable to %s resource %s", operation.Type, operation.ResourceName), + fmt.Sprintf("Unable to %s %s %s", operation.Type, operation.ResourceType, operation.ResourceName), err.Error(), ) } if operation.SchemaWriterFactory == nil { - tflog.Debug(ctx, fmt.Sprintf("No SchemaWriterFactory found to %s resource %s", operation.Type, operation.ResourceName)) - } else { + tflog.Debug(ctx, "=> No SchemaWriterFactory found.") + } else if body != nil { if responseData := operation.SchemaWriterFactory(d); responseData != nil { - tflog.Debug(ctx, fmt.Sprintf("NewResponseData function call performed. d: %#v", d)) + tflog.Debug(ctx, fmt.Sprintf("=> operation.SchemaWriterFactory function call performed. d: %#v", d)) if err := json.Unmarshal(body, responseData); err != nil { + tflog.Debug(ctx, fmt.Sprintf("End handleRequests to %s %s %s - Error: %s", operation.Type, operation.ResourceType, operation.ResourceName, err.Error())) return utils.CreateError("Unable to unmarshall JSON", err.Error()) } - tflog.Debug(ctx, fmt.Sprintf("Response body (unmarshalled): %#v", responseData)) - tflog.Debug(ctx, fmt.Sprintf("Calling WriteToSchema: responseData: %#v", responseData)) + tflog.Debug(ctx, fmt.Sprintf("=> Response body (unmarshalled): %#v", responseData)) + tflog.Debug(ctx, fmt.Sprintf("=> Calling WriteToSchema: responseData: %#v", responseData)) if err := responseData.WriteToSchema(d); err != nil { + tflog.Debug(ctx, fmt.Sprintf("End handleRequests to %s %s %s - Error: %s", operation.Type, operation.ResourceType, operation.ResourceName, err.Error())) return utils.CreateError( - fmt.Sprintf("Unable to %s resource %s", operation.Type, operation.ResourceName), + fmt.Sprintf("Unable to %s %s %s", operation.Type, operation.ResourceType, operation.ResourceName), err.Error(), ) } - tflog.Debug(ctx, fmt.Sprintf("Succesful call to WriteToSchema. d: %#v", d)) + tflog.Debug(ctx, fmt.Sprintf("=> Succesful call to WriteToSchema. d: %#v", d)) } } - tflog.Debug(ctx, fmt.Sprintf("End %s - %s", operation.ResourceName, operation.Type)) + tflog.Debug(ctx, fmt.Sprintf("End handleRequests to %s %s %s - Success", operation.Type, operation.ResourceType, operation.ResourceName)) } return diag.Diagnostics{} } diff --git a/cyral/internal/integration/idpsaml/resource_cyral_integration_idp_saml_test.go b/cyral/internal/integration/idpsaml/resource_cyral_integration_idp_saml_test.go index 44c6f84f..b7904acb 100644 --- a/cyral/internal/integration/idpsaml/resource_cyral_integration_idp_saml_test.go +++ b/cyral/internal/integration/idpsaml/resource_cyral_integration_idp_saml_test.go @@ -46,12 +46,8 @@ func TestAccIntegrationIdPSAMLResource(t *testing.T) { "upgrade_test", samlMetadataDocumentSample("fakeCertificateUpdated")) updatedAgainConfig, updatedAgainChecks := setupIntegrationIdPSAMLTest( "upgrade_test", samlMetadataDocumentSample("fakeCertificateUpdated")) - - println("========> initialConfig: " + initialConfig) - println("========> updatedConfig: " + updatedConfig) - println("========> updatedAgainConfig: " + updatedAgainConfig) - // newConfig, newChecks := setupIntegrationIdPSAMLTest( - // "new_test", samlMetadataDocumentSample("fakeCertificateNew")) + newConfig, newChecks := setupIntegrationIdPSAMLTest( + "new_test", samlMetadataDocumentSample("fakeCertificateNew")) resource.ParallelTest(t, resource.TestCase{ ProviderFactories: provider.ProviderFactories, @@ -72,18 +68,18 @@ func TestAccIntegrationIdPSAMLResource(t *testing.T) { // If user runs apply again, it should work. Check: updatedAgainChecks, }, - // { - // Config: newConfig, - // // When a new SAML draft and a new integration - // // are created, there should be no no problem. - // Check: newChecks, - // }, - // { - // ImportState: true, - // ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"idp_metadata_xml", "saml_draft_id"}, - // ResourceName: "cyral_integration_idp_saml.new_test", - // }, + { + Config: newConfig, + // When a new SAML draft and a new integration + // are created, there should be no no problem. + Check: newChecks, + }, + { + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"idp_metadata_xml", "saml_draft_id"}, + ResourceName: "cyral_integration_idp_saml.new_test", + }, }, }) } diff --git a/cyral/internal/repository/confanalysis/model.go b/cyral/internal/repository/confanalysis/model.go index 386d3eaa..e304c76a 100644 --- a/cyral/internal/repository/confanalysis/model.go +++ b/cyral/internal/repository/confanalysis/model.go @@ -7,7 +7,7 @@ import ( // TODO: v2 of this API should either return the repository ID // or something else as an ID. Currently it accepts a `UserConfig` // for the PUT payload, but returns a `RepositoryConfAnalysisData`. -// This makes the whole API confusing. +// This makes the whole API utilization quite confusing. type RepositoryConfAnalysisData struct { UserConfig UserConfig `json:"userConfig"` diff --git a/cyral/internal/sidecar/resource.go b/cyral/internal/sidecar/resource.go index e68dfb95..82bc44de 100644 --- a/cyral/internal/sidecar/resource.go +++ b/cyral/internal/sidecar/resource.go @@ -13,6 +13,7 @@ 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/operationtype" + "github.com/cyralinc/terraform-provider-cyral/cyral/core/types/resourcetype" ) // Currently, the sidecar API always returns a status code of 500 for every error, @@ -31,21 +32,26 @@ func (h *SidecarDeleteIgnoreHttpNotFound) HandleError( _ *client.Client, err error, ) error { - httpError, ok := err.(*client.HttpError) - if !ok || httpError.StatusCode != http.StatusNotFound { - return err - } + tflog.Debug(ctx, "==> Init HandleError SidecarDeleteIgnoreHttpNotFound") matched, regexpError := regexp.MatchString( "NotFound", err.Error(), ) if regexpError == nil && matched { - tflog.Debug(ctx, fmt.Sprintf("Sidecar not found. Skipping deletion. Error: %v", err)) + tflog.Debug(ctx, fmt.Sprintf("===> %s not found. Skipping deletion. Error: %v", resourceName, err)) r.SetId("") + tflog.Debug(ctx, "==> End HandleError SidecarDeleteIgnoreHttpNotFound - Success") return nil } + httpError, ok := err.(*client.HttpError) + if !ok || httpError.StatusCode != http.StatusNotFound { + tflog.Debug(ctx, "===> End HandleError SidecarDeleteIgnoreHttpNotFound - Error") + return err + } + + tflog.Debug(ctx, "==> End HandleError SidecarDeleteIgnoreHttpNotFound - Success") return nil } @@ -58,13 +64,27 @@ func (h *SidecarReadIgnoreHttpNotFound) HandleError( _ *client.Client, err error, ) error { + tflog.Debug(ctx, "==> Init HandleError SidecarReadIgnoreHttpNotFound") + + matched, regexpError := regexp.MatchString( + "NotFound", + err.Error(), + ) + if regexpError == nil && matched { + tflog.Debug(ctx, fmt.Sprintf("===> %s not found. Marking resource for recreation.", resourceName)) + r.SetId("") + tflog.Debug(ctx, "==> End HandleError SidecarReadIgnoreHttpNotFound - Success") + return nil + } + httpError, ok := err.(*client.HttpError) if !ok || httpError.StatusCode != http.StatusNotFound { + tflog.Debug(ctx, "===> End HandleError SidecarReadIgnoreHttpNotFound - Error") return err } - r.SetId("") - tflog.Debug(ctx, resourceName+" not found. Marking resource for recreation.") + tflog.Debug(ctx, "==> End HandleError SidecarReadIgnoreHttpNotFound - - Success") + return nil } @@ -74,6 +94,7 @@ var urlFactory = func(d *schema.ResourceData, c *client.Client) string { var readSidecarConfig = core.ResourceOperationConfig{ ResourceName: resourceName, + ResourceType: resourcetype.Resource, Type: operationtype.Read, HttpMethod: http.MethodGet, URLFactory: urlFactory, @@ -87,6 +108,7 @@ func resourceSchema() *schema.Resource { CreateContext: core.CreateResource( core.ResourceOperationConfig{ ResourceName: resourceName, + ResourceType: resourcetype.Resource, Type: operationtype.Create, HttpMethod: http.MethodPost, URLFactory: func(d *schema.ResourceData, c *client.Client) string { @@ -101,6 +123,7 @@ func resourceSchema() *schema.Resource { UpdateContext: core.UpdateResource( core.ResourceOperationConfig{ ResourceName: resourceName, + ResourceType: resourcetype.Resource, Type: operationtype.Update, HttpMethod: http.MethodPut, URLFactory: urlFactory, @@ -112,6 +135,7 @@ func resourceSchema() *schema.Resource { DeleteContext: core.DeleteResource( core.ResourceOperationConfig{ ResourceName: resourceName, + ResourceType: resourcetype.Resource, Type: operationtype.Delete, HttpMethod: http.MethodDelete, URLFactory: urlFactory,