Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: retry mechanism for all cloud resources #81

Merged
merged 8 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions examples/resource_lacework_integration_aws_cfg/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ resource "lacework_integration_aws_cfg" "example" {
role_arn = "arn:aws:iam::1234567890:role/lacework_iam_example_role"
external_id = "12345"
}

retries = 10
}
1 change: 1 addition & 0 deletions examples/resource_lacework_integration_aws_ct/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ resource "lacework_integration_aws_ct" "example" {
role_arn = "arn:aws:iam::1234567890:role/lacework_iam_example_role"
external_id = "12345"
}
retries = 10
}

resource "lacework_integration_aws_ct" "consolidated" {
Expand Down
1 change: 1 addition & 0 deletions examples/resource_lacework_integration_azure_al/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ resource "lacework_integration_azure_al" "example" {
client_id = "1234567890-abcd-client-id"
client_secret = "SUPER_SECURE_SECRET"
}
retries = 10
}
1 change: 1 addition & 0 deletions examples/resource_lacework_integration_azure_cfg/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ resource "lacework_integration_azure_cfg" "example" {
client_id = "1234567890-abcd-client-id"
client_secret = "SUPER_SECURE_SECRET"
}
retries = 10
}
1 change: 1 addition & 0 deletions examples/resource_lacework_integration_gcp_at/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ resource "lacework_integration_gcp_at" "example" {
resource_level = "PROJECT"
resource_id = "example-project_id"
subscription = "projects/example-project_id/subscriptions/example-subscription"
retries = 10
}
1 change: 1 addition & 0 deletions examples/resource_lacework_integration_gcp_cfg/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ resource "lacework_integration_gcp_cfg" "example" {
}
resource_level = "PROJECT"
resource_id = "example-project_id"
retries = 10
}
6 changes: 0 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ go 1.15
require (
github.com/BurntSushi/toml v0.3.1
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/aws/aws-sdk-go v1.33.3 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/hashicorp/hcl/v2 v2.6.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.3
github.com/hashicorp/terraform-svchost v0.0.0-20191119180714-d2e4933b9136 // indirect
github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce // indirect
github.com/lacework/go-sdk v0.2.21-0.20210224193400-129bc2861f7b
github.com/mattn/go-colorable v0.1.7 // indirect
Expand All @@ -20,12 +18,8 @@ require (
github.com/mitchellh/mapstructure v1.3.2 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pkg/errors v0.9.1
github.com/posener/complete v1.2.3 // indirect
github.com/spf13/afero v1.3.1 // indirect
github.com/stretchr/testify v1.7.0
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/zclconf/go-cty v1.5.1 // indirect
github.com/zclconf/go-cty-yaml v1.0.2 // indirect
go.uber.org/zap v1.15.0 // indirect
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
)
67 changes: 1 addition & 66 deletions go.sum

Large diffs are not rendered by default.

95 changes: 63 additions & 32 deletions lacework/resource_lacework_integration_aws_cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/lacework/go-sdk/api"
Expand Down Expand Up @@ -34,6 +35,12 @@ func resourceLaceworkIntegrationAwsCfg() *schema.Resource {
Optional: true,
Default: true,
},
"retries": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scottford-lw @dmurray-lacework Should this be max_retries instead? 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, i think that better describes this parameters function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max_retries seems to be more the common nomenclature. At least from a quick search.
https://registry.terraform.io/providers/hashicorp/aws/latest/docs#max_retries

Not a sticking point for me and happy for this to go with either. But I do prefer max_retries

Type: schema.TypeInt,
Optional: true,
Default: 5,
Description: "The number of attempts to create the external integration.",
},
"credentials": {
Type: schema.TypeList,
MaxItems: 1,
Expand Down Expand Up @@ -74,6 +81,7 @@ func resourceLaceworkIntegrationAwsCfg() *schema.Resource {
func resourceLaceworkIntegrationAwsCfgCreate(d *schema.ResourceData, meta interface{}) error {
var (
lacework = meta.(*api.Client)
retries = d.Get("retries").(int)
aws = api.NewAwsIntegration(d.Get("name").(string),
api.AwsCfgIntegration,
api.AwsIntegrationData{
Expand All @@ -84,43 +92,61 @@ func resourceLaceworkIntegrationAwsCfgCreate(d *schema.ResourceData, meta interf
},
)
)

if !d.Get("enabled").(bool) {
aws.Enabled = 0
}

// @afiune should we do this if there is sensitive information?
log.Printf("[INFO] Creating %s integration with data:\n%+v\n", api.AwsCfgIntegration.String(), aws)
response, err := lacework.Integrations.CreateAws(aws)
if err != nil {
return err
}

log.Println("[INFO] Verifying server response data")
err = validateAwsIntegrationResponse(&response)
if err != nil {
return err
}

// @afiune at this point of time, we know the data field has a single value
integration := response.Data[0]
d.SetId(integration.IntgGuid)
d.Set("name", integration.Name)
d.Set("intg_guid", integration.IntgGuid)
d.Set("enabled", integration.Enabled == 1)
return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
retries--
log.Printf("[INFO] Creating %s integration\n", api.AwsCfgIntegration.String())
response, err := lacework.Integrations.CreateAws(aws)
if err != nil {
if retries <= 0 {
return resource.NonRetryableError(
fmt.Errorf("Error creating %s integration: %s",
api.AwsCfgIntegration.String(), err,
))
}
log.Printf(
"[INFO] Unable to create %s integration. (retrying %d more time(s))\n%s\n",
api.AwsCfgIntegration.String(), retries, err,
)
return resource.RetryableError(fmt.Errorf(
"Unable to create %s integration (retrying %d more time(s))",
api.AwsCfgIntegration.String(), retries,
))
}

d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime)
d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy)
d.Set("type_name", integration.TypeName)
d.Set("org_level", integration.IsOrg == 1)
log.Printf("[INFO] Verifying server response")
err = validateAwsIntegrationResponse(&response)
if err != nil {
return resource.NonRetryableError(err)
}

log.Printf("[INFO] Created %s integration with guid: %v\n", api.AwsCfgIntegration.String(), integration.IntgGuid)
return nil
// @afiune at this point in time, we know the data field has a single value
integration := response.Data[0]
d.SetId(integration.IntgGuid)
d.Set("name", integration.Name)
d.Set("intg_guid", integration.IntgGuid)
d.Set("enabled", integration.Enabled == 1)

d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime)
d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy)
d.Set("type_name", integration.TypeName)
d.Set("org_level", integration.IsOrg == 1)

