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

[Enhancement:] azurerm_cdn_frontdoor_profile - add support for the identity property #28068

Closed
wants to merge 10 commits into from
4 changes: 3 additions & 1 deletion internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,9 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
if client.Bot, err = bot.NewClient(o); err != nil {
return fmt.Errorf("building clients for Bot: %+v", err)
}
client.Cdn = cdn.NewClient(o)
if client.Cdn, err = cdn.NewClient(o); err != nil {
return fmt.Errorf("building clients for cdn: %+v", err)
}
if client.CodeSigning, err = codesigning.NewClient(o); err != nil {
return fmt.Errorf("building clients for Code Signing: %+v", err)
}
Expand Down
49 changes: 38 additions & 11 deletions internal/services/cdn/cdn_frontdoor_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/Azure/azure-sdk-for-go/services/cdn/mgmt/2021-06-01/cdn" // nolint: staticcheck
"github.com/Azure/azure-sdk-for-go/services/frontdoor/mgmt/2020-11-01/frontdoor" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/lang/pointer"
dnsValidate "github.com/hashicorp/go-azure-sdk/resource-manager/dns/2018-05-01/zones"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
Expand Down Expand Up @@ -109,6 +110,36 @@ func flattenHttpsRedirectToBool(input cdn.HTTPSRedirect) bool {
return input == cdn.HTTPSRedirectEnabled
}

func expandNewFrontDoorTagsPointer(tagMap map[string]interface{}) *map[string]string {
t := make(map[string]string)

for k, v := range tagMap {
tagKey := k
tagValue := v
t[tagKey] = tagValue.(string)
}

return pointer.To(t)
}

func flattenNewFrontDoorTags(tagMap *map[string]string) map[string]interface{} {
if tagMap == nil {
return make(map[string]interface{}, 0)
}

t := make(map[string]interface{}, len(*tagMap))

for k, v := range *tagMap {
if v == "" {
continue
}

t[k] = v
}

return t
}

