diff --git a/.github/labeler-issue-triage.yml b/.github/labeler-issue-triage.yml index 4ed2475cf41c..50a9cc268245 100644 --- a/.github/labeler-issue-triage.yml +++ b/.github/labeler-issue-triage.yml @@ -119,6 +119,9 @@ service/datadog: service/dev-center: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_dev_center((.|\n)*)###' +service/deviceregistry: + - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_device_registry_asset((.|\n)*)###' + service/devtestlabs: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_dev_test_((.|\n)*)###' diff --git a/.github/labeler-pull-request-triage.yml b/.github/labeler-pull-request-triage.yml index f2a786bebfa9..67646d289314 100644 --- a/.github/labeler-pull-request-triage.yml +++ b/.github/labeler-pull-request-triage.yml @@ -198,6 +198,11 @@ service/dev-center: - any-glob-to-any-file: - internal/services/devcenter/**/* +service/deviceregistry: +- changed-files: + - any-glob-to-any-file: + - internal/services/deviceregistry/**/* + service/devtestlabs: - changed-files: - any-glob-to-any-file: diff --git a/.teamcity/components/generated/services.kt b/.teamcity/components/generated/services.kt index 9d296b6a355b..3419bfbd85db 100644 --- a/.teamcity/components/generated/services.kt +++ b/.teamcity/components/generated/services.kt @@ -46,6 +46,7 @@ var services = mapOf( "desktopvirtualization" to "Desktop Virtualization", "devcenter" to "Dev Center", "devtestlabs" to "Dev Test", + "deviceregistry" to "Device Registry", "digitaltwins" to "Digital Twins", "domainservices" to "DomainServices", "dynatrace" to "Dynatrace", diff --git a/CODEOWNERS b/CODEOWNERS index aa9fe086b7e1..65f4630c319a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1,4 @@ * @hashicorp/terraform-azure + +# PRLabel: %Device Registry +/internal/services/deviceregistry/ @marcodalessandro @rohankhandelwal @riteshrao @davidemontanari \ No newline at end of file diff --git a/internal/clients/client.go b/internal/clients/client.go index 1c2f60354183..b9363d621537 100644 --- a/internal/clients/client.go +++ b/internal/clients/client.go @@ -63,6 +63,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" + deviceregistry "github.com/hashicorp/terraform-provider-azurerm/internal/services/deviceregistry/client" devtestlabs "github.com/hashicorp/terraform-provider-azurerm/internal/services/devtestlabs/client" digitaltwins "github.com/hashicorp/terraform-provider-azurerm/internal/services/digitaltwins/client" dns "github.com/hashicorp/terraform-provider-azurerm/internal/services/dns/client" @@ -199,6 +200,7 @@ type Client struct { DataProtection *dataprotection.Client DataShare *datashare.Client DesktopVirtualization *desktopvirtualization.Client + DeviceRegistry *deviceregistry.Client DevTestLabs *devtestlabs.Client DigitalTwins *digitaltwins.Client Dns *dns_v2018_05_01.Client @@ -421,6 +423,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.DeviceRegistry, err = deviceregistry.NewClient(o); err != nil { + return fmt.Errorf("building clients for DeviceRegistry: %+v", err) + } if client.DevTestLabs, err = devtestlabs.NewClient(o); err != nil { return fmt.Errorf("building clients for DevTestLabs: %+v", err) } diff --git a/internal/provider/services.go b/internal/provider/services.go index 8e5e45fa358f..2c6c99ff1e95 100644 --- a/internal/provider/services.go +++ b/internal/provider/services.go @@ -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/deviceregistry" "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/dns" @@ -167,6 +168,7 @@ func SupportedTypedServices() []sdk.TypedServiceRegistration { datafactory.Registration{}, dataprotection.Registration{}, desktopvirtualization.Registration{}, + deviceregistry.Registration{}, digitaltwins.Registration{}, dns.Registration{}, domainservices.Registration{}, diff --git a/internal/services/deviceregistry/client/client.go b/internal/services/deviceregistry/client/client.go new file mode 100644 index 000000000000..07856fa1a0b2 --- /dev/null +++ b/internal/services/deviceregistry/client/client.go @@ -0,0 +1,34 @@ +package client + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles" + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets" + + "github.com/hashicorp/terraform-provider-azurerm/internal/common" +) + +type Client struct { + AssetClient *assets.AssetsClient + AssetEndpointProfileClient *assetendpointprofiles.AssetEndpointProfilesClient +} + +func NewClient(o *common.ClientOptions) (*Client, error) { + assetEndpointProfileClient, err := assetendpointprofiles.NewAssetEndpointProfilesClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("creating AssetEndpointProfiles Client: %+v", err) + } + o.Configure(assetEndpointProfileClient.Client, o.Authorizers.ResourceManager) + + assetClient, err := assets.NewAssetsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("creating Asset Client: %+v", err) + } + o.Configure(assetClient.Client, o.Authorizers.ResourceManager) + + return &Client{ + AssetClient: assetClient, + AssetEndpointProfileClient: assetEndpointProfileClient, + }, nil +} diff --git a/internal/services/deviceregistry/device_registry_asset_resource.go b/internal/services/deviceregistry/device_registry_asset_resource.go new file mode 100644 index 000000000000..c94f57cb0a90 --- /dev/null +++ b/internal/services/deviceregistry/device_registry_asset_resource.go @@ -0,0 +1,743 @@ +package deviceregistry + +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/location" + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets" + "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.Resource = AssetResource{} + +type AssetResource struct{} + +type AssetResourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + Tags map[string]string `tfschema:"tags"` + ExtendedLocationName string `tfschema:"extended_location_name"` + ExtendedLocationType string `tfschema:"extended_location_type"` + Enabled bool `tfschema:"enabled"` + ExternalAssetId string `tfschema:"external_asset_id"` + DisplayName string `tfschema:"display_name"` + Description string `tfschema:"description"` + AssetEndpointProfileRef string `tfschema:"asset_endpoint_profile_ref"` + Manufacturer string `tfschema:"manufacturer"` + ManufacturerUri string `tfschema:"manufacturer_uri"` + Model string `tfschema:"model"` + ProductCode string `tfschema:"product_code"` + HardwareRevision string `tfschema:"hardware_revision"` + SoftwareRevision string `tfschema:"software_revision"` + DocumentationUri string `tfschema:"documentation_uri"` + SerialNumber string `tfschema:"serial_number"` + Attributes map[string]interface{} `tfschema:"attributes"` + DiscoveredAssetRefs []string `tfschema:"discovered_asset_refs"` + DefaultDatasetsConfiguration string `tfschema:"default_datasets_configuration"` + DefaultEventsConfiguration string `tfschema:"default_events_configuration"` + DefaultTopicPath string `tfschema:"default_topic_path"` + DefaultTopicRetain string `tfschema:"default_topic_retain"` + Datasets []Dataset `tfschema:"datasets"` + Events []Event `tfschema:"events"` +} + +type Dataset struct { + Name string `tfschema:"name"` + DatasetConfiguration string `tfschema:"dataset_configuration"` + TopicPath string `tfschema:"topic_path"` + TopicRetain string `tfschema:"topic_retain"` + DataPoints []DataPoint `tfschema:"data_points"` +} + +type DataPoint struct { + Name string `tfschema:"name"` + DataSource string `tfschema:"data_source"` + ObservabilityMode string `tfschema:"observability_mode"` + DataPointConfiguration string `tfschema:"data_point_configuration"` +} + +type Event struct { + Name string `tfschema:"name"` + EventNotifier string `tfschema:"event_notifier"` + ObservabilityMode string `tfschema:"observability_mode"` + EventConfiguration string `tfschema:"event_configuration"` + TopicPath string `tfschema:"topic_path"` + TopicRetain string `tfschema:"topic_retain"` +} + +func (AssetResource) Arguments() map[string]*pluginsdk.Schema { + // add the other asset properties + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "resource_group_name": commonschema.ResourceGroupName(), + "location": commonschema.Location(), + "tags": commonschema.Tags(), + "extended_location_name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "extended_location_type": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + }, + "external_asset_id": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "display_name": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "description": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "asset_endpoint_profile_ref": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "manufacturer": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "manufacturer_uri": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "model": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "product_code": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "hardware_revision": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "software_revision": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "documentation_uri": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "serial_number": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "attributes": { + Type: pluginsdk.TypeMap, + Optional: true, + Elem: &pluginsdk.Schema{Type: pluginsdk.TypeString}, + }, + "discovered_asset_refs": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + "default_datasets_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "default_events_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "default_topic_path": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "default_topic_retain": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(assets.PossibleValuesForTopicRetainType(), false), + RequiredWith: []string{"default_topic_path"}, + }, + "datasets": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + }, + "dataset_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "topic_path": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "topic_retain": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(assets.PossibleValuesForTopicRetainType(), false), + }, + "data_points": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + }, + "data_source": { + Type: pluginsdk.TypeString, + Required: true, + }, + "observability_mode": { + Type: pluginsdk.TypeString, + Optional: true, + Default: string(assets.DataPointObservabilityModeNone), + ValidateFunc: validation.StringInSlice(assets.PossibleValuesForDataPointObservabilityMode(), false), + }, + "data_point_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "events": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + }, + "event_notifier": { + Type: pluginsdk.TypeString, + Required: true, + }, + "observability_mode": { + Type: pluginsdk.TypeString, + Optional: true, + Default: string(assets.EventObservabilityModeNone), + ValidateFunc: validation.StringInSlice(assets.PossibleValuesForEventObservabilityMode(), false), + }, + "event_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "topic_path": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "topic_retain": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(assets.PossibleValuesForTopicRetainType(), false), + }, + }, + }, + }, + } +} + +func (AssetResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (AssetResource) ModelObject() interface{} { + return &AssetResourceModel{} +} + +func (AssetResource) ResourceType() string { + return "azurerm_device_registry_asset" +} + +func (r AssetResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetClient + subscriptionId := metadata.Client.Account.SubscriptionId + + var config AssetResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + id := assets.NewAssetID(subscriptionId, config.ResourceGroupName, config.Name) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + // Convert the TF model to the ARM model + // Optional ARM resource properties are pointers. + param := assets.Asset{ + Location: location.Normalize(config.Location), + Tags: pointer.To(config.Tags), + ExtendedLocation: assets.ExtendedLocation{ + Name: config.ExtendedLocationName, + Type: config.ExtendedLocationType, + }, + Properties: &assets.AssetProperties{ + AssetEndpointProfileRef: config.AssetEndpointProfileRef, + }, + } + + // Enabled in config will be default set to false if not explicitly set in Terraform. + // We must check the raw value if it is null so we don't just send false if user didn't specify + if !pluginsdk.IsExplicitlyNullInConfig(metadata.ResourceData, "enabled") { + param.Properties.Enabled = pointer.To(config.Enabled) + } + + if config.ExternalAssetId != "" { + param.Properties.ExternalAssetId = pointer.To(config.ExternalAssetId) + } + + if config.DisplayName != "" { + param.Properties.DisplayName = pointer.To(config.DisplayName) + } + + if config.Description != "" { + param.Properties.Description = pointer.To(config.Description) + } + + if config.Manufacturer != "" { + param.Properties.Manufacturer = pointer.To(config.Manufacturer) + } + + if config.ManufacturerUri != "" { + param.Properties.ManufacturerUri = pointer.To(config.ManufacturerUri) + } + + if config.Model != "" { + param.Properties.Model = pointer.To(config.Model) + } + + if config.ProductCode != "" { + param.Properties.ProductCode = pointer.To(config.ProductCode) + } + + if config.HardwareRevision != "" { + param.Properties.HardwareRevision = pointer.To(config.HardwareRevision) + } + + if config.SoftwareRevision != "" { + param.Properties.SoftwareRevision = pointer.To(config.SoftwareRevision) + } + + if config.DocumentationUri != "" { + param.Properties.DocumentationUri = pointer.To(config.DocumentationUri) + } + + if config.SerialNumber != "" { + param.Properties.SerialNumber = pointer.To(config.SerialNumber) + } + + if config.Attributes != nil { + param.Properties.Attributes = pointer.To(config.Attributes) + } + + if config.DiscoveredAssetRefs != nil { + param.Properties.DiscoveredAssetRefs = pointer.To(config.DiscoveredAssetRefs) + } + + if config.DefaultDatasetsConfiguration != "" { + param.Properties.DefaultDatasetsConfiguration = pointer.To(config.DefaultDatasetsConfiguration) + } + + if config.DefaultEventsConfiguration != "" { + param.Properties.DefaultEventsConfiguration = pointer.To(config.DefaultEventsConfiguration) + } + + param.Properties.DefaultTopic = toAzureTopic(config.DefaultTopicPath, config.DefaultTopicRetain) + + param.Properties.Datasets = toAzureDatasets(config.Datasets) + + param.Properties.Events = toAzureEvents(config.Events) + + if err := client.CreateOrReplaceThenPoll(ctx, id, param); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r AssetResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetClient + + id, err := assets.ParseAssetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var config AssetResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + // Change the properties that can be updated + param := assets.AssetUpdate{ + Properties: &assets.AssetUpdateProperties{}, + } + + if metadata.ResourceData.HasChange("tags") { + param.Tags = pointer.To(config.Tags) + } + + if metadata.ResourceData.HasChange("attributes") { + param.Properties.Attributes = pointer.To(config.Attributes) + } + + if metadata.ResourceData.HasChange("datasets") { + param.Properties.Datasets = toAzureDatasets(config.Datasets) + } + + if metadata.ResourceData.HasChange("default_datasets_configuration") { + param.Properties.DefaultDatasetsConfiguration = pointer.To(config.DefaultDatasetsConfiguration) + } + + if metadata.ResourceData.HasChange("default_events_configuration") { + param.Properties.DefaultEventsConfiguration = pointer.To(config.DefaultEventsConfiguration) + } + + defaultTopicPathChanged := metadata.ResourceData.HasChange("default_topic_path") + defaultTopicRetainChanged := metadata.ResourceData.HasChange("default_topic_retain") + if defaultTopicPathChanged || defaultTopicRetainChanged { + param.Properties.DefaultTopic = &assets.TopicUpdate{} + if defaultTopicPathChanged { + param.Properties.DefaultTopic.Path = pointer.To(config.DefaultTopicPath) + } + if defaultTopicRetainChanged { + // Bug with `go-azure-sdk` library: you can't set retain to null because empty string will cause + // ARM to throw validation error (retain must be one of the property's possible enum values), + // and go-azure-sdk library will ignore the retain field if it's set to nil, even if explicitly set. + param.Properties.DefaultTopic.Retain = pointer.To(assets.TopicRetainType(config.DefaultTopicRetain)) + } + } + + if metadata.ResourceData.HasChange("description") { + param.Properties.Description = pointer.To(config.Description) + } + + if metadata.ResourceData.HasChange("display_name") { + param.Properties.DisplayName = pointer.To(config.DisplayName) + } + + if metadata.ResourceData.HasChange("documentation_uri") { + param.Properties.DocumentationUri = pointer.To(config.DocumentationUri) + } + + if metadata.ResourceData.HasChange("enabled") { + param.Properties.Enabled = pointer.To(config.Enabled) + } + + if metadata.ResourceData.HasChange("events") { + param.Properties.Events = toAzureEvents(config.Events) + } + + if metadata.ResourceData.HasChange("hardware_revision") { + param.Properties.HardwareRevision = pointer.To(config.HardwareRevision) + } + + if metadata.ResourceData.HasChange("manufacturer") { + param.Properties.Manufacturer = pointer.To(config.Manufacturer) + } + + if metadata.ResourceData.HasChange("manufacturer_uri") { + param.Properties.ManufacturerUri = pointer.To(config.ManufacturerUri) + } + + if metadata.ResourceData.HasChange("model") { + param.Properties.Model = pointer.To(config.Model) + } + + if metadata.ResourceData.HasChange("product_code") { + param.Properties.ProductCode = pointer.To(config.ProductCode) + } + + if metadata.ResourceData.HasChange("serial_number") { + param.Properties.SerialNumber = pointer.To(config.SerialNumber) + } + + if metadata.ResourceData.HasChange("software_revision") { + param.Properties.SoftwareRevision = pointer.To(config.SoftwareRevision) + } + + if err := client.UpdateThenPoll(ctx, *id, param); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + return nil + }, + } +} + +func (AssetResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetClient + + id, err := assets.ParseAssetID(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("retrieving %s: %+v", id, err) + } + + // Convert the ARM model to the TF model + state := AssetResourceModel{ + Name: id.AssetName, + ResourceGroupName: id.ResourceGroupName, + } + + if model := resp.Model; model != nil { + state.Location = location.Normalize(model.Location) + state.Tags = pointer.From(model.Tags) + state.ExtendedLocationName = model.ExtendedLocation.Name + state.ExtendedLocationType = model.ExtendedLocation.Type + if props := model.Properties; props != nil { + state.AssetEndpointProfileRef = props.AssetEndpointProfileRef + state.Enabled = pointer.From(props.Enabled) + state.ExternalAssetId = pointer.From(props.ExternalAssetId) + state.DisplayName = pointer.From(props.DisplayName) + state.Description = pointer.From(props.Description) + state.Manufacturer = pointer.From(props.Manufacturer) + state.ManufacturerUri = pointer.From(props.ManufacturerUri) + state.Model = pointer.From(props.Model) + state.ProductCode = pointer.From(props.ProductCode) + state.HardwareRevision = pointer.From(props.HardwareRevision) + state.SoftwareRevision = pointer.From(props.SoftwareRevision) + state.DocumentationUri = pointer.From(props.DocumentationUri) + state.SerialNumber = pointer.From(props.SerialNumber) + state.Attributes = pointer.From(props.Attributes) + state.DiscoveredAssetRefs = pointer.From(props.DiscoveredAssetRefs) + state.DefaultDatasetsConfiguration = pointer.From(props.DefaultDatasetsConfiguration) + state.DefaultEventsConfiguration = pointer.From(props.DefaultEventsConfiguration) + + if defaultTopic := props.DefaultTopic; defaultTopic != nil { + state.DefaultTopicPath, state.DefaultTopicRetain = toTFTopic(props.DefaultTopic) + } + + if datasets := props.Datasets; datasets != nil { + state.Datasets = toTFDatasets(datasets) + } + + if events := props.Events; events != nil { + state.Events = toTFEvents(events) + } + } + } + return metadata.Encode(&state) + }, + } +} + +func (AssetResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetClient + + id, err := assets.ParseAssetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} + +func (AssetResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return assets.ValidateAssetID +} + +func toAzureDatasets(datasets []Dataset) *[]assets.Dataset { + if datasets == nil { + return nil + } + + azureDatasets := make([]assets.Dataset, len(datasets)) + for i, dataset := range datasets { + azureDatasets[i] = assets.Dataset{ + Name: dataset.Name, + DatasetConfiguration: pointer.To(dataset.DatasetConfiguration), + Topic: toAzureTopic(dataset.TopicPath, dataset.TopicRetain), + DataPoints: toAzureDataPoints(dataset.DataPoints), + } + } + + return &azureDatasets +} + +func toAzureDataPoints(dataPoints []DataPoint) *[]assets.DataPoint { + if dataPoints == nil { + return nil + } + + azureDataPoints := make([]assets.DataPoint, len(dataPoints)) + for i, dataPoint := range dataPoints { + azureDataPoints[i] = assets.DataPoint{ + Name: dataPoint.Name, + DataSource: dataPoint.DataSource, + ObservabilityMode: pointer.To(assets.DataPointObservabilityMode(dataPoint.ObservabilityMode)), + DataPointConfiguration: pointer.To(dataPoint.DataPointConfiguration), + } + } + + return &azureDataPoints +} + +func toAzureEvents(events []Event) *[]assets.Event { + if events == nil { + return nil + } + + azureEvents := make([]assets.Event, len(events)) + for i, event := range events { + azureEvents[i] = assets.Event{ + Name: event.Name, + EventNotifier: event.EventNotifier, + EventConfiguration: pointer.To(event.EventConfiguration), + ObservabilityMode: pointer.To(assets.EventObservabilityMode(event.ObservabilityMode)), + Topic: toAzureTopic(event.TopicPath, event.TopicRetain), + } + } + + return &azureEvents +} + +func toAzureTopic(topicPath string, topicRetain string) *assets.Topic { + if topicPath == "" && topicRetain == "" { + return nil + } + + azureTopic := assets.Topic{ + Path: topicPath, + } + + // Topic retain is optional, but if it's set, it must be one of the possible values + if topicRetain != "" { + azureTopic.Retain = pointer.To(assets.TopicRetainType(topicRetain)) + } + + return &azureTopic +} + +func toTFDatasets(datasets *[]assets.Dataset) []Dataset { + if datasets == nil { + return nil + } + + tfDatasets := make([]Dataset, len(*datasets)) + for i, dataset := range *datasets { + topicPath, topicRetain := toTFTopic(dataset.Topic) + tfDatasets[i] = Dataset{ + Name: dataset.Name, + DatasetConfiguration: pointer.From(dataset.DatasetConfiguration), + DataPoints: toTFDataPoints(dataset.DataPoints), + TopicPath: topicPath, + TopicRetain: topicRetain, + } + } + + return tfDatasets +} + +func toTFDataPoints(dataPoints *[]assets.DataPoint) []DataPoint { + if dataPoints == nil { + return nil + } + + tfDataPoints := make([]DataPoint, len(*dataPoints)) + for i, dataPoint := range *dataPoints { + tfDataPoints[i] = DataPoint{ + Name: dataPoint.Name, + DataSource: dataPoint.DataSource, + ObservabilityMode: string(pointer.From(dataPoint.ObservabilityMode)), + DataPointConfiguration: pointer.From(dataPoint.DataPointConfiguration), + } + } + + return tfDataPoints +} + +func toTFEvents(events *[]assets.Event) []Event { + if events == nil { + return nil + } + + tfEvents := make([]Event, len(*events)) + for i, event := range *events { + topicPath, topicRetain := toTFTopic(event.Topic) + tfEvents[i] = Event{ + Name: event.Name, + EventNotifier: event.EventNotifier, + ObservabilityMode: string(pointer.From(event.ObservabilityMode)), + EventConfiguration: pointer.From(event.EventConfiguration), + TopicPath: topicPath, + TopicRetain: topicRetain, + } + } + + return tfEvents +} + +func toTFTopic(topic *assets.Topic) (string, string) { + if topic == nil { + return "", "" + } + + if topic.Retain == nil { + return topic.Path, "" + } else { + return topic.Path, string(pointer.From(topic.Retain)) + } +} diff --git a/internal/services/deviceregistry/device_registry_asset_resource_test.go b/internal/services/deviceregistry/device_registry_asset_resource_test.go new file mode 100644 index 000000000000..16ec5d0c06bb --- /dev/null +++ b/internal/services/deviceregistry/device_registry_asset_resource_test.go @@ -0,0 +1,420 @@ +package deviceregistry_test + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type AssetTestResource struct{} + +const ( + ASSET_CUSTOM_LOCATION_NAME = "ARM_DEVICE_REGISTRY_CUSTOM_LOCATION" + ASSET_RESOURCE_GROUP_NAME = "ARM_DEVICE_REGISTRY_RESOURCE_GROUP" +) + +func TestAccAsset_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset", "test") + r := AssetTestResource{} + + if os.Getenv(ASSET_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_CUSTOM_LOCATION_NAME, ASSET_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("asset_endpoint_profile_ref").HasValue("myAssetEndpointProfile"), + check.That(data.ResourceName).Key("discovered_asset_refs.#").HasValue("3"), + check.That(data.ResourceName).Key("discovered_asset_refs.0").HasValue("foo"), + check.That(data.ResourceName).Key("discovered_asset_refs.1").HasValue("bar"), + check.That(data.ResourceName).Key("discovered_asset_refs.2").HasValue("baz"), + check.That(data.ResourceName).Key("display_name").HasValue("my asset"), + check.That(data.ResourceName).Key("enabled").HasValue("false"), + check.That(data.ResourceName).Key("external_asset_id").HasValue("8ZBA6LRHU0A458969"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAsset_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset", "test") + r := AssetTestResource{} + + if os.Getenv(ASSET_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_CUSTOM_LOCATION_NAME, ASSET_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("asset_endpoint_profile_ref").HasValue("myAssetEndpointProfile"), + check.That(data.ResourceName).Key("display_name").HasValue("my asset"), + check.That(data.ResourceName).Key("enabled").HasValue("true"), + check.That(data.ResourceName).Key("external_asset_id").HasValue("8ZBA6LRHU0A458969"), + check.That(data.ResourceName).Key("attributes.foo").HasValue("bar"), + check.That(data.ResourceName).Key("attributes.x").HasValue("y"), + check.That(data.ResourceName).Key("default_datasets_configuration").HasValue("{\"defaultPublishingInterval\":200,\"defaultQueueSize\":10,\"defaultSamplingInterval\":500}"), + check.That(data.ResourceName).Key("default_events_configuration").HasValue("{\"defaultPublishingInterval\":200,\"defaultQueueSize\":10,\"defaultSamplingInterval\":500}"), + check.That(data.ResourceName).Key("default_topic_path").HasValue("/path/defaultTopic"), + check.That(data.ResourceName).Key("default_topic_retain").HasValue("Keep"), + check.That(data.ResourceName).Key("description").HasValue("this is my asset"), + check.That(data.ResourceName).Key("discovered_asset_refs.#").HasValue("3"), + check.That(data.ResourceName).Key("discovered_asset_refs.0").HasValue("foo"), + check.That(data.ResourceName).Key("discovered_asset_refs.1").HasValue("bar"), + check.That(data.ResourceName).Key("discovered_asset_refs.2").HasValue("baz"), + check.That(data.ResourceName).Key("documentation_uri").HasValue("https://example.com/about"), + check.That(data.ResourceName).Key("hardware_revision").HasValue("1.0"), + check.That(data.ResourceName).Key("manufacturer").HasValue("Contoso"), + check.That(data.ResourceName).Key("manufacturer_uri").HasValue("https://www.contoso.com/manufacturerUri"), + check.That(data.ResourceName).Key("model").HasValue("ContosoModel"), + check.That(data.ResourceName).Key("product_code").HasValue("SA34VDG"), + check.That(data.ResourceName).Key("serial_number").HasValue("64-103816-519918-8"), + check.That(data.ResourceName).Key("software_revision").HasValue("2.0"), + check.That(data.ResourceName).Key("tags.site").HasValue("building-1"), + check.That(data.ResourceName).Key("datasets.#").HasValue("1"), + check.That(data.ResourceName).Key("datasets.0.dataset_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.name").HasValue("dataset1"), + check.That(data.ResourceName).Key("datasets.0.topic_path").HasValue("/path/dataset1"), + check.That(data.ResourceName).Key("datasets.0.topic_retain").HasValue("Keep"), + check.That(data.ResourceName).Key("datasets.0.data_points.#").HasValue("2"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.data_point_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.data_source").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.name").HasValue("datapoint1"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.observability_mode").HasValue("Counter"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.data_point_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.data_source").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.name").HasValue("datapoint2"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.observability_mode").HasValue("None"), + check.That(data.ResourceName).Key("events.#").HasValue("2"), + check.That(data.ResourceName).Key("events.0.event_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("events.0.event_notifier").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt3"), + check.That(data.ResourceName).Key("events.0.name").HasValue("event1"), + check.That(data.ResourceName).Key("events.0.observability_mode").HasValue("Log"), + check.That(data.ResourceName).Key("events.0.topic_path").HasValue("/path/event1"), + check.That(data.ResourceName).Key("events.0.topic_retain").HasValue("Never"), + check.That(data.ResourceName).Key("events.1.event_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("events.1.event_notifier").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt4"), + check.That(data.ResourceName).Key("events.1.name").HasValue("event2"), + check.That(data.ResourceName).Key("events.1.observability_mode").HasValue("None"), + check.That(data.ResourceName).Key("events.1.topic_path").HasValue("/path/event2"), + check.That(data.ResourceName).Key("events.1.topic_retain").HasValue("Keep"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAsset_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset", "test") + r := AssetTestResource{} + + if os.Getenv(ASSET_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_CUSTOM_LOCATION_NAME, ASSET_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccAsset_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset", "test") + r := AssetTestResource{} + + if os.Getenv(ASSET_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_CUSTOM_LOCATION_NAME, ASSET_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("asset_endpoint_profile_ref").HasValue("myAssetEndpointProfile"), + check.That(data.ResourceName).Key("display_name").HasValue("my asset"), + check.That(data.ResourceName).Key("enabled").HasValue("true"), + check.That(data.ResourceName).Key("external_asset_id").HasValue("8ZBA6LRHU0A458969"), + check.That(data.ResourceName).Key("attributes.foo").HasValue("bar"), + check.That(data.ResourceName).Key("attributes.x").HasValue("y"), + check.That(data.ResourceName).Key("default_datasets_configuration").HasValue("{\"defaultPublishingInterval\":200,\"defaultQueueSize\":10,\"defaultSamplingInterval\":500}"), + check.That(data.ResourceName).Key("default_events_configuration").HasValue("{\"defaultPublishingInterval\":200,\"defaultQueueSize\":10,\"defaultSamplingInterval\":500}"), + check.That(data.ResourceName).Key("default_topic_path").HasValue("/path/defaultTopic"), + check.That(data.ResourceName).Key("default_topic_retain").HasValue("Keep"), + check.That(data.ResourceName).Key("description").HasValue("this is my asset"), + check.That(data.ResourceName).Key("discovered_asset_refs.#").HasValue("3"), + check.That(data.ResourceName).Key("discovered_asset_refs.0").HasValue("foo"), + check.That(data.ResourceName).Key("discovered_asset_refs.1").HasValue("bar"), + check.That(data.ResourceName).Key("discovered_asset_refs.2").HasValue("baz"), + check.That(data.ResourceName).Key("documentation_uri").HasValue("https://example.com/about"), + check.That(data.ResourceName).Key("hardware_revision").HasValue("1.0"), + check.That(data.ResourceName).Key("manufacturer").HasValue("Contoso"), + check.That(data.ResourceName).Key("manufacturer_uri").HasValue("https://www.contoso.com/manufacturerUri"), + check.That(data.ResourceName).Key("model").HasValue("ContosoModel"), + check.That(data.ResourceName).Key("product_code").HasValue("SA34VDG"), + check.That(data.ResourceName).Key("serial_number").HasValue("64-103816-519918-8"), + check.That(data.ResourceName).Key("software_revision").HasValue("2.0"), + check.That(data.ResourceName).Key("tags.site").HasValue("building-1"), + check.That(data.ResourceName).Key("datasets.#").HasValue("1"), + check.That(data.ResourceName).Key("datasets.0.dataset_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.name").HasValue("dataset1"), + check.That(data.ResourceName).Key("datasets.0.topic_path").HasValue("/path/dataset1"), + check.That(data.ResourceName).Key("datasets.0.topic_retain").HasValue("Keep"), + check.That(data.ResourceName).Key("datasets.0.data_points.#").HasValue("2"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.data_point_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.data_source").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.name").HasValue("datapoint1"), + check.That(data.ResourceName).Key("datasets.0.data_points.0.observability_mode").HasValue("Counter"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.data_point_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.data_source").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.name").HasValue("datapoint2"), + check.That(data.ResourceName).Key("datasets.0.data_points.1.observability_mode").HasValue("None"), + check.That(data.ResourceName).Key("events.#").HasValue("2"), + check.That(data.ResourceName).Key("events.0.event_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("events.0.event_notifier").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt3"), + check.That(data.ResourceName).Key("events.0.name").HasValue("event1"), + check.That(data.ResourceName).Key("events.0.observability_mode").HasValue("Log"), + check.That(data.ResourceName).Key("events.0.topic_path").HasValue("/path/event1"), + check.That(data.ResourceName).Key("events.0.topic_retain").HasValue("Never"), + check.That(data.ResourceName).Key("events.1.event_configuration").HasValue("{\"publishingInterval\":7,\"queueSize\":8,\"samplingInterval\":1000}"), + check.That(data.ResourceName).Key("events.1.event_notifier").HasValue("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt4"), + check.That(data.ResourceName).Key("events.1.name").HasValue("event2"), + check.That(data.ResourceName).Key("events.1.observability_mode").HasValue("None"), + check.That(data.ResourceName).Key("events.1.topic_path").HasValue("/path/event2"), + check.That(data.ResourceName).Key("events.1.topic_retain").HasValue("Keep"), + ), + }, + data.ImportStep(), + }) +} + +func (AssetTestResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := assets.ParseAssetID(state.ID) + if err != nil { + return nil, err + } + resp, err := client.DeviceRegistry.AssetClient.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) + } + return utils.Bool(true), nil +} + +func (r AssetTestResource) basic(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset" "test" { + name = "acctest-asset-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + asset_endpoint_profile_ref = "myAssetEndpointProfile" + discovered_asset_refs = [ + "foo", + "bar", + "baz", + ] + display_name = "my asset" + enabled = false + external_asset_id = "8ZBA6LRHU0A458969" + location = "%[3]s" +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetTestResource) complete(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset" "test" { + name = "acctest-asset-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + location = "%[3]s" + asset_endpoint_profile_ref = "myAssetEndpointProfile" + display_name = "my asset" + enabled = true + external_asset_id = "8ZBA6LRHU0A458969" + attributes = { + "foo" = "bar" + "x" = "y" + } + default_datasets_configuration = jsonencode( + { + defaultPublishingInterval = 200 + defaultQueueSize = 10 + defaultSamplingInterval = 500 + } + ) + default_events_configuration = jsonencode( + { + defaultPublishingInterval = 200 + defaultQueueSize = 10 + defaultSamplingInterval = 500 + } + ) + default_topic_path = "/path/defaultTopic" + default_topic_retain = "Keep" + description = "this is my asset" + discovered_asset_refs = [ + "foo", + "bar", + "baz", + ] + documentation_uri = "https://example.com/about" + hardware_revision = "1.0" + manufacturer = "Contoso" + manufacturer_uri = "https://www.contoso.com/manufacturerUri" + model = "ContosoModel" + product_code = "SA34VDG" + serial_number = "64-103816-519918-8" + software_revision = "2.0" + tags = { + "site" = "building-1" + } + + datasets { + dataset_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + name = "dataset1" + topic_path = "/path/dataset1" + topic_retain = "Keep" + + data_points { + data_point_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + data_source = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" + name = "datapoint1" + observability_mode = "Counter" + } + data_points { + data_point_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + data_source = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2" + name = "datapoint2" + observability_mode = "None" + } + } + + events { + event_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + event_notifier = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt3" + name = "event1" + observability_mode = "Log" + topic_path = "/path/event1" + topic_retain = "Never" + } + events { + event_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + event_notifier = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt4" + name = "event2" + observability_mode = "None" + topic_path = "/path/event2" + topic_retain = "Keep" + } +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetTestResource) requiresImport(data acceptance.TestData) string { + template := r.basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset" "import" { + name = azurerm_device_registry_asset.test.name + resource_group_name = azurerm_device_registry_asset.test.resource_group_name + extended_location_name = azurerm_device_registry_asset.test.extended_location_name + extended_location_type = azurerm_device_registry_asset.test.extended_location_type + asset_endpoint_profile_ref = azurerm_device_registry_asset.test.asset_endpoint_profile_ref + display_name = azurerm_device_registry_asset.test.display_name + enabled = azurerm_device_registry_asset.test.enabled + external_asset_id = azurerm_device_registry_asset.test.external_asset_id + location = azurerm_device_registry_asset.test.location +} + + +`, template) +} + +/* +Creates the terraform template for AzureRm provider and needed constants +*/ +func (AssetTestResource) template() string { + customLocation := os.Getenv(ASSET_CUSTOM_LOCATION_NAME) + resourceGroup := os.Getenv(ASSET_RESOURCE_GROUP_NAME) + + return fmt.Sprintf(` +locals { + custom_location_name = "%[1]s" + resource_group_name = "%[2]s" +} + +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} +`, customLocation, resourceGroup) +} diff --git a/internal/services/deviceregistry/device_registry_assetendpointprofile_resource.go b/internal/services/deviceregistry/device_registry_assetendpointprofile_resource.go new file mode 100644 index 000000000000..edb3211d31c2 --- /dev/null +++ b/internal/services/deviceregistry/device_registry_assetendpointprofile_resource.go @@ -0,0 +1,346 @@ +package deviceregistry + +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/location" + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles" + "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.Resource = AssetEndpointProfileResource{} + +type AssetEndpointProfileResource struct{} + +type AssetEndpointProfileResourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + Tags map[string]string `tfschema:"tags"` + ExtendedLocationName string `tfschema:"extended_location_name"` + ExtendedLocationType string `tfschema:"extended_location_type"` + TargetAddress string `tfschema:"target_address"` + EndpointProfileType string `tfschema:"endpoint_profile_type"` + DiscoveredAssetEndpointProfileRef string `tfschema:"discovered_asset_endpoint_profile_ref"` + AdditionalConfiguration string `tfschema:"additional_configuration"` + AuthenticationMethod string `tfschema:"authentication_method"` + UsernamePasswordCredentialsUsernameSecretName string `tfschema:"username_password_credentials_username_secret_name"` + UsernamePasswordCredentialsPasswordSecretName string `tfschema:"username_password_credentials_password_secret_name"` + X509CredentialsCertificateSecretName string `tfschema:"x509_credentials_certificate_secret_name"` +} + +func (AssetEndpointProfileResource) Arguments() map[string]*pluginsdk.Schema { + // add the other assetendpointprofile properties + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "resource_group_name": commonschema.ResourceGroupName(), + "extended_location_name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "extended_location_type": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "target_address": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "endpoint_profile_type": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "discovered_asset_endpoint_profile_ref": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "additional_configuration": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "authentication_method": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(assetendpointprofiles.PossibleValuesForAuthenticationMethod(), false), + }, + "username_password_credentials_username_secret_name": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "username_password_credentials_password_secret_name": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "x509_credentials_certificate_secret_name": { + Type: pluginsdk.TypeString, + Optional: true, + }, + "location": commonschema.Location(), + "tags": commonschema.Tags(), + } +} + +func (AssetEndpointProfileResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (AssetEndpointProfileResource) ModelObject() interface{} { + return &AssetEndpointProfileResourceModel{} +} + +func (AssetEndpointProfileResource) ResourceType() string { + return "azurerm_device_registry_asset_endpoint_profile" +} + +func (r AssetEndpointProfileResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetEndpointProfileClient + subscriptionId := metadata.Client.Account.SubscriptionId + + var config AssetEndpointProfileResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + id := assetendpointprofiles.NewAssetEndpointProfileID(subscriptionId, config.ResourceGroupName, config.Name) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + // Convert the TF model to the ARM model + // Optional ARM resource properties are pointers. + param := assetendpointprofiles.AssetEndpointProfile{ + Location: location.Normalize(config.Location), + Tags: pointer.To(config.Tags), + ExtendedLocation: assetendpointprofiles.ExtendedLocation{ + Name: config.ExtendedLocationName, + Type: config.ExtendedLocationType, + }, + Properties: &assetendpointprofiles.AssetEndpointProfileProperties{ + TargetAddress: config.TargetAddress, + EndpointProfileType: config.EndpointProfileType, + }, + } + + if config.DiscoveredAssetEndpointProfileRef != "" { + param.Properties.DiscoveredAssetEndpointProfileRef = pointer.To(config.DiscoveredAssetEndpointProfileRef) + } + + if config.AdditionalConfiguration != "" { + param.Properties.AdditionalConfiguration = pointer.To(config.AdditionalConfiguration) + } + + populateAuthenticationProperties(¶m, config) + + if err := client.CreateOrReplaceThenPoll(ctx, id, param); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r AssetEndpointProfileResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetEndpointProfileClient + + id, err := assetendpointprofiles.ParseAssetEndpointProfileID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var config AssetEndpointProfileResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + // Convert the TF model to the ARM model + param := assetendpointprofiles.AssetEndpointProfileUpdate{ + Properties: &assetendpointprofiles.AssetEndpointProfileUpdateProperties{}, + } + + if metadata.ResourceData.HasChange("tags") { + param.Tags = pointer.To(config.Tags) + } + + if metadata.ResourceData.HasChange("target_address") { + param.Properties.TargetAddress = pointer.To(config.TargetAddress) + } + + if metadata.ResourceData.HasChange("endpoint_profile_type") { + param.Properties.EndpointProfileType = pointer.To(config.EndpointProfileType) + } + + if metadata.ResourceData.HasChange("additional_configuration") { + param.Properties.AdditionalConfiguration = pointer.To(config.AdditionalConfiguration) + } + + authenticationMethodChanged := metadata.ResourceData.HasChange("authentication_method") + usernameSecretNameChanged := metadata.ResourceData.HasChange("username_password_credentials_username_secret_name") + passwordSecretNameChanged := metadata.ResourceData.HasChange("username_password_credentials_password_secret_name") + certificateSecretNameChanged := metadata.ResourceData.HasChange("x509_credentials_certificate_secret_name") + if authenticationMethodChanged || usernameSecretNameChanged || passwordSecretNameChanged || certificateSecretNameChanged { + authentication := assetendpointprofiles.AuthenticationUpdate{} + param.Properties.Authentication = &authentication + + if authenticationMethodChanged { + authentication.Method = pointer.To(assetendpointprofiles.AuthenticationMethod(config.AuthenticationMethod)) + } + + if usernameSecretNameChanged || passwordSecretNameChanged { + usernamePasswordCreds := assetendpointprofiles.UsernamePasswordCredentialsUpdate{} + authentication.UsernamePasswordCredentials = &usernamePasswordCreds + + if usernameSecretNameChanged { + usernamePasswordCreds.UsernameSecretName = pointer.To(config.UsernamePasswordCredentialsUsernameSecretName) + } + + if passwordSecretNameChanged { + usernamePasswordCreds.PasswordSecretName = pointer.To(config.UsernamePasswordCredentialsPasswordSecretName) + } + } + + if certificateSecretNameChanged { + authentication.X509Credentials = &assetendpointprofiles.X509CredentialsUpdate{ + CertificateSecretName: pointer.To(config.X509CredentialsCertificateSecretName), + } + } + } + + if err := client.UpdateThenPoll(ctx, *id, param); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + return nil + }, + } +} + +func (AssetEndpointProfileResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetEndpointProfileClient + + id, err := assetendpointprofiles.ParseAssetEndpointProfileID(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("retrieving %s: %+v", id, err) + } + + // Convert the ARM model to the TF model + state := AssetEndpointProfileResourceModel{ + Name: id.AssetEndpointProfileName, + ResourceGroupName: id.ResourceGroupName, + } + + if model := resp.Model; model != nil { + state.Location = location.Normalize(model.Location) + state.Tags = pointer.From(model.Tags) + state.ExtendedLocationName = model.ExtendedLocation.Name + state.ExtendedLocationType = model.ExtendedLocation.Type + + if props := model.Properties; props != nil { + state.TargetAddress = props.TargetAddress + state.EndpointProfileType = props.EndpointProfileType + state.DiscoveredAssetEndpointProfileRef = pointer.From(props.DiscoveredAssetEndpointProfileRef) + state.AdditionalConfiguration = pointer.From(props.AdditionalConfiguration) + + if auth := props.Authentication; auth != nil { + state.AuthenticationMethod = string(auth.Method) + + if x509 := auth.X509Credentials; x509 != nil { + state.X509CredentialsCertificateSecretName = x509.CertificateSecretName + } + + if up := auth.UsernamePasswordCredentials; up != nil { + state.UsernamePasswordCredentialsUsernameSecretName = up.UsernameSecretName + state.UsernamePasswordCredentialsPasswordSecretName = up.PasswordSecretName + } + } + } + } + return metadata.Encode(&state) + }, + } +} + +func (AssetEndpointProfileResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DeviceRegistry.AssetEndpointProfileClient + + id, err := assetendpointprofiles.ParseAssetEndpointProfileID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} + +func (AssetEndpointProfileResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return assetendpointprofiles.ValidateAssetEndpointProfileID +} + +func populateAuthenticationProperties(param *assetendpointprofiles.AssetEndpointProfile, config AssetEndpointProfileResourceModel) { + // If the authentication method is not set, we don't need to populate the authentication properties + if config.AuthenticationMethod == "" { + return + } + + param.Properties.Authentication = &assetendpointprofiles.Authentication{ + Method: assetendpointprofiles.AuthenticationMethod(config.AuthenticationMethod), + } + + if config.X509CredentialsCertificateSecretName != "" { + param.Properties.Authentication.X509Credentials = &assetendpointprofiles.X509Credentials{ + CertificateSecretName: config.X509CredentialsCertificateSecretName, + } + } + + if config.UsernamePasswordCredentialsUsernameSecretName != "" || config.UsernamePasswordCredentialsPasswordSecretName != "" { + param.Properties.Authentication.UsernamePasswordCredentials = &assetendpointprofiles.UsernamePasswordCredentials{ + UsernameSecretName: config.UsernamePasswordCredentialsUsernameSecretName, + PasswordSecretName: config.UsernamePasswordCredentialsPasswordSecretName, + } + } +} diff --git a/internal/services/deviceregistry/device_registry_assetendpointprofile_resource_test.go b/internal/services/deviceregistry/device_registry_assetendpointprofile_resource_test.go new file mode 100644 index 000000000000..e3c0a633d7df --- /dev/null +++ b/internal/services/deviceregistry/device_registry_assetendpointprofile_resource_test.go @@ -0,0 +1,366 @@ +package deviceregistry_test + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type AssetEndpointProfileTestResource struct{} + +const ( + ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME = "ARM_DEVICE_REGISTRY_CUSTOM_LOCATION" + ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME = "ARM_DEVICE_REGISTRY_RESOURCE_GROUP" +) + +func TestAccAssetEndpointProfile_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue(""), + check.That(data.ResourceName).Key("authentication_method").HasValue(""), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue(""), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAssetEndpointProfile_complete_certificate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeCertificate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("Certificate"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue("myCertificateRef"), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue(""), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAssetEndpointProfile_complete_usernamePassword(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeUsernamePassword(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("UsernamePassword"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue("myUsernameRef"), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue("myPasswordRef"), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAssetEndpointProfile_complete_anonymous(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeAnonymous(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("Anonymous"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue(""), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccAssetEndpointProfile_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccAssetEndpointProfile_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_device_registry_asset_endpoint_profile", "test") + r := AssetEndpointProfileTestResource{} + + if os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) == "" || os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) == "" { + t.Skipf("Skipping test due to missing environment variables %s and/or %s", ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME, ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { // first create the resource + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { // update the authentication method to certificate + Config: r.completeCertificate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("Certificate"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue("myCertificateRef"), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue(""), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + { // update the authentication method to username/password + Config: r.completeUsernamePassword(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("UsernamePassword"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue("myUsernameRef"), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue("myPasswordRef"), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + { // update the authentication method to anonymous + Config: r.completeAnonymous(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("target_address").HasValue("opc.tcp://foo"), + check.That(data.ResourceName).Key("endpoint_profile_type").HasValue("OpcUa"), + check.That(data.ResourceName).Key("discovered_asset_endpoint_profile_ref").HasValue("discoveredAssetEndpointProfile123"), + check.That(data.ResourceName).Key("additional_configuration").HasValue("{\"foo\": \"bar\"}"), + check.That(data.ResourceName).Key("authentication_method").HasValue("Anonymous"), + check.That(data.ResourceName).Key("x509_credentials_certificate_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_username_secret_name").HasValue(""), + check.That(data.ResourceName).Key("username_password_credentials_password_secret_name").HasValue(""), + check.That(data.ResourceName).Key("tags.sensor").HasValue("temperature,humidity"), + ), + }, + data.ImportStep(), + }) +} + +func (AssetEndpointProfileTestResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := assetendpointprofiles.ParseAssetEndpointProfileID(state.ID) + if err != nil { + return nil, err + } + resp, err := client.DeviceRegistry.AssetEndpointProfileClient.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) + } + return utils.Bool(true), nil +} + +func (r AssetEndpointProfileTestResource) basic(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset_endpoint_profile" "test" { + name = "acctest-assetendpointprofile-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + discovered_asset_endpoint_profile_ref = "discoveredAssetEndpointProfile123" + location = "%[3]s" +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetEndpointProfileTestResource) completeCertificate(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset_endpoint_profile" "test" { + name = "acctest-assetendpointprofile-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + discovered_asset_endpoint_profile_ref = "discoveredAssetEndpointProfile123" + additional_configuration = "{\"foo\": \"bar\"}" + authentication_method = "Certificate" + x509_credentials_certificate_secret_name = "myCertificateRef" + tags = { + "sensor" = "temperature,humidity" + } + location = "%[3]s" +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetEndpointProfileTestResource) completeUsernamePassword(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset_endpoint_profile" "test" { + name = "acctest-assetendpointprofile-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + discovered_asset_endpoint_profile_ref = "discoveredAssetEndpointProfile123" + additional_configuration = "{\"foo\": \"bar\"}" + authentication_method = "UsernamePassword" + username_password_credentials_username_secret_name = "myUsernameRef" + username_password_credentials_password_secret_name = "myPasswordRef" + tags = { + "sensor" = "temperature,humidity" + } + location = "%[3]s" +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetEndpointProfileTestResource) completeAnonymous(data acceptance.TestData) string { + template := r.template() + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset_endpoint_profile" "test" { + name = "acctest-assetendpointprofile-%[2]d" + resource_group_name = local.resource_group_name + extended_location_name = local.custom_location_name + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + discovered_asset_endpoint_profile_ref = "discoveredAssetEndpointProfile123" + additional_configuration = "{\"foo\": \"bar\"}" + authentication_method = "Anonymous" + tags = { + "sensor" = "temperature,humidity" + } + location = "%[3]s" +} +`, template, data.RandomInteger, data.Locations.Primary) +} + +func (r AssetEndpointProfileTestResource) requiresImport(data acceptance.TestData) string { + template := r.basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_device_registry_asset_endpoint_profile" "import" { + name = azurerm_device_registry_asset_endpoint_profile.test.name + resource_group_name = azurerm_device_registry_asset_endpoint_profile.test.resource_group_name + extended_location_name = azurerm_device_registry_asset_endpoint_profile.test.extended_location_name + extended_location_type = azurerm_device_registry_asset_endpoint_profile.test.extended_location_type + target_address = azurerm_device_registry_asset_endpoint_profile.test.target_address + endpoint_profile_type = azurerm_device_registry_asset_endpoint_profile.test.endpoint_profile_type + discovered_asset_endpoint_profile_ref = azurerm_device_registry_asset_endpoint_profile.test.discovered_asset_endpoint_profile_ref + location = azurerm_device_registry_asset_endpoint_profile.test.location +} + + +`, template) +} + +/* +Creates the terraform template for AzureRm provider and needed constants +*/ +func (AssetEndpointProfileTestResource) template() string { + customLocation := os.Getenv(ASSET_ENDPOINT_PROFILE_CUSTOM_LOCATION_NAME) + resourceGroup := os.Getenv(ASSET_ENDPOINT_PROFILE_RESOURCE_GROUP_NAME) + + return fmt.Sprintf(` +locals { + custom_location_name = "%[1]s" + resource_group_name = "%[2]s" +} + +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} +`, customLocation, resourceGroup) +} diff --git a/internal/services/deviceregistry/registration.go b/internal/services/deviceregistry/registration.go new file mode 100644 index 000000000000..388787fefe8b --- /dev/null +++ b/internal/services/deviceregistry/registration.go @@ -0,0 +1,38 @@ +package deviceregistry + +import ( + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" +) + +type Registration struct{} + +var ( + _ sdk.TypedServiceRegistrationWithAGitHubLabel = Registration{} +) + +func (r Registration) AssociatedGitHubLabel() string { + return "service/deviceregistry" +} + +func (r Registration) DataSources() []sdk.DataSource { + return []sdk.DataSource{} +} + +func (r Registration) Resources() []sdk.Resource { + return []sdk.Resource{ + AssetResource{}, + AssetEndpointProfileResource{}, + } +} + +// Name is the name of this Service +func (r Registration) Name() string { + return "Device Registry" +} + +// WebsiteCategories returns a list of categories which can be used for the sidebar +func (r Registration) WebsiteCategories() []string { + return []string{ + "Device Registry", + } +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/README.md new file mode 100644 index 000000000000..833988a0fe2a --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/README.md @@ -0,0 +1,117 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles` Documentation + +The `assetendpointprofiles` SDK allows for interaction with Azure Resource Manager `deviceregistry` (API Version `2024-11-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +import "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles" +``` + + +### Client Initialization + +```go +client := assetendpointprofiles.NewAssetEndpointProfilesClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `AssetEndpointProfilesClient.CreateOrReplace` + +```go +ctx := context.TODO() +id := assetendpointprofiles.NewAssetEndpointProfileID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetEndpointProfileName") + +payload := assetendpointprofiles.AssetEndpointProfile{ + // ... +} + + +if err := client.CreateOrReplaceThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` + + +### Example Usage: `AssetEndpointProfilesClient.Delete` + +```go +ctx := context.TODO() +id := assetendpointprofiles.NewAssetEndpointProfileID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetEndpointProfileName") + +if err := client.DeleteThenPoll(ctx, id); err != nil { + // handle the error +} +``` + + +### Example Usage: `AssetEndpointProfilesClient.Get` + +```go +ctx := context.TODO() +id := assetendpointprofiles.NewAssetEndpointProfileID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetEndpointProfileName") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `AssetEndpointProfilesClient.ListByResourceGroup` + +```go +ctx := context.TODO() +id := commonids.NewResourceGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group") + +// alternatively `client.ListByResourceGroup(ctx, id)` can be used to do batched pagination +items, err := client.ListByResourceGroupComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `AssetEndpointProfilesClient.ListBySubscription` + +```go +ctx := context.TODO() +id := commonids.NewSubscriptionID("12345678-1234-9876-4563-123456789012") + +// alternatively `client.ListBySubscription(ctx, id)` can be used to do batched pagination +items, err := client.ListBySubscriptionComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `AssetEndpointProfilesClient.Update` + +```go +ctx := context.TODO() +id := assetendpointprofiles.NewAssetEndpointProfileID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetEndpointProfileName") + +payload := assetendpointprofiles.AssetEndpointProfileUpdate{ + // ... +} + + +if err := client.UpdateThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/client.go new file mode 100644 index 000000000000..099374a758a0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/client.go @@ -0,0 +1,26 @@ +package assetendpointprofiles + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfilesClient struct { + Client *resourcemanager.Client +} + +func NewAssetEndpointProfilesClientWithBaseURI(sdkApi sdkEnv.Api) (*AssetEndpointProfilesClient, error) { + client, err := resourcemanager.NewClient(sdkApi, "assetendpointprofiles", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating AssetEndpointProfilesClient: %+v", err) + } + + return &AssetEndpointProfilesClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/constants.go new file mode 100644 index 000000000000..3d109615ec09 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/constants.go @@ -0,0 +1,104 @@ +package assetendpointprofiles + +import ( + "encoding/json" + "fmt" + "strings" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AuthenticationMethod string + +const ( + AuthenticationMethodAnonymous AuthenticationMethod = "Anonymous" + AuthenticationMethodCertificate AuthenticationMethod = "Certificate" + AuthenticationMethodUsernamePassword AuthenticationMethod = "UsernamePassword" +) + +func PossibleValuesForAuthenticationMethod() []string { + return []string{ + string(AuthenticationMethodAnonymous), + string(AuthenticationMethodCertificate), + string(AuthenticationMethodUsernamePassword), + } +} + +func (s *AuthenticationMethod) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseAuthenticationMethod(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseAuthenticationMethod(input string) (*AuthenticationMethod, error) { + vals := map[string]AuthenticationMethod{ + "anonymous": AuthenticationMethodAnonymous, + "certificate": AuthenticationMethodCertificate, + "usernamepassword": AuthenticationMethodUsernamePassword, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := AuthenticationMethod(input) + return &out, nil +} + +type ProvisioningState string + +const ( + ProvisioningStateAccepted ProvisioningState = "Accepted" + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" +) + +func PossibleValuesForProvisioningState() []string { + return []string{ + string(ProvisioningStateAccepted), + string(ProvisioningStateCanceled), + string(ProvisioningStateDeleting), + string(ProvisioningStateFailed), + string(ProvisioningStateSucceeded), + } +} + +func (s *ProvisioningState) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseProvisioningState(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseProvisioningState(input string) (*ProvisioningState, error) { + vals := map[string]ProvisioningState{ + "accepted": ProvisioningStateAccepted, + "canceled": ProvisioningStateCanceled, + "deleting": ProvisioningStateDeleting, + "failed": ProvisioningStateFailed, + "succeeded": ProvisioningStateSucceeded, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ProvisioningState(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/id_assetendpointprofile.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/id_assetendpointprofile.go new file mode 100644 index 000000000000..e372455f8ffa --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/id_assetendpointprofile.go @@ -0,0 +1,130 @@ +package assetendpointprofiles + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/recaser" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +func init() { + recaser.RegisterResourceId(&AssetEndpointProfileId{}) +} + +var _ resourceids.ResourceId = &AssetEndpointProfileId{} + +// AssetEndpointProfileId is a struct representing the Resource ID for a Asset Endpoint Profile +type AssetEndpointProfileId struct { + SubscriptionId string + ResourceGroupName string + AssetEndpointProfileName string +} + +// NewAssetEndpointProfileID returns a new AssetEndpointProfileId struct +func NewAssetEndpointProfileID(subscriptionId string, resourceGroupName string, assetEndpointProfileName string) AssetEndpointProfileId { + return AssetEndpointProfileId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AssetEndpointProfileName: assetEndpointProfileName, + } +} + +// ParseAssetEndpointProfileID parses 'input' into a AssetEndpointProfileId +func ParseAssetEndpointProfileID(input string) (*AssetEndpointProfileId, error) { + parser := resourceids.NewParserFromResourceIdType(&AssetEndpointProfileId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := AssetEndpointProfileId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseAssetEndpointProfileIDInsensitively parses 'input' case-insensitively into a AssetEndpointProfileId +// note: this method should only be used for API response data and not user input +func ParseAssetEndpointProfileIDInsensitively(input string) (*AssetEndpointProfileId, error) { + parser := resourceids.NewParserFromResourceIdType(&AssetEndpointProfileId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := AssetEndpointProfileId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *AssetEndpointProfileId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.SubscriptionId, ok = input.Parsed["subscriptionId"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", input) + } + + if id.ResourceGroupName, ok = input.Parsed["resourceGroupName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", input) + } + + if id.AssetEndpointProfileName, ok = input.Parsed["assetEndpointProfileName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "assetEndpointProfileName", input) + } + + return nil +} + +// ValidateAssetEndpointProfileID checks that 'input' can be parsed as a Asset Endpoint Profile ID +func ValidateAssetEndpointProfileID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseAssetEndpointProfileID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Asset Endpoint Profile ID +func (id AssetEndpointProfileId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.DeviceRegistry/assetEndpointProfiles/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AssetEndpointProfileName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Asset Endpoint Profile ID +func (id AssetEndpointProfileId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftDeviceRegistry", "Microsoft.DeviceRegistry", "Microsoft.DeviceRegistry"), + resourceids.StaticSegment("staticAssetEndpointProfiles", "assetEndpointProfiles", "assetEndpointProfiles"), + resourceids.UserSpecifiedSegment("assetEndpointProfileName", "assetEndpointProfileName"), + } +} + +// String returns a human-readable description of this Asset Endpoint Profile ID +func (id AssetEndpointProfileId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Asset Endpoint Profile Name: %q", id.AssetEndpointProfileName), + } + return fmt.Sprintf("Asset Endpoint Profile (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_createorreplace.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_createorreplace.go new file mode 100644 index 000000000000..1dd13be906dc --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_createorreplace.go @@ -0,0 +1,75 @@ +package assetendpointprofiles + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOrReplaceOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData + Model *AssetEndpointProfile +} + +// CreateOrReplace ... +func (c AssetEndpointProfilesClient) CreateOrReplace(ctx context.Context, id AssetEndpointProfileId, input AssetEndpointProfile) (result CreateOrReplaceOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusCreated, + http.StatusOK, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// CreateOrReplaceThenPoll performs CreateOrReplace then polls until it's completed +func (c AssetEndpointProfilesClient) CreateOrReplaceThenPoll(ctx context.Context, id AssetEndpointProfileId, input AssetEndpointProfile) error { + result, err := c.CreateOrReplace(ctx, id, input) + if err != nil { + return fmt.Errorf("performing CreateOrReplace: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after CreateOrReplace: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_delete.go new file mode 100644 index 000000000000..b24134a6027c --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_delete.go @@ -0,0 +1,70 @@ +package assetendpointprofiles + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData +} + +// Delete ... +func (c AssetEndpointProfilesClient) Delete(ctx context.Context, id AssetEndpointProfileId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusAccepted, + http.StatusNoContent, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// DeleteThenPoll performs Delete then polls until it's completed +func (c AssetEndpointProfilesClient) DeleteThenPoll(ctx context.Context, id AssetEndpointProfileId) error { + result, err := c.Delete(ctx, id) + if err != nil { + return fmt.Errorf("performing Delete: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after Delete: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_get.go new file mode 100644 index 000000000000..2a5f882cc3c4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_get.go @@ -0,0 +1,53 @@ +package assetendpointprofiles + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *AssetEndpointProfile +} + +// Get ... +func (c AssetEndpointProfilesClient) Get(ctx context.Context, id AssetEndpointProfileId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model AssetEndpointProfile + result.Model = &model + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbyresourcegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbyresourcegroup.go new file mode 100644 index 000000000000..dba6b469adb4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbyresourcegroup.go @@ -0,0 +1,106 @@ +package assetendpointprofiles + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListByResourceGroupOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]AssetEndpointProfile +} + +type ListByResourceGroupCompleteResult struct { + LatestHttpResponse *http.Response + Items []AssetEndpointProfile +} + +type ListByResourceGroupCustomPager struct { + NextLink *odata.Link `json:"nextLink"` +} + +func (p *ListByResourceGroupCustomPager) NextPageLink() *odata.Link { + defer func() { + p.NextLink = nil + }() + + return p.NextLink +} + +// ListByResourceGroup ... +func (c AssetEndpointProfilesClient) ListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (result ListByResourceGroupOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Pager: &ListByResourceGroupCustomPager{}, + Path: fmt.Sprintf("%s/providers/Microsoft.DeviceRegistry/assetEndpointProfiles", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]AssetEndpointProfile `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListByResourceGroupComplete retrieves all the results into a single object +func (c AssetEndpointProfilesClient) ListByResourceGroupComplete(ctx context.Context, id commonids.ResourceGroupId) (ListByResourceGroupCompleteResult, error) { + return c.ListByResourceGroupCompleteMatchingPredicate(ctx, id, AssetEndpointProfileOperationPredicate{}) +} + +// ListByResourceGroupCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c AssetEndpointProfilesClient) ListByResourceGroupCompleteMatchingPredicate(ctx context.Context, id commonids.ResourceGroupId, predicate AssetEndpointProfileOperationPredicate) (result ListByResourceGroupCompleteResult, err error) { + items := make([]AssetEndpointProfile, 0) + + resp, err := c.ListByResourceGroup(ctx, id) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListByResourceGroupCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbysubscription.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbysubscription.go new file mode 100644 index 000000000000..13b32409dc6c --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_listbysubscription.go @@ -0,0 +1,106 @@ +package assetendpointprofiles + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListBySubscriptionOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]AssetEndpointProfile +} + +type ListBySubscriptionCompleteResult struct { + LatestHttpResponse *http.Response + Items []AssetEndpointProfile +} + +type ListBySubscriptionCustomPager struct { + NextLink *odata.Link `json:"nextLink"` +} + +func (p *ListBySubscriptionCustomPager) NextPageLink() *odata.Link { + defer func() { + p.NextLink = nil + }() + + return p.NextLink +} + +// ListBySubscription ... +func (c AssetEndpointProfilesClient) ListBySubscription(ctx context.Context, id commonids.SubscriptionId) (result ListBySubscriptionOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Pager: &ListBySubscriptionCustomPager{}, + Path: fmt.Sprintf("%s/providers/Microsoft.DeviceRegistry/assetEndpointProfiles", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]AssetEndpointProfile `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListBySubscriptionComplete retrieves all the results into a single object +func (c AssetEndpointProfilesClient) ListBySubscriptionComplete(ctx context.Context, id commonids.SubscriptionId) (ListBySubscriptionCompleteResult, error) { + return c.ListBySubscriptionCompleteMatchingPredicate(ctx, id, AssetEndpointProfileOperationPredicate{}) +} + +// ListBySubscriptionCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c AssetEndpointProfilesClient) ListBySubscriptionCompleteMatchingPredicate(ctx context.Context, id commonids.SubscriptionId, predicate AssetEndpointProfileOperationPredicate) (result ListBySubscriptionCompleteResult, err error) { + items := make([]AssetEndpointProfile, 0) + + resp, err := c.ListBySubscription(ctx, id) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListBySubscriptionCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_update.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_update.go new file mode 100644 index 000000000000..2af77249a09b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/method_update.go @@ -0,0 +1,75 @@ +package assetendpointprofiles + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UpdateOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData + Model *AssetEndpointProfile +} + +// Update ... +func (c AssetEndpointProfilesClient) Update(ctx context.Context, id AssetEndpointProfileId, input AssetEndpointProfileUpdate) (result UpdateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusAccepted, + http.StatusOK, + }, + HttpMethod: http.MethodPatch, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// UpdateThenPoll performs Update then polls until it's completed +func (c AssetEndpointProfilesClient) UpdateThenPoll(ctx context.Context, id AssetEndpointProfileId, input AssetEndpointProfileUpdate) error { + result, err := c.Update(ctx, id, input) + if err != nil { + return fmt.Errorf("performing Update: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after Update: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofile.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofile.go new file mode 100644 index 000000000000..8968e9fd724d --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofile.go @@ -0,0 +1,19 @@ +package assetendpointprofiles + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/systemdata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfile struct { + ExtendedLocation ExtendedLocation `json:"extendedLocation"` + Id *string `json:"id,omitempty"` + Location string `json:"location"` + Name *string `json:"name,omitempty"` + Properties *AssetEndpointProfileProperties `json:"properties,omitempty"` + SystemData *systemdata.SystemData `json:"systemData,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileproperties.go new file mode 100644 index 000000000000..f4ca0e2ffc31 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileproperties.go @@ -0,0 +1,15 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileProperties struct { + AdditionalConfiguration *string `json:"additionalConfiguration,omitempty"` + Authentication *Authentication `json:"authentication,omitempty"` + DiscoveredAssetEndpointProfileRef *string `json:"discoveredAssetEndpointProfileRef,omitempty"` + EndpointProfileType string `json:"endpointProfileType"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` + Status *AssetEndpointProfileStatus `json:"status,omitempty"` + TargetAddress string `json:"targetAddress"` + Uuid *string `json:"uuid,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatus.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatus.go new file mode 100644 index 000000000000..b9352a519b4c --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatus.go @@ -0,0 +1,8 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileStatus struct { + Errors *[]AssetEndpointProfileStatusError `json:"errors,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatuserror.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatuserror.go new file mode 100644 index 000000000000..43ef3ee71882 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofilestatuserror.go @@ -0,0 +1,9 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileStatusError struct { + Code *int64 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdate.go new file mode 100644 index 000000000000..0bfe71251331 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdate.go @@ -0,0 +1,9 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileUpdate struct { + Properties *AssetEndpointProfileUpdateProperties `json:"properties,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdateproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdateproperties.go new file mode 100644 index 000000000000..a05bb6eefb02 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_assetendpointprofileupdateproperties.go @@ -0,0 +1,11 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileUpdateProperties struct { + AdditionalConfiguration *string `json:"additionalConfiguration,omitempty"` + Authentication *AuthenticationUpdate `json:"authentication,omitempty"` + EndpointProfileType *string `json:"endpointProfileType,omitempty"` + TargetAddress *string `json:"targetAddress,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authentication.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authentication.go new file mode 100644 index 000000000000..67a43dfa2cdd --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authentication.go @@ -0,0 +1,10 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Authentication struct { + Method AuthenticationMethod `json:"method"` + UsernamePasswordCredentials *UsernamePasswordCredentials `json:"usernamePasswordCredentials,omitempty"` + X509Credentials *X509Credentials `json:"x509Credentials,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authenticationupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authenticationupdate.go new file mode 100644 index 000000000000..b0f0d7ef0f65 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_authenticationupdate.go @@ -0,0 +1,10 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AuthenticationUpdate struct { + Method *AuthenticationMethod `json:"method,omitempty"` + UsernamePasswordCredentials *UsernamePasswordCredentialsUpdate `json:"usernamePasswordCredentials,omitempty"` + X509Credentials *X509CredentialsUpdate `json:"x509Credentials,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_extendedlocation.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_extendedlocation.go new file mode 100644 index 000000000000..0fb2e13abacc --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_extendedlocation.go @@ -0,0 +1,9 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ExtendedLocation struct { + Name string `json:"name"` + Type string `json:"type"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentials.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentials.go new file mode 100644 index 000000000000..b108ab27db68 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentials.go @@ -0,0 +1,9 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UsernamePasswordCredentials struct { + PasswordSecretName string `json:"passwordSecretName"` + UsernameSecretName string `json:"usernameSecretName"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentialsupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentialsupdate.go new file mode 100644 index 000000000000..cf8424825657 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_usernamepasswordcredentialsupdate.go @@ -0,0 +1,9 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UsernamePasswordCredentialsUpdate struct { + PasswordSecretName *string `json:"passwordSecretName,omitempty"` + UsernameSecretName *string `json:"usernameSecretName,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentials.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentials.go new file mode 100644 index 000000000000..5b3cd78827c5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentials.go @@ -0,0 +1,8 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type X509Credentials struct { + CertificateSecretName string `json:"certificateSecretName"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentialsupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentialsupdate.go new file mode 100644 index 000000000000..920bb4fb03b6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/model_x509credentialsupdate.go @@ -0,0 +1,8 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type X509CredentialsUpdate struct { + CertificateSecretName *string `json:"certificateSecretName,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/predicates.go new file mode 100644 index 000000000000..fb0fb8f73ebb --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/predicates.go @@ -0,0 +1,32 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetEndpointProfileOperationPredicate struct { + Id *string + Location *string + Name *string + Type *string +} + +func (p AssetEndpointProfileOperationPredicate) Matches(input AssetEndpointProfile) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Location != nil && *p.Location != input.Location { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/version.go new file mode 100644 index 000000000000..b100815e9e49 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles/version.go @@ -0,0 +1,10 @@ +package assetendpointprofiles + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2024-11-01" + +func userAgent() string { + return "hashicorp/go-azure-sdk/assetendpointprofiles/2024-11-01" +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/README.md new file mode 100644 index 000000000000..74b768e7d483 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/README.md @@ -0,0 +1,117 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets` Documentation + +The `assets` SDK allows for interaction with Azure Resource Manager `deviceregistry` (API Version `2024-11-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +import "github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets" +``` + + +### Client Initialization + +```go +client := assets.NewAssetsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `AssetsClient.CreateOrReplace` + +```go +ctx := context.TODO() +id := assets.NewAssetID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetName") + +payload := assets.Asset{ + // ... +} + + +if err := client.CreateOrReplaceThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` + + +### Example Usage: `AssetsClient.Delete` + +```go +ctx := context.TODO() +id := assets.NewAssetID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetName") + +if err := client.DeleteThenPoll(ctx, id); err != nil { + // handle the error +} +``` + + +### Example Usage: `AssetsClient.Get` + +```go +ctx := context.TODO() +id := assets.NewAssetID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetName") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `AssetsClient.ListByResourceGroup` + +```go +ctx := context.TODO() +id := commonids.NewResourceGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group") + +// alternatively `client.ListByResourceGroup(ctx, id)` can be used to do batched pagination +items, err := client.ListByResourceGroupComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `AssetsClient.ListBySubscription` + +```go +ctx := context.TODO() +id := commonids.NewSubscriptionID("12345678-1234-9876-4563-123456789012") + +// alternatively `client.ListBySubscription(ctx, id)` can be used to do batched pagination +items, err := client.ListBySubscriptionComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `AssetsClient.Update` + +```go +ctx := context.TODO() +id := assets.NewAssetID("12345678-1234-9876-4563-123456789012", "example-resource-group", "assetName") + +payload := assets.AssetUpdate{ + // ... +} + + +if err := client.UpdateThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/client.go new file mode 100644 index 000000000000..a72f6492047b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/client.go @@ -0,0 +1,26 @@ +package assets + +import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + sdkEnv "github.com/hashicorp/go-azure-sdk/sdk/environments" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetsClient struct { + Client *resourcemanager.Client +} + +func NewAssetsClientWithBaseURI(sdkApi sdkEnv.Api) (*AssetsClient, error) { + client, err := resourcemanager.NewClient(sdkApi, "assets", defaultApiVersion) + if err != nil { + return nil, fmt.Errorf("instantiating AssetsClient: %+v", err) + } + + return &AssetsClient{ + Client: client, + }, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/constants.go new file mode 100644 index 000000000000..ac288b945675 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/constants.go @@ -0,0 +1,192 @@ +package assets + +import ( + "encoding/json" + "fmt" + "strings" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DataPointObservabilityMode string + +const ( + DataPointObservabilityModeCounter DataPointObservabilityMode = "Counter" + DataPointObservabilityModeGauge DataPointObservabilityMode = "Gauge" + DataPointObservabilityModeHistogram DataPointObservabilityMode = "Histogram" + DataPointObservabilityModeLog DataPointObservabilityMode = "Log" + DataPointObservabilityModeNone DataPointObservabilityMode = "None" +) + +func PossibleValuesForDataPointObservabilityMode() []string { + return []string{ + string(DataPointObservabilityModeCounter), + string(DataPointObservabilityModeGauge), + string(DataPointObservabilityModeHistogram), + string(DataPointObservabilityModeLog), + string(DataPointObservabilityModeNone), + } +} + +func (s *DataPointObservabilityMode) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseDataPointObservabilityMode(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseDataPointObservabilityMode(input string) (*DataPointObservabilityMode, error) { + vals := map[string]DataPointObservabilityMode{ + "counter": DataPointObservabilityModeCounter, + "gauge": DataPointObservabilityModeGauge, + "histogram": DataPointObservabilityModeHistogram, + "log": DataPointObservabilityModeLog, + "none": DataPointObservabilityModeNone, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := DataPointObservabilityMode(input) + return &out, nil +} + +type EventObservabilityMode string + +const ( + EventObservabilityModeLog EventObservabilityMode = "Log" + EventObservabilityModeNone EventObservabilityMode = "None" +) + +func PossibleValuesForEventObservabilityMode() []string { + return []string{ + string(EventObservabilityModeLog), + string(EventObservabilityModeNone), + } +} + +func (s *EventObservabilityMode) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseEventObservabilityMode(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseEventObservabilityMode(input string) (*EventObservabilityMode, error) { + vals := map[string]EventObservabilityMode{ + "log": EventObservabilityModeLog, + "none": EventObservabilityModeNone, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := EventObservabilityMode(input) + return &out, nil +} + +type ProvisioningState string + +const ( + ProvisioningStateAccepted ProvisioningState = "Accepted" + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" +) + +func PossibleValuesForProvisioningState() []string { + return []string{ + string(ProvisioningStateAccepted), + string(ProvisioningStateCanceled), + string(ProvisioningStateDeleting), + string(ProvisioningStateFailed), + string(ProvisioningStateSucceeded), + } +} + +func (s *ProvisioningState) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseProvisioningState(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseProvisioningState(input string) (*ProvisioningState, error) { + vals := map[string]ProvisioningState{ + "accepted": ProvisioningStateAccepted, + "canceled": ProvisioningStateCanceled, + "deleting": ProvisioningStateDeleting, + "failed": ProvisioningStateFailed, + "succeeded": ProvisioningStateSucceeded, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ProvisioningState(input) + return &out, nil +} + +type TopicRetainType string + +const ( + TopicRetainTypeKeep TopicRetainType = "Keep" + TopicRetainTypeNever TopicRetainType = "Never" +) + +func PossibleValuesForTopicRetainType() []string { + return []string{ + string(TopicRetainTypeKeep), + string(TopicRetainTypeNever), + } +} + +func (s *TopicRetainType) UnmarshalJSON(bytes []byte) error { + var decoded string + if err := json.Unmarshal(bytes, &decoded); err != nil { + return fmt.Errorf("unmarshaling: %+v", err) + } + out, err := parseTopicRetainType(decoded) + if err != nil { + return fmt.Errorf("parsing %q: %+v", decoded, err) + } + *s = *out + return nil +} + +func parseTopicRetainType(input string) (*TopicRetainType, error) { + vals := map[string]TopicRetainType{ + "keep": TopicRetainTypeKeep, + "never": TopicRetainTypeNever, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := TopicRetainType(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/id_asset.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/id_asset.go new file mode 100644 index 000000000000..bb7b45f0c337 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/id_asset.go @@ -0,0 +1,130 @@ +package assets + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/recaser" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +func init() { + recaser.RegisterResourceId(&AssetId{}) +} + +var _ resourceids.ResourceId = &AssetId{} + +// AssetId is a struct representing the Resource ID for a Asset +type AssetId struct { + SubscriptionId string + ResourceGroupName string + AssetName string +} + +// NewAssetID returns a new AssetId struct +func NewAssetID(subscriptionId string, resourceGroupName string, assetName string) AssetId { + return AssetId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + AssetName: assetName, + } +} + +// ParseAssetID parses 'input' into a AssetId +func ParseAssetID(input string) (*AssetId, error) { + parser := resourceids.NewParserFromResourceIdType(&AssetId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := AssetId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +// ParseAssetIDInsensitively parses 'input' case-insensitively into a AssetId +// note: this method should only be used for API response data and not user input +func ParseAssetIDInsensitively(input string) (*AssetId, error) { + parser := resourceids.NewParserFromResourceIdType(&AssetId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + id := AssetId{} + if err = id.FromParseResult(*parsed); err != nil { + return nil, err + } + + return &id, nil +} + +func (id *AssetId) FromParseResult(input resourceids.ParseResult) error { + var ok bool + + if id.SubscriptionId, ok = input.Parsed["subscriptionId"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", input) + } + + if id.ResourceGroupName, ok = input.Parsed["resourceGroupName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", input) + } + + if id.AssetName, ok = input.Parsed["assetName"]; !ok { + return resourceids.NewSegmentNotSpecifiedError(id, "assetName", input) + } + + return nil +} + +// ValidateAssetID checks that 'input' can be parsed as a Asset ID +func ValidateAssetID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseAssetID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Asset ID +func (id AssetId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.DeviceRegistry/assets/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.AssetName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Asset ID +func (id AssetId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftDeviceRegistry", "Microsoft.DeviceRegistry", "Microsoft.DeviceRegistry"), + resourceids.StaticSegment("staticAssets", "assets", "assets"), + resourceids.UserSpecifiedSegment("assetName", "assetName"), + } +} + +// String returns a human-readable description of this Asset ID +func (id AssetId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Asset Name: %q", id.AssetName), + } + return fmt.Sprintf("Asset (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_createorreplace.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_createorreplace.go new file mode 100644 index 000000000000..b6a7798f315e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_createorreplace.go @@ -0,0 +1,75 @@ +package assets + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOrReplaceOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData + Model *Asset +} + +// CreateOrReplace ... +func (c AssetsClient) CreateOrReplace(ctx context.Context, id AssetId, input Asset) (result CreateOrReplaceOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusCreated, + http.StatusOK, + }, + HttpMethod: http.MethodPut, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// CreateOrReplaceThenPoll performs CreateOrReplace then polls until it's completed +func (c AssetsClient) CreateOrReplaceThenPoll(ctx context.Context, id AssetId, input Asset) error { + result, err := c.CreateOrReplace(ctx, id, input) + if err != nil { + return fmt.Errorf("performing CreateOrReplace: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after CreateOrReplace: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_delete.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_delete.go new file mode 100644 index 000000000000..34b6146a5f28 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_delete.go @@ -0,0 +1,70 @@ +package assets + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData +} + +// Delete ... +func (c AssetsClient) Delete(ctx context.Context, id AssetId) (result DeleteOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusAccepted, + http.StatusNoContent, + }, + HttpMethod: http.MethodDelete, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// DeleteThenPoll performs Delete then polls until it's completed +func (c AssetsClient) DeleteThenPoll(ctx context.Context, id AssetId) error { + result, err := c.Delete(ctx, id) + if err != nil { + return fmt.Errorf("performing Delete: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after Delete: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_get.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_get.go new file mode 100644 index 000000000000..8eabe4d065a5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_get.go @@ -0,0 +1,53 @@ +package assets + +import ( + "context" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *Asset +} + +// Get ... +func (c AssetsClient) Get(ctx context.Context, id AssetId) (result GetOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var model Asset + result.Model = &model + if err = resp.Unmarshal(result.Model); err != nil { + return + } + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbyresourcegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbyresourcegroup.go new file mode 100644 index 000000000000..c063d4d77dbd --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbyresourcegroup.go @@ -0,0 +1,106 @@ +package assets + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListByResourceGroupOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]Asset +} + +type ListByResourceGroupCompleteResult struct { + LatestHttpResponse *http.Response + Items []Asset +} + +type ListByResourceGroupCustomPager struct { + NextLink *odata.Link `json:"nextLink"` +} + +func (p *ListByResourceGroupCustomPager) NextPageLink() *odata.Link { + defer func() { + p.NextLink = nil + }() + + return p.NextLink +} + +// ListByResourceGroup ... +func (c AssetsClient) ListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (result ListByResourceGroupOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Pager: &ListByResourceGroupCustomPager{}, + Path: fmt.Sprintf("%s/providers/Microsoft.DeviceRegistry/assets", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]Asset `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListByResourceGroupComplete retrieves all the results into a single object +func (c AssetsClient) ListByResourceGroupComplete(ctx context.Context, id commonids.ResourceGroupId) (ListByResourceGroupCompleteResult, error) { + return c.ListByResourceGroupCompleteMatchingPredicate(ctx, id, AssetOperationPredicate{}) +} + +// ListByResourceGroupCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c AssetsClient) ListByResourceGroupCompleteMatchingPredicate(ctx context.Context, id commonids.ResourceGroupId, predicate AssetOperationPredicate) (result ListByResourceGroupCompleteResult, err error) { + items := make([]Asset, 0) + + resp, err := c.ListByResourceGroup(ctx, id) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListByResourceGroupCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbysubscription.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbysubscription.go new file mode 100644 index 000000000000..fe6c812e1cbf --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_listbysubscription.go @@ -0,0 +1,106 @@ +package assets + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListBySubscriptionOperationResponse struct { + HttpResponse *http.Response + OData *odata.OData + Model *[]Asset +} + +type ListBySubscriptionCompleteResult struct { + LatestHttpResponse *http.Response + Items []Asset +} + +type ListBySubscriptionCustomPager struct { + NextLink *odata.Link `json:"nextLink"` +} + +func (p *ListBySubscriptionCustomPager) NextPageLink() *odata.Link { + defer func() { + p.NextLink = nil + }() + + return p.NextLink +} + +// ListBySubscription ... +func (c AssetsClient) ListBySubscription(ctx context.Context, id commonids.SubscriptionId) (result ListBySubscriptionOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusOK, + }, + HttpMethod: http.MethodGet, + Pager: &ListBySubscriptionCustomPager{}, + Path: fmt.Sprintf("%s/providers/Microsoft.DeviceRegistry/assets", id.ID()), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + var resp *client.Response + resp, err = req.ExecutePaged(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + var values struct { + Values *[]Asset `json:"value"` + } + if err = resp.Unmarshal(&values); err != nil { + return + } + + result.Model = values.Values + + return +} + +// ListBySubscriptionComplete retrieves all the results into a single object +func (c AssetsClient) ListBySubscriptionComplete(ctx context.Context, id commonids.SubscriptionId) (ListBySubscriptionCompleteResult, error) { + return c.ListBySubscriptionCompleteMatchingPredicate(ctx, id, AssetOperationPredicate{}) +} + +// ListBySubscriptionCompleteMatchingPredicate retrieves all the results and then applies the predicate +func (c AssetsClient) ListBySubscriptionCompleteMatchingPredicate(ctx context.Context, id commonids.SubscriptionId, predicate AssetOperationPredicate) (result ListBySubscriptionCompleteResult, err error) { + items := make([]Asset, 0) + + resp, err := c.ListBySubscription(ctx, id) + if err != nil { + result.LatestHttpResponse = resp.HttpResponse + err = fmt.Errorf("loading results: %+v", err) + return + } + if resp.Model != nil { + for _, v := range *resp.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + result = ListBySubscriptionCompleteResult{ + LatestHttpResponse: resp.HttpResponse, + Items: items, + } + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_update.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_update.go new file mode 100644 index 000000000000..42754ffb9425 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/method_update.go @@ -0,0 +1,75 @@ +package assets + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/client" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" + "github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager" + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UpdateOperationResponse struct { + Poller pollers.Poller + HttpResponse *http.Response + OData *odata.OData + Model *Asset +} + +// Update ... +func (c AssetsClient) Update(ctx context.Context, id AssetId, input AssetUpdate) (result UpdateOperationResponse, err error) { + opts := client.RequestOptions{ + ContentType: "application/json; charset=utf-8", + ExpectedStatusCodes: []int{ + http.StatusAccepted, + http.StatusOK, + }, + HttpMethod: http.MethodPatch, + Path: id.ID(), + } + + req, err := c.Client.NewRequest(ctx, opts) + if err != nil { + return + } + + if err = req.Marshal(input); err != nil { + return + } + + var resp *client.Response + resp, err = req.Execute(ctx) + if resp != nil { + result.OData = resp.OData + result.HttpResponse = resp.Response + } + if err != nil { + return + } + + result.Poller, err = resourcemanager.PollerFromResponse(resp, c.Client) + if err != nil { + return + } + + return +} + +// UpdateThenPoll performs Update then polls until it's completed +func (c AssetsClient) UpdateThenPoll(ctx context.Context, id AssetId, input AssetUpdate) error { + result, err := c.Update(ctx, id, input) + if err != nil { + return fmt.Errorf("performing Update: %+v", err) + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + return fmt.Errorf("polling after Update: %+v", err) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_asset.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_asset.go new file mode 100644 index 000000000000..24857b429fa7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_asset.go @@ -0,0 +1,19 @@ +package assets + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/systemdata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Asset struct { + ExtendedLocation ExtendedLocation `json:"extendedLocation"` + Id *string `json:"id,omitempty"` + Location string `json:"location"` + Name *string `json:"name,omitempty"` + Properties *AssetProperties `json:"properties,omitempty"` + SystemData *systemdata.SystemData `json:"systemData,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetproperties.go new file mode 100644 index 000000000000..73ce93da09be --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetproperties.go @@ -0,0 +1,31 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetProperties struct { + AssetEndpointProfileRef string `json:"assetEndpointProfileRef"` + Attributes *map[string]interface{} `json:"attributes,omitempty"` + Datasets *[]Dataset `json:"datasets,omitempty"` + DefaultDatasetsConfiguration *string `json:"defaultDatasetsConfiguration,omitempty"` + DefaultEventsConfiguration *string `json:"defaultEventsConfiguration,omitempty"` + DefaultTopic *Topic `json:"defaultTopic,omitempty"` + Description *string `json:"description,omitempty"` + DiscoveredAssetRefs *[]string `json:"discoveredAssetRefs,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + DocumentationUri *string `json:"documentationUri,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Events *[]Event `json:"events,omitempty"` + ExternalAssetId *string `json:"externalAssetId,omitempty"` + HardwareRevision *string `json:"hardwareRevision,omitempty"` + Manufacturer *string `json:"manufacturer,omitempty"` + ManufacturerUri *string `json:"manufacturerUri,omitempty"` + Model *string `json:"model,omitempty"` + ProductCode *string `json:"productCode,omitempty"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` + SerialNumber *string `json:"serialNumber,omitempty"` + SoftwareRevision *string `json:"softwareRevision,omitempty"` + Status *AssetStatus `json:"status,omitempty"` + Uuid *string `json:"uuid,omitempty"` + Version *int64 `json:"version,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatus.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatus.go new file mode 100644 index 000000000000..59adc5ba1c85 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatus.go @@ -0,0 +1,11 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetStatus struct { + Datasets *[]AssetStatusDataset `json:"datasets,omitempty"` + Errors *[]AssetStatusError `json:"errors,omitempty"` + Events *[]AssetStatusEvent `json:"events,omitempty"` + Version *int64 `json:"version,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusdataset.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusdataset.go new file mode 100644 index 000000000000..511593b5e8f8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusdataset.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetStatusDataset struct { + MessageSchemaReference *MessageSchemaReference `json:"messageSchemaReference,omitempty"` + Name string `json:"name"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatuserror.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatuserror.go new file mode 100644 index 000000000000..c87108ecc088 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatuserror.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetStatusError struct { + Code *int64 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusevent.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusevent.go new file mode 100644 index 000000000000..2438f4620ca8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetstatusevent.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetStatusEvent struct { + MessageSchemaReference *MessageSchemaReference `json:"messageSchemaReference,omitempty"` + Name string `json:"name"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdate.go new file mode 100644 index 000000000000..6ff6aa0a80ba --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdate.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetUpdate struct { + Properties *AssetUpdateProperties `json:"properties,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdateproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdateproperties.go new file mode 100644 index 000000000000..e18024904a9f --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_assetupdateproperties.go @@ -0,0 +1,24 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetUpdateProperties struct { + Attributes *map[string]interface{} `json:"attributes,omitempty"` + Datasets *[]Dataset `json:"datasets,omitempty"` + DefaultDatasetsConfiguration *string `json:"defaultDatasetsConfiguration,omitempty"` + DefaultEventsConfiguration *string `json:"defaultEventsConfiguration,omitempty"` + DefaultTopic *TopicUpdate `json:"defaultTopic,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + DocumentationUri *string `json:"documentationUri,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Events *[]Event `json:"events,omitempty"` + HardwareRevision *string `json:"hardwareRevision,omitempty"` + Manufacturer *string `json:"manufacturer,omitempty"` + ManufacturerUri *string `json:"manufacturerUri,omitempty"` + Model *string `json:"model,omitempty"` + ProductCode *string `json:"productCode,omitempty"` + SerialNumber *string `json:"serialNumber,omitempty"` + SoftwareRevision *string `json:"softwareRevision,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_datapoint.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_datapoint.go new file mode 100644 index 000000000000..455636216003 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_datapoint.go @@ -0,0 +1,11 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DataPoint struct { + DataPointConfiguration *string `json:"dataPointConfiguration,omitempty"` + DataSource string `json:"dataSource"` + Name string `json:"name"` + ObservabilityMode *DataPointObservabilityMode `json:"observabilityMode,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_dataset.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_dataset.go new file mode 100644 index 000000000000..6bd5a412380f --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_dataset.go @@ -0,0 +1,11 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Dataset struct { + DataPoints *[]DataPoint `json:"dataPoints,omitempty"` + DatasetConfiguration *string `json:"datasetConfiguration,omitempty"` + Name string `json:"name"` + Topic *Topic `json:"topic,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_event.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_event.go new file mode 100644 index 000000000000..0586fe3f37b0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_event.go @@ -0,0 +1,12 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Event struct { + EventConfiguration *string `json:"eventConfiguration,omitempty"` + EventNotifier string `json:"eventNotifier"` + Name string `json:"name"` + ObservabilityMode *EventObservabilityMode `json:"observabilityMode,omitempty"` + Topic *Topic `json:"topic,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_extendedlocation.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_extendedlocation.go new file mode 100644 index 000000000000..1ab2aa85f80f --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_extendedlocation.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ExtendedLocation struct { + Name string `json:"name"` + Type string `json:"type"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_messageschemareference.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_messageschemareference.go new file mode 100644 index 000000000000..098722031b94 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_messageschemareference.go @@ -0,0 +1,10 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type MessageSchemaReference struct { + SchemaName string `json:"schemaName"` + SchemaRegistryNamespace string `json:"schemaRegistryNamespace"` + SchemaVersion string `json:"schemaVersion"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topic.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topic.go new file mode 100644 index 000000000000..83d513322ab2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topic.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Topic struct { + Path string `json:"path"` + Retain *TopicRetainType `json:"retain,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topicupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topicupdate.go new file mode 100644 index 000000000000..d43a63c0c8ea --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/model_topicupdate.go @@ -0,0 +1,9 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type TopicUpdate struct { + Path *string `json:"path,omitempty"` + Retain *TopicRetainType `json:"retain,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/predicates.go new file mode 100644 index 000000000000..cedd4ebc1011 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/predicates.go @@ -0,0 +1,32 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AssetOperationPredicate struct { + Id *string + Location *string + Name *string + Type *string +} + +func (p AssetOperationPredicate) Matches(input Asset) bool { + + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { + return false + } + + if p.Location != nil && *p.Location != input.Location { + return false + } + + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/version.go new file mode 100644 index 000000000000..296a730ec87b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets/version.go @@ -0,0 +1,10 @@ +package assets + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2024-11-01" + +func userAgent() string { + return "hashicorp/go-azure-sdk/assets/2024-11-01" +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 47c3a44135ce..9520f5dc649e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -485,6 +485,8 @@ github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/skus github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/usages github.com/hashicorp/go-azure-sdk/resource-manager/deviceprovisioningservices/2022-02-05/dpscertificate github.com/hashicorp/go-azure-sdk/resource-manager/deviceprovisioningservices/2022-02-05/iotdpsresource +github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assetendpointprofiles +github.com/hashicorp/go-azure-sdk/resource-manager/deviceregistry/2024-11-01/assets github.com/hashicorp/go-azure-sdk/resource-manager/deviceupdate/2022-10-01/deviceupdates github.com/hashicorp/go-azure-sdk/resource-manager/devtestlab/2018-09-15/globalschedules github.com/hashicorp/go-azure-sdk/resource-manager/devtestlab/2018-09-15/labs diff --git a/website/allowed-subcategories b/website/allowed-subcategories index e0c83f7f73c6..0f0008864de8 100644 --- a/website/allowed-subcategories +++ b/website/allowed-subcategories @@ -48,6 +48,7 @@ Datadog Desktop Virtualization Dev Center Dev Test +Device Registry Digital Twins Dynatrace Elastic diff --git a/website/docs/r/device_registry_asset.html.markdown b/website/docs/r/device_registry_asset.html.markdown new file mode 100644 index 000000000000..482f6d7402ce --- /dev/null +++ b/website/docs/r/device_registry_asset.html.markdown @@ -0,0 +1,208 @@ +--- +subcategory: "Device Registry" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_device_registry_asset" +description: |- + Manages a Device Registry Asset. +--- + +# azurerm_device_registry_asset + +Manages a Device Registry Asset. + +## Example Usage + +Creates an asset with 2 events and 1 dataset containing 2 data points: +```hcl +resource "azurerm_device_registry_asset" "example" { + asset_endpoint_profile_ref = "myAssetEndpointProfileRef" + attributes = { + "foo" = "bar" + "x" = "y" + } + default_datasets_configuration = jsonencode( + { + defaultPublishingInterval = 200 + defaultQueueSize = 10 + defaultSamplingInterval = 500 + } + ) + default_events_configuration = jsonencode( + { + defaultPublishingInterval = 200 + defaultQueueSize = 10 + defaultSamplingInterval = 500 + } + ) + default_topic_path = "/path/defaultTopic" + default_topic_retain = "Keep" + description = "This is my asset" + discovered_asset_refs = [ + "foo", + "bar", + "baz", + ] + display_name = "My Asset" + documentation_uri = "https://example.com/about" + enabled = false + extended_location_name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ExtendedLocation/customLocations/my-custom-location" + extended_location_type = "CustomLocation" + external_asset_id = "foobar" + hardware_revision = "1.0" + location = "westus2" + manufacturer = "Contoso" + manufacturer_uri = "https://example.com" + model = "Model123" + name = "myassetbasic" + product_code = "3E1YZ7" + resource_group_name = "my-resource-group" + serial_number = "1234" + software_revision = "2.0" + tags = { + "sensor" = "temperature,humidity" + } + + datasets { + name = "dataset1" + dataset_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + topic_path = "/path/dataset1" + topic_retain = "Keep" + + data_points { + name = "dataPoint1" + data_source = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" + observability_mode = "Log" + data_point_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + } + + data_points { + name = "dataPoint2" + data_source = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2" + observability_mode = "Counter" + data_point_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + } + } + + events { + event_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + event_notifier = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt3" + name = "event1" + observability_mode = "Log" + topic_path = "/path/event1" + topic_retain = "Never" + } + events { + event_configuration = jsonencode( + { + publishingInterval = 7 + queueSize = 8 + samplingInterval = 1000 + } + ) + event_notifier = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt4" + name = "event2" + observability_mode = "None" + topic_path = "/path/event2" + topic_retain = "Keep" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `asset_endpoint_profile_ref` - (Required) A reference to the asset endpoint profile (connection information) used by brokers to connect to an endpoint that provides data points for this asset. Must provide asset endpoint profile name. + +* `extended_location_name` - (Required) The extended location name. + +* `extended_location_type` - (Required) The extended location type. + +* `location` - (Required) The Azure Region where the Asset should exist. Changing this forces a new Asset to be created. + +* `name` - (Required) The name which should be used for this Asset. + +* `resource_group_name` - (Required) The name of the Resource Group where the Asset should exist. Changing this forces a new Asset to be created. + +--- + +* `attributes` - (Optional) A set of key-value pairs that contain custom attributes set by the customer. + +* `datasets` - (Optional) Array of datasets that are part of the asset. Each dataset describes the data points that make up the set. + +* `default_datasets_configuration` - (Optional) Stringified JSON that contains connector-specific default configuration for all datasets. Each dataset can have its own configuration that overrides the default settings here. + +* `default_events_configuration` - (Optional) Stringified JSON that contains connector-specific default configuration for all events. Each event can have its own configuration that overrides the default settings here. + +* `default_topic` - (Optional) Object that describes the default topic information for the asset. + +* `description` - (Optional) Human-readable description of the asset. + +* `discovered_asset_refs` - (Optional) Reference to a list of discovered assets. Populated only if the asset has been created from discovery flow. Discovered asset names must be provided. + +* `display_name` - (Optional) Human-readable display name. + +* `documentation_uri` - (Optional) Reference to the documentation. + +* `enabled` - (Optional) Enabled/Disabled status of the asset. + +* `events` - (Optional) Array of events that are part of the asset. Each event can have per-event configuration. + +* `external_asset_id` - (Optional) Asset id provided by the customer. + +* `hardware_revision` - (Optional) Revision number of the hardware. + +* `manufacturer` - (Optional) Asset manufacturer name. + +* `manufacturer_uri` - (Optional) Asset manufacturer URI. + +* `model` - (Optional) Asset model name. + +* `product_code` - (Optional) Asset product code. + +* `serial_number` - (Optional) Asset serial number. + +* `software_revision` - (Optional) Revision number of the software. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Asset. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Asset. +* `read` - (Defaults to 5 minutes) Used when retrieving the Asset. +* `update` - (Defaults to 30 minutes) Used when updating the Asset. +* `delete` - (Defaults to 30 minutes) Used when deleting the Asset. + +## Import + +Assets can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_device_registry_asset.example C:/Program Files/Git/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/adr-terraform-rg/providers/Microsoft.DeviceRegistry/assets/test-asset +``` diff --git a/website/docs/r/device_registry_asset_endpoint_profile.html.markdown b/website/docs/r/device_registry_asset_endpoint_profile.html.markdown new file mode 100644 index 000000000000..2e25a582ec7a --- /dev/null +++ b/website/docs/r/device_registry_asset_endpoint_profile.html.markdown @@ -0,0 +1,115 @@ +--- +subcategory: "Device Registry" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_device_registry_asset_endpoint_profile" +description: |- + Manages a Device Registry Asset Endpoint Profile. +--- + +# azurerm_device_registry_asset_endpoint_profile + +Manages a Device Registry Asset Endpoint Profile. + +## Example Usage + +### Asset Endpoint Profile with Certificate authentication +```hcl +resource "azurerm_device_registry_asset_endpoint_profile" "example" { + name = "myassetendpointprofile" + resource_group_name = "my-resource-group" + extended_location_name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ExtendedLocation/customLocations/my-custom-location" + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + authentication_method = "Certificate" + x509_credentials_certificate_secret_name = "mycertificate" + discovered_asset_endpoint_profile_ref = "myDiscoveredAssetEndpointProfile" + additional_configuration = "{\"foo\": \"bar\"}" + location = "westus2" +} +``` + +### Asset Endpoint Profile with UsernamePassword authentication +```hcl +resource "azurerm_device_registry_asset_endpoint_profile" "example" { + name = "myassetendpointprofile" + resource_group_name = "my-resource-group" + extended_location_name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ExtendedLocation/customLocations/my-custom-location" + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + authentication_method = "UsernamePassword" + username_password_credentials_username_secret_name = "myusername" + username_password_credentials_password_secret_name = "mypassword" + discovered_asset_endpoint_profile_ref = "myDiscoveredAssetEndpointProfile" + additional_configuration = "{\"foo\": \"bar\"}" + location = "westus2" +} +``` + +### Asset Endpoint Profile with Anonymous authentication +```hcl +resource "azurerm_device_registry_asset_endpoint_profile" "example" { + name = "myassetendpointprofile" + resource_group_name = "my-resource-group" + extended_location_name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ExtendedLocation/customLocations/my-custom-location" + extended_location_type = "CustomLocation" + target_address = "opc.tcp://foo" + endpoint_profile_type = "OpcUa" + authentication_method = "Anonymous" + discovered_asset_endpoint_profile_ref = "myDiscoveredAssetEndpointProfile" + additional_configuration = "{\"foo\": \"bar\"}" + location = "westus2" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `endpoint_profile_type` - (Required) Defines the configuration for the connector type that is being used with the endpoint profile. + +* `extended_location_name` - (Required) The extended location name. + +* `extended_location_type` - (Required) The extended location type. + +* `location` - (Required) The Azure Region where the Asset Endpoint Profile should exist. Changing this forces a new Asset Endpoint Profile to be created. + +* `name` - (Required) The name which should be used for this Asset Endpoint Profile. + +* `resource_group_name` - (Required) The name of the Resource Group where the Asset Endpoint Profile should exist. Changing this forces a new Asset Endpoint Profile to be created. + +* `target_address` - (Required) The local valid URI specifying the network address/DNS name of a southbound device. The scheme part of the targetAddress URI specifies the type of the device. The additionalConfiguration field holds further connector type specific configuration. + +--- + +* `additional_configuration` - (Optional) Stringified JSON that contains connectivity type specific further configuration (e.g. OPC UA, Modbus, ONVIF). + +* `authentication_method` - (Optional) Defines the method to authenticate the user of the client at the server. Defaults to `Certificate`. + +* `discovered_asset_endpoint_profile_ref` - (Optional) Reference to a discovered asset endpoint profile. Populated only if the asset endpoint profile has been created from discovery flow. Discovered asset endpoint profile name must be provided. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Asset Endpoint Profile. + +* `username_password_credentials_password_secret_name` - (Optional) The name of the secret containing the password for authentication mode UsernamePassword. + +* `username_password_credentials_username_secret_name` - (Optional) The name of the secret containing the username for authentication mode UsernamePassword. + +* `x509_credentials_certificate_secret_name` - (Optional) The name of the secret containing the certificate and private key (e.g. stored as .der/.pem or .der/.pfx) for authentication mode Certificate. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Asset Endpoint Profile. +* `read` - (Defaults to 5 minutes) Used when retrieving the Asset Endpoint Profile. +* `update` - (Defaults to 30 minutes) Used when updating the Asset Endpoint Profile. +* `delete` - (Defaults to 30 minutes) Used when deleting the Asset Endpoint Profile. + +## Import + +Asset Endpoint Profile can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_device_registry_asset_endpoint_profile.example C:/Program Files/Git/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/adr-terraform-rg/providers/Microsoft.DeviceRegistry/assetendpointprofiles/test-asset-endpoint-profile +```