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_dev_center #23522

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .github/labeler-issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ service/databricks:
service/datadog:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_datadog_monitor((.|\n)*)###'

service/dev-center:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_dev_center((.|\n)*)###'

service/devtestlabs:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_dev_test_((.|\n)*)###'

Expand Down
3 changes: 3 additions & 0 deletions .github/labeler-pull-request-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ service/databricks:
service/datadog:
- internal/services/datadog/**/*

service/dev-center:
- internal/services/devcenter/**/*

service/devtestlabs:
- internal/services/devtestlabs/**/*

Expand Down
1 change: 1 addition & 0 deletions .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var services = mapOf(
"databoxedge" to "Databox Edge",
"datadog" to "Datadog",
"desktopvirtualization" to "Desktop Virtualization",
"devcenter" to "Dev Center",
"devtestlabs" to "Dev Test",
"digitaltwins" to "Digital Twins",
"disks" to "Disks",
Expand Down
5 changes: 5 additions & 0 deletions internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import (
dataprotection "github.com/hashicorp/terraform-provider-azurerm/internal/services/dataprotection/client"
datashare "github.com/hashicorp/terraform-provider-azurerm/internal/services/datashare/client"
desktopvirtualization "github.com/hashicorp/terraform-provider-azurerm/internal/services/desktopvirtualization/client"
devcenter "github.com/hashicorp/terraform-provider-azurerm/internal/services/devcenter/client"
devtestlabs "github.com/hashicorp/terraform-provider-azurerm/internal/services/devtestlabs/client"
digitaltwins "github.com/hashicorp/terraform-provider-azurerm/internal/services/digitaltwins/client"
disks "github.com/hashicorp/terraform-provider-azurerm/internal/services/disks/client"
Expand Down Expand Up @@ -196,6 +197,7 @@ type Client struct {
DataProtection *dataprotection.Client
DataShare *datashare.Client
DesktopVirtualization *desktopvirtualization.Client
DevCenter *devcenter.Client
DevTestLabs *devtestlabs.Client
DigitalTwins *digitaltwins.Client
Disks *disks.Client
Expand Down Expand Up @@ -406,6 +408,9 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
if client.DesktopVirtualization, err = desktopvirtualization.NewClient(o); err != nil {
return fmt.Errorf("building clients for DesktopVirtualization: %+v", err)
}
if client.DevCenter, err = devcenter.NewClient(o); err != nil {
return fmt.Errorf("building clients for DevCenter: %+v", err)
}
if client.DevTestLabs, err = devtestlabs.NewClient(o); err != nil {
return fmt.Errorf("building clients for DevTestLabs: %+v", err)
}
Expand Down
2 changes: 2 additions & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/services/dataprotection"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/datashare"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/desktopvirtualization"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/devcenter"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/devtestlabs"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/digitaltwins"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/disks"
Expand Down Expand Up @@ -159,6 +160,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration {
databoxedge.Registration{},
databricks.Registration{},
datafactory.Registration{},
devcenter.Registration{},
digitaltwins.Registration{},
disks.Registration{},
domainservices.Registration{},
Expand Down
26 changes: 26 additions & 0 deletions internal/services/devcenter/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package client

import (
"fmt"

"github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/attachednetworkconnections"
"github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/devcenters"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

type Client struct {
DevCenterClient *devcenters.DevCentersClient
AttachedNetworkConnectionsClient *attachednetworkconnections.AttachedNetworkConnectionsClient
}

func NewClient(o *common.ClientOptions) (*Client, error) {
devCenterClient, err := devcenters.NewDevCentersClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Devcenter client: %+v", err)
}
o.Configure(devCenterClient.Client, o.Authorizers.ResourceManager)

return &Client{
DevCenterClient: devCenterClient,
}, nil
}
207 changes: 207 additions & 0 deletions internal/services/devcenter/dev_center_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package devcenter

import (
"context"
"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/devcenter/2023-04-01/devcenters"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type DevCenterResource struct{}

type DevCenterModel struct {
Name string `tfschema:"name"`
ResourceGroup string `tfschema:"resource_group_name"`
Location string `tfschema:"location"`
Tags map[string]string `tfschema:"tags"`
}

var _ sdk.ResourceWithUpdate = DevCenterResource{}

func (r DevCenterResource) Arguments() map[string]*schema.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"resource_group_name": commonschema.ResourceGroupName(),

"location": commonschema.Location(),

"identity": commonschema.SystemAssignedUserAssignedIdentityOptional(),

"tags": commonschema.Tags(),
}
}

func (r DevCenterResource) Attributes() map[string]*schema.Schema {
return map[string]*schema.Schema{}
}

func (r DevCenterResource) ModelObject() interface{} {
return &DevCenterModel{}
}

func (r DevCenterResource) ResourceType() string {
return "azurerm_dev_center"
}

func (r DevCenterResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.DevCenter.DevCenterClient
subscriptionId := metadata.Client.Account.SubscriptionId

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

id := devcenters.NewDevCenterID(subscriptionId, model.ResourceGroup, model.Name)
existing, err := client.Get(ctx, id)
if err != nil && !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

if !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

devCenterIdentity, err := identity.ExpandSystemAndUserAssignedMap(metadata.ResourceData.Get("identity").([]interface{}))
if err != nil {
return fmt.Errorf("expanding `identity`: %+v", err)
}

devCenter := devcenters.DevCenter{
Id: utils.String(id.ID()),
Identity: devCenterIdentity,
Location: model.Location,
Name: utils.String(model.Name),
Tags: pointer.To(model.Tags),
}

if err := client.CreateOrUpdateThenPoll(ctx, id, devCenter); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

metadata.SetID(id)
return nil
},
}
}

func (r DevCenterResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.DevCenter.DevCenterClient
id, err := devcenters.ParseDevCenterID(metadata.ResourceData.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}
return fmt.Errorf("reading %s: %+v", *id, err)
}

if model := resp.Model; model != nil {
state := DevCenterModel{
Name: id.DevCenterName,
ResourceGroup: id.ResourceGroupName,
Location: model.Location,
}
if model.Tags != nil {
state.Tags = pointer.From(model.Tags)
}
devCenterIdentity, err := identity.FlattenSystemAndUserAssignedMap(model.Identity)
if err != nil {
return fmt.Errorf("flattening `identity`: %+v", err)
}
if err := metadata.ResourceData.Set("identity", devCenterIdentity); err != nil {
return fmt.Errorf("setting `identity`: %+v", err)
}

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

func (r DevCenterResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.DevCenter.DevCenterClient
id, err := devcenters.ParseDevCenterID(metadata.ResourceData.Id())
if err != nil {
return err
}

metadata.Logger.Infof("deleting %s", *id)

if err := client.DeleteThenPoll(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %+v", *id, err)
}

return nil
},
}
}

func (r DevCenterResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return devcenters.ValidateDevCenterID
}

func (r DevCenterResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.DevCenter.DevCenterClient
id, err := devcenters.ParseDevCenterID(metadata.ResourceData.Id())
if err != nil {
return err
}

var state DevCenterModel
if err := metadata.Decode(&state); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

devCenterIdentity, err := identity.ExpandSystemAndUserAssignedMap(metadata.ResourceData.Get("identity").([]interface{}))
if err != nil {
return fmt.Errorf("expanding `identity`: %+v", err)
}

if metadata.ResourceData.HasChangesExcept("name", "resource_group_name", "location") {
devCenter := devcenters.DevCenterUpdate{
Identity: devCenterIdentity,
Tags: pointer.To(state.Tags),
}

if err := client.UpdateThenPoll(ctx, *id, devCenter); err != nil {
return fmt.Errorf("updating %s: %+v", *id, err)
}
}
return nil
},
}
}
Loading