Skip to content

Commit

Permalink
[New Resource] `azurerm_machine_learning_workspace_network_outbound_r…
Browse files Browse the repository at this point in the history
…ule_service_tag` (#27931)

* add support for MLW vnet outbound rule service tag

* fix lint

* remove local val

* update document and refactor code

* update documentation and nil check
  • Loading branch information
xuzhang3 authored Jan 8, 2025
1 parent c5b2f19 commit 04eefb6
Show file tree
Hide file tree
Showing 5 changed files with 670 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,12 @@ func TestAccMachineLearningWorkspaceNetworkOutboundRuleFqdn_requiresImport(t *te
}

func (r WorkspaceNetworkOutboundRuleFqdnResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
maangedNetworkClient := client.MachineLearning.ManagedNetwork
id, err := managednetwork.ParseOutboundRuleID(state.ID)
if err != nil {
return nil, err
}

resp, err := maangedNetworkClient.SettingsRuleGet(ctx, *id)
resp, err := client.MachineLearning.ManagedNetwork.SettingsRuleGet(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return utils.Bool(false), nil
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package machinelearning

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-sdk/resource-manager/machinelearningservices/2024-04-01/managednetwork"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"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"
)

var _ sdk.ResourceWithUpdate = WorkspaceNetworkOutboundRuleServiceTag{}

type MachineLearningWorkspaceServiceTagOutboundRuleModel struct {
Name string `tfschema:"name"`
WorkspaceId string `tfschema:"workspace_id"`
ServiceTag string `tfschema:"service_tag"`
Protocol string `tfschema:"protocol"`
PortRanges string `tfschema:"port_ranges"`
}

type WorkspaceNetworkOutboundRuleServiceTag struct{}

var _ sdk.Resource = WorkspaceNetworkOutboundRuleServiceTag{}

func (r WorkspaceNetworkOutboundRuleServiceTag) ResourceType() string {
return "azurerm_machine_learning_workspace_network_outbound_rule_service_tag"
}

func (r WorkspaceNetworkOutboundRuleServiceTag) ModelObject() interface{} {
return &MachineLearningWorkspaceServiceTagOutboundRuleModel{}
}

func (r WorkspaceNetworkOutboundRuleServiceTag) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return managednetwork.ValidateOutboundRuleID
}

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

"workspace_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: managednetwork.ValidateWorkspaceID,
},

"service_tag": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"AppConfiguration",
"AppService",
"AzureActiveDirectory",
"AzureAdvancedThreatProtection",
"AzureArcInfrastructure",
"AzureAttestation",
"AzureBackup",
"AzureBotService",
"AzureContainerRegistry",
"AzureCosmosDB",
"AzureDataLake",
"AzureDevSpaces",
"AzureInformationProtection",
"AzureIoTHub",
"AzureKeyVault",
"AzureManagedGrafana",
"AzureMonitor",
"AzureOpenDatasets",
"AzurePlatformDNS",
"AzurePlatformIMDS",
"AzurePlatformLKM",
"AzureResourceManager",
"AzureSignalR",
"AzureSiteRecovery",
"AzureSpringCloud",
"AzureStack",
"AzureUpdateDelivery",
"DataFactoryManagement",
"EventHub",
"GuestAndHybridManagement",
"M365ManagementActivityApi",
"M365ManagementActivityApi",
"MicrosoftAzureFluidRelay",
"MicrosoftCloudAppSecurity",
"MicrosoftContainerRegistry",
"PowerPlatformInfra",
"ServiceBus",
"Sql",
"Storage",
"WindowsAdminCenter",
"AppServiceManagement",
"AutonomousDevelopmentPlatform",
"AzureActiveDirectoryDomainServices",
"AzureCloud",
"AzureConnectors",
"AzureContainerAppsService",
"AzureDatabricks",
"AzureDeviceUpdate",
"AzureEventGrid",
"AzureFrontDoor.Frontend",
"AzureFrontDoor.Backend",
"AzureFrontDoor.FirstParty",
"AzureHealthcareAPIs",
"AzureLoadBalancer",
"AzureMachineLearning",
"AzureSphere",
"AzureWebPubSub",
"BatchNodeManagement",
"ChaosStudio",
"CognitiveServicesFrontend",
"CognitiveServicesManagement",
"DataFactory",
"Dynamics365ForMarketingEmail",
"Dynamics365BusinessCentral",
"EOPExternalPublishedIPs",
"Internet",
"LogicApps",
"Marketplace",
"MicrosoftDefenderForEndpoint",
"PowerBI",
"PowerQueryOnline",
"ServiceFabric",
"SqlManagement",
"StorageSyncService",
"WindowsVirtualDesktop",
"VirtualNetwork",
}, false),
},

