Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: azurerm_communication_service_email_domain_association #26432

Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f50852f
New Resource: `azurerm_communication_service_email_domain_association`
jkroepke Jun 22, 2024
a78c100
Merge branch 'hashicorp:main' into azurerm_communication_service_emai…
jkroepke Jul 5, 2024
cc06532
Merge branch 'hashicorp:main' into azurerm_communication_service_emai…
jkroepke Jul 29, 2024
5807abe
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
4f4ebb7
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
f4c1e72
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
903152b
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
ccd0fcc
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
28ae1bf
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
351a7cf
Update internal/services/communication/registration.go
jkroepke Aug 5, 2024
b1a8832
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
bf6cee3
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
e471938
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
9787dfc
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
6e78a60
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
1dc442c
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
4a918c3
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
f3eb377
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
21665d5
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
a4a7ae7
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
45cd358
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
12e4ce9
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
c6d5a25
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
9b65099
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
7ec8af9
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
2248290
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
a0ba818
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
a587064
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
c90485e
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
291ed83
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 5, 2024
d16700b
apply fixes from review
jkroepke Aug 5, 2024
3072c8b
apply fixes from review
jkroepke Aug 5, 2024
29da675
Merge branch 'main' into azurerm_communication_service_email_domain_a…
jkroepke Aug 5, 2024
d051b91
apply fixes from review
jkroepke Aug 5, 2024
25aa1f7
Update internal/services/communication/communication_service_email_do…
jkroepke Aug 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package communication

import (
"context"
"fmt"
"log"
"slices"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/communication/2023-03-31/communicationservices"
"github.com/hashicorp/go-azure-sdk/resource-manager/communication/2023-03-31/domains"
"github.com/hashicorp/terraform-provider-azurerm/internal/locks"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

var _ sdk.Resource = CommunicationServiceEmailDomainAssociationResource{}

type EmailDomainAssociationResource struct{}

type EmailDomainAssociationResourceModel struct {
CommunicationServiceId string `tfschema:"communication_service_id"`
EMailServiceDomainId string `tfschema:"email_service_domain_id"`
}

func (CommunicationServiceEmailDomainAssociationResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"communication_service_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: communicationservices.ValidateCommunicationServiceID,
},
"email_service_domain_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: domains.ValidateDomainID,
},
}
}

func (CommunicationServiceEmailDomainAssociationResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{}
}

func (CommunicationServiceEmailDomainAssociationResource) ModelObject() interface{} {
return &CommunicationServiceEmailDomainAssociationResourceModel{}
}

func (CommunicationServiceEmailDomainAssociationResource) ResourceType() string {
return "azurerm_communication_service_email_domain_association"
}

func (r CommunicationServiceEmailDomainAssociationResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Communication.ServiceClient
domainClient := metadata.Client.Communication.DomainClient

var model CommunicationServiceEmailDomainAssociationResourceModel

if err := metadata.Decode(&model); err != nil {
return err
}

communicationServiceId, err := communicationservices.ParseCommunicationServiceID(model.CommunicationServiceId)
if err != nil {
return err
}

eMailServiceDomainId, err := domains.ParseDomainID(model.EMailServiceDomainId)
if err != nil {
return err
}

locks.ByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")
defer locks.UnlockByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")

locks.ByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")
defer locks.UnlockByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")

existingEMailServiceDomain, err := domainClient.Get(ctx, *eMailServiceDomainId)
if err != nil && !response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return fmt.Errorf("checking for the presence of existing %s: %+v", *eMailServiceDomainId, err)
}

if response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return fmt.Errorf("%s was not found", eMailServiceDomainId)
}

existingCommunicationService, err := client.Get(ctx, *communicationServiceId)
if err != nil && !response.WasNotFound(existingCommunicationService.HttpResponse) {
return fmt.Errorf("checking for the presence of existing %s: %+v", communicationServiceId, err)
}

