From f4aa6a97ddda673c75c1c9f12dca67395702605c Mon Sep 17 00:00:00 2001 From: David Bloss Date: Mon, 7 Oct 2024 13:12:20 -0500 Subject: [PATCH 1/5] add region_override field to opslevel_aws_integration resource --- .../unreleased/Feature-20241007-131137.yaml | 4 +++ .../opslevel_integration_aws/resource.tf | 1 + opslevel/resource_opslevel_integration_aws.go | 19 +++++++++++++ tests/remote/integration_aws/main.tf | 1 + tests/remote/integration_aws/variables.tf | 6 ++++ tests/remote/integration_aws_all.tftest.hcl | 28 +++++++++++++++++++ tests/remote/integration_aws_min.tftest.hcl | 27 ++++++++++++++++++ 7 files changed, 86 insertions(+) create mode 100644 .changes/unreleased/Feature-20241007-131137.yaml diff --git a/.changes/unreleased/Feature-20241007-131137.yaml b/.changes/unreleased/Feature-20241007-131137.yaml new file mode 100644 index 00000000..25411fdf --- /dev/null +++ b/.changes/unreleased/Feature-20241007-131137.yaml @@ -0,0 +1,4 @@ +kind: Feature +body: can override aws regions with "region_override" field on opslevel_aws_integration + resource +time: 2024-10-07T13:11:37.315799-05:00 diff --git a/examples/resources/opslevel_integration_aws/resource.tf b/examples/resources/opslevel_integration_aws/resource.tf index 0868c273..b857ce9e 100644 --- a/examples/resources/opslevel_integration_aws/resource.tf +++ b/examples/resources/opslevel_integration_aws/resource.tf @@ -97,4 +97,5 @@ resource "opslevel_integration_aws" "dev" { external_id = random_string.external_id.result ownership_tag_overrides = true ownership_tag_keys = ["owner", "team", "group"] + region_override = ["eu-west-1", "us-east-1"] } diff --git a/opslevel/resource_opslevel_integration_aws.go b/opslevel/resource_opslevel_integration_aws.go index b2ab21b7..759f2dc1 100644 --- a/opslevel/resource_opslevel_integration_aws.go +++ b/opslevel/resource_opslevel_integration_aws.go @@ -40,6 +40,7 @@ type IntegrationAwsResourceModel struct { Name types.String `tfsdk:"name"` OwnershipTagOverrides types.Bool `tfsdk:"ownership_tag_overrides"` OwnershipTagKeys types.List `tfsdk:"ownership_tag_keys"` + RegionOverride types.List `tfsdk:"region_override"` } func NewIntegrationAwsResourceModel(awsIntegration opslevel.Integration) IntegrationAwsResourceModel { @@ -50,6 +51,7 @@ func NewIntegrationAwsResourceModel(awsIntegration opslevel.Integration) Integra Name: RequiredStringValue(awsIntegration.Name), OwnershipTagKeys: OptionalStringListValue(awsIntegration.AWSIntegrationFragment.OwnershipTagKeys), OwnershipTagOverrides: types.BoolValue(awsIntegration.OwnershipTagOverride), + RegionOverride: OptionalStringListValue(awsIntegration.AWSIntegrationFragment.RegionOverride), } } @@ -101,6 +103,11 @@ func (r *IntegrationAwsResource) Schema(ctx context.Context, req resource.Schema Description: "The name of the integration.", Required: true, }, + "region_override": schema.ListAttribute{ + ElementType: types.StringType, + Description: "Overrides the AWS region(s) that will be synchronized by this integration.", + Optional: true, + }, }, } } @@ -119,12 +126,18 @@ func (r *IntegrationAwsResource) Create(ctx context.Context, req resource.Create resp.Diagnostics.Append(diags...) return } + regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) + if diags != nil && diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } input := opslevel.AWSIntegrationInput{ Name: planModel.Name.ValueStringPointer(), IAMRole: planModel.IamRole.ValueStringPointer(), ExternalID: planModel.ExternalID.ValueStringPointer(), OwnershipTagOverride: planModel.OwnershipTagOverrides.ValueBoolPointer(), OwnershipTagKeys: ownershipTagKeys, + RegionOverride: ®ionOverride, } awsIntegration, err := r.client.CreateIntegrationAWS(input) @@ -175,12 +188,18 @@ func (r *IntegrationAwsResource) Update(ctx context.Context, req resource.Update resp.Diagnostics.Append(diags...) return } + regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) + if diags != nil && diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } input := opslevel.AWSIntegrationInput{ Name: opslevel.RefOf(planModel.Name.ValueString()), IAMRole: opslevel.RefOf(planModel.IamRole.ValueString()), ExternalID: opslevel.RefOf(planModel.ExternalID.ValueString()), OwnershipTagOverride: opslevel.RefOf(planModel.OwnershipTagOverrides.ValueBool()), OwnershipTagKeys: ownershipTagKeys, + RegionOverride: ®ionOverride, } awsIntegration, err := r.client.UpdateIntegrationAWS(planModel.Id.ValueString(), input) diff --git a/tests/remote/integration_aws/main.tf b/tests/remote/integration_aws/main.tf index 3ce40f67..7ee85bef 100644 --- a/tests/remote/integration_aws/main.tf +++ b/tests/remote/integration_aws/main.tf @@ -4,4 +4,5 @@ resource "opslevel_integration_aws" "this" { external_id = var.external_id ownership_tag_overrides = var.ownership_tag_overrides ownership_tag_keys = var.ownership_tag_keys + region_override = var.region_override } diff --git a/tests/remote/integration_aws/variables.tf b/tests/remote/integration_aws/variables.tf index c1056f29..3b06d05e 100644 --- a/tests/remote/integration_aws/variables.tf +++ b/tests/remote/integration_aws/variables.tf @@ -24,3 +24,9 @@ variable "name" { type = string description = "The name of the integration." } + +variable "region_override" { + type = list(string) + description = "Overrides the AWS region(s) that will be synchronized by this integration." + default = null +} diff --git a/tests/remote/integration_aws_all.tftest.hcl b/tests/remote/integration_aws_all.tftest.hcl index e653e0a8..61579c86 100644 --- a/tests/remote/integration_aws_all.tftest.hcl +++ b/tests/remote/integration_aws_all.tftest.hcl @@ -9,6 +9,7 @@ variables { # optional fields ownership_tag_overrides = false ownership_tag_keys = ["one", "two", "three", "four", "five"] + region_override = ["eu-west-1", "us-east-1"] # default values - computed from API default_ownership_tag_keys = tolist(["owner"]) @@ -29,6 +30,7 @@ run "resource_integration_aws_create_with_all_fields" { can(opslevel_integration_aws.this.ownership_tag_keys), can(opslevel_integration_aws.this.ownership_tag_overrides), can(opslevel_integration_aws.this.name), + can(opslevel_integration_aws.this.region_override), ]) error_message = replace(var.error_unexpected_resource_fields, "TYPE", var.resource_name) } @@ -83,6 +85,15 @@ run "resource_integration_aws_create_with_all_fields" { ) } + assert { + condition = opslevel_integration_aws.this.region_override == var.region_override + error_message = format( + "expected '%v' but got '%v'", + var.region_override, + opslevel_integration_aws.this.region_override, + ) + } + } run "resource_integration_aws_unset_ownership_tag_keys" { @@ -126,3 +137,20 @@ run "resource_integration_aws_unset_ownership_tag_overrides" { } } + +run "resource_integration_aws_unset_region_override" { + + variables { + region_override = null + } + + module { + source = "./integration_aws" + } + + assert { + condition = opslevel_integration_aws.this.region_override == null + error_message = var.error_expected_null_field + } + +} diff --git a/tests/remote/integration_aws_min.tftest.hcl b/tests/remote/integration_aws_min.tftest.hcl index 0e716f04..5afa096f 100644 --- a/tests/remote/integration_aws_min.tftest.hcl +++ b/tests/remote/integration_aws_min.tftest.hcl @@ -9,6 +9,7 @@ variables { # optional fields ownership_tag_overrides = null ownership_tag_keys = null + region_override = null # default values - computed from API default_ownership_tag_keys = tolist(["owner"]) @@ -71,6 +72,11 @@ run "resource_integration_aws_create_with_required_fields" { ) } + assert { + condition = opslevel_integration_aws.this.region_override == null + error_message = var.error_expected_null_field + } + } run "resource_integration_aws_set_ownership_tag_keys" { @@ -115,3 +121,24 @@ run "resource_integration_aws_set_ownership_tag_overrides" { } + +run "resource_integration_aws_set_region_override" { + + variables { + region_override = ["eu-west-1", "us-east-1"] + } + + module { + source = "./integration_aws" + } + + assert { + condition = opslevel_integration_aws.this.region_override == var.region_override + error_message = format( + "expected '%v' but got '%v'", + var.region_override, + opslevel_integration_aws.this.region_override, + ) + } + +} From 2711e1b0a9a68bb65dba6fa178388a64a5906278 Mon Sep 17 00:00:00 2001 From: David Bloss Date: Wed, 9 Oct 2024 11:14:47 -0500 Subject: [PATCH 2/5] Update .changes/unreleased/Feature-20241007-131137.yaml Co-authored-by: Kyle --- .changes/unreleased/Feature-20241007-131137.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.changes/unreleased/Feature-20241007-131137.yaml b/.changes/unreleased/Feature-20241007-131137.yaml index 25411fdf..88265387 100644 --- a/.changes/unreleased/Feature-20241007-131137.yaml +++ b/.changes/unreleased/Feature-20241007-131137.yaml @@ -1,4 +1,3 @@ kind: Feature -body: can override aws regions with "region_override" field on opslevel_aws_integration - resource +body: can override aws regions with "region_override" field on opslevel_aws_integration resource time: 2024-10-07T13:11:37.315799-05:00 From 2049c2022d5952e11b22a05040215de5875ff968 Mon Sep 17 00:00:00 2001 From: David Bloss Date: Wed, 9 Oct 2024 11:15:52 -0500 Subject: [PATCH 3/5] update submodule hash --- submodules/opslevel-go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/opslevel-go b/submodules/opslevel-go index a05d27a2..91ff8258 160000 --- a/submodules/opslevel-go +++ b/submodules/opslevel-go @@ -1 +1 @@ -Subproject commit a05d27a21d24d397ae28789b9b05a384bfa1f821 +Subproject commit 91ff8258b1dda1ea082ba62ea66eb22d561bda66 From e5efd013d21faca4f8c483d94ce8ce73560adcce Mon Sep 17 00:00:00 2001 From: David Bloss Date: Wed, 9 Oct 2024 15:33:08 -0500 Subject: [PATCH 4/5] only update aws regionOverride if tracked by TF state or in plan --- opslevel/resource_opslevel_integration_aws.go | 20 +++++++++++-------- submodules/opslevel-go | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/opslevel/resource_opslevel_integration_aws.go b/opslevel/resource_opslevel_integration_aws.go index 759f2dc1..53a8d993 100644 --- a/opslevel/resource_opslevel_integration_aws.go +++ b/opslevel/resource_opslevel_integration_aws.go @@ -175,10 +175,11 @@ func (r *IntegrationAwsResource) Read(ctx context.Context, req resource.ReadRequ } func (r *IntegrationAwsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var planModel IntegrationAwsResourceModel + var planModel, stateModel IntegrationAwsResourceModel // Read Terraform plan data into the model resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) + resp.Diagnostics.Append(req.State.Get(ctx, &stateModel)...) if resp.Diagnostics.HasError() { return } @@ -188,18 +189,21 @@ func (r *IntegrationAwsResource) Update(ctx context.Context, req resource.Update resp.Diagnostics.Append(diags...) return } - regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) - if diags != nil && diags.HasError() { - resp.Diagnostics.Append(diags...) - return - } input := opslevel.AWSIntegrationInput{ Name: opslevel.RefOf(planModel.Name.ValueString()), IAMRole: opslevel.RefOf(planModel.IamRole.ValueString()), ExternalID: opslevel.RefOf(planModel.ExternalID.ValueString()), OwnershipTagOverride: opslevel.RefOf(planModel.OwnershipTagOverrides.ValueBool()), OwnershipTagKeys: ownershipTagKeys, - RegionOverride: ®ionOverride, + } + + if !planModel.RegionOverride.IsNull() || !stateModel.RegionOverride.IsNull() { + regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) + if diags != nil && diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + input.RegionOverride = ®ionOverride } awsIntegration, err := r.client.UpdateIntegrationAWS(planModel.Id.ValueString(), input) @@ -208,7 +212,7 @@ func (r *IntegrationAwsResource) Update(ctx context.Context, req resource.Update return } - stateModel := NewIntegrationAwsResourceModel(*awsIntegration) + stateModel = NewIntegrationAwsResourceModel(*awsIntegration) tflog.Trace(ctx, "updated an AWS integration resource") resp.Diagnostics.Append(resp.State.Set(ctx, &stateModel)...) diff --git a/submodules/opslevel-go b/submodules/opslevel-go index 91ff8258..be6cd2f2 160000 --- a/submodules/opslevel-go +++ b/submodules/opslevel-go @@ -1 +1 @@ -Subproject commit 91ff8258b1dda1ea082ba62ea66eb22d561bda66 +Subproject commit be6cd2f28a1c5551fac0017370264b4a5d131a92 From 2370b93110a899c8c803f324011e22d68ab5a2f5 Mon Sep 17 00:00:00 2001 From: David Bloss Date: Thu, 10 Oct 2024 10:32:50 -0500 Subject: [PATCH 5/5] set region override on create if known --- opslevel/resource_opslevel_integration_aws.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/opslevel/resource_opslevel_integration_aws.go b/opslevel/resource_opslevel_integration_aws.go index 53a8d993..f1696d88 100644 --- a/opslevel/resource_opslevel_integration_aws.go +++ b/opslevel/resource_opslevel_integration_aws.go @@ -126,18 +126,20 @@ func (r *IntegrationAwsResource) Create(ctx context.Context, req resource.Create resp.Diagnostics.Append(diags...) return } - regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) - if diags != nil && diags.HasError() { - resp.Diagnostics.Append(diags...) - return - } input := opslevel.AWSIntegrationInput{ Name: planModel.Name.ValueStringPointer(), IAMRole: planModel.IamRole.ValueStringPointer(), ExternalID: planModel.ExternalID.ValueStringPointer(), OwnershipTagOverride: planModel.OwnershipTagOverrides.ValueBoolPointer(), OwnershipTagKeys: ownershipTagKeys, - RegionOverride: ®ionOverride, + } + if !planModel.RegionOverride.IsNull() && !planModel.RegionOverride.IsUnknown() { + regionOverride, diags := ListValueToStringSlice(ctx, planModel.RegionOverride) + if diags != nil && diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + input.RegionOverride = ®ionOverride } awsIntegration, err := r.client.CreateIntegrationAWS(input)