log.Printf("[INFO] Created %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), integration.IntgGuid)
return nil
})
}

func resourceLaceworkIntegrationAwsCfgRead(d *schema.ResourceData, meta interface{}) error {
lacework := meta.(*api.Client)

log.Printf("[INFO] Reading %s integration with guid: %v\n", api.AwsCfgIntegration.String(), d.Id())
log.Printf("[INFO] Reading %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), d.Id())
response, err := lacework.Integrations.GetAws(d.Id())
if err != nil {
return err
Expand All @@ -141,7 +167,8 @@ func resourceLaceworkIntegrationAwsCfgRead(d *schema.ResourceData, meta interfac
creds["external_id"] = integration.Data.Credentials.ExternalID
d.Set("credentials", []map[string]string{creds})

log.Printf("[INFO] Read %s integration with guid: %v\n", api.AwsCfgIntegration.String(), integration.IntgGuid)
log.Printf("[INFO] Read %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), integration.IntgGuid)
return nil
}
}
Expand Down Expand Up @@ -170,7 +197,8 @@ func resourceLaceworkIntegrationAwsCfgUpdate(d *schema.ResourceData, meta interf

aws.IntgGuid = d.Id()

log.Printf("[INFO] Updating %s integration with data:\n%+v\n", api.AwsCfgIntegration.String(), aws)
log.Printf("[INFO] Updating %s integration with data:\n%+v\n",
api.AwsCfgIntegration.String(), aws)
response, err := lacework.Integrations.UpdateAws(aws)
if err != nil {
return err
Expand All @@ -182,7 +210,7 @@ func resourceLaceworkIntegrationAwsCfgUpdate(d *schema.ResourceData, meta interf
return err
}

// @afiune at this point of time, we know the data field has a single value
// @afiune at this point in time, we know the data field has a single value
integration := response.Data[0]
d.Set("name", integration.Name)
d.Set("intg_guid", integration.IntgGuid)
Expand All @@ -192,20 +220,23 @@ func resourceLaceworkIntegrationAwsCfgUpdate(d *schema.ResourceData, meta interf
d.Set("type_name", integration.TypeName)
d.Set("org_level", integration.IsOrg == 1)

log.Printf("[INFO] Updated %s integration with guid: %v\n", api.AwsCfgIntegration.String(), d.Id())
log.Printf("[INFO] Updated %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), d.Id())
return nil
}

func resourceLaceworkIntegrationAwsCfgDelete(d *schema.ResourceData, meta interface{}) error {
lacework := meta.(*api.Client)

log.Printf("[INFO] Deleting %s integration with guid: %v\n", api.AwsCfgIntegration.String(), d.Id())
log.Printf("[INFO] Deleting %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), d.Id())
_, err := lacework.Integrations.DeleteAws(d.Id())
if err != nil {
return err
}

log.Printf("[INFO] Deleted %s integration with guid: %v\n", api.AwsCfgIntegration.String(), d.Id())
log.Printf("[INFO] Deleted %s integration with guid: %v\n",
api.AwsCfgIntegration.String(), d.Id())
return nil
}

Expand Down
75 changes: 49 additions & 26 deletions lacework/resource_lacework_integration_aws_ct.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/lacework/go-sdk/api"
Expand All @@ -26,6 +27,12 @@ var awsCloudTrailIntegrationSchema = map[string]*schema.Schema{
Default: true,
Description: "The state of the external integration.",
},
"retries": {
Type: schema.TypeInt,
Optional: true,
Default: 5,
Description: "The number of attempts to create the external integration.",
},
"queue_url": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -117,6 +124,7 @@ func resourceLaceworkIntegrationAwsCloudTrail() *schema.Resource {
func resourceLaceworkIntegrationAwsCloudTrailCreate(d *schema.ResourceData, meta interface{}) error {
var (
lacework = meta.(*api.Client)
retries = d.Get("retries").(int)
aws = api.NewAwsIntegration(d.Get("name").(string),
api.AwsCloudTrailIntegration,
api.AwsIntegrationData{
Expand Down Expand Up @@ -146,34 +154,49 @@ func resourceLaceworkIntegrationAwsCloudTrailCreate(d *schema.ResourceData, meta
aws.IsOrg = 1
}

// @afiune should we do this if there is sensitive information?
log.Printf("[INFO] Creating %s integration with data:\n%+v\n", api.AwsCloudTrailIntegration.String(), aws)
response, err := lacework.Integrations.CreateAws(aws)
if err != nil {
return err
}

log.Println("[INFO] Verifying server response data")
err = validateAwsIntegrationResponse(&response)
if err != nil {
return err
}

// @afiune at this point of time, we know the data field has a single value
integration := response.Data[0]
d.SetId(integration.IntgGuid)
d.Set("name", integration.Name)
d.Set("intg_guid", integration.IntgGuid)
d.Set("enabled", integration.Enabled == 1)
return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
retries--
log.Printf("[INFO] Creating %s integration\n", api.AwsCloudTrailIntegration.String())
response, err := lacework.Integrations.CreateAws(aws)
if err != nil {
if retries <= 0 {
return resource.NonRetryableError(
fmt.Errorf("Error creating %s integration: %s",
api.AwsCloudTrailIntegration.String(), err,
))
}
log.Printf(
"[INFO] Unable to create %s integration. (retrying %d more time(s))\n%s\n",
api.AwsCloudTrailIntegration.String(), retries, err,
)
return resource.RetryableError(fmt.Errorf(
"Unable to create %s integration (retrying %d more time(s))",
api.AwsCloudTrailIntegration.String(), retries,
))
}

d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime)
d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy)
d.Set("type_name", integration.TypeName)
d.Set("org_level", integration.IsOrg == 1)
log.Println("[INFO] Verifying server response data")
err = validateAwsIntegrationResponse(&response)
if err != nil {
return resource.NonRetryableError(err)
}

log.Printf("[INFO] Created %s integration with guid: %v\n",
api.AwsCloudTrailIntegration.String(), integration.IntgGuid)
return nil
// @afiune at this point of time, we know the data field has a single value
integration := response.Data[0]
d.SetId(integration.IntgGuid)
d.Set("name", integration.Name)
d.Set("intg_guid", integration.IntgGuid)
d.Set("enabled", integration.Enabled == 1)

d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime)
d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy)
d.Set("type_name", integration.TypeName)
d.Set("org_level", integration.IsOrg == 1)

log.Printf("[INFO] Created %s integration with guid: %v\n",
api.AwsCloudTrailIntegration.String(), integration.IntgGuid)
return nil
})
}

func resourceLaceworkIntegrationAwsCloudTrailRead(d *schema.ResourceData, meta interface{}) error {
Expand Down
Loading