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_machine_learning_datastore_blobstorage #19909

Merged
merged 19 commits into from
Jan 20, 2023
1 change: 1 addition & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration {
loadbalancer.Registration{},
loganalytics.Registration{},
media.Registration{},
machinelearning.Registration{},
monitor.Registration{},
mssql.Registration{},
network.Registration{},
Expand Down
6 changes: 6 additions & 0 deletions internal/services/machinelearning/client/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2022-05-01/datastore"
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2022-05-01/machinelearningcomputes"
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2022-05-01/workspaces"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
Expand All @@ -9,6 +10,7 @@ import (
type Client struct {
ComputeClient *machinelearningcomputes.MachineLearningComputesClient
WorkspacesClient *workspaces.WorkspacesClient
DatastoreClient *datastore.DatastoreClient
}

func NewClient(o *common.ClientOptions) *Client {
Expand All @@ -18,8 +20,12 @@ func NewClient(o *common.ClientOptions) *Client {
WorkspacesClient := workspaces.NewWorkspacesClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&WorkspacesClient.Client, o.ResourceManagerAuthorizer)

DatastoreClient := datastore.NewDatastoreClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&DatastoreClient.Client, o.ResourceManagerAuthorizer)

return &Client{
ComputeClient: &ComputeClient,
WorkspacesClient: &WorkspacesClient,
DatastoreClient: &DatastoreClient,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
package machinelearning

import (
"context"
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2022-05-01/datastore"
"github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2022-05-01/workspaces"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/machinelearning/validate"
storageparse "github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/parse"
"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 MachineLearningDataStoreBlobStorage struct{}

type MachineLearningDataStoreBlobStorageModel struct {
Name string `tfschema:"name"`
WorkSpaceID string `tfschema:"workspace_id"`
StorageContainerID string `tfschema:"storage_container_id"`
Description string `tfschema:"description"`
IsDefault bool `tfschema:"is_default"`
ServiceDataAuthIdentity string `tfschema:"service_data_auth_identity"`
AccountKey string `tfschema:"account_key"`
SharedAccessSignature string `tfschema:"shared_access_signature"`
Tags map[string]string `tfschema:"tags"`
}

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

func (r MachineLearningDataStoreBlobStorage) ModelObject() interface{} {
return &MachineLearningDataStoreBlobStorageModel{}
}

func (r MachineLearningDataStoreBlobStorage) ResourceType() string {
return "azurerm_machine_learning_datastore_blobstorage"
}

func (r MachineLearningDataStoreBlobStorage) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return datastore.ValidateDataStoreID
}

var _ sdk.ResourceWithUpdate = MachineLearningDataStoreBlobStorage{}

func (r MachineLearningDataStoreBlobStorage) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.DataStoreName,
},

"workspace_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.WorkspaceID,
},

"storage_container_id": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"description": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
},

"is_default": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
},

"service_data_auth_identity": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(datastore.ServiceDataAccessAuthIdentityNone),
string(datastore.ServiceDataAccessAuthIdentityWorkspaceSystemAssignedIdentity),
string(datastore.ServiceDataAccessAuthIdentityWorkspaceUserAssignedIdentity),
},
false),
Default: string(datastore.ServiceDataAccessAuthIdentityNone),
},

"account_key": {
Type: pluginsdk.TypeString,
Optional: true,
Sensitive: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"account_key", "shared_access_signature"},
},

"shared_access_signature": {
Type: pluginsdk.TypeString,
Optional: true,
Sensitive: true,
ValidateFunc: validation.StringIsNotEmpty,
AtLeastOneOf: []string{"account_key", "shared_access_signature"},
},

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

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

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

workspaceId, err := workspaces.ParseWorkspaceID(model.WorkSpaceID)
if err != nil {
return err
}

id := datastore.NewDataStoreID(subscriptionId, workspaceId.ResourceGroupName, workspaceId.WorkspaceName, model.Name)

existing, err := client.Get(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_datastore_blobstorage", id.ID())
}

containerId, err := storageparse.StorageContainerResourceManagerID(model.StorageContainerID)
if err != nil {
return err
}

datastoreRaw := datastore.DatastoreResource{
Name: utils.String(model.Name),
Type: utils.ToPtr(string(datastore.DatastoreTypeAzureBlob)),
}

