Skip to content

Commit

Permalink
feat: retry mechanism for all cloud resources (#81)
Browse files Browse the repository at this point in the history
* feat: retry mechanism for all cloud resources

Signed-off-by: Salim Afiune Maya <afiune@lacework.net>
  • Loading branch information
afiune authored Mar 8, 2021
1 parent ec8299f commit 61893af
Show file tree
Hide file tree
Showing 1,429 changed files with 40,837 additions and 198,479 deletions.
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": {
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

0 comments on commit 61893af

Please sign in to comment.