func expandFrontDoorTags(tagMap *map[string]string) map[string]*string {
t := make(map[string]*string)

Expand Down Expand Up @@ -144,10 +175,8 @@ func flattenTransformSlice(input *[]frontdoor.TransformType) []interface{} {
return result
}

if input != nil {
for _, item := range *input {
result = append(result, string(item))
}
for _, item := range *input {
result = append(result, string(item))
}

return result
Expand All @@ -159,14 +188,12 @@ func flattenFrontendEndpointLinkSlice(input *[]frontdoor.FrontendEndpointLink) [
return result
}

if input != nil {
for _, item := range *input {
if item.ID == nil {
continue
}

result = append(result, *item.ID)
for _, item := range *input {
if item.ID == nil {
continue
}

result = append(result, *item.ID)
}

return result
Expand Down
70 changes: 53 additions & 17 deletions internal/services/cdn/cdn_frontdoor_origin_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
"time"

"github.com/Azure/azure-sdk-for-go/services/cdn/mgmt/2021-06-01/cdn" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/location"
"github.com/hashicorp/go-azure-sdk/resource-manager/cdn/2024-02-01/profiles"
"github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-11-01/privatelinkservices"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
Expand Down Expand Up @@ -177,7 +180,7 @@ func resourceCdnFrontDoorOrigin() *pluginsdk.Resource {

func resourceCdnFrontDoorOriginCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Cdn.FrontDoorOriginsClient
profileClient := meta.(*clients.Client).Cdn.FrontDoorProfileClient
profileClient := meta.(*clients.Client).Cdn.FrontDoorProfilesClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

Expand All @@ -202,21 +205,37 @@ func resourceCdnFrontDoorOriginCreate(d *pluginsdk.ResourceData, meta interface{

// I need to get the profile SKU so I know if it is valid or not to define a private link as
// private links are only allowed in the premium sku...
profileId := parse.NewFrontDoorProfileID(id.SubscriptionId, id.ResourceGroup, id.ProfileName)
profile := parse.NewFrontDoorProfileID(id.SubscriptionId, id.ResourceGroup, id.ProfileName)

profile, err := profileClient.Get(ctx, profileId.ResourceGroup, profileId.ProfileName)
profileId := profiles.ProfileId{
SubscriptionId: profile.SubscriptionId,
ResourceGroupName: profile.ResourceGroup,
ProfileName: profile.ProfileName,
}

profileResp, err := profileClient.Get(ctx, profileId)
if err != nil {
if utils.ResponseWasNotFound(profile.Response) {
if response.WasNotFound(profileResp.HttpResponse) {
return fmt.Errorf("retrieving parent %s: not found", profileId)
}

return fmt.Errorf("retrieving parent %s: %+v", profileId, err)
}

if profile.Sku == nil {
return fmt.Errorf("retrieving parent %s: 'sku' was nil", profileId)
profileModel := profileResp.Model

if profileModel == nil {
return fmt.Errorf("profileModel is 'nil'")
}

if profileModel.Properties == nil {
return fmt.Errorf("profileModel.Properties is 'nil'")
}

if profileModel.Sku.Name == nil {
return fmt.Errorf("profileModel.Sku.Name' is 'nil'")
}
skuName := profile.Sku.Name
skuName := string(pointer.From(profileModel.Sku.Name))

var enabled bool
if !features.FourPointOhBeta() {
Expand All @@ -241,7 +260,7 @@ func resourceCdnFrontDoorOriginCreate(d *pluginsdk.ResourceData, meta interface{
props.OriginHostHeader = utils.String(originHostHeader)
}

expanded, err := expandPrivateLinkSettings(d.Get("private_link").([]interface{}), skuName, enableCertNameCheck)
expanded, err := expandPrivateLinkSettings(d.Get("private_link").([]interface{}), cdn.SkuName(skuName), enableCertNameCheck)
if err != nil {
return err
}
Expand Down Expand Up @@ -310,7 +329,7 @@ func resourceCdnFrontDoorOriginRead(d *pluginsdk.ResourceData, meta interface{})
func resourceCdnFrontDoorOriginUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Cdn.FrontDoorOriginsClient
workaroundClient := azuresdkhacks.NewCdnFrontDoorOriginsWorkaroundClient(client)
profileClient := meta.(*clients.Client).Cdn.FrontDoorProfileClient
profileClient := meta.(*clients.Client).Cdn.FrontDoorProfilesClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

Expand Down Expand Up @@ -357,21 +376,38 @@ func resourceCdnFrontDoorOriginUpdate(d *pluginsdk.ResourceData, meta interface{
if d.HasChange("private_link") {
// I need to get the profile SKU so I know if it is valid or not to define a private link as
// private links are only allowed in the premium sku...
profileId := parse.NewFrontDoorProfileID(id.SubscriptionId, id.ResourceGroup, id.ProfileName)
profile, err := profileClient.Get(ctx, profileId.ResourceGroup, profileId.ProfileName)
profile := parse.NewFrontDoorProfileID(id.SubscriptionId, id.ResourceGroup, id.ProfileName)

profileId := profiles.ProfileId{
SubscriptionId: profile.SubscriptionId,
ResourceGroupName: profile.ResourceGroup,
ProfileName: profile.ProfileName,
}

profileResp, err := profileClient.Get(ctx, profileId)
if err != nil {
if utils.ResponseWasNotFound(profile.Response) {
return fmt.Errorf("retrieving parent %s: not found", profileId)
if response.WasNotFound(profileResp.HttpResponse) {
d.SetId("")
return nil
}
return fmt.Errorf("retrieving %s: %+v", profile, err)
}

profileModel := profileResp.Model

if profileModel == nil {
return fmt.Errorf("profileModel is 'nil'")
}

return fmt.Errorf("retrieving parent %s: %+v", profileId, err)
if profileModel.Properties == nil {
return fmt.Errorf("profileModel.Properties is 'nil'")
}

if profile.Sku == nil {
return fmt.Errorf("retrieving parent %s: 'sku' was nil", profileId)
if profileModel.Sku.Name == nil {
return fmt.Errorf("retrieving parent %s: 'profileModel.Sku.Name' was 'nil'", profile)
}

skuName := profile.Sku.Name
skuName := cdn.SkuName(pointer.From(profileModel.Sku.Name))

enableCertNameCheck := d.Get("certificate_name_check_enabled").(bool)
privateLinkSettings, err := expandPrivateLinkSettings(d.Get("private_link").([]interface{}), skuName, enableCertNameCheck)
Expand Down
54 changes: 38 additions & 16 deletions internal/services/cdn/cdn_frontdoor_profile_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import (
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/identity"
"github.com/hashicorp/go-azure-sdk/resource-manager/cdn/2024-02-01/profiles"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/cdn/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/cdn/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tags"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

func dataSourceCdnFrontDoorProfile() *pluginsdk.Resource {
Expand All @@ -34,6 +36,8 @@ func dataSourceCdnFrontDoorProfile() *pluginsdk.Resource {

"resource_group_name": commonschema.ResourceGroupNameForDataSource(),

"identity": commonschema.SystemAssignedUserAssignedIdentityOptional(),

"response_timeout_seconds": {
Type: pluginsdk.TypeInt,
Computed: true,
Expand All @@ -55,41 +59,59 @@ func dataSourceCdnFrontDoorProfile() *pluginsdk.Resource {
}

func dataSourceCdnFrontDoorProfileRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Cdn.FrontDoorProfileClient
client := meta.(*clients.Client).Cdn.FrontDoorProfilesClient
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id := parse.NewFrontDoorProfileID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string))
resp, err := client.Get(ctx, id.ResourceGroup, id.ProfileName)

profileId := profiles.ProfileId{
SubscriptionId: id.SubscriptionId,
ResourceGroupName: id.ResourceGroup,
ProfileName: id.ProfileName,
}

resp, err := client.Get(ctx, profileId)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("retrieving %s: %+v", id, err)
}

model := resp.Model

if model == nil {
return fmt.Errorf("model is 'nil'")
}

if model.Properties == nil {
return fmt.Errorf("model.Properties is 'nil'")
}

d.SetId(id.ID())
d.Set("name", id.ProfileName)
d.Set("resource_group_name", id.ResourceGroup)

if props := resp.ProfileProperties; props != nil {
d.Set("response_timeout_seconds", props.OriginResponseTimeoutSeconds)
d.Set("response_timeout_seconds", int(pointer.From(model.Properties.OriginResponseTimeoutSeconds)))

// whilst this is returned in the API as FrontDoorID other resources refer to
// this as the Resource GUID, so we will for consistency
d.Set("resource_guid", pointer.From(model.Properties.FrontDoorId))

// whilst this is returned in the API as FrontDoorID other resources refer to
// this as the Resource GUID, so we will for consistency
d.Set("resource_guid", props.FrontDoorID)
identity, err := identity.FlattenSystemAndUserAssignedMap(model.Identity)
if err == nil {
d.Set("identity", identity)
}

skuName := ""
if resp.Sku != nil {
skuName = string(resp.Sku.Name)
if model.Sku.Name != nil {
skuName = string(pointer.From(model.Sku.Name))
}
d.Set("sku_name", skuName)

if err := tags.FlattenAndSet(d, resp.Tags); err != nil {
return err
}
d.Set("sku_name", skuName)
d.Set("tags", flattenNewFrontDoorTags(model.Tags))

return nil
}
Loading
Loading