props := &datastore.AzureBlobDatastore{
AccountName: utils.String(containerId.StorageAccountName),
ContainerName: utils.String(containerId.ContainerName),
Description: utils.String(model.Description),
ServiceDataAccessAuthIdentity: utils.ToPtr(datastore.ServiceDataAccessAuthIdentity(model.ServiceDataAuthIdentity)),
IsDefault: utils.Bool(model.IsDefault),
Tags: utils.ToPtr(model.Tags),
}

accountKey := model.AccountKey
if accountKey != "" {
props.Credentials = map[string]interface{}{
"credentialsType": string(datastore.CredentialsTypeAccountKey),
"secrets": map[string]interface{}{
"secretsType": "AccountKey",
"key": accountKey,
},
}
}

sasToken := model.SharedAccessSignature
if sasToken != "" {
props.Credentials = map[string]interface{}{
"credentialsType": string(datastore.CredentialsTypeSas),
"secrets": map[string]interface{}{
"secretsType": "Sas",
"sasToken": sasToken,
},
}
}
datastoreRaw.Properties = props

_, err = client.CreateOrUpdate(ctx, id, datastoreRaw, datastore.DefaultCreateOrUpdateOperationOptions())
if err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

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

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

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

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

containerId, err := storageparse.StorageContainerResourceManagerID(state.StorageContainerID)
if err != nil {
return err
}

datastoreRaw := datastore.DatastoreResource{
Name: utils.String(id.Name),
Type: utils.ToPtr(string(datastore.DatastoreTypeAzureBlob)),
}

props := &datastore.AzureBlobDatastore{
AccountName: utils.String(containerId.StorageAccountName),
ContainerName: utils.String(containerId.ContainerName),
Description: utils.String(state.Description),
ServiceDataAccessAuthIdentity: utils.ToPtr(datastore.ServiceDataAccessAuthIdentity(state.ServiceDataAuthIdentity)),
IsDefault: utils.Bool(state.IsDefault),
Tags: utils.ToPtr(state.Tags),
}

accountKey := state.AccountKey
if accountKey != "" {
props.Credentials = map[string]interface{}{
"credentialsType": string(datastore.CredentialsTypeAccountKey),
"secrets": map[string]interface{}{
"secretsType": "AccountKey",
"key": accountKey,
},
}
}

sasToken := state.SharedAccessSignature
if sasToken != "" {
props.Credentials = map[string]interface{}{
"credentialsType": string(datastore.CredentialsTypeSas),
"secrets": map[string]interface{}{
"secretsType": "Sas",
"sasToken": sasToken,
},
}
}
datastoreRaw.Properties = props

_, err = client.CreateOrUpdate(ctx, *id, datastoreRaw, datastore.DefaultCreateOrUpdateOperationOptions())
if err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}

return nil
},
}
}

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

id, err := datastore.ParseDataStoreID(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)
}

workspaceId := workspaces.NewWorkspaceID(subscriptionId, id.ResourceGroupName, id.WorkspaceName)
model := MachineLearningDataStoreBlobStorageModel{
Name: *resp.Model.Name,
WorkSpaceID: workspaceId.ID(),
}

data := resp.Model.Properties.(datastore.AzureBlobDatastore)
serviceDataAuth := ""
if v := data.ServiceDataAccessAuthIdentity; v != nil {
serviceDataAuth = string(*v)
}
model.ServiceDataAuthIdentity = serviceDataAuth

containerId := storageparse.NewStorageContainerResourceManagerID(subscriptionId, workspaceId.ResourceGroupName, *data.AccountName, "default", *data.ContainerName)
model.StorageContainerID = containerId.ID()
model.IsDefault = *data.IsDefault

if v, ok := metadata.ResourceData.GetOk("account_key"); ok {
if v.(string) != "" {
model.AccountKey = v.(string)
}
}

if v, ok := metadata.ResourceData.GetOk("shared_access_signature"); ok {
if v.(string) != "" {
model.SharedAccessSignature = v.(string)
}
}

desc := ""
if v := data.Description; v != nil {
desc = *v
}
model.Description = desc

if data.Tags != nil {
model.Tags = *data.Tags
}

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

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

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

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

return nil
},
}
}
Loading