From 77ba1ce1b887ed0f24c55ce5e6314e7806610846 Mon Sep 17 00:00:00 2001 From: Michal Dobaczewski Date: Mon, 29 Jul 2024 15:48:44 +0300 Subject: [PATCH] Add resource for config property --- docs/resources/config_property.md | 31 ++ go.mod | 2 +- go.sum | 4 + .../config_property_resource.go | 277 ++++++++++++++++++ .../config_property_resource_test.go | 269 +++++++++++++++++ internal/provider/provider.go | 2 + 6 files changed, 584 insertions(+), 1 deletion(-) create mode 100644 docs/resources/config_property.md create mode 100644 internal/provider/configproperty/config_property_resource.go create mode 100644 internal/provider/configproperty/config_property_resource_test.go diff --git a/docs/resources/config_property.md b/docs/resources/config_property.md new file mode 100644 index 0000000..e094931 --- /dev/null +++ b/docs/resources/config_property.md @@ -0,0 +1,31 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "dependencytrack_config_property Resource - dependencytrack" +subcategory: "" +description: |- + Configuration property +--- + +# dependencytrack_config_property (Resource) + +Configuration property + + + + +## Schema + +### Required + +- `group_name` (String) Name of the property group +- `name` (String) Name of the property +- `value` (String, Sensitive) Value of the property + +### Optional + +- `destroy_value` (String, Sensitive) Value of the property to set on destroy + +### Read-Only + +- `id` (String) Synthetic property ID in the form of group_name/name +- `original_value` (String, Sensitive) Original value of the property to be restored on destroy (if any) unless `destroy_value` is set diff --git a/go.mod b/go.mod index 8495329..4de5169 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/futurice/terraform-provider-dependencytrack go 1.21 require ( - github.com/futurice/dependency-track-client-go v0.0.0-20240408102005-c3ad5fb57202 + github.com/futurice/dependency-track-client-go v0.0.0-20240730102435-ec2e22cc097c github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/hashicorp/terraform-plugin-docs v0.19.0 diff --git a/go.sum b/go.sum index 8da2c37..d099442 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,10 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3 github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/futurice/dependency-track-client-go v0.0.0-20240408102005-c3ad5fb57202 h1:RIhdzp/3/9vIx+lMOwJzmo8kLJoGp70JPSu6jlehqgU= github.com/futurice/dependency-track-client-go v0.0.0-20240408102005-c3ad5fb57202/go.mod h1:nSSUhNjXItvlllTmfE3BdooP1GtAuu6dDXFAHSem0Jk= +github.com/futurice/dependency-track-client-go v0.0.0-20240730072954-1cd773465f63 h1:ic7N/FIPMYsLvBp/Q8k0JXY41QJd//sSrOLAOtJ7Pak= +github.com/futurice/dependency-track-client-go v0.0.0-20240730072954-1cd773465f63/go.mod h1:nSSUhNjXItvlllTmfE3BdooP1GtAuu6dDXFAHSem0Jk= +github.com/futurice/dependency-track-client-go v0.0.0-20240730102435-ec2e22cc097c h1:rUmqDSw/clCENP/eMA8EMhlqoPL0n9ILOLiKwWttmW8= +github.com/futurice/dependency-track-client-go v0.0.0-20240730102435-ec2e22cc097c/go.mod h1:nSSUhNjXItvlllTmfE3BdooP1GtAuu6dDXFAHSem0Jk= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= diff --git a/internal/provider/configproperty/config_property_resource.go b/internal/provider/configproperty/config_property_resource.go new file mode 100644 index 0000000..00eaddb --- /dev/null +++ b/internal/provider/configproperty/config_property_resource.go @@ -0,0 +1,277 @@ +// Copyright (c) 2024 Futurice Oy +// SPDX-License-Identifier: MPL-2.0 + +package configproperty + +import ( + "context" + "fmt" + dtrack "github.com/futurice/dependency-track-client-go" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var _ resource.Resource = &ConfigPropertyResource{} +var _ resource.ResourceWithImportState = &ConfigPropertyResource{} + +func NewConfigPropertyResource() resource.Resource { + return &ConfigPropertyResource{} +} + +// ConfigPropertyResource defines the resource implementation. +type ConfigPropertyResource struct { + client *dtrack.Client +} + +// ConfigPropertyResourceModel describes the resource data model. +type ConfigPropertyResourceModel struct { + ID types.String `tfsdk:"id"` + GroupName types.String `tfsdk:"group_name"` + Name types.String `tfsdk:"name"` + Value types.String `tfsdk:"value"` + DestroyValue types.String `tfsdk:"destroy_value"` + OriginalValue types.String `tfsdk:"original_value"` +} + +func (r *ConfigPropertyResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_config_property" +} + +func (r *ConfigPropertyResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Configuration property", + + Attributes: map[string]schema.Attribute{ + "group_name": schema.StringAttribute{ + MarkdownDescription: "Name of the property group", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "name": schema.StringAttribute{ + MarkdownDescription: "Name of the property", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "value": schema.StringAttribute{ + MarkdownDescription: "Value of the property", + Required: true, + Sensitive: true, // not for all variables, but for some yes + }, + "destroy_value": schema.StringAttribute{ + MarkdownDescription: "Value of the property to set on destroy", + Optional: true, + Sensitive: true, + }, + "original_value": schema.StringAttribute{ + MarkdownDescription: "Original value of the property to be restored on destroy (if any) unless `destroy_value` is set", + Computed: true, + Sensitive: true, + }, + "id": schema.StringAttribute{ + MarkdownDescription: "Synthetic property ID in the form of group_name/name", + Computed: true, + }, + }, + } +} + +func (r *ConfigPropertyResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*dtrack.Client) + + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *dtrack.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.client = client +} + +func (r *ConfigPropertyResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan, state ConfigPropertyResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + groupName := plan.GroupName.ValueString() + name := plan.Name.ValueString() + value := plan.Value.ValueString() + + originalProperty, originalPropertyDiags := r.findConfigProperty(ctx, groupName, name) + resp.Diagnostics.Append(originalPropertyDiags...) + if resp.Diagnostics.HasError() { + return + } + + setConfigPropertyRequest := dtrack.SetConfigPropertyRequest{ + GroupName: groupName, + PropertyName: name, + PropertyValue: value, + } + + _, err := r.client.Config.SetConfigProperty(ctx, setConfigPropertyRequest) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to set config property, got error: %s", err)) + return + } + + state.ID = types.StringValue(makeConfigPropertyID(groupName, name)) + state.GroupName = types.StringValue(groupName) + state.Name = types.StringValue(name) + state.Value = types.StringValue(value) + state.DestroyValue = plan.DestroyValue + + if originalProperty != nil && originalProperty.PropertyValue != nil { + state.OriginalValue = types.StringValue(*originalProperty.PropertyValue) + } else { + state.OriginalValue = types.StringNull() + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *ConfigPropertyResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state ConfigPropertyResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + groupName := state.GroupName.ValueString() + name := state.Name.ValueString() + + property, propertyDiags := r.findConfigProperty(ctx, groupName, name) + resp.Diagnostics.Append(propertyDiags...) + if resp.Diagnostics.HasError() { + return + } + + if property == nil { + resp.State.RemoveResource(ctx) + return + } + + if property.PropertyValue != nil { + state.Value = types.StringValue(*property.PropertyValue) + } else { + state.Value = types.StringNull() + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *ConfigPropertyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan, state ConfigPropertyResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + // only value can change via Update, destroy_value can change in TF state only + groupName := state.GroupName.ValueString() + name := state.Name.ValueString() + value := plan.Value.ValueString() + + setConfigPropertyRequest := dtrack.SetConfigPropertyRequest{ + GroupName: groupName, + PropertyName: name, + PropertyValue: value, + } + + _, err := r.client.Config.SetConfigProperty(ctx, setConfigPropertyRequest) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to set config property, got error: %s", err)) + return + } + + state.Value = types.StringValue(value) + state.DestroyValue = plan.DestroyValue + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *ConfigPropertyResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state ConfigPropertyResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + groupName := state.GroupName.ValueString() + name := state.Name.ValueString() + + var restoreValue *string + if !state.DestroyValue.IsUnknown() && !state.DestroyValue.IsNull() { + destroyValueTmp := state.DestroyValue.ValueString() + restoreValue = &destroyValueTmp + } else if !state.OriginalValue.IsUnknown() && !state.OriginalValue.IsNull() { + originalValueTmp := state.OriginalValue.ValueString() + restoreValue = &originalValueTmp + } else { + resp.Diagnostics.AddWarning("No value to restore", "Neither destroy_value not original_value is available on destroy - the property will not be modified in Dependency-Track") + } + + if restoreValue != nil { + setConfigPropertyRequest := dtrack.SetConfigPropertyRequest{ + GroupName: groupName, + PropertyName: name, + PropertyValue: *restoreValue, + } + + _, err := r.client.Config.SetConfigProperty(ctx, setConfigPropertyRequest) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to reset config property to original value, got error: %s", err)) + return + } + } + + resp.State.RemoveResource(ctx) +} + +func (r *ConfigPropertyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resp.Diagnostics.AddError("Not supported", "Importing this resource is not necessary. Instead just create a resource to set the property value to what you want it to be") +} + +func (r *ConfigPropertyResource) findConfigProperty(ctx context.Context, groupName, name string) (*dtrack.ConfigProperty, diag.Diagnostics) { + var diags diag.Diagnostics + + configProperties, err := r.client.Config.GetAllConfigProperties(ctx) + if err != nil { + diags.AddError("Client Error", fmt.Sprintf("Unable to get config properties, got error: %s", err)) + return nil, diags + } + + for _, configProperty := range configProperties { + if configProperty.GroupName == groupName && configProperty.PropertyName == name { + return &configProperty, diags + } + } + + return nil, diags +} + +func makeConfigPropertyID(groupName string, name string) string { + return fmt.Sprintf("%s/%s", groupName, name) +} diff --git a/internal/provider/configproperty/config_property_resource_test.go b/internal/provider/configproperty/config_property_resource_test.go new file mode 100644 index 0000000..eea465d --- /dev/null +++ b/internal/provider/configproperty/config_property_resource_test.go @@ -0,0 +1,269 @@ +// Copyright (c) 2024 Futurice Oy +// SPDX-License-Identifier: MPL-2.0 + +package configproperty_test + +import ( + "context" + "fmt" + dtrack "github.com/futurice/dependency-track-client-go" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "os" + "testing" + + "github.com/futurice/terraform-provider-dependencytrack/internal/testutils" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +var testDependencyTrack *testutils.TestDependencyTrack + +func TestMain(m *testing.M) { + if os.Getenv(resource.EnvTfAcc) != "" { + var cleanup func() + testDependencyTrack, cleanup = testutils.InitTestDependencyTrack() + defer cleanup() + } + + m.Run() +} + +func TestAccConfigPropertyResource_basic(t *testing.T) { + ctx := testutils.CreateTestContext(t) + + groupName := "email" + name := "smtp.from.address" + value := "test@example.com" + updatedValue := "test2@example.com" + originalValue := "original@example.com" + + configPropertyResourceName := createConfigPropertyResourceName("test") + + // fix the "original" value before the test + err := setConfigProperty(ctx, testDependencyTrack, groupName, name, originalValue) + if err != nil { + t.Fatalf("Failed to set original value before the test: %v", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testutils.TestAccPreCheck(t) }, + ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccConfigPropertyConfigBasic(testDependencyTrack, groupName, name, value), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, value), + resource.TestCheckResourceAttrSet(configPropertyResourceName, "id"), + resource.TestCheckResourceAttr(configPropertyResourceName, "group_name", groupName), + resource.TestCheckResourceAttr(configPropertyResourceName, "name", name), + resource.TestCheckResourceAttr(configPropertyResourceName, "value", value), + resource.TestCheckNoResourceAttr(configPropertyResourceName, "destroy_value"), + resource.TestCheckResourceAttr(configPropertyResourceName, "original_value", originalValue), + ), + }, + { + Config: testAccConfigPropertyConfigBasic(testDependencyTrack, groupName, name, updatedValue), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, updatedValue), + resource.TestCheckResourceAttrSet(configPropertyResourceName, "id"), + resource.TestCheckResourceAttr(configPropertyResourceName, "group_name", groupName), + resource.TestCheckResourceAttr(configPropertyResourceName, "name", name), + resource.TestCheckResourceAttr(configPropertyResourceName, "value", updatedValue), + resource.TestCheckNoResourceAttr(configPropertyResourceName, "destroy_value"), + resource.TestCheckResourceAttr(configPropertyResourceName, "original_value", originalValue), + ), + }, + }, + CheckDestroy: testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, originalValue), + }) +} + +func TestAccConfigPropertyResource_destroyValue(t *testing.T) { + ctx := testutils.CreateTestContext(t) + + groupName := "email" + name := "smtp.from.address" + value := "test@example.com" + destroyValue := "destroy@example.com" + updatedDestroyValue := "destroy2@example.com" + originalValue := "original@example.com" + + configPropertyResourceName := createConfigPropertyResourceName("test") + + // fix the "original" value before the test + err := setConfigProperty(ctx, testDependencyTrack, groupName, name, originalValue) + if err != nil { + t.Fatalf("Failed to set original value before the test: %v", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testutils.TestAccPreCheck(t) }, + ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccConfigPropertyConfigDestroyValue(testDependencyTrack, groupName, name, value, destroyValue), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, value), + resource.TestCheckResourceAttrSet(configPropertyResourceName, "id"), + resource.TestCheckResourceAttr(configPropertyResourceName, "group_name", groupName), + resource.TestCheckResourceAttr(configPropertyResourceName, "name", name), + resource.TestCheckResourceAttr(configPropertyResourceName, "value", value), + resource.TestCheckResourceAttr(configPropertyResourceName, "destroy_value", destroyValue), + resource.TestCheckResourceAttr(configPropertyResourceName, "original_value", originalValue), + ), + }, + { + Config: testAccConfigPropertyConfigDestroyValue(testDependencyTrack, groupName, name, value, updatedDestroyValue), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, value), + resource.TestCheckResourceAttrSet(configPropertyResourceName, "id"), + resource.TestCheckResourceAttr(configPropertyResourceName, "group_name", groupName), + resource.TestCheckResourceAttr(configPropertyResourceName, "name", name), + resource.TestCheckResourceAttr(configPropertyResourceName, "value", value), + resource.TestCheckResourceAttr(configPropertyResourceName, "destroy_value", updatedDestroyValue), + resource.TestCheckResourceAttr(configPropertyResourceName, "original_value", originalValue), + ), + }, + }, + CheckDestroy: testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, updatedDestroyValue), + }) +} + +func TestAccConfigPropertyResource_changeProperty(t *testing.T) { + ctx := testutils.CreateTestContext(t) + + groupName := "email" + name := "smtp.from.address" + value := "test@example.com" + originalValue := "original@example.com" + + otherGroupName := "integrations" + otherName := "defectdojo.apiKey" + otherValue := "someKey" + otherOriginalValue := "originalKey" + + configPropertyResourceName := createConfigPropertyResourceName("test") + + // fix the "original" values before the test + err := setConfigProperty(ctx, testDependencyTrack, groupName, name, originalValue) + if err != nil { + t.Fatalf("Failed to set original value before the test: %v", err) + } + + err = setConfigProperty(ctx, testDependencyTrack, otherGroupName, otherName, otherOriginalValue) + if err != nil { + t.Fatalf("Failed to set original value before the test: %v", err) + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testutils.TestAccPreCheck(t) }, + ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccConfigPropertyConfigBasic(testDependencyTrack, groupName, name, value), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, value), + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, otherGroupName, otherName, otherOriginalValue), + ), + }, + { + Config: testAccConfigPropertyConfigBasic(testDependencyTrack, otherGroupName, otherName, otherValue), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, groupName, name, originalValue), + testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, otherGroupName, otherName, otherValue), + resource.TestCheckResourceAttrSet(configPropertyResourceName, "id"), + resource.TestCheckResourceAttr(configPropertyResourceName, "group_name", otherGroupName), + resource.TestCheckResourceAttr(configPropertyResourceName, "name", otherName), + resource.TestCheckResourceAttr(configPropertyResourceName, "value", otherValue), + resource.TestCheckNoResourceAttr(configPropertyResourceName, "destroy_value"), + resource.TestCheckResourceAttr(configPropertyResourceName, "original_value", otherOriginalValue), + ), + }, + }, + CheckDestroy: testAccCheckConfigPropertyHasExpectedValue(ctx, testDependencyTrack, otherGroupName, otherName, otherOriginalValue), + }) +} + +func testAccConfigPropertyConfigBasic(testDependencyTrack *testutils.TestDependencyTrack, groupName, name, value string) string { + return testDependencyTrack.AddProviderConfiguration( + fmt.Sprintf(` +resource "dependencytrack_config_property" "test" { + group_name = %[1]q + name = %[2]q + value = %[3]q +} +`, + groupName, name, value, + ), + ) +} + +func testAccConfigPropertyConfigDestroyValue(testDependencyTrack *testutils.TestDependencyTrack, groupName, name, value, destroyValue string) string { + return testDependencyTrack.AddProviderConfiguration( + fmt.Sprintf(` +resource "dependencytrack_config_property" "test" { + group_name = %[1]q + name = %[2]q + value = %[3]q + destroy_value = %[4]q +} +`, + groupName, name, value, destroyValue, + ), + ) +} + +func createConfigPropertyResourceName(localName string) string { + return fmt.Sprintf("dependencytrack_config_property.%s", localName) +} + +func testAccCheckConfigPropertyHasExpectedValue(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, groupName, name, expectedValue string) resource.TestCheckFunc { + return func(state *terraform.State) error { + configProperty, err := findConfigProperty(ctx, testDependencyTrack, groupName, name) + if err != nil { + return err + } + if configProperty == nil { + return fmt.Errorf("failed to find config property [%s]/[%s] from Dependency-Track", groupName, name) + } + if configProperty.PropertyValue == nil { + return fmt.Errorf("config property [%s]/[%s] has no value", groupName, name) + } + + configPropertyValue := *configProperty.PropertyValue + if configPropertyValue != expectedValue { + return fmt.Errorf("config property [%s]/[%s] has value [%s] instead of the expected [%s]", groupName, name, configPropertyValue, expectedValue) + } + + return nil + } +} + +func findConfigProperty(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, groupName, name string) (*dtrack.ConfigProperty, error) { + configProperties, err := testDependencyTrack.Client.Config.GetAllConfigProperties(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get config properties from Dependency-Track: %w", err) + } + + for _, configProperty := range configProperties { + if configProperty.GroupName == groupName && configProperty.PropertyName == name { + return &configProperty, nil + } + } + + return nil, nil +} + +func setConfigProperty(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, groupName, name, value string) error { + setConfigPropertyRequest := dtrack.SetConfigPropertyRequest{ + GroupName: groupName, + PropertyName: name, + PropertyValue: value, + } + + _, err := testDependencyTrack.Client.Config.SetConfigProperty(ctx, setConfigPropertyRequest) + if err != nil { + return fmt.Errorf("failed to set config property in Dependency-Track: %w", err) + } + + return nil +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index e19b958..d4fabf9 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -7,6 +7,7 @@ import ( "context" dtrack "github.com/futurice/dependency-track-client-go" "github.com/futurice/terraform-provider-dependencytrack/internal/provider/aclmapping" + "github.com/futurice/terraform-provider-dependencytrack/internal/provider/configproperty" "github.com/futurice/terraform-provider-dependencytrack/internal/provider/notificationpublisher" "github.com/futurice/terraform-provider-dependencytrack/internal/provider/notificationrule" "github.com/futurice/terraform-provider-dependencytrack/internal/provider/notificationruleproject" @@ -103,6 +104,7 @@ func (p *DependencyTrackProvider) Configure(ctx context.Context, req provider.Co func (p *DependencyTrackProvider) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ + configproperty.NewConfigPropertyResource, team.NewTeamResource, teamapikey.NewTeamAPIKeyResource, teampermission.NewTeamPermissionResource,