if response.WasNotFound(existingCommunicationService.HttpResponse) {
return fmt.Errorf("%s was not found", communicationServiceId)
}

if existingCommunicationService.Model == nil {
return fmt.Errorf("model for %s was nil", communicationServiceId)
}
if existingCommunicationService.Model.Properties == nil {
return fmt.Errorf("properties for %s was nil", communicationServiceId)
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

domainList := make([]string, 0)
if existingDomainList := existingCommunicationService.Model.Properties.LinkedDomains; existingDomainList != nil {
domainList = pointer.From(existingDomainList)
}

domainList = append(domainList, eMailServiceDomainId.ID())

input := communicationservices.CommunicationServiceResourceUpdate{
Properties: &communicationservices.CommunicationServiceUpdateProperties{
LinkedDomains: pointer.To(domainList),
},
}

if _, err = client.Update(ctx, *communicationServiceId, input); err != nil {
return fmt.Errorf("updating %s: %+v", *communicationServiceId, err)
}

id := commonids.NewCompositeResourceID(communicationServiceId, eMailServiceDomainId)
if slices.Contains(domainList, eMailServiceDomainId.ID()) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

metadata.SetID(id)

return nil
},

Check failure on line 139 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / document-lint

syntax error: unexpected comma at end of statement

Check failure on line 139 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / test

expected ';', found ','
}

Check failure on line 140 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / document-lint

syntax error: unexpected newline in composite literal; possibly missing comma or }

Check failure on line 140 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / test

missing ',' before newline in composite literal
}

func (CommunicationServiceEmailDomainAssociationResource) Read() sdk.ResourceFunc {

Check failure on line 143 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / document-lint

syntax error: unexpected sdk at end of statement

Check failure on line 143 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / test

expected ';', found sdk
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Communication.ServiceClient
domainClient := metadata.Client.Communication.DomainClient

id, err := commonids.ParseCompositeResourceID(metadata.ResourceData.Id(), &communicationservices.CommunicationServiceId{}, &domains.DomainId{})
if err != nil {
return err
}

state := CommunicationServiceEmailDomainAssociationResourceModel{}
state.CommunicationServiceId = id.First.ID()
state.EMailServiceDomainId = id.Second.ID()

communicationServiceId, err := communicationservices.ParseCommunicationServiceID(state.CommunicationServiceId)
if err != nil {
return fmt.Errorf("parsing Communication Service ID: %w", err)
}

eMailServiceDomainId, err := domains.ParseDomainID(state.EMailServiceDomainId)
if err != nil {
return fmt.Errorf("parsing EMail Service Domain ID: %w", err)
}
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

locks.ByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")
defer locks.UnlockByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")

locks.ByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")
defer locks.UnlockByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")

existingEMailServiceDomain, err := domainClient.Get(ctx, *eMailServiceDomainId)
if err != nil && !response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return fmt.Errorf("checking for the presence of existing EMail Service Domain %q: %+v", state.EMailServiceDomainId, err)
}

if response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return metadata.MarkAsGone(id)
}

existingCommunicationService, err := client.Get(ctx, *communicationServiceId)
if err != nil && !response.WasNotFound(existingCommunicationService.HttpResponse) {
return fmt.Errorf("checking for the presence of existing Communication Service %q: %+v", state.CommunicationServiceId, err)
}

if response.WasNotFound(existingCommunicationService.HttpResponse) {
return metadata.MarkAsGone(id)
}

if existingCommunicationService.Model == nil || existingCommunicationService.Model.Properties == nil {
return fmt.Errorf("model/properties for %s was nil", state.CommunicationServiceId)
}
jkroepke marked this conversation as resolved.
Show resolved Hide resolved
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

domainList := existingCommunicationService.Model.Properties.LinkedDomains
if domainList == nil {
return fmt.Errorf("checking for Domain Association %s for %s", *eMailServiceDomainId, *communicationServiceId)
}

