Skip to content

Commit e8d5187

Browse files
authored
[New Resource] azurerm_machine_learning_workspace_network_outbound_rule_private_endpoint (hashicorp#27874)
* add support for machine learning workspace network settings private endpoint * fix lint and test case * format * update error msg * remove local val * update document and refactor code * update error msg * update documentation and pointer utils
1 parent c21a300 commit e8d5187

4 files changed

+817
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package machinelearning
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
"time"
11+
12+
"github.com/hashicorp/go-azure-helpers/lang/pointer"
13+
"github.com/hashicorp/go-azure-helpers/lang/response"
14+
"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
15+
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2024-04-01/managednetwork"
16+
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
17+
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
18+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
19+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
20+
)
21+
22+
var resourceTypeSupportSubResType = map[string][]string{
23+
"Microsoft.KeyVault": {"vault"},
24+
"Microsoft.Cache": {"redisCache"},
25+
"Microsoft.MachineLearningServices": {"amlworkspace"},
26+
"Microsoft.Storage": {"blob", "table", "queue", "file", "web", "dfs"},
27+
}
28+
29+
type machineLearningWorkspaceOutboundRulePrivateEndpointModel struct {
30+
Name string `tfschema:"name"`
31+
WorkspaceId string `tfschema:"workspace_id"`
32+
ServiceResourceId string `tfschema:"service_resource_id"`
33+
SubresourceTarget string `tfschema:"sub_resource_target"`
34+
SparkEnabled bool `tfschema:"spark_enabled"`
35+
}
36+
37+
type WorkspaceNetworkOutboundRulePrivateEndpoint struct{}
38+
39+
var _ sdk.Resource = WorkspaceNetworkOutboundRulePrivateEndpoint{}
40+
41+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) ResourceType() string {
42+
return "azurerm_machine_learning_workspace_network_outbound_rule_private_endpoint"
43+
}
44+
45+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) ModelObject() interface{} {
46+
return &machineLearningWorkspaceOutboundRulePrivateEndpointModel{}
47+
}
48+
49+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) IDValidationFunc() pluginsdk.SchemaValidateFunc {
50+
return managednetwork.ValidateOutboundRuleID
51+
}
52+
53+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) Arguments() map[string]*pluginsdk.Schema {
54+
arguments := map[string]*pluginsdk.Schema{
55+
"name": {
56+
Type: pluginsdk.TypeString,
57+
Required: true,
58+
ForceNew: true,
59+
ValidateFunc: validation.StringIsNotEmpty,
60+
},
61+
62+
"workspace_id": {
63+
Type: pluginsdk.TypeString,
64+
Required: true,
65+
ForceNew: true,
66+
ValidateFunc: managednetwork.ValidateWorkspaceID,
67+
},
68+
69+
"service_resource_id": {
70+
Type: pluginsdk.TypeString,
71+
Required: true,
72+
ForceNew: true,
73+
ValidateFunc: validation.StringIsNotEmpty,
74+
},
75+
76+
"sub_resource_target": {
77+
Type: pluginsdk.TypeString,
78+
Required: true,
79+
ForceNew: true,
80+
ValidateFunc: validation.StringInSlice([]string{
81+
"vault",
82+
"amlworkspace",
83+
"blob",
84+
"table",
85+
"queue",
86+
"file",
87+
"web",
88+
"dfs",
89+
"redisCache",
90+
}, false),
91+
},
92+
93+
"spark_enabled": {
94+
Type: pluginsdk.TypeBool,
95+
Optional: true,
96+
Default: false,
97+
ForceNew: true,
98+
},
99+
}
100+
return arguments
101+
}
102+
103+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) Attributes() map[string]*pluginsdk.Schema {
104+
return map[string]*pluginsdk.Schema{}
105+
}
106+
107+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) Create() sdk.ResourceFunc {
108+
return sdk.ResourceFunc{
109+
Timeout: 30 * time.Minute,
110+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
111+
client := metadata.Client.MachineLearning.ManagedNetwork
112+
subscriptionId := metadata.Client.Account.SubscriptionId
113+
114+
var model machineLearningWorkspaceOutboundRulePrivateEndpointModel
115+
if err := metadata.Decode(&model); err != nil {
116+
return fmt.Errorf("decoding: %+v", err)
117+
}
118+
119+
workspaceId, err := managednetwork.ParseWorkspaceID(model.WorkspaceId)
120+
if err != nil {
121+
return err
122+
}
123+
id := managednetwork.NewOutboundRuleID(subscriptionId, workspaceId.ResourceGroupName, workspaceId.WorkspaceName, model.Name)
124+
existing, err := client.SettingsRuleGet(ctx, id)
125+
if err != nil {
126+
if !response.WasNotFound(existing.HttpResponse) {
127+
return fmt.Errorf("checking for presence of existing %s: %+v", id, err)
128+
}
129+
}
130+
if !response.WasNotFound(existing.HttpResponse) {
131+
return tf.ImportAsExistsError("azurerm_machine_learning_workspace_network_outbound_rule_private_endpoint", id.ID())
132+
}
133+
134+
resId, err := resourceids.ParseAzureResourceID(model.ServiceResourceId)
135+
if err != nil {
136+
return err
137+
}
138+
139+
supportType := false
140+
if subTypes, ok := resourceTypeSupportSubResType[resId.Provider]; ok {
141+
for _, typ := range subTypes {
142+
if strings.EqualFold(typ, model.SubresourceTarget) {
143+
supportType = true
144+
break
145+
}
146+
}
147+
}
148+
149+
if !supportType {
150+
return fmt.Errorf(" unsupported resource type: %s. Sub resource type supported by Service Resource ID: %s is %s ",
151+
model.SubresourceTarget, model.ServiceResourceId,
152+
strings.Join(resourceTypeSupportSubResType[resId.Provider], ", "))
153+
}
154+
155+
outboundRule := managednetwork.OutboundRuleBasicResource{
156+
Name: pointer.To(model.Name),
157+
Type: pointer.To(string(managednetwork.RuleTypePrivateEndpoint)),
158+
Properties: managednetwork.PrivateEndpointOutboundRule{
159+
Category: pointer.To(managednetwork.RuleCategoryUserDefined),
160+
Destination: &managednetwork.PrivateEndpointDestination{
161+
ServiceResourceId: pointer.To(model.ServiceResourceId),
162+
SubresourceTarget: pointer.To(model.SubresourceTarget),
163+
SparkEnabled: pointer.To(model.SparkEnabled),
164+
},
165+
},
166+
}
167+
168+
if err = client.SettingsRuleCreateOrUpdateThenPoll(ctx, id, outboundRule); err != nil {
169+
return fmt.Errorf("creating %s: %+v", id, err)
170+
}
171+
172+
metadata.SetID(id)
173+
return nil
174+
},
175+
}
176+
}
177+
178+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) Read() sdk.ResourceFunc {
179+
return sdk.ResourceFunc{
180+
Timeout: 5 * time.Minute,
181+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
182+
client := metadata.Client.MachineLearning.ManagedNetwork
183+
184+
id, err := managednetwork.ParseOutboundRuleID(metadata.ResourceData.Id())
185+
if err != nil {
186+
return err
187+
}
188+
189+
resp, err := client.SettingsRuleGet(ctx, *id)
190+
if err != nil {
191+
if response.WasNotFound(resp.HttpResponse) {
192+
return metadata.MarkAsGone(id)
193+
}
194+
195+
return fmt.Errorf("retrieving %s: %+v", *id, err)
196+
}
197+
198+
state := machineLearningWorkspaceOutboundRulePrivateEndpointModel{
199+
Name: id.OutboundRuleName,
200+
WorkspaceId: managednetwork.NewWorkspaceID(id.SubscriptionId, id.ResourceGroupName, id.WorkspaceName).ID(),
201+
}
202+
203+
if model := resp.Model; model != nil {
204+
if props := model.Properties; props != nil {
205+
if prop, ok := props.(managednetwork.PrivateEndpointOutboundRule); ok && prop.Destination != nil {
206+
state.SparkEnabled = pointer.From(prop.Destination.SparkEnabled)
207+
state.SubresourceTarget = pointer.From(prop.Destination.SubresourceTarget)
208+
state.ServiceResourceId = pointer.From(prop.Destination.ServiceResourceId)
209+
}
210+
}
211+
}
212+
return metadata.Encode(&state)
213+
},
214+
}
215+
}
216+
217+
func (r WorkspaceNetworkOutboundRulePrivateEndpoint) Delete() sdk.ResourceFunc {
218+
return sdk.ResourceFunc{
219+
Timeout: 30 * time.Minute,
220+
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
221+
client := metadata.Client.MachineLearning.ManagedNetwork
222+
223+
id, err := managednetwork.ParseOutboundRuleID(metadata.ResourceData.Id())
224+
if err != nil {
225+
return err
226+
}
227+
228+
if err = client.SettingsRuleDeleteThenPoll(ctx, *id); err != nil {
229+
return fmt.Errorf("deleting %s: %+v", id, err)
230+
}
231+
return nil
232+
},
233+
}
234+
}

0 commit comments

Comments
 (0)