"protocol": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"*", "TCP", "UDP", "ICMP"}, false),
},

"port_ranges": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
}
return arguments
}

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

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

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

workspaceId, err := managednetwork.ParseWorkspaceID(model.WorkspaceId)
if err != nil {
return err
}
id := managednetwork.NewOutboundRuleID(subscriptionId, workspaceId.ResourceGroupName, workspaceId.WorkspaceName, model.Name)
existing, err := client.SettingsRuleGet(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing %s: %+v", id, err)
}
}
if !response.WasNotFound(existing.HttpResponse) {
return tf.ImportAsExistsError("azurerm_machine_learning_workspace_network_outbound_rule_service_tag", id.ID())
}

outboundRule := managednetwork.OutboundRuleBasicResource{
Name: pointer.To(model.Name),
Type: pointer.To(string(managednetwork.RuleTypeServiceTag)),
Properties: managednetwork.ServiceTagOutboundRule{
Category: pointer.To(managednetwork.RuleCategoryUserDefined),
Destination: &managednetwork.ServiceTagDestination{
PortRanges: &model.PortRanges,
Protocol: &model.Protocol,
ServiceTag: &model.ServiceTag,
},
},
}

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

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

func (r WorkspaceNetworkOutboundRuleServiceTag) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MachineLearning.ManagedNetwork
id, err := managednetwork.ParseOutboundRuleID(metadata.ResourceData.Id())

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

if err != nil {
return err
}

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

if existing.Model == nil {
return fmt.Errorf("retrieving %s: `model` was nil", id)
}

if existing.Model.Properties == nil {
return fmt.Errorf("retrieving %s: `properties` was nil", id)
}

payload := existing.Model
serviceTagOutboundRule := payload.Properties.(managednetwork.ServiceTagOutboundRule)
if metadata.ResourceData.HasChange("service_tag") {
serviceTagOutboundRule.Destination.ServiceTag = pointer.To(model.ServiceTag)
}

if metadata.ResourceData.HasChange("protocol") {
serviceTagOutboundRule.Destination.Protocol = pointer.To(model.Protocol)
}

if metadata.ResourceData.HasChange("port_ranges") {
serviceTagOutboundRule.Destination.PortRanges = pointer.To(model.PortRanges)
}

payload.Properties = serviceTagOutboundRule
if err := client.SettingsRuleCreateOrUpdateThenPoll(ctx, *id, *payload); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}
return nil
},
}
}

func (r WorkspaceNetworkOutboundRuleServiceTag) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MachineLearning.ManagedNetwork

id, err := managednetwork.ParseOutboundRuleID(metadata.ResourceData.Id())
if err != nil {
return err
}

resp, err := client.SettingsRuleGet(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}

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

state := MachineLearningWorkspaceServiceTagOutboundRuleModel{
Name: id.OutboundRuleName,
WorkspaceId: managednetwork.NewWorkspaceID(id.SubscriptionId, id.ResourceGroupName, id.WorkspaceName).ID(),
}

if model := resp.Model; model != nil {
if props := model.Properties; props != nil {
if prop, ok := props.(managednetwork.ServiceTagOutboundRule); ok && prop.Destination != nil {
state.ServiceTag = pointer.From(prop.Destination.ServiceTag)
state.Protocol = pointer.From(prop.Destination.Protocol)
state.PortRanges = pointer.From(prop.Destination.PortRanges)
}
}
}
return metadata.Encode(&state)
},
}
}

func (r WorkspaceNetworkOutboundRuleServiceTag) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.MachineLearning.ManagedNetwork

id, err := managednetwork.ParseOutboundRuleID(metadata.ResourceData.Id())
if err != nil {
return err
}

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

0 comments on commit 04eefb6

Please sign in to comment.