From 0cef57e69f615518ed99e5e3bb28de6f530b7fb1 Mon Sep 17 00:00:00 2001 From: Ivan Bakalov Date: Thu, 7 Sep 2023 15:58:54 +0700 Subject: [PATCH] Revert (#142) Manage contact for registered domains (#149) --- .github/workflows/test.yaml | 6 - CHANGELOG.md | 2 - docs/data-sources/registrant_change_check.md | 59 ------- docs/resources/registered_domain_contact.md | 76 --------- internal/consts/provider.go | 19 +-- .../registrant_change_check_data_source.go | 159 ------------------ ...egistrant_change_check_data_source_test.go | 44 ----- internal/framework/provider/provider.go | 3 - .../resources/registered_domain/common.go | 23 +-- .../registered_domain/resource_test.go | 32 ---- .../resources/registered_domain/update.go | 12 +- .../registered_domain_contact/common.go | 82 --------- .../registered_domain_contact/configure.go | 29 ---- .../registered_domain_contact/create.go | 107 ------------ .../registered_domain_contact/delete.go | 22 --- .../registered_domain_contact/import.go | 31 ---- .../registered_domain_contact/modifiers.go | 46 ----- .../modifiers_test.go | 100 ----------- .../registered_domain_contact/read.go | 38 ----- .../resource_test.go | 140 --------------- .../registered_domain_contact/schema.go | 145 ---------------- .../registered_domain_contact/update.go | 89 ---------- 22 files changed, 19 insertions(+), 1245 deletions(-) delete mode 100644 docs/data-sources/registrant_change_check.md delete mode 100644 docs/resources/registered_domain_contact.md delete mode 100644 internal/framework/datasources/registrant_change_check_data_source.go delete mode 100644 internal/framework/datasources/registrant_change_check_data_source_test.go delete mode 100644 internal/framework/resources/registered_domain_contact/common.go delete mode 100644 internal/framework/resources/registered_domain_contact/configure.go delete mode 100644 internal/framework/resources/registered_domain_contact/create.go delete mode 100644 internal/framework/resources/registered_domain_contact/delete.go delete mode 100644 internal/framework/resources/registered_domain_contact/import.go delete mode 100644 internal/framework/resources/registered_domain_contact/modifiers.go delete mode 100644 internal/framework/resources/registered_domain_contact/modifiers_test.go delete mode 100644 internal/framework/resources/registered_domain_contact/read.go delete mode 100644 internal/framework/resources/registered_domain_contact/resource_test.go delete mode 100644 internal/framework/resources/registered_domain_contact/schema.go delete mode 100644 internal/framework/resources/registered_domain_contact/update.go diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 538cc748..a343a65d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -66,16 +66,12 @@ jobs: include: - terraform: '1.0.*' domain: 'dnsimple-1-0-terraform.bio' - registrant_change_domain: '6xjh9macv560eydj0frnloi0v1sgz1i1wcxsytjqt9pmo4y8vq21n2h8sqm4zu.eu' - terraform: '1.1.*' domain: 'dnsimple-1-1-terraform.bio' - registrant_change_domain: '6e640p3gc3yoh1szlntwhxvkk23f8jo8q7a64kuoghepq0q77iyg0nyqnc7nap.eu' - terraform: '1.2.*' domain: 'dnsimple-1-2-terraform.bio' - registrant_change_domain: '56gz94oqngp5xb82a04ugewpbv80hqj72kc8p3o3gd550esemiv2bzhjhoihs8.eu' - terraform: '1.4.*' domain: 'dnsimple-1-4-terraform.bio' - registrant_change_domain: '3177iktacmv2bg05lkvgsmpoysq5i1vniu6glxl6kq4picv5lvlj2blexwi6bw.eu' steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 @@ -94,8 +90,6 @@ jobs: DNSIMPLE_TOKEN: ${{ secrets.DNSIMPLE_TOKEN }} DNSIMPLE_DOMAIN: ${{ matrix.domain }} DNSIMPLE_CONTACT_ID: ${{ secrets.DNSIMPLE_CONTACT_ID }} - DNSIMPLE_REGISTRANT_CHANGE_DOMAIN: ${{ matrix.registrant_change_domain }} - DNSIMPLE_REGISTRANT_CHANGE_CONTACT_ID: 10854 run: go test -v -cover ./internal/... -timeout 15m timeout-minutes: 10 diff --git a/CHANGELOG.md b/CHANGELOG.md index 93e6fa23..34290e54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,6 @@ FEATURES: -- **New Resource:** `dnsimple_registered_domain_contact` (dnsimple/terraform-provider-dnsimple#142) -- **New Data Source:** `dnsimple_registrant_change_check` (dnsimple/terraform-provider-dnsimple#142) - **Updated Resource:** `dnsimple_registered_domain` now supports `transfer_lock_enabled` argument which you can use to manage the domain transfer lock state of your registered domains (dnsimple/terraform-provider-dnsimple#143) ## 1.1.2 diff --git a/docs/data-sources/registrant_change_check.md b/docs/data-sources/registrant_change_check.md deleted file mode 100644 index 7f36c959..00000000 --- a/docs/data-sources/registrant_change_check.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -page_title: "DNSimple: dnsimple_registrant_change_check" ---- - -# dnsimple\_registrant_change_check - -Get information on the requirements of a registrant change. - --> **Note:** The registrant change API is currently in developer preview and is subject to change. - -# Example Usage - -Get registrant change requirements for the `dnsimple.com` domain and the contact with ID `1234`: - -```hcl -data "dnsimple_registrant_change_check" "example" { - domain_id = "dnsimple.com" - contact_id = "1234" -} -``` - -# Argument Reference - -The following arguments are supported: - -* `domain_id` - (Required) The name or ID of the domain. -* `contact_id` - (Required) The ID of the contact you are planning to change to. - -# Attributes Reference - -The following additional attributes are exported: - -* `contact_id` - The ID of the contact you are planning to change to. -* `domain_id` - The name or ID of the domain. -* `extended_attributes` - (List) A list of extended attributes that are required for the registrant change. (see [below for nested schema](#nestedblock--extended_attributes)) -* `registry_owner_change` - (Boolean) Whether the registrant change is going to result in an owner change at the registry. - - - -### Nested Schema for `extended_attributes` - -Attributes Reference: - -- `name` (String) - The name of the extended attribute. e.g. `x-au-registrant-id-type` -- `description` (String) - The description of the extended attribute. -- `required` (Boolean) - Whether the extended attribute is required. -- `options` (List) - A list of options for the extended attribute. (see [below for nested schema](#nestedblock--options)) - - - -### Nested Schema for `extended_attributes.options` - -Attributes Reference: - -- `title` (String) - The human readable title of the option. e.g. `Australian Company Number (ACN)` -- `value` (String) - The value of the option. -- `description` (String) - The description of the option. - - diff --git a/docs/resources/registered_domain_contact.md b/docs/resources/registered_domain_contact.md deleted file mode 100644 index f677f364..00000000 --- a/docs/resources/registered_domain_contact.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -page_title: "DNSimple: dnsimple_registered_domain_contact" ---- - -# dnsimple\_registered\_domain\_contact - -Provides a way to manage your registered domain's contact at DNSimple. - --> **Note:** The registrant change API is currently in developer preview and is subject to change. - -## Example Usage - -```hcl -resource "dnsimple_contact" "alice_main" { - label = "Alice Appleseed" - first_name = "Alice Main" - last_name = "Appleseed" - organization_name = "Contoso" - job_title = "Manager" - address1 = "Level 1, 2 Main St" - address2 = "Marsfield" - city = "San Francisco" - state_province = "California" - postal_code = "90210" - country = "US" - phone = "+1401239523" - fax = "+1849491024" - email = "apple@contoso.com" -} - -resource "dnsimple_registered_domain_contact" "appleseed_bio" { - domain_id = "appleseed.bio" - contact_id = dnsimple_contact.alice_main.id - - extended_attributes = { - "bio_agree" = "I Agree" - } -} -``` - -## Argument Reference - -The following argument(s) are supported: - -* `domain_id` - (Required) The domain name or id for which the contact should be updated -* `contact_id` - (Required) The ID of the new contact -* `extended_attributes` - (Optional) A map of extended attributes to be set for the domain registration. To see if there are any required extended attributes for the contact change. You can use the `dnsimple_registrant_change_check` data source to check if there are any required extended attributes for the contact change. (see [data source](../data-sources/registrant_change_check.md)) -* `timeouts` - (Optional) (see [below for nested schema](#nestedblock--timeouts)) - -# Attributes Reference - -- `id` - The ID of this resource. -- `account_id` - The account ID that owns the domain. -- `state` - The state of the registrant change. -* `registry_owner_change` - (Boolean) Whether the registrant change has resulted in an owner change at the registry. -* `irt_lock_lifted_by` - (String) The date when the Inter-Registrar Transfer (IRT) lock will/was lifted. - - - - -### Nested Schema for `timeouts` - -Optional: - -- `create` (String) - The timeout for the read operation e.g. `5m` -- `update` (String) - The timeout for the read operation e.g. `5m` - -## Import - -DNSimple registrant change resource can be imported using its ID. - -**Importing registrant change with ID 1234** - -```bash -terraform import dnsimple_registered_domain_contact.resource_name 1234 -``` diff --git a/internal/consts/provider.go b/internal/consts/provider.go index ad90027a..cfe064e4 100644 --- a/internal/consts/provider.go +++ b/internal/consts/provider.go @@ -1,16 +1,11 @@ package consts const ( - BaseURLSandbox = "https://api.sandbox.dnsimple.com" - DomainStateRegistered = "registered" - DomainStateHosted = "hosted" - DomainStateNew = "new" - DomainStateFailed = "failed" - DomainStateCancelling = "cancelling" - DomainStateCancelled = "cancelled" - RegistrantChangeStateNew = "new" - RegistrantChangeStatePending = "pending" - RegistrantChangeStateCompleted = "completed" - RegistrantChangeStateCancelling = "cancelling" - RegistrantChangeStateCancelled = "cancelled" + BaseURLSandbox = "https://api.sandbox.dnsimple.com" + DomainStateRegistered = "registered" + DomainStateHosted = "hosted" + DomainStateNew = "new" + DomainStateFailed = "failed" + DomainStateCancelling = "cancelling" + DomainStateCancelled = "cancelled" ) diff --git a/internal/framework/datasources/registrant_change_check_data_source.go b/internal/framework/datasources/registrant_change_check_data_source.go deleted file mode 100644 index 7362fe83..00000000 --- a/internal/framework/datasources/registrant_change_check_data_source.go +++ /dev/null @@ -1,159 +0,0 @@ -package datasources - -import ( - "context" - "fmt" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/datasource" - "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/common" -) - -// Ensure provider defined types fully satisfy framework interfaces. -var _ datasource.DataSource = &RegistrantChangeCheckDataSource{} - -func NewRegistrantChangeCheckDataSource() datasource.DataSource { - return &RegistrantChangeCheckDataSource{} -} - -// RegistrantChangeCheckDataSource defines the data source implementation. -type RegistrantChangeCheckDataSource struct { - config *common.DnsimpleProviderConfig -} - -// RegistrantChangeCheckDataSourceModel describes the data source data model. -type RegistrantChangeCheckDataSourceModel struct { - Id types.String `tfsdk:"id"` - ContactId types.String `tfsdk:"contact_id"` - DomainId types.String `tfsdk:"domain_id"` - ExtendedAttributes []ExtendedAttribute `tfsdk:"extended_attributes"` - RegistryOwnerChange types.Bool `tfsdk:"registry_owner_change"` -} - -type ExtendedAttribute struct { - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - Required types.Bool `tfsdk:"required"` - Options []ExtendedAttributeOption `tfsdk:"options"` -} - -type ExtendedAttributeOption struct { - Title types.String `tfsdk:"title"` - Value types.String `tfsdk:"value"` - Description types.String `tfsdk:"description"` -} - -func (d *RegistrantChangeCheckDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_registrant_change_check" -} - -func (d *RegistrantChangeCheckDataSource) 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: "DNSimple registrant change check data source", - - Attributes: map[string]schema.Attribute{ - "id": common.IDStringAttribute(), - "contact_id": schema.StringAttribute{ - MarkdownDescription: "DNSimple contact ID for which the registrant change check is being performed", - Required: true, - }, - "domain_id": schema.StringAttribute{ - MarkdownDescription: "DNSimple domain ID for which the registrant change check is being performed", - Required: true, - }, - "extended_attributes": schema.ListAttribute{ - MarkdownDescription: "Extended attributes for the registrant change", - ElementType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "name": types.StringType, - "description": types.StringType, - "required": types.BoolType, - "options": types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "title": types.StringType, - "value": types.StringType, - "description": types.StringType, - }, - }, - }, - }, - }, - Computed: true, - }, - "registry_owner_change": schema.BoolAttribute{ - MarkdownDescription: "True if the registrant change will result in a registry owner change", - Computed: true, - }, - }, - } -} - -func (d *RegistrantChangeCheckDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. - if req.ProviderData == nil { - return - } - - config, ok := req.ProviderData.(*common.DnsimpleProviderConfig) - - if !ok { - resp.Diagnostics.AddError( - "Unexpected Resource Configure Type", - fmt.Sprintf("Expected *provider.DnsimpleProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), - ) - - return - } - - d.config = config -} - -func (d *RegistrantChangeCheckDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - var data RegistrantChangeCheckDataSourceModel - - // Read Terraform configuration data into the model - resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - requestInput := dnsimple.CheckRegistrantChangeInput{ - ContactId: data.ContactId.ValueString(), - DomainId: data.DomainId.ValueString(), - } - - response, err := d.config.Client.Registrar.CheckRegistrantChange(ctx, d.config.AccountID, &requestInput) - if err != nil { - resp.Diagnostics.AddError( - "failed to check registrant change", - err.Error(), - ) - return - } - - contactIdString := fmt.Sprintf("%d", response.Data.ContactId) - data.Id = types.StringValue(data.DomainId.ValueString() + ":" + contactIdString) - data.ContactId = types.StringValue(contactIdString) - data.ExtendedAttributes = make([]ExtendedAttribute, len(response.Data.ExtendedAttributes)) - for i, extendedAttribute := range response.Data.ExtendedAttributes { - data.ExtendedAttributes[i].Name = types.StringValue(extendedAttribute.Name) - data.ExtendedAttributes[i].Description = types.StringValue(extendedAttribute.Description) - data.ExtendedAttributes[i].Required = types.BoolValue(extendedAttribute.Required) - data.ExtendedAttributes[i].Options = make([]ExtendedAttributeOption, len(extendedAttribute.Options)) - for j, option := range extendedAttribute.Options { - data.ExtendedAttributes[i].Options[j].Title = types.StringValue(option.Title) - data.ExtendedAttributes[i].Options[j].Value = types.StringValue(option.Value) - data.ExtendedAttributes[i].Options[j].Description = types.StringValue(option.Description) - } - } - data.RegistryOwnerChange = types.BoolValue(response.Data.RegistryOwnerChange) - - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} diff --git a/internal/framework/datasources/registrant_change_check_data_source_test.go b/internal/framework/datasources/registrant_change_check_data_source_test.go deleted file mode 100644 index 9dcafd69..00000000 --- a/internal/framework/datasources/registrant_change_check_data_source_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package datasources_test - -import ( - "fmt" - "os" - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/provider" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/test_utils" -) - -func TestAccRegistrantChangeCheckDataSource(t *testing.T) { - // Get convert the contact id to int - contactId := os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_CONTACT_ID") - domainName := os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_DOMAIN") - resourceName := "data.dnsimple_registrant_change_check.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { test_utils.TestAccPreCheck(t) }, - ProtoV6ProviderFactories: provider.NewProto6ProviderFactory(), - Steps: []resource.TestStep{ - // Read testing - { - Config: testAccRegistrantChangeCheckDataSourceConfig(contactId, domainName), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "contact_id", contactId), - resource.TestCheckResourceAttr(resourceName, "domain_id", domainName), - resource.TestCheckResourceAttrSet(resourceName, "extended_attributes.#"), - resource.TestCheckResourceAttrSet(resourceName, "registry_owner_change"), - resource.TestCheckResourceAttrSet(resourceName, "id"), - ), - }, - }, - }) -} - -func testAccRegistrantChangeCheckDataSourceConfig(contactId, domainName string) string { - return fmt.Sprintf(` -data "dnsimple_registrant_change_check" "test" { - contact_id = %[1]q - domain_id = %[2]q -}`, contactId, domainName) -} diff --git a/internal/framework/provider/provider.go b/internal/framework/provider/provider.go index 07f4bbcd..719ecf4d 100644 --- a/internal/framework/provider/provider.go +++ b/internal/framework/provider/provider.go @@ -17,7 +17,6 @@ import ( "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/datasources" "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/resources" "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/resources/registered_domain" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/resources/registered_domain_contact" "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/utils" "golang.org/x/oauth2" ) @@ -172,7 +171,6 @@ func (p *DnsimpleProvider) Resources(ctx context.Context) []func() resource.Reso resources.NewContactResource, resources.NewDomainDelegationResource, resources.NewDomainResource, - registered_domain_contact.NewRegisteredDomainContactResource, registered_domain.NewRegisteredDomainResource, resources.NewDsRecordResource, resources.NewEmailForwardResource, @@ -186,7 +184,6 @@ func (p *DnsimpleProvider) DataSources(ctx context.Context) []func() datasource. return []func() datasource.DataSource{ datasources.NewCertificateDataSource, datasources.NewZoneDataSource, - datasources.NewRegistrantChangeCheckDataSource, } } diff --git a/internal/framework/resources/registered_domain/common.go b/internal/framework/resources/registered_domain/common.go index e69e3ba9..64b5012e 100644 --- a/internal/framework/resources/registered_domain/common.go +++ b/internal/framework/resources/registered_domain/common.go @@ -132,8 +132,6 @@ func (r *RegisteredDomainResource) setTransferLock(ctx context.Context, data *Re } func (r *RegisteredDomainResource) updateModelFromAPIResponse(ctx context.Context, data *RegisteredDomainResourceModel, domainRegistration *dnsimple.DomainRegistration, domain *dnsimple.Domain, dnssec *dnsimple.Dnssec, transferLock *dnsimple.DomainTransferLock) diag.Diagnostics { - diags := diag.Diagnostics{} - if domainRegistration != nil { domainRegistrationObject, diags := r.domainRegistrationAPIResponseToObject(ctx, domainRegistration) @@ -151,24 +149,7 @@ func (r *RegisteredDomainResource) updateModelFromAPIResponse(ctx context.Contex data.State = types.StringValue(domain.State) data.UnicodeName = types.StringValue(domain.UnicodeName) data.AccountId = types.Int64Value(domain.AccountID) - - // If the contact_id is null, we need to set it to the registrant_id from the domain - // this can happen when the contact_id is not set in the config, and the domain is imported - if data.ContactId.IsNull() { - data.ContactId = types.Int64Value(domain.RegistrantID) - } - - if data.ContactId.ValueInt64() != domain.RegistrantID { - diags.AddWarning( - fmt.Sprintf(`The contact_id does not match your local state and what you have at DNSimple for: domain=%s config_contact_id=%d remote_contact_id=%d. -This can be due to a contact change that has not been reflected in your local config, -if you have changed your local config due to a registered_domain_contact change. -It may be that the contact change has not yet been completed. -Until the change has completed successfully you will continue to receive this warning.`, data.Name.ValueString(), data.ContactId.ValueInt64(), domain.RegistrantID), - "update plan's resource contact_id to match remote state", - ) - } - + data.ContactId = types.Int64Value(domain.RegistrantID) data.ExpiresAt = types.StringValue(domain.ExpiresAt) data.Name = types.StringValue(domain.Name) } @@ -181,7 +162,7 @@ Until the change has completed successfully you will continue to receive this wa data.TransferLockEnabled = types.BoolValue(transferLock.Enabled) } - return diags + return nil } func (r *RegisteredDomainResource) updateModelFromAPIResponsePartialCreate(ctx context.Context, data *RegisteredDomainResourceModel, domainRegistration *dnsimple.DomainRegistration, domain *dnsimple.Domain) *diag.Diagnostics { diff --git a/internal/framework/resources/registered_domain/resource_test.go b/internal/framework/resources/registered_domain/resource_test.go index 0a77649e..8648c639 100644 --- a/internal/framework/resources/registered_domain/resource_test.go +++ b/internal/framework/resources/registered_domain/resource_test.go @@ -181,38 +181,6 @@ func TestAccRegisteredDomainResource_ImportedWithDomainOnly(t *testing.T) { }) } -func TestAccRegisteredDomainResource_WithContactChange(t *testing.T) { - domainName := os.Getenv("DNSIMPLE_DOMAIN") - resourceName := "dnsimple_registered_domain.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheckRegisteredDomain(t) }, - ProtoV6ProviderFactories: test_utils.TestAccProtoV6ProviderFactories(), - Steps: []resource.TestStep{ - { - ResourceName: resourceName, - Config: testAccRegisteredDomainResourceConfig(domainName, 1234), - ImportStateId: domainName, - ImportState: true, - ImportStateVerify: false, - ImportStatePersist: true, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", domainName), - resource.TestCheckResourceAttr(resourceName, "state", "registered"), - resource.TestCheckResourceAttr(resourceName, "contact_id", "1234"), - resource.TestCheckNoResourceAttr(resourceName, "domain_registration"), - ), - }, - { - Config: testAccRegisteredDomainResourceConfig(domainName, 5678), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "contact_id", "5678"), - ), - }, - }, - }) -} - func testAccPreCheckRegisteredDomain(t *testing.T) { test_utils.TestAccPreCheck(t) if os.Getenv("DNSIMPLE_CONTACT_ID") == "" { diff --git a/internal/framework/resources/registered_domain/update.go b/internal/framework/resources/registered_domain/update.go index 55b610d6..b296add7 100644 --- a/internal/framework/resources/registered_domain/update.go +++ b/internal/framework/resources/registered_domain/update.go @@ -34,6 +34,14 @@ func (r *RegisteredDomainResource) Update(ctx context.Context, req resource.Upda return } + if planData.ContactId.ValueInt64() != stateData.ContactId.ValueInt64() { + resp.Diagnostics.AddError( + fmt.Sprintf("contact_id change not supported: %s, %d", planData.Name.ValueString(), planData.Id.ValueInt64()), + "contact_id change not supported by the DNSimple API", + ) + return + } + if !planData.ExtendedAttributes.Equal(stateData.ExtendedAttributes) { resp.Diagnostics.AddError( fmt.Sprintf("extended_attributes change not supported: %s, %d", planData.Name.ValueString(), planData.Id.ValueInt64()), @@ -169,8 +177,8 @@ func (r *RegisteredDomainResource) Update(ctx context.Context, req resource.Upda } else { diags = r.updateModelFromAPIResponse(ctx, planData, domainRegistrationResponse.Data, domainResponse.Data, dnssecResponse.Data, transferLockResponse.Data) } - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { + if diags != nil && diags.HasError() { + resp.Diagnostics.Append(diags...) return } diff --git a/internal/framework/resources/registered_domain_contact/common.go b/internal/framework/resources/registered_domain_contact/common.go deleted file mode 100644 index 28363dd8..00000000 --- a/internal/framework/resources/registered_domain_contact/common.go +++ /dev/null @@ -1,82 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "fmt" - "time" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/common" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/utils" -) - -const ( - RegistrantChangeConverged = "registrant_change_converged" - RegistrantChangeConvergenceTimeout = "registrant_change_converged_timeout" - RegistrantChangeFailed = "registrant_change_failed" -) - -func (r *RegisteredDomainContactResource) updateModelFromAPIResponse(registrantChange *dnsimple.RegistrantChange, data *RegisteredDomainContactResourceModel) { - data.Id = types.Int64Value(int64(registrantChange.Id)) - data.AccountId = types.Int64Value(int64(registrantChange.AccountId)) - data.ContactId = types.Int64Value(int64(registrantChange.ContactId)) - data.State = types.StringValue(registrantChange.State) - data.RegistryOwnerChange = types.BoolValue(registrantChange.RegistryOwnerChange) - data.IrtLockLiftedBy = types.StringValue(registrantChange.IrtLockLiftedBy) -} - -func getTimeouts(ctx context.Context, model *RegisteredDomainContactResourceModel) (*common.Timeouts, diag.Diagnostics) { - timeouts := &common.Timeouts{} - diags := model.Timeouts.As(ctx, timeouts, basetypes.ObjectAsOptions{UnhandledNullAsEmpty: true, UnhandledUnknownAsEmpty: true}) - - return timeouts, diags -} - -func tryToConvergeRegistration(ctx context.Context, data *RegisteredDomainContactResourceModel, diagnostics *diag.Diagnostics, r *RegisteredDomainContactResource, registrantChangeId int) (string, error) { - timeouts, diags := getTimeouts(ctx, data) - diagnostics.Append(diags...) - if diagnostics.HasError() { - return RegistrantChangeFailed, nil - } - - err := utils.RetryWithTimeout(ctx, func() (error, bool) { - registrantChangeResponse, err := r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, registrantChangeId) - - if err != nil { - return err, false - } - - if registrantChangeResponse.Data.State == consts.RegistrantChangeStateCancelled || registrantChangeResponse.Data.State == consts.RegistrantChangeStateCancelling { - diagnostics.AddError( - fmt.Sprintf("failed to change registrant for DNSimple Domain: %s, registrant change id: %d", data.DomainId.ValueString(), registrantChangeId), - "Registrant change was cancelled, please investigate why this happened. You can refer to our support article https://support.dnsimple.com/articles/changing-domain-contact/ to get started and if you need assistance, please contact support at support@dnsimple.com.", - ) - return nil, true - } - - if registrantChangeResponse.Data.State != consts.DomainStateRegistered { - tflog.Info(ctx, fmt.Sprintf("[RETRYING] Registrant change is not complete, current state: %s", registrantChangeResponse.Data.State)) - - return fmt.Errorf("Registrant change is not complete, current state: %s. You can try to run terraform again to try and converge the registrant change", registrantChangeResponse.Data.State), false - } - - return nil, false - }, timeouts.CreateDuration(), 20*time.Second) - - if diagnostics.HasError() { - // If we have diagnostic errors, we suspended the retry loop because the domain is in a bad state, and cannot converge. - return RegistrantChangeFailed, nil - } - - if err != nil { - // If we have an error, it means the retry loop timed out, and we cannot converge during this run. - return RegistrantChangeConvergenceTimeout, err - } - - return RegistrantChangeConverged, nil -} diff --git a/internal/framework/resources/registered_domain_contact/configure.go b/internal/framework/resources/registered_domain_contact/configure.go deleted file mode 100644 index f20aea3a..00000000 --- a/internal/framework/resources/registered_domain_contact/configure.go +++ /dev/null @@ -1,29 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/common" -) - -func (r *RegisteredDomainContactResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. - if req.ProviderData == nil { - return - } - - config, ok := req.ProviderData.(*common.DnsimpleProviderConfig) - - if !ok { - resp.Diagnostics.AddError( - "Unexpected Resource Configure Type", - fmt.Sprintf("Expected *provider.DnsimpleProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), - ) - - return - } - - r.config = config -} diff --git a/internal/framework/resources/registered_domain_contact/create.go b/internal/framework/resources/registered_domain_contact/create.go deleted file mode 100644 index 9eab755b..00000000 --- a/internal/framework/resources/registered_domain_contact/create.go +++ /dev/null @@ -1,107 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "errors" - "fmt" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/utils" -) - -func (r *RegisteredDomainContactResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var data *RegisteredDomainContactResourceModel - - // Read Terraform plan data into the model - resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - registrantChangeAttributes := dnsimple.CreateRegistrantChangeInput{ - DomainId: data.DomainId.ValueString(), - ContactId: fmt.Sprintf("%d", data.ContactId.ValueInt64()), - } - - if !data.ExtendedAttributes.IsNull() { - extendedAttrs := make(map[string]string) - diags := data.ExtendedAttributes.ElementsAs(ctx, &extendedAttrs, false) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } - registrantChangeAttributes.ExtendedAttributes = extendedAttrs - } - - registrantChangeResponse, err := r.config.Client.Registrar.CreateRegistrantChange(ctx, r.config.AccountID, ®istrantChangeAttributes) - - if err != nil { - var errorResponse *dnsimple.ErrorResponse - if errors.As(err, &errorResponse) { - resp.Diagnostics.Append(utils.AttributeErrorsToDiagnostics(errorResponse)...) - return - } - - resp.Diagnostics.AddError( - "failed to create DNSimple registrant change", - err.Error(), - ) - return - } - - if registrantChangeResponse.Data.State != consts.RegistrantChangeStateCompleted { - if registrantChangeResponse.Data.State == consts.RegistrantChangeStateCancelled || registrantChangeResponse.Data.State == consts.RegistrantChangeStateCancelling { - resp.Diagnostics.AddError( - fmt.Sprintf("failed to create DNSimple registrant change current state: %s", registrantChangeResponse.Data.State), - "", - ) - return - } - - // Registrant change has been created, but is not yet completed - if registrantChangeResponse.Data.State == consts.RegistrantChangeStateNew || registrantChangeResponse.Data.State == consts.RegistrantChangeStatePending { - convergenceState, err := tryToConvergeRegistration(ctx, data, &resp.Diagnostics, r, registrantChangeResponse.Data.Id) - if convergenceState == RegistrantChangeFailed { - // Response is already populated with the error we can safely return - return - } - - if convergenceState == RegistrantChangeConvergenceTimeout { - // We attempted to converge on the registrant change, but the registrant change was not ready - // user needs to run terraform again to try and converge the registrant change - - // Update the data with the current registrant change - r.updateModelFromAPIResponse(registrantChangeResponse.Data, data) - - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) - - // Exit with warning to prevent the state from being tainted - resp.Diagnostics.AddWarning( - "failed to converge on registrant change", - err.Error(), - ) - return - } - - registrantChangeResponse, err = r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, int(data.Id.ValueInt64())) - - if err != nil { - resp.Diagnostics.AddError( - fmt.Sprintf("failed to read DNSimple Registrant Change for: %s, %d", data.DomainId.ValueString(), data.Id.ValueInt64()), - err.Error(), - ) - return - } - } - } - - // Registrant change was successful, we can now update the resource model - r.updateModelFromAPIResponse(registrantChangeResponse.Data, data) - - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} diff --git a/internal/framework/resources/registered_domain_contact/delete.go b/internal/framework/resources/registered_domain_contact/delete.go deleted file mode 100644 index 1e4caf6c..00000000 --- a/internal/framework/resources/registered_domain_contact/delete.go +++ /dev/null @@ -1,22 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-log/tflog" -) - -func (r *RegisteredDomainContactResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var data *RegisteredDomainContactResourceModel - - // Read Terraform prior state data into the model - resp.Diagnostics.Append(req.State.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - tflog.Warn(ctx, fmt.Sprintf("Removing DNSimple Registered Domain Contact from Terraform state only: %s, %d", data.DomainId.ValueString(), data.Id.ValueInt64())) -} diff --git a/internal/framework/resources/registered_domain_contact/import.go b/internal/framework/resources/registered_domain_contact/import.go deleted file mode 100644 index 41e6fed0..00000000 --- a/internal/framework/resources/registered_domain_contact/import.go +++ /dev/null @@ -1,31 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "strconv" - - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/resource" -) - -func (r *RegisteredDomainContactResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - id, err := strconv.Atoi(req.ID) - if err != nil { - resp.Diagnostics.AddError("Invalid ID", "The ID must be an integer") - return - } - - registrantChangeResponse, err := r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, id) - if err != nil { - resp.Diagnostics.AddError( - "Failed to read DNSimple Registrant Change", - err.Error(), - ) - return - } - - domainId := strconv.Itoa(registrantChangeResponse.Data.DomainId) - - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), int64(id))...) - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("domain_id"), domainId)...) -} diff --git a/internal/framework/resources/registered_domain_contact/modifiers.go b/internal/framework/resources/registered_domain_contact/modifiers.go deleted file mode 100644 index 71f20d70..00000000 --- a/internal/framework/resources/registered_domain_contact/modifiers.go +++ /dev/null @@ -1,46 +0,0 @@ -package registered_domain_contact - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" -) - -type registrantChangeState struct { -} - -// RegistrantChangeState return a object plan modifier that sets the specified value if the planned value is Null. -func RegistrantChangeState() planmodifier.String { - return registrantChangeState{} -} - -func (m registrantChangeState) Description(context.Context) string { - return "If the registrant change state is not completed, set it to completed. Unless the state is a cancelled or cancelling state" -} - -func (m registrantChangeState) MarkdownDescription(ctx context.Context) string { - return m.Description(ctx) -} - -func (m registrantChangeState) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { - if !req.ConfigValue.IsNull() || req.PlanValue.IsUnknown() || req.PlanValue.IsNull() { - return - } - - state := req.PlanValue.ValueString() - - // If the registrant change state is a cancelled state, do not attempt to update it - if state == consts.RegistrantChangeStateCancelling || state == consts.RegistrantChangeStateCancelled { - return - } - - // If the registrant change state is not completed, set it to completed - // this will trigger a plan change and result in an update so we can attempt to sync - if state == consts.RegistrantChangeStateCompleted { - return - } - - resp.PlanValue = types.StringValue(consts.RegistrantChangeStateCompleted) -} diff --git a/internal/framework/resources/registered_domain_contact/modifiers_test.go b/internal/framework/resources/registered_domain_contact/modifiers_test.go deleted file mode 100644 index 93f4e065..00000000 --- a/internal/framework/resources/registered_domain_contact/modifiers_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package registered_domain_contact_test - -import ( - "context" - "testing" - - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/stretchr/testify/assert" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/resources/registered_domain_contact" -) - -func TestRegistrantChangeStateModifier(t *testing.T) { - t.Parallel() - - type testCase struct { - skipDomainRegistration bool - plannedValue types.String - currentValue types.String - expectedValue types.String - expectError bool - } - tests := map[string]testCase{ - "imported has no plan and state and is unkown": { - plannedValue: types.StringUnknown(), - currentValue: types.StringNull(), - expectedValue: types.StringNull(), - }, - "imported has no plan and is null": { - plannedValue: types.StringNull(), - currentValue: types.StringNull(), - expectedValue: types.StringNull(), - }, - "not completed has plan and state": { - plannedValue: types.StringValue(consts.RegistrantChangeStateNew), - currentValue: types.StringValue(consts.RegistrantChangeStateNew), - expectedValue: types.StringValue(consts.RegistrantChangeStateCompleted), - }, - "state null but plan is known": { - plannedValue: types.StringValue(consts.RegistrantChangeStateNew), - currentValue: types.StringNull(), - expectedValue: types.StringValue(consts.RegistrantChangeStateCompleted), - }, - "null planned": { - plannedValue: types.StringNull(), - currentValue: types.StringValue(consts.RegistrantChangeStateCancelled), - expectedValue: types.StringNull(), - }, - "state cancelled": { - plannedValue: types.StringValue(consts.RegistrantChangeStateCancelled), - currentValue: types.StringValue(consts.RegistrantChangeStateCancelled), - expectedValue: types.StringValue(consts.RegistrantChangeStateCancelled), - }, - "state cancelling": { - plannedValue: types.StringValue(consts.RegistrantChangeStateCancelling), - currentValue: types.StringValue(consts.RegistrantChangeStateCancelling), - expectedValue: types.StringValue(consts.RegistrantChangeStateCancelling), - }, - "on create": { - plannedValue: types.StringNull(), - currentValue: types.StringNull(), - expectedValue: types.StringNull(), - }, - } - - for name, test := range tests { - name, test := name, test - t.Run(name, func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - request := planmodifier.StringRequest{ - Path: path.Root("test"), - PlanValue: test.plannedValue, - StateValue: test.currentValue, - } - - if test.skipDomainRegistration { - request.Private.SetKey(ctx, "skipDomainRegistration", []byte("true")) - } - - response := planmodifier.StringResponse{ - PlanValue: request.PlanValue, - } - registered_domain_contact.RegistrantChangeState().PlanModifyString(ctx, request, &response) - - if !response.Diagnostics.HasError() && test.expectError { - t.Fatal("expected error, got no error") - } - - if response.Diagnostics.HasError() && !test.expectError { - t.Fatalf("got unexpected error: %s", response.Diagnostics) - } - - assert.Equal(t, test.expectedValue.ValueString(), response.PlanValue.ValueString()) - }) - } -} diff --git a/internal/framework/resources/registered_domain_contact/read.go b/internal/framework/resources/registered_domain_contact/read.go deleted file mode 100644 index 895c0009..00000000 --- a/internal/framework/resources/registered_domain_contact/read.go +++ /dev/null @@ -1,38 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "fmt" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-framework/resource" -) - -func (r *RegisteredDomainContactResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var data *RegisteredDomainContactResourceModel - - // Read Terraform prior state data into the model - resp.Diagnostics.Append(req.State.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - var registrantChangeResponse *dnsimple.RegistrantChangeResponse - var err error - - registrantChangeResponse, err = r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, int(data.Id.ValueInt64())) - - if err != nil { - resp.Diagnostics.AddError( - fmt.Sprintf("failed to read DNSimple Registrant Change Id: %d", data.Id.ValueInt64()), - err.Error(), - ) - return - } - - r.updateModelFromAPIResponse(registrantChangeResponse.Data, data) - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} diff --git a/internal/framework/resources/registered_domain_contact/resource_test.go b/internal/framework/resources/registered_domain_contact/resource_test.go deleted file mode 100644 index a22992ea..00000000 --- a/internal/framework/resources/registered_domain_contact/resource_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package registered_domain_contact_test - -import ( - "context" - "errors" - "fmt" - "os" - "strconv" - "testing" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/test_utils" -) - -var ( - // dnsimpleClient is the DNSimple client used to make API calls during - // acceptance testing. - dnsimpleClient *dnsimple.Client - // testAccAccount is the DNSimple account used to make API calls during - // acceptance testing. - testAccAccount string -) - -func init() { - // If we are running acceptance tests TC_ACC then we initialize the DNSimple client - // with the credentials provided in the environment variables. - dnsimpleClient, testAccAccount = test_utils.LoadDNSimpleTestClient() -} - -func TestAccRegisteredDomainContactResource_WithExtendedAttrs(t *testing.T) { - contactID, err := strconv.Atoi(os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_CONTACT_ID")) - if err != nil { - t.Fatal(err) - } - domainName := os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_DOMAIN") - resourceName := "dnsimple_registered_domain_contact.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheckRegisteredDomainContact(t) }, - ProtoV6ProviderFactories: test_utils.TestAccProtoV6ProviderFactories(), - CheckDestroy: testAccCheckRegisteredDomainContactResourceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccRegisteredDomainContactResourceConfig_WithExtendedAttrs(domainName, contactID), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "id"), - resource.TestCheckResourceAttrSet(resourceName, "state"), - resource.TestCheckResourceAttrSet(resourceName, "registry_owner_change"), - resource.TestCheckResourceAttr(resourceName, "domain_id", domainName), - resource.TestCheckResourceAttr(resourceName, "contact_id", fmt.Sprintf("%d", contactID)), - resource.TestCheckResourceAttr(resourceName, "extended_attributes.x-eu-registrant-citizenship", "bg"), - ), - // We expect the plan to be non-empty because we are creating a registrant change that will not be completed - // and we will attempt to converge it by setting the state to completed - ExpectNonEmptyPlan: true, - }, - { - ResourceName: resourceName, - ImportStateIdFunc: testAccRegisteredDomainImportStateIDFunc(resourceName), - ImportState: true, - ImportStateVerify: false, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "id"), - resource.TestCheckResourceAttrSet(resourceName, "state"), - resource.TestCheckResourceAttrSet(resourceName, "registry_owner_change"), - resource.TestCheckResourceAttrSet(resourceName, "domain_id"), - ), - }, - // Delete testing automatically occurs in TestCase - }, - }) -} - -func testAccPreCheckRegisteredDomainContact(t *testing.T) { - test_utils.TestAccPreCheck(t) - if os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_CONTACT_ID") == "" { - t.Fatal("DNSIMPLE_REGISTRANT_CHANGE_CONTACT_ID must be set for acceptance tests") - } - if os.Getenv("DNSIMPLE_REGISTRANT_CHANGE_DOMAIN") == "" { - t.Fatal("DNSIMPLE_REGISTRANT_CHANGE_DOMAIN must be set for acceptance tests") - } -} - -func testAccRegisteredDomainImportStateIDFunc(resourceName string) resource.ImportStateIdFunc { - return func(s *terraform.State) (string, error) { - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return "", fmt.Errorf("Resource not found: %s", resourceName) - } - - if rs.Primary.Attributes["id"] == "" { - return "", errors.New("No resource Id set") - } - - return rs.Primary.Attributes["id"], nil - } -} - -func testAccCheckRegisteredDomainContactResourceDestroy(state *terraform.State) error { - for _, rs := range state.RootModule().Resources { - if rs.Type != "dnsimple_registered_domain_contact" { - continue - } - - id, err := strconv.Atoi(rs.Primary.Attributes["id"]) - if err != nil { - return err - } - - if rs.Primary.Attributes["state"] == consts.RegistrantChangeStateCompleted || - rs.Primary.Attributes["state"] == consts.RegistrantChangeStateCancelled || - rs.Primary.Attributes["state"] == consts.RegistrantChangeStateCancelling { - continue - } - - _, err = dnsimpleClient.Registrar.DeleteRegistrantChange(context.Background(), testAccAccount, id) - - if err != nil { - return err - } - } - return nil -} - -func testAccRegisteredDomainContactResourceConfig_WithExtendedAttrs(domainName string, contactId int) string { - return fmt.Sprintf(` -resource "dnsimple_registered_domain_contact" "test" { - domain_id = %[1]q - contact_id = %[2]d - extended_attributes = { - "x-eu-registrant-citizenship" = "bg" - } - timeouts = { - create = "40s" - } -}`, domainName, contactId) -} diff --git a/internal/framework/resources/registered_domain_contact/schema.go b/internal/framework/resources/registered_domain_contact/schema.go deleted file mode 100644 index 1ff1f245..00000000 --- a/internal/framework/resources/registered_domain_contact/schema.go +++ /dev/null @@ -1,145 +0,0 @@ -package registered_domain_contact - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/common" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/modifiers" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/validators" -) - -// Ensure the implementation satisfies the expected interfaces. -var ( - _ resource.Resource = &RegisteredDomainContactResource{} - _ resource.ResourceWithConfigure = &RegisteredDomainContactResource{} - _ resource.ResourceWithImportState = &RegisteredDomainContactResource{} -) - -func NewRegisteredDomainContactResource() resource.Resource { - return &RegisteredDomainContactResource{} -} - -// RegisteredDomainContactResource defines the resource implementation. -type RegisteredDomainContactResource struct { - config *common.DnsimpleProviderConfig -} - -// RegisteredDomainContactResourceModel describes the resource data model. -type RegisteredDomainContactResourceModel struct { - Id types.Int64 `tfsdk:"id"` - AccountId types.Int64 `tfsdk:"account_id"` - ContactId types.Int64 `tfsdk:"contact_id"` - DomainId types.String `tfsdk:"domain_id"` - State types.String `tfsdk:"state"` - ExtendedAttributes types.Map `tfsdk:"extended_attributes"` - RegistryOwnerChange types.Bool `tfsdk:"registry_owner_change"` - IrtLockLiftedBy types.String `tfsdk:"irt_lock_lifted_by"` - Timeouts types.Object `tfsdk:"timeouts"` -} - -func (r *RegisteredDomainContactResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_registered_domain_contact" -} - -func (r *RegisteredDomainContactResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "DNSimple registered domain contact resource", - Attributes: map[string]schema.Attribute{ - "id": common.IDInt64Attribute(), - "account_id": schema.Int64Attribute{ - MarkdownDescription: "DNSimple Account ID to which the registrant change belongs to", - Computed: true, - }, - "contact_id": schema.Int64Attribute{ - MarkdownDescription: "DNSimple contact ID for which the registrant change is being performed", - Required: true, - PlanModifiers: []planmodifier.Int64{ - int64planmodifier.RequiresReplace(), - }, - }, - "domain_id": schema.StringAttribute{ - MarkdownDescription: "DNSimple domain ID for which the registrant change is being performed", - Required: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), - }, - }, - "state": schema.StringAttribute{ - MarkdownDescription: "State of the registrant change", - PlanModifiers: []planmodifier.String{ - RegistrantChangeState(), - }, - Computed: true, - Optional: true, - }, - "extended_attributes": schema.MapAttribute{ - MarkdownDescription: "Extended attributes for the registrant change", - ElementType: types.StringType, - Optional: true, - PlanModifiers: []planmodifier.Map{ - mapplanmodifier.RequiresReplaceIfConfigured(), - }, - }, - "registry_owner_change": schema.BoolAttribute{ - MarkdownDescription: "True if the registrant change will result in a registry owner change", - Computed: true, - }, - "irt_lock_lifted_by": schema.StringAttribute{ - MarkdownDescription: "Date when the registrant change lock was lifted for the domain", - Computed: true, - }, - "timeouts": schema.SingleNestedAttribute{ - MarkdownDescription: "Timeouts for operations, given as a parsable string as in `10m` or `30s`.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "create": schema.StringAttribute{ - Optional: true, - Computed: true, - Description: "Create timeout.", - Validators: []validator.String{ - validators.Duration{}, - }, - PlanModifiers: []planmodifier.String{ - modifiers.StringDefaultValue("5m"), - }, - }, - "update": schema.StringAttribute{ - Optional: true, - Computed: true, - Description: "Update timeout.", - Validators: []validator.String{ - validators.Duration{}, - }, - PlanModifiers: []planmodifier.String{ - modifiers.StringDefaultValue("1m"), - }, - }, - "delete": schema.StringAttribute{ - Optional: true, - Computed: true, - Description: "Delete timeout.", - Validators: []validator.String{ - validators.Duration{}, - }, - PlanModifiers: []planmodifier.String{ - modifiers.StringDefaultValue("1m"), - }, - }, - }, - PlanModifiers: []planmodifier.Object{ - objectplanmodifier.UseStateForUnknown(), - }, - }, - }, - } -} diff --git a/internal/framework/resources/registered_domain_contact/update.go b/internal/framework/resources/registered_domain_contact/update.go deleted file mode 100644 index 308b782b..00000000 --- a/internal/framework/resources/registered_domain_contact/update.go +++ /dev/null @@ -1,89 +0,0 @@ -package registered_domain_contact - -import ( - "context" - "errors" - "fmt" - - "github.com/dnsimple/dnsimple-go/dnsimple" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/consts" - "github.com/terraform-providers/terraform-provider-dnsimple/internal/framework/utils" -) - -func (r *RegisteredDomainContactResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var ( - configData *RegisteredDomainContactResourceModel - planData *RegisteredDomainContactResourceModel - stateData *RegisteredDomainContactResourceModel - ) - - resp.Diagnostics.Append(req.Plan.Get(ctx, &planData)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(req.State.Get(ctx, &stateData)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(req.Config.Get(ctx, &configData)...) - if resp.Diagnostics.HasError() { - return - } - - var registrantChangeResponse *dnsimple.RegistrantChangeResponse - var err error - registrantChangeResponse, err = r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, int(planData.Id.ValueInt64())) - - if err != nil { - var errorResponse *dnsimple.ErrorResponse - if errors.As(err, &errorResponse) { - resp.Diagnostics.Append(utils.AttributeErrorsToDiagnostics(errorResponse)...) - return - } - - resp.Diagnostics.AddError( - "failed to read DNSimple registrant change", - err.Error(), - ) - return - } - - // Check if the registrant change is completed - if registrantChangeResponse.Data.State != consts.RegistrantChangeStateCompleted { - convergenceState, err := tryToConvergeRegistration(ctx, planData, &resp.Diagnostics, r, registrantChangeResponse.Data.Id) - if convergenceState == RegistrantChangeFailed { - // Response is already populated with the error we can safely return - return - } - - if convergenceState == RegistrantChangeConvergenceTimeout { - // We attempted to converge on the registrant change, but the registrant change was not ready - // user needs to run terraform again to try and converge the registrant change - - // Exit with warning to prevent the state from being tainted - resp.Diagnostics.AddError( - "failed to converge on registrant change", - err.Error(), - ) - return - } - - registrantChangeResponse, err = r.config.Client.Registrar.GetRegistrantChange(ctx, r.config.AccountID, int(planData.Id.ValueInt64())) - - if err != nil { - resp.Diagnostics.AddError( - fmt.Sprintf("failed to read DNSimple Registrant Change for: %s, %d", planData.DomainId.ValueString(), planData.Id.ValueInt64()), - err.Error(), - ) - return - } - } - - r.updateModelFromAPIResponse(registrantChangeResponse.Data, planData) - - // Save updated planData into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &planData)...) -}