From dc4ce8a6fde55ab5405c840b58d8e76bfcd7e1b7 Mon Sep 17 00:00:00 2001 From: Gagan Date: Fri, 6 Dec 2024 15:00:46 +0530 Subject: [PATCH] feat: Add project, environment resource and orgnanisation data resource (#168) * feat: Add organisation data source * feat: Add project resource * feat: Add environment resource * Add test data * Add docs * !fixup: Add project resource * bump terraform-plugin-docs * bump terraform-plugin-sdk/v2 * bump terraform-plugin-framework-validators * update changelog * remove outdated comment --- .github/workflows/test.yml | 3 + CHANGELOG.md | 20 ++ docs/data-sources/organisation.md | 28 +++ docs/resources/environment.md | 38 ++++ docs/resources/project.md | 35 ++++ flagsmith/data_source_organisation.go | 96 +++++++++ flagsmith/data_source_organisation_test.go | 42 ++++ flagsmith/models.go | 144 +++++++++++++ flagsmith/provider.go | 7 +- flagsmith/provider_test.go | 22 ++ flagsmith/resource_environment.go | 233 +++++++++++++++++++++ flagsmith/resource_environment_test.go | 123 +++++++++++ flagsmith/resource_project.go | 220 +++++++++++++++++++ flagsmith/resource_project_test.go | 123 +++++++++++ go.mod | 52 ++--- go.sum | 110 +++++----- 16 files changed, 1215 insertions(+), 81 deletions(-) create mode 100644 docs/data-sources/organisation.md create mode 100644 docs/resources/environment.md create mode 100644 docs/resources/project.md create mode 100644 flagsmith/data_source_organisation.go create mode 100644 flagsmith/data_source_organisation_test.go create mode 100644 flagsmith/resource_environment.go create mode 100644 flagsmith/resource_environment_test.go create mode 100644 flagsmith/resource_project.go create mode 100644 flagsmith/resource_project_test.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1961c75..053df33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,6 +82,9 @@ jobs: FLAGSMITH_ENVIRONMENT_ID: 18143 FLAGSMITH_FEATURE_ID: 25142 FLAGSMITH_PROJECT_UUID: 97907de4-66d4-4d78-aae3-04f5a4518a55 + FLAGSMITH_PROJECT_ID: 7721 + FLAGSMITH_ORGANISATION_UUID: 0ee0578e-f2b8-467d-ba49-4cda324cea91 + FLAGSMITH_ORGANISATION_ID: 6880 TF_ACC: "1" run: go test -v -cover ./flagsmith/ timeout-minutes: 10 diff --git a/CHANGELOG.md b/CHANGELOG.md index d036b55..6d89141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 0.9.0 +FEATURES: +* Add resource `flagsmith_project` +* Add resource `flagsmith_environment` +* Add data resource `flagsmith_organisation` + + +## 0.8.2 +ENHANCEMENTS: +* resource(flagsmith_tag): Make `tag_colour` optional + +## 0.8.1 +BUG FIXES +fix https://github.com/Flagsmith/terraform-provider-flagsmith/issues/155 + + +## 0.8.0 +NOTES: +* This Go module(and related dependencies) has been updated to GO 1.21 as per the Go Support policy + ## 0.7.0 FEATURES: * Add resource `flagsmith_tag` diff --git a/docs/data-sources/organisation.md b/docs/data-sources/organisation.md new file mode 100644 index 0000000..19ee7e0 --- /dev/null +++ b/docs/data-sources/organisation.md @@ -0,0 +1,28 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "flagsmith_organisation Data Source - terraform-provider-flagsmith" +subcategory: "" +description: |- + Flagsmith Organisation +--- + +# flagsmith_organisation (Data Source) + +Flagsmith Organisation + + + + +## Schema + +### Required + +- `uuid` (String) UUID of the organisation + +### Read-Only + +- `force_2fa` (Boolean) If true, signup will require 2FA +- `id` (Number) ID of the organisation +- `name` (String) Name of the organisation +- `persist_trait_data` (Boolean) If false, trait data for this organisation identities will not stored +- `restrict_project_create_to_admin` (Boolean) If true, only organisation admin can create projects diff --git a/docs/resources/environment.md b/docs/resources/environment.md new file mode 100644 index 0000000..258e443 --- /dev/null +++ b/docs/resources/environment.md @@ -0,0 +1,38 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "flagsmith_environment Resource - terraform-provider-flagsmith" +subcategory: "" +description: |- + Flagsmith Environment +--- + +# flagsmith_environment (Resource) + +Flagsmith Environment + + + + +## Schema + +### Required + +- `name` (String) Name of the environment +- `project_id` (Number) ID of the project + +### Optional + +- `allow_client_traits` (Boolean) Allows clients using the client API key to set traits. +- `banner_colour` (String) hex code for the UI banner colour +- `banner_text` (String) Banner text to display in the UI +- `description` (String) Description of the environment +- `hide_disabled_flags` (Boolean) If true will exclude flags from SDK which are disabled +- `hide_sensitive_data` (Boolean) If true, will hide sensitive data(e.g: traits, description etc) from the SDK endpoints +- `minimum_change_request_approvals` (Number) Minimum number of approvals required for a change request +- `use_identity_composite_key_for_hashing` (Boolean) Enable this to have consistent multivariate and percentage split evaluations across all SDKs (in local and server side mode) + +### Read-Only + +- `api_key` (String) Client side API Key +- `id` (Number) ID of the environment +- `uuid` (String) UUID of the environment diff --git a/docs/resources/project.md b/docs/resources/project.md new file mode 100644 index 0000000..8294d6b --- /dev/null +++ b/docs/resources/project.md @@ -0,0 +1,35 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "flagsmith_project Resource - terraform-provider-flagsmith" +subcategory: "" +description: |- + Flagsmith Project +--- + +# flagsmith_project (Resource) + +Flagsmith Project + + + + +## Schema + +### Required + +- `name` (String) Name of the project +- `organisation_id` (Number) ID of the organisation project belongs to + +### Optional + +- `enable_realtime_updates` (Boolean) Enable this to trigger a realtime(sse) event whenever the value of a flag changes +- `feature_name_regex` (String) Used for validating feature names +- `hide_disabled_flags` (Boolean) If true will exclude flags from SDK which are disabled +- `only_allow_lower_case_feature_names` (Boolean) Used by UI to validate feature names +- `prevent_flag_defaults` (Boolean) Prevent defaults from being set in all environments when creating a feature. +- `stale_flags_limit_days` (Number) Number of days without modification in any environment before a flag is considered stale. + +### Read-Only + +- `id` (Number) ID of the project +- `uuid` (String) UUID of the project diff --git a/flagsmith/data_source_organisation.go b/flagsmith/data_source_organisation.go new file mode 100644 index 0000000..831b3c0 --- /dev/null +++ b/flagsmith/data_source_organisation.go @@ -0,0 +1,96 @@ +package flagsmith + +import ( + "context" + "fmt" + "github.com/Flagsmith/flagsmith-go-api-client" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" +) + +// Ensure provider defined types fully satisfy framework interfaces +var _ datasource.DataSource = &organisationDataResource{} + +func newOrganisationDataResource() datasource.DataSource { + return &organisationDataResource{} +} + +type organisationDataResource struct { + client *flagsmithapi.Client +} + +func (o *organisationDataResource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_organisation" +} + +func (o *organisationDataResource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*flagsmithapi.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *flagsmithapi.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + o.client = client +} +func (o *organisationDataResource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Flagsmith Organisation", + + Attributes: map[string]schema.Attribute{ + "uuid": schema.StringAttribute{ + Required: true, + MarkdownDescription: "UUID of the organisation", + }, + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "ID of the organisation", + }, + "name": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Name of the organisation", + }, + "force_2fa": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "If true, signup will require 2FA", + }, + "persist_trait_data": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "If false, trait data for this organisation identities will not stored", + }, + "restrict_project_create_to_admin": schema.BoolAttribute{ + Computed: true, + MarkdownDescription: "If true, only organisation admin can create projects", + }, + }, + } +} +func (o *organisationDataResource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data OrganisationResourceData + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + + // Early return if the state is wrong + if diags.HasError() { + return + } + + organisation, err := o.client.GetOrganisationByUUID(data.UUID.ValueString()) + if err != nil { + panic(err) + + } + resourceData := MakeOrganisationResourceDataFromClientOrganisation(organisation) + + diags = resp.State.Set(ctx, &resourceData) + resp.Diagnostics.Append(diags...) + +} diff --git a/flagsmith/data_source_organisation_test.go b/flagsmith/data_source_organisation_test.go new file mode 100644 index 0000000..7f0ecd5 --- /dev/null +++ b/flagsmith/data_source_organisation_test.go @@ -0,0 +1,42 @@ +package flagsmith_test + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" + "strconv" +) + +func TestAccOrganisationDataResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccOrganisationDataResourceConfig(organisationUUID()), + Check: resource.ComposeAggregateTestCheckFunc( + + resource.TestCheckResourceAttr("data.flagsmith_organisation.test_org", "id", strconv.Itoa( organisationID())), + resource.TestCheckResourceAttr("data.flagsmith_organisation.test_org", "uuid", organisationUUID()), + + resource.TestCheckResourceAttrSet("data.flagsmith_organisation.test_org", "name"), + + ), + }, + }, + }) +} + + +func testAccOrganisationDataResourceConfig(organisationUUID string) string { + return fmt.Sprintf(` +provider "flagsmith" { +} + +data "flagsmith_organisation" "test_org" { + uuid = "%s" +} + +`,organisationUUID) +} diff --git a/flagsmith/models.go b/flagsmith/models.go index 100ffab..d41a30e 100644 --- a/flagsmith/models.go +++ b/flagsmith/models.go @@ -500,3 +500,147 @@ func MakeTagResourceDataFromClientTag(clientTag *flagsmithapi.Tag) TagResourceDa return resourceData } + +type ProjectResourceData struct { + ID types.Int64 `tfsdk:"id"` + UUID types.String `tfsdk:"uuid"` + Name types.String `tfsdk:"name"` + OrganisationID types.Int64 `tfsdk:"organisation_id"` + HideDisabledFlags types.Bool `tfsdk:"hide_disabled_flags"` + PreventFlagDefaults types.Bool `tfsdk:"prevent_flag_defaults"` + EnableRealtimeUpdates types.Bool `tfsdk:"enable_realtime_updates"` + OnlyAllowLowerCaseFeatureNames types.Bool `tfsdk:"only_allow_lower_case_feature_names"` + FeatureNameRegex types.String `tfsdk:"feature_name_regex"` + StaleFlagsLimitDays types.Int64 `tfsdk:"stale_flags_limit_days"` +} + + +func (p *ProjectResourceData) ToClientProject() *flagsmithapi.Project { + project := flagsmithapi.Project{ + UUID: p.UUID.ValueString(), + Name: p.Name.ValueString(), + Organisation: p.OrganisationID.ValueInt64(), + } + if !p.ID.IsNull() && !p.ID.IsUnknown() { + project.ID = p.ID.ValueInt64() + } + + if p.HideDisabledFlags.ValueBool() { + project.HideDisabledFlags = p.HideDisabledFlags.ValueBool() + } + if p.PreventFlagDefaults.ValueBool() { + project.PreventFlagDefaults = p.PreventFlagDefaults.ValueBool() + } + if p.EnableRealtimeUpdates.ValueBool() { + project.EnableRealtimeUpdates = p.EnableRealtimeUpdates.ValueBool() + } + if p.OnlyAllowLowerCaseFeatureNames.ValueBool() { + project.OnlyAllowLowerCaseFeatureNames = p.OnlyAllowLowerCaseFeatureNames.ValueBool() + } + if p.FeatureNameRegex.ValueString() != "" { + project.FeatureNameRegex = p.FeatureNameRegex.ValueString() + } + if !p.StaleFlagsLimitDays.IsNull() && !p.StaleFlagsLimitDays.IsUnknown() { + project.StaleFlagsLimitDays = p.StaleFlagsLimitDays.ValueInt64() + } + return &project + +} +func MakeProjectResourceDataFromClientProject(clientProject *flagsmithapi.Project) ProjectResourceData { + resourceData := ProjectResourceData{ + ID: types.Int64Value(clientProject.ID), + UUID: types.StringValue(clientProject.UUID), + Name: types.StringValue(clientProject.Name), + OrganisationID: types.Int64Value(clientProject.Organisation), + HideDisabledFlags: types.BoolValue(clientProject.HideDisabledFlags), + PreventFlagDefaults: types.BoolValue(clientProject.PreventFlagDefaults), + EnableRealtimeUpdates: types.BoolValue(clientProject.EnableRealtimeUpdates), + OnlyAllowLowerCaseFeatureNames: types.BoolValue(clientProject.OnlyAllowLowerCaseFeatureNames), + FeatureNameRegex: types.StringValue(clientProject.FeatureNameRegex), + StaleFlagsLimitDays: types.Int64Value(clientProject.StaleFlagsLimitDays), + } + return resourceData +} +type OrganisationResourceData struct { + ID types.Int64 `tfsdk:"id"` + UUID types.String `tfsdk:"uuid"` + Name types.String `tfsdk:"name"` + Force2FA types.Bool `tfsdk:"force_2fa"` + PersistTraitData types.Bool `tfsdk:"persist_trait_data"` + RestrictProjectCreateToAdmin types.Bool `tfsdk:"restrict_project_create_to_admin"` +} +func MakeOrganisationResourceDataFromClientOrganisation(clientOrganisation *flagsmithapi.Organisation) OrganisationResourceData { + resourceData := OrganisationResourceData{ + ID: types.Int64Value(clientOrganisation.ID), + UUID: types.StringValue(clientOrganisation.UUID), + Name: types.StringValue(clientOrganisation.Name), + Force2FA: types.BoolValue(clientOrganisation.Force2FA), + PersistTraitData: types.BoolValue(clientOrganisation.PersistTraitData), + RestrictProjectCreateToAdmin: types.BoolValue(clientOrganisation.RestrictProjectCreateToAdmin), + } + return resourceData +} + +type EnvironmentResourceData struct { + ID types.Int64 `tfsdk:"id"` + UUID types.String `tfsdk:"uuid"` + Name types.String `tfsdk:"name"` + APIKey types.String `tfsdk:"api_key"` + ProjectID types.Int64 `tfsdk:"project_id"` + Description types.String `tfsdk:"description"` + AllowClientTraits types.Bool `tfsdk:"allow_client_traits"` + BannerText types.String `tfsdk:"banner_text"` + BannerColour types.String `tfsdk:"banner_colour"` + HideDisabledFlags types.Bool `tfsdk:"hide_disabled_flags"` + HideSensitiveData types.Bool `tfsdk:"hide_sensitive_data"` + UseIdentityCompositeKeyForHashing types.Bool `tfsdk:"use_identity_composite_key_for_hashing"` + MinimumChangeRequestApprovals types.Int64 `tfsdk:"minimum_change_request_approvals"` + +} + +func (e *EnvironmentResourceData) ToClientEnvironment() *flagsmithapi.Environment { + environment := flagsmithapi.Environment{ + UUID: e.UUID.ValueString(), + Name: e.Name.ValueString(), + APIKey: e.APIKey.ValueString(), + ProjectID: e.ProjectID.ValueInt64(), + Description: e.Description.ValueString(), + AllowClientTraits: e.AllowClientTraits.ValueBool(), + BannerText: e.BannerText.ValueString(), + BannerColour: e.BannerColour.ValueString(), + HideDisabledFlags: e.HideDisabledFlags.ValueBool(), + HideSensitiveData: e.HideSensitiveData.ValueBool(), + UseIdentityCompositeKeyForHashing: e.UseIdentityCompositeKeyForHashing.ValueBool(), + MinimumChangeRequestApprovals: e.MinimumChangeRequestApprovals.ValueInt64(), + } + if !e.ID.IsNull() && !e.ID.IsUnknown() { + environment.ID = e.ID.ValueInt64() + } + return &environment +} + +func MakeEnvironmentResourceDataFromClientEnvironment(clientEnvironment *flagsmithapi.Environment) EnvironmentResourceData { + resourceData := EnvironmentResourceData{ + ID: types.Int64Value(clientEnvironment.ID), + UUID: types.StringValue(clientEnvironment.UUID), + Name: types.StringValue(clientEnvironment.Name), + APIKey: types.StringValue(clientEnvironment.APIKey), + ProjectID: types.Int64Value(clientEnvironment.ProjectID), + MinimumChangeRequestApprovals: types.Int64Value(clientEnvironment.MinimumChangeRequestApprovals), + AllowClientTraits: types.BoolValue(clientEnvironment.AllowClientTraits), + HideDisabledFlags: types.BoolValue(clientEnvironment.HideDisabledFlags), + HideSensitiveData: types.BoolValue(clientEnvironment.HideSensitiveData), + UseIdentityCompositeKeyForHashing: types.BoolValue(clientEnvironment.UseIdentityCompositeKeyForHashing), + } + if clientEnvironment.Description != "" { + resourceData.Description = types.StringValue(clientEnvironment.Description) + } + + if clientEnvironment.BannerText != "" { + resourceData.BannerText = types.StringValue(clientEnvironment.BannerText) + } + if clientEnvironment.BannerColour != "" { + resourceData.BannerColour = types.StringValue(clientEnvironment.BannerColour) + } + return resourceData +} diff --git a/flagsmith/provider.go b/flagsmith/provider.go index d089eff..786240a 100644 --- a/flagsmith/provider.go +++ b/flagsmith/provider.go @@ -80,13 +80,16 @@ func (p *fsProvider) Resources(ctx context.Context) []func() resource.Resource { newSegmentResource, newMultivariateResource, newTagResource, + newProjectResource, + newEnvironmentResource, } } func (p *fsProvider) DataSources(ctx context.Context) []func() datasource.DataSource { - // Does not define any data source - return []func() datasource.DataSource{} + return []func() datasource.DataSource{ + newOrganisationDataResource, + } } func (p *fsProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { diff --git a/flagsmith/provider_test.go b/flagsmith/provider_test.go index 1ec0d21..f47b3e3 100644 --- a/flagsmith/provider_test.go +++ b/flagsmith/provider_test.go @@ -24,6 +24,9 @@ func testAccPreCheck(t *testing.T) { mustHaveEnv(t, "FLAGSMITH_ENVIRONMENT_ID") mustHaveEnv(t, "FLAGSMITH_FEATURE_ID") mustHaveEnv(t, "FLAGSMITH_PROJECT_UUID") + mustHaveEnv(t, "FLAGSMITH_PROJECT_ID") + mustHaveEnv(t, "FLAGSMITH_ORGANISATION_ID") + mustHaveEnv(t, "FLAGSMITH_ORGANISATION_UUID") } func mustHaveEnv(t *testing.T, name string) { @@ -49,6 +52,15 @@ func environmentID() int { } return v } +func projectID() int { + v, err := strconv.Atoi(os.Getenv("FLAGSMITH_PROJECT_ID")) + if err != nil { + panic(err) + + } + return v +} + func featureID() int { v, err := strconv.Atoi(os.Getenv("FLAGSMITH_FEATURE_ID")) if err != nil { @@ -56,6 +68,16 @@ func featureID() int { } return v } +func organisationID() int { + v, err := strconv.Atoi(os.Getenv("FLAGSMITH_ORGANISATION_ID")) + if err != nil { + panic(err) + } + return v +} +func organisationUUID() string{ + return os.Getenv("FLAGSMITH_ORGANISATION_UUID") +} var tc *flagsmithapi.Client diff --git a/flagsmith/resource_environment.go b/flagsmith/resource_environment.go new file mode 100644 index 0000000..6b7944d --- /dev/null +++ b/flagsmith/resource_environment.go @@ -0,0 +1,233 @@ +package flagsmith + +import ( + "context" + "fmt" + "github.com/Flagsmith/flagsmith-go-api-client" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces +var _ resource.Resource = &environmentResource{} +var _ resource.ResourceWithImportState = &environmentResource{} + +func newEnvironmentResource() resource.Resource { + return &environmentResource{} +} + +type environmentResource struct { + client *flagsmithapi.Client +} + +func (r *environmentResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_environment" +} + +func (r *environmentResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*flagsmithapi.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *flagsmithapi.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + r.client = client +} +func (t *environmentResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Flagsmith Environment", + + Attributes: map[string]schema.Attribute{ + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "ID of the environment", + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, + }, + "uuid": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "UUID of the environment", + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "project_id": schema.Int64Attribute{ + Required: true, + MarkdownDescription: "ID of the project", + PlanModifiers: []planmodifier.Int64{int64planmodifier.RequiresReplace()}, + }, + "name": schema.StringAttribute{ + Required: true, + MarkdownDescription: "Name of the environment", + }, + "api_key": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Client side API Key", + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "description": schema.StringAttribute{ + Optional: true, + MarkdownDescription: "Description of the environment", + }, + "banner_text": schema.StringAttribute{ + Optional: true, + MarkdownDescription: "Banner text to display in the UI", + }, + "banner_colour": schema.StringAttribute{ + Optional: true, + MarkdownDescription: "hex code for the UI banner colour", + }, + "minimum_change_request_approvals": schema.Int64Attribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Minimum number of approvals required for a change request", + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, + Default: int64default.StaticInt64(0), + }, + "hide_disabled_flags": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "If true will exclude flags from SDK which are disabled", + Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "hide_sensitive_data": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "If true, will hide sensitive data(e.g: traits, description etc) from the SDK endpoints", + Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "allow_client_traits": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Allows clients using the client API key to set traits.", + Default: booldefault.StaticBool(true), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "use_identity_composite_key_for_hashing": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Enable this to have consistent multivariate and percentage split evaluations across all SDKs (in local and server side mode) ", + Default: booldefault.StaticBool(true), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + }, + } +} + +func (r *environmentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data EnvironmentResourceData + + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + return + } + + clientEnvironment := data.ToClientEnvironment() + + // Create the environment + err := r.client.CreateEnvironment(clientEnvironment) + + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create environment, got error: %s", err)) + return + } + resourceData := MakeEnvironmentResourceDataFromClientEnvironment(clientEnvironment) + + diags = resp.State.Set(ctx, &resourceData) + resp.Diagnostics.Append(diags...) +} + +func (r *environmentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data EnvironmentResourceData + diags := req.State.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + + // Early return if the state is wrong + if diags.HasError() { + return + } + + environment, err := r.client.GetEnvironmentByUUID(data.UUID.ValueString()) + if err != nil { + panic(err) + + } + resourceData := MakeEnvironmentResourceDataFromClientEnvironment(environment) + + diags = resp.State.Set(ctx, &resourceData) + resp.Diagnostics.Append(diags...) + +} + +func (r *environmentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + //Get plan values + var plan EnvironmentResourceData + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + tflog.Error(ctx, "Update: Error reading plan data") + return + } + + // Generate API request body from plan + clientEnvironment := plan.ToClientEnvironment() + + err := r.client.UpdateEnvironment(clientEnvironment) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update environment, got error: %s", err)) + return + } + + resourceData := MakeEnvironmentResourceDataFromClientEnvironment(clientEnvironment) + + // Update the state with the new values + diags = resp.State.Set(ctx, &resourceData) + + resp.Diagnostics.Append(diags...) + +} + +func (r *environmentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + // Get current state + var state EnvironmentResourceData + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + tflog.Error(ctx, "Delete: Error reading state data") + return + } + apiKey := state.APIKey.ValueString() + if apiKey != "" { + err := r.client.DeleteEnvironment(apiKey) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete environment, got error: %s", err)) + return + } + } + resp.State.RemoveResource(ctx) + +} +func (r *environmentResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("uuid"), req, resp) +} diff --git a/flagsmith/resource_environment_test.go b/flagsmith/resource_environment_test.go new file mode 100644 index 0000000..eeda264 --- /dev/null +++ b/flagsmith/resource_environment_test.go @@ -0,0 +1,123 @@ +package flagsmith_test + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "testing" + "strconv" +) + +func TestAccEnvironmentResource(t *testing.T) { + environmentName := acctest.RandString(16) + + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testAccCheckEnvironmentResourceDestroy, + Steps: []resource.TestStep{ + // Create and Read testing + { + Config: testAccEnvironmentResourceConfig(environmentName, projectID(), "new environment"), + Check: resource.ComposeAggregateTestCheckFunc( + + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "name", environmentName), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "project_id", strconv.Itoa(projectID())), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "description", "new environment"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "minimum_change_request_approvals", "0"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_sensitive_data", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "allow_client_traits", "true"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "use_identity_composite_key_for_hashing", "true"), + + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "id"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "api_key"), + + ), + }, + + // ImportState testing + { + ResourceName: "flagsmith_environment.test_environment", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: getEnvironmentImportID("flagsmith_environment.test_environment"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "name", environmentName), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "project_id", strconv.Itoa(projectID())), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "description", "new environment"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "minimum_change_request_approvals", "0"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_sensitive_data", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "allow_client_traits", "true"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "use_identity_composite_key_for_hashing", "true"), + + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "id"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "api_key"), + + ), + }, + + // Update testing + { + Config: testAccEnvironmentResourceConfig(environmentName, projectID(), "updated environment"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "name", environmentName), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "project_id", strconv.Itoa(projectID())), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "description", "updated environment"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "minimum_change_request_approvals", "0"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "hide_sensitive_data", "false"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "allow_client_traits", "true"), + resource.TestCheckResourceAttr("flagsmith_environment.test_environment", "use_identity_composite_key_for_hashing", "true"), + + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "id"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_environment.test_environment", "api_key"), + + ), + }, + }, + }) +} + + +func getEnvironmentImportID(n string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + return getAttributefromState(s, n, "uuid") + } +} + +func testAccCheckEnvironmentResourceDestroy(s *terraform.State) error { + id , err := getAttributefromState(s, "flagsmith_environment.test_environment", "id") + if err != nil { + return err + } + + _, err = testClient().GetEnvironment(id) + if err == nil { + return fmt.Errorf("environment still exists") + } + return nil + +} + +func testAccEnvironmentResourceConfig(environmentName string, projectID int, description string ) string { + return fmt.Sprintf(` +provider "flagsmith" { + +} + +resource "flagsmith_environment" "test_environment" { + name = "%s" + project_id = %d + description = "%s" +} + +`,environmentName, projectID, description) +} diff --git a/flagsmith/resource_project.go b/flagsmith/resource_project.go new file mode 100644 index 0000000..4345c5d --- /dev/null +++ b/flagsmith/resource_project.go @@ -0,0 +1,220 @@ +package flagsmith + +import ( + "context" + "fmt" + "github.com/Flagsmith/flagsmith-go-api-client" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces +var _ resource.Resource = &projectResource{} +var _ resource.ResourceWithImportState = &projectResource{} + +func newProjectResource() resource.Resource { + return &projectResource{} +} + +type projectResource struct { + client *flagsmithapi.Client +} + +func (r *projectResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_project" +} + +func (r *projectResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*flagsmithapi.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *flagsmithapi.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + r.client = client +} +func (t *projectResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Flagsmith Project", + + Attributes: map[string]schema.Attribute{ + "id": schema.Int64Attribute{ + Computed: true, + MarkdownDescription: "ID of the project", + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, + }, + "uuid": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "UUID of the project", + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "organisation_id": schema.Int64Attribute{ + Required: true, + MarkdownDescription: "ID of the organisation project belongs to", + PlanModifiers: []planmodifier.Int64{int64planmodifier.RequiresReplace()}, + }, + "name": schema.StringAttribute{ + Required: true, + MarkdownDescription: "Name of the project", + }, + "hide_disabled_flags": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "If true will exclude flags from SDK which are disabled", + Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "prevent_flag_defaults": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Prevent defaults from being set in all environments when creating a feature.", + Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "enable_realtime_updates": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Enable this to trigger a realtime(sse) event whenever the value of a flag changes", + Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "only_allow_lower_case_feature_names": schema.BoolAttribute{ + Optional: true, + Computed: true, + MarkdownDescription: "Used by UI to validate feature names", + Default: booldefault.StaticBool(true), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, + }, + "feature_name_regex": schema.StringAttribute{ + Computed: true, + Optional: true, + MarkdownDescription: "Used for validating feature names", + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "stale_flags_limit_days": schema.Int64Attribute{ + Computed: true, + Optional: true, + MarkdownDescription: "Number of days without modification in any environment before a flag is considered stale.", + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, + }, + }, + } +} + +func (r *projectResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data ProjectResourceData + + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + return + } + + clientProject := data.ToClientProject() + + // Create the project + err := r.client.CreateProject(clientProject) + + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create project, got error: %s", err)) + return + } + resourceData := MakeProjectResourceDataFromClientProject(clientProject) + + diags = resp.State.Set(ctx, &resourceData) + resp.Diagnostics.Append(diags...) +} + +func (r *projectResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data ProjectResourceData + diags := req.State.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + + // Early return if the state is wrong + if diags.HasError() { + return + } + + project, err := r.client.GetProject(data.UUID.ValueString()) + if err != nil { + panic(err) + + } + resourceData := MakeProjectResourceDataFromClientProject(project) + + diags = resp.State.Set(ctx, &resourceData) + resp.Diagnostics.Append(diags...) + +} + +func (r *projectResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + //Get plan values + var plan ProjectResourceData + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + tflog.Error(ctx, "Update: Error reading plan data") + return + } + + // Generate API request body from plan + clientProject := plan.ToClientProject() + + err := r.client.UpdateProject(clientProject) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update project, got error: %s", err)) + return + } + + resourceData := MakeProjectResourceDataFromClientProject(clientProject) + + // Update the state with the new values + diags = resp.State.Set(ctx, &resourceData) + + resp.Diagnostics.Append(diags...) + +} + +func (r *projectResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + // Get current state + var state ProjectResourceData + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + + if resp.Diagnostics.HasError() { + tflog.Error(ctx, "Delete: Error reading state data") + return + } + projectID := state.ID.ValueInt64() + if projectID != 0 { + err := r.client.DeleteProject(projectID) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete project, got error: %s", err)) + return + } + } + resp.State.RemoveResource(ctx) + +} +func (r *projectResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("uuid"), req, resp) +} diff --git a/flagsmith/resource_project_test.go b/flagsmith/resource_project_test.go new file mode 100644 index 0000000..7483ba2 --- /dev/null +++ b/flagsmith/resource_project_test.go @@ -0,0 +1,123 @@ +package flagsmith_test + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "testing" + "strconv" +) + +func TestAccProjectResource(t *testing.T) { + projectName := acctest.RandString(16) + newProjectName := acctest.RandString(16) + + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + //CheckDestroy: testAccCheckProjectResourceDestroy, + Steps: []resource.TestStep{ + // Create and Read testing + { + Config: testAccProjectResourceConfig(projectName), + Check: resource.ComposeAggregateTestCheckFunc( + + resource.TestCheckResourceAttr("flagsmith_project.test_project", "name", projectName), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "organisation_id", strconv.Itoa( organisationID())), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "prevent_flag_defaults", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "enable_realtime_updates", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "only_allow_lower_case_feature_names", "true"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "feature_name_regex", ""), + + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "id"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "stale_flags_limit_days"), + ), + }, + + // ImportState testing + { + ResourceName: "flagsmith_project.test_project", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: getProjectImportID("flagsmith_project.test_project"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("flagsmith_project.test_project", "name", projectName), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "organisation_id", strconv.Itoa( organisationID())), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "prevent_flag_defaults", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "enable_realtime_updates", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "only_allow_lower_case_feature_names", "true"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "feature_name_regex", ""), + + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "id"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "stale_flags_limit_days"), + + ), + }, + + // Update testing + { + Config: testAccProjectResourceConfig(newProjectName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("flagsmith_project.test_project", "name", newProjectName), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "organisation_id", strconv.Itoa( organisationID())), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "hide_disabled_flags", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "prevent_flag_defaults", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "enable_realtime_updates", "false"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "only_allow_lower_case_feature_names", "true"), + resource.TestCheckResourceAttr("flagsmith_project.test_project", "feature_name_regex", ""), + + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "id"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "uuid"), + resource.TestCheckResourceAttrSet("flagsmith_project.test_project", "stale_flags_limit_days"), + + ), + }, + }, + }) +} + + +func getProjectImportID(n string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + return getAttributefromState(s, n, "uuid") + } +} + +func testAccCheckProjectResourceDestroy(s *terraform.State) error { + uuid, err := getAttributefromState(s, "flagsmith_project.test_project", "uuid") + if err != nil { + return err + } + + _, err = testClient().GetProject(uuid) + if err == nil { + return fmt.Errorf("project still exists") + } + return nil + +} + +func testAccProjectResourceConfig(projectName string) string { + return fmt.Sprintf(` +provider "flagsmith" { + +} +data "flagsmith_organisation" "test_org" { + uuid = "%s" +} + +resource "flagsmith_project" "test_project" { + name = "%s" + organisation_id = data.flagsmith_organisation.test_org.id + +} + +`,organisationUUID(), projectName) +} diff --git a/go.mod b/go.mod index 74d3e05..3946acc 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,17 @@ module github.com/Flagsmith/terraform-provider-flagsmith -go 1.22 +go 1.22.7 -toolchain go1.22.2 +toolchain go1.23.3 require ( - github.com/Flagsmith/flagsmith-go-api-client v0.9.0 - github.com/hashicorp/terraform-plugin-docs v0.19.4 - github.com/hashicorp/terraform-plugin-framework v1.11.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 - github.com/hashicorp/terraform-plugin-go v0.23.0 + github.com/Flagsmith/flagsmith-go-api-client v0.10.0 + github.com/hashicorp/terraform-plugin-docs v0.20.1 + github.com/hashicorp/terraform-plugin-framework v1.13.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 + github.com/hashicorp/terraform-plugin-go v0.25.0 github.com/hashicorp/terraform-plugin-log v0.9.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 github.com/stretchr/testify v1.9.0 ) @@ -27,7 +27,7 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.16.0 // indirect @@ -40,16 +40,17 @@ require ( github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect - github.com/hashicorp/hc-install v0.7.0 // indirect - github.com/hashicorp/hcl/v2 v2.20.1 // indirect + github.com/hashicorp/hc-install v0.9.0 // indirect + github.com/hashicorp/hcl/v2 v2.22.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect - github.com/hashicorp/terraform-json v0.22.1 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -71,21 +72,22 @@ require ( github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/yuin/goldmark v1.7.1 // indirect + github.com/yuin/goldmark v1.7.7 // indirect github.com/yuin/goldmark-meta v1.1.0 // indirect - github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect - golang.org/x/crypto v0.23.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.22.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f98a64f..62769a2 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Flagsmith/flagsmith-go-api-client v0.9.0 h1:kGIz6iQ/UNJzVRwNm8ylHdN7IbWrv9RntyZrq5yi37w= -github.com/Flagsmith/flagsmith-go-api-client v0.9.0/go.mod h1:T+Vcd9tL6TxqHovTzoy9V1rGS7cKrM9u6XntK+7gh8Q= +github.com/Flagsmith/flagsmith-go-api-client v0.10.0 h1:6FoNU1JE3GI44dnIzUJ6pksVzl49et2OwKckB/luCfc= +github.com/Flagsmith/flagsmith-go-api-client v0.10.0/go.mod h1:T+Vcd9tL6TxqHovTzoy9V1rGS7cKrM9u6XntK+7gh8Q= github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0= github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -25,8 +25,8 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= -github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= +github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= @@ -79,40 +79,42 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= -github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= -github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= -github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= +github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE= +github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg= +github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= +github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ= github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= -github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec= -github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= -github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c= -github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA= -github.com/hashicorp/terraform-plugin-framework v1.11.0 h1:M7+9zBArexHFXDx/pKTxjE6n/2UCXY6b8FIq9ZYhwfE= -github.com/hashicorp/terraform-plugin-framework v1.11.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0 h1:bxZfGo9DIUoLLtHMElsu+zwqI4IsMZQBRRy4iLzZJ8E= -github.com/hashicorp/terraform-plugin-framework-validators v0.13.0/go.mod h1:wGeI02gEhj9nPANU62F2jCaHjXulejm/X+af4PdZaNo= -github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= -github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWSYfWEOWnylFhYQIoys= +github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= +github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= +github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= +github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= +github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 h1:wyKCCtn6pBBL46c1uIIBNUOWlNfYXfXpVo16iDyLp8Y= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0/go.mod h1:B0Al8NyYVr8Mp/KLwssKXG1RqnTk7FySqSn4fRuLNgw= github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= @@ -168,8 +170,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -197,28 +199,28 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= +github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= -github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= -github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -227,14 +229,14 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -251,16 +253,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -270,29 +272,29 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=