for _, v := range pointer.From(domainList) {
tmpID, tmpErr := domains.ParseDomainID(v)
if tmpErr != nil {
return fmt.Errorf("parsing domain ID %q from LinkedDomains for %s: %+v", v, communicationServiceId, err)
}
if strings.EqualFold(eMailServiceDomainId.ID(), tmpID.ID()) {
found = true
}
if !found {
return metadata.MarkAsGone(id)
}
}

return metadata.Encode(&state)
},
}
}

func (CommunicationServiceEmailDomainAssociationResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Communication.ServiceClient
domainClient := metadata.Client.Communication.DomainClient

var model CommunicationServiceEmailDomainAssociationResourceModel

if err := metadata.Decode(&model); err != nil {
return err
}

communicationServiceId, err := communicationservices.ParseCommunicationServiceID(model.CommunicationServiceId)
if err != nil {
return err
}

eMailServiceDomainId, err := domains.ParseDomainID(model.EMailServiceDomainId)
if err != nil {
return err
}

locks.ByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")
defer locks.UnlockByName(communicationServiceId.CommunicationServiceName, "azurerm_communication_service")

locks.ByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")
defer locks.UnlockByName(eMailServiceDomainId.DomainName, "azurerm_email_communication_service_domain")

existingEMailServiceDomain, err := domainClient.Get(ctx, *eMailServiceDomainId)
if err != nil && !response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return fmt.Errorf("checking for the presence of existing %s: %+v", *eMailServiceDomainId, err)
}

if response.WasNotFound(existingEMailServiceDomain.HttpResponse) {
return return metadata.MarkAsGone(id)

Check failure on line 255 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / document-lint

syntax error: unexpected return, expected expression

Check failure on line 255 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / test

expected operand, found 'return'
}

existingCommunicationService, err := client.Get(ctx, *communicationServiceId)
if err != nil && !response.WasNotFound(existingCommunicationService.HttpResponse) {
return fmt.Errorf("checking for the presence of existing %s: %+v", *communicationServiceId, err)
}

if response.WasNotFound(existingCommunicationService.HttpResponse) {
return return metadata.MarkAsGone(id)

Check failure on line 264 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / document-lint

syntax error: unexpected return, expected expression

Check failure on line 264 in internal/services/communication/communication_service_email_domain_association_resource.go

View workflow job for this annotation

GitHub Actions / test

expected operand, found 'return'
}

if existingCommunicationService.Model == nil || existingCommunicationService.Model.Properties == nil {
return fmt.Errorf("model/properties for %s was nil", model.CommunicationServiceId)
}
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

domainList := existingCommunicationService.Model.Properties.LinkedDomains
if domainList == nil {
domainList = pointer.FromSliceOfStrings(make([]string, 0, 1))
}
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

if !slices.Contains(*domainList, eMailServiceDomainId.ID()) {
return nil
}

*domainList = slices.DeleteFunc(*domainList, func(n string) bool {
return n == eMailServiceDomainId.ID()
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again here, we cannot rely on the list being correctly cased, so will need to normalise by parsing to check, then remove is we find a match.



input := communicationservices.CommunicationServiceResourceUpdate{
Properties: &communicationservices.CommunicationServiceUpdateProperties{
LinkedDomains: domainList,
},
}

if _, err := client.Update(ctx, *communicationServiceId, input); err != nil {
return fmt.Errorf("deleting Email Domain Association for %s from %s: %+v", *eMailServiceDomainId, *communicationServiceId, err)
}

return nil
},
}
}

func (CommunicationServiceEmailDomainAssociationResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return func(input interface{}, key string) (warnings []string, errors []error) {
v, ok := input.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected %q to be a string", key))
return
}

if _, err := commonids.ParseCompositeResourceID(v, &communicationservices.CommunicationServiceId{}, &domains.DomainId{}); err != nil {
errors = append(errors, err)
}

return
}
}
Loading
Loading