From aede3b77c5b61e2ef8057b9baf2a1d93b04cf68f Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 8 Nov 2022 16:17:54 +0800 Subject: [PATCH 01/12] azurerm_network_packet_capture - support for the target_type and scope properties --- .../migration/network_packet_capture.go | 34 ++++++++ .../network_packet_capture_resource.go | 85 +++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/internal/services/network/migration/network_packet_capture.go b/internal/services/network/migration/network_packet_capture.go index 58197a333965..2c22b0114b74 100644 --- a/internal/services/network/migration/network_packet_capture.go +++ b/internal/services/network/migration/network_packet_capture.go @@ -38,6 +38,12 @@ func (NetworkPacketCaptureV0ToV1) Schema() map[string]*pluginsdk.Schema { ForceNew: true, }, + "target_type": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "maximum_bytes_per_packet": { Type: pluginsdk.TypeInt, Optional: true, @@ -123,6 +129,34 @@ func (NetworkPacketCaptureV0ToV1) Schema() map[string]*pluginsdk.Schema { }, }, }, + + "scope": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "exclude": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "include": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + }, + }, + }, } } diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 062c759db666..604b4d01e98a 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -60,6 +60,16 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { ForceNew: true, }, + "target_type": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.PacketCaptureTargetTypeAzureVM), + string(network.PacketCaptureTargetTypeAzureVMSS), + }, false), + }, + "maximum_bytes_per_packet": { Type: pluginsdk.TypeInt, Optional: true, @@ -146,6 +156,36 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { }, }, }, + + "scope": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "exclude": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + + "include": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + }, }, } } @@ -190,6 +230,14 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac }, } + if v, ok := d.GetOk("target_type"); ok { + properties.PacketCaptureParameters.TargetType = network.PacketCaptureTargetType(v.(string)) + } + + if v, ok := d.GetOk("scope"); ok { + properties.PacketCaptureParameters.Scope = expandNetworkPacketCaptureScope(v.([]interface{})) + } + future, err := client.Create(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name, properties) if err != nil { return fmt.Errorf("creating %s: %+v", id, err) @@ -231,6 +279,7 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ if props := resp.PacketCaptureResultProperties; props != nil { d.Set("target_resource_id", props.Target) + d.Set("target_type", props.TargetType) d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) @@ -244,6 +293,10 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ if err := d.Set("filter", filters); err != nil { return fmt.Errorf("setting `filter`: %+v", err) } + + if err := d.Set("scope", flattenNetworkPacketCaptureScope(props.Scope)); err != nil { + return fmt.Errorf(`setting "scope": %+v`, err) + } } return nil @@ -374,3 +427,35 @@ func flattenNetworkPacketCaptureFilters(input *[]network.PacketCaptureFilter) [] return filters } + +func expandNetworkPacketCaptureScope(input []interface{}) *network.PacketCaptureMachineScope { + if len(input) == 0 || input[0] == nil { + return nil + } + + raw := input[0].(map[string]interface{}) + output := &network.PacketCaptureMachineScope{} + + if exclude := raw["exclude"].([]interface{}); len(exclude) > 0 { + output.Exclude = utils.ExpandStringSlice(exclude) + } + + if include := raw["include"].([]interface{}); len(include) > 0 { + output.Include = utils.ExpandStringSlice(include) + } + + return output +} + +func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) []interface{} { + if input == nil { + return []interface{}{} + } + + return []interface{}{ + map[string]interface{}{ + "exclude": utils.FlattenStringSlice(input.Exclude), + "include": utils.FlattenStringSlice(input.Include), + }, + } +} From a5a78d9880ed3403e7324e4b4eb215857645434d Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 22 Nov 2022 14:14:40 +0800 Subject: [PATCH 02/12] azurerm_network_packet_capture - support for the target_type and scope properties --- .../migration/network_packet_capture.go | 2 + .../network_packet_capture_resource.go | 24 +++- .../network_packet_capture_resource_test.go | 115 ++++++++++++++++++ .../network/network_watcher_resource_test.go | 1 + .../r/network_packet_capture.html.markdown | 12 ++ 5 files changed, 151 insertions(+), 3 deletions(-) diff --git a/internal/services/network/migration/network_packet_capture.go b/internal/services/network/migration/network_packet_capture.go index 2c22b0114b74..cb0525c20c5a 100644 --- a/internal/services/network/migration/network_packet_capture.go +++ b/internal/services/network/migration/network_packet_capture.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/tombuildsstuff/kermit/sdk/network/2022-05-01/network" ) var _ pluginsdk.StateUpgrade = NetworkPacketCaptureV0ToV1{} @@ -42,6 +43,7 @@ func (NetworkPacketCaptureV0ToV1) Schema() map[string]*pluginsdk.Schema { Type: pluginsdk.TypeString, Optional: true, ForceNew: true, + Default: string(network.PacketCaptureTargetTypeAzureVM), }, "maximum_bytes_per_packet": { diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 604b4d01e98a..2bdfce5274ca 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -3,6 +3,7 @@ package network import ( "fmt" "log" + "strings" "time" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" @@ -64,6 +65,7 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { Type: pluginsdk.TypeString, Optional: true, ForceNew: true, + Default: string(network.PacketCaptureTargetTypeAzureVM), ValidateFunc: validation.StringInSlice([]string{ string(network.PacketCaptureTargetTypeAzureVM), string(network.PacketCaptureTargetTypeAzureVMSS), @@ -448,14 +450,30 @@ func expandNetworkPacketCaptureScope(input []interface{}) *network.PacketCapture } func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) []interface{} { - if input == nil { + if input == nil || (input.Exclude == nil && input.Include == nil) || (len(*input.Exclude) == 0 && len(*input.Include) == 0) { return []interface{}{} } return []interface{}{ map[string]interface{}{ - "exclude": utils.FlattenStringSlice(input.Exclude), - "include": utils.FlattenStringSlice(input.Include), + "exclude": flattenNetworkPacketCaptureScopeInstanceIds(input.Exclude), + "include": flattenNetworkPacketCaptureScopeInstanceIds(input.Include), }, } } + +func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) []string { + instances := make([]string, 0) + if input == nil { + return instances + } + + for _, instance := range *input { + instanceSegments := strings.Split(instance, "/") + instanceLastSegment := instanceSegments[len(instanceSegments)-1] + + instances = append(instances, instanceLastSegment) + } + + return instances +} diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index 280c23a5d86f..862d636b5292 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -93,6 +93,21 @@ func testAccNetworkPacketCapture_withFilters(t *testing.T) { }) } +func testAccNetworkPacketCapture_scope(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") + r := NetworkPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.scope(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (t NetworkPacketCaptureResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.PacketCaptureID(state.ID) if err != nil { @@ -318,3 +333,103 @@ resource "azurerm_network_packet_capture" "test" { } `, r.base(data), data.RandomString, data.RandomInteger) } + +func (NetworkPacketCaptureResource) scope(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-watcher-%d" + location = "%s" +} + +resource "azurerm_network_watcher" "test" { + name = "acctestnw-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_linux_virtual_machine_scale_set" "test" { + name = "acctestvmss-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 4 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + computer_name_prefix = "my-linux-computer-name-prefix" + upgrade_mode = "Automatic" + + disable_password_authentication = false + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + } + } +} + +resource "azurerm_virtual_machine_scale_set_extension" "test" { + name = "network-watcher" + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true + automatic_upgrade_enabled = true +} + +resource "azurerm_network_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + target_type = "AzureVMSS" + + scope { + include = ["0", "1"] + exclude = ["2", "3"] + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} diff --git a/internal/services/network/network_watcher_resource_test.go b/internal/services/network/network_watcher_resource_test.go index 9120e0fd5af9..f1786fce98e9 100644 --- a/internal/services/network/network_watcher_resource_test.go +++ b/internal/services/network/network_watcher_resource_test.go @@ -57,6 +57,7 @@ func TestAccNetworkWatcher(t *testing.T) { "storageAccountAndLocalDisk": testAccNetworkPacketCapture_storageAccountAndLocalDisk, "withFilters": testAccNetworkPacketCapture_withFilters, "requiresImport": testAccNetworkPacketCapture_requiresImport, + "scope": testAccNetworkPacketCapture_scope, }, "FlowLog": { "basic": testAccNetworkWatcherFlowLog_basic, diff --git a/website/docs/r/network_packet_capture.html.markdown b/website/docs/r/network_packet_capture.html.markdown index 17373c0453a9..277783bd37e8 100644 --- a/website/docs/r/network_packet_capture.html.markdown +++ b/website/docs/r/network_packet_capture.html.markdown @@ -140,6 +140,10 @@ The following arguments are supported: * `filter` - (Optional) One or more `filter` blocks as defined below. Changing this forces a new resource to be created. +* `target_type` - (Optional) The target type of the resource provided. Possible values are `AzureVM` and `AzureVMSS`. Defaults to `AzureVM`. Changing this forces a new resource to be created. + +* `scope` - (Required) A `scope` block as defined below. Changing this forces a new resource to be created. + --- A `storage_location` block contains: @@ -162,6 +166,14 @@ A `filter` block contains: * `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +--- + +A `scope` block contains: + +* `exclude` - (Optional) A list of Azure VMSS instance IDs which has to be excluded from Azure VMSS from running Packet Capture. Changing this forces a new resource to be created. + +* `include` - (Optional) A list of Azure VMSS instance IDs to run Packet Capture on. Changing this forces a new resource to be created. + ## Attributes Reference The following attributes are exported: From eb0253d55e0e95c700d8d46407a46cdfb90d6174 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 22 Nov 2022 14:22:26 +0800 Subject: [PATCH 03/12] update code --- website/docs/r/network_packet_capture.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/network_packet_capture.html.markdown b/website/docs/r/network_packet_capture.html.markdown index 277783bd37e8..6f1d83919812 100644 --- a/website/docs/r/network_packet_capture.html.markdown +++ b/website/docs/r/network_packet_capture.html.markdown @@ -142,7 +142,7 @@ The following arguments are supported: * `target_type` - (Optional) The target type of the resource provided. Possible values are `AzureVM` and `AzureVMSS`. Defaults to `AzureVM`. Changing this forces a new resource to be created. -* `scope` - (Required) A `scope` block as defined below. Changing this forces a new resource to be created. +* `scope` - (Optional) A `scope` block as defined below. Changing this forces a new resource to be created. --- From 1819582366ee9a42486dc2c0d064ba2ace064c8a Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 29 Nov 2022 15:17:16 +0800 Subject: [PATCH 04/12] update code --- .../network_packet_capture_resource.go | 47 +++++-- .../network_packet_capture_resource_test.go | 8 ++ .../services/network/parse/vmss_instance.go | 75 ++++++++++ .../network/parse/vmss_instance_test.go | 128 ++++++++++++++++++ internal/services/network/resourceids.go | 1 + .../network/validate/vmss_instance_id.go | 23 ++++ .../network/validate/vmss_instance_id_test.go | 88 ++++++++++++ 7 files changed, 355 insertions(+), 15 deletions(-) create mode 100644 internal/services/network/parse/vmss_instance.go create mode 100644 internal/services/network/parse/vmss_instance_test.go create mode 100644 internal/services/network/validate/vmss_instance_id.go create mode 100644 internal/services/network/validate/vmss_instance_id_test.go diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 2bdfce5274ca..19eed2e89c0b 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -3,7 +3,6 @@ package network import ( "fmt" "log" - "strings" "time" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" @@ -296,7 +295,11 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ return fmt.Errorf("setting `filter`: %+v", err) } - if err := d.Set("scope", flattenNetworkPacketCaptureScope(props.Scope)); err != nil { + scope, err := flattenNetworkPacketCaptureScope(props.Scope) + if err != nil { + return err + } + if err := d.Set("scope", scope); err != nil { return fmt.Errorf(`setting "scope": %+v`, err) } } @@ -449,31 +452,45 @@ func expandNetworkPacketCaptureScope(input []interface{}) *network.PacketCapture return output } -func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) []interface{} { +func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) ([]interface{}, error) { + outputs := make([]interface{}, 0) if input == nil || (input.Exclude == nil && input.Include == nil) || (len(*input.Exclude) == 0 && len(*input.Include) == 0) { - return []interface{}{} + return outputs, nil } - return []interface{}{ - map[string]interface{}{ - "exclude": flattenNetworkPacketCaptureScopeInstanceIds(input.Exclude), - "include": flattenNetworkPacketCaptureScopeInstanceIds(input.Include), - }, + output := make(map[string]interface{}, 0) + + excludedInstanceIds, err := flattenNetworkPacketCaptureScopeInstanceIds(input.Exclude) + if err != nil { + return nil, err } + output["exclude"] = excludedInstanceIds + + includedInstanceIds, err := flattenNetworkPacketCaptureScopeInstanceIds(input.Include) + if err != nil { + return nil, err + } + output["include"] = includedInstanceIds + + outputs = append(outputs, output) + + return outputs, nil } -func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) []string { +func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) ([]string, error) { instances := make([]string, 0) if input == nil { - return instances + return instances, nil } for _, instance := range *input { - instanceSegments := strings.Split(instance, "/") - instanceLastSegment := instanceSegments[len(instanceSegments)-1] + instance, err := parse.VMSSInstanceID(instance) + if err != nil { + return nil, err + } - instances = append(instances, instanceLastSegment) + instances = append(instances, instance.VirtualMachineName) } - return instances + return instances, nil } diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index 862d636b5292..f29522dc0a2f 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -197,6 +197,10 @@ resource "azurerm_virtual_machine" "test" { os_profile_linux_config { disable_password_authentication = false } + + lifecycle { + ignore_changes = [tags] + } } resource "azurerm_virtual_machine_extension" "test" { @@ -400,6 +404,10 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { subnet_id = azurerm_subnet.test.id } } + + lifecycle { + ignore_changes = [identity, tags] + } } resource "azurerm_virtual_machine_scale_set_extension" "test" { diff --git a/internal/services/network/parse/vmss_instance.go b/internal/services/network/parse/vmss_instance.go new file mode 100644 index 000000000000..60c0dc9e17f9 --- /dev/null +++ b/internal/services/network/parse/vmss_instance.go @@ -0,0 +1,75 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +type VMSSInstanceId struct { + SubscriptionId string + ResourceGroup string + VirtualMachineScaleSetName string + VirtualMachineName string +} + +func NewVMSSInstanceID(subscriptionId, resourceGroup, virtualMachineScaleSetName, virtualMachineName string) VMSSInstanceId { + return VMSSInstanceId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + VirtualMachineScaleSetName: virtualMachineScaleSetName, + VirtualMachineName: virtualMachineName, + } +} + +func (id VMSSInstanceId) String() string { + segments := []string{ + fmt.Sprintf("Virtual Machine Name %q", id.VirtualMachineName), + fmt.Sprintf("Virtual Machine Scale Set Name %q", id.VirtualMachineScaleSetName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "V M S S Instance", segmentsStr) +} + +func (id VMSSInstanceId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.VirtualMachineScaleSetName, id.VirtualMachineName) +} + +// VMSSInstanceID parses a VMSSInstance ID into an VMSSInstanceId struct +func VMSSInstanceID(input string) (*VMSSInstanceId, error) { + id, err := resourceids.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := VMSSInstanceId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + if resourceId.VirtualMachineScaleSetName, err = id.PopSegment("virtualMachineScaleSets"); err != nil { + return nil, err + } + if resourceId.VirtualMachineName, err = id.PopSegment("virtualMachines"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/network/parse/vmss_instance_test.go b/internal/services/network/parse/vmss_instance_test.go new file mode 100644 index 000000000000..1f7ccb4a74fa --- /dev/null +++ b/internal/services/network/parse/vmss_instance_test.go @@ -0,0 +1,128 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.Id = VMSSInstanceId{} + +func TestVMSSInstanceIDFormatter(t *testing.T) { + actual := NewVMSSInstanceID("12345678-1234-9876-4563-123456789012", "resGroup1", "vmss1", "vm1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestVMSSInstanceID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *VMSSInstanceId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing VirtualMachineScaleSetName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/", + Error: true, + }, + + { + // missing value for VirtualMachineScaleSetName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/", + Error: true, + }, + + { + // missing VirtualMachineName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/", + Error: true, + }, + + { + // missing value for VirtualMachineName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1", + Expected: &VMSSInstanceId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resGroup1", + VirtualMachineScaleSetName: "vmss1", + VirtualMachineName: "vm1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/VMSS1/VIRTUALMACHINES/VM1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := VMSSInstanceID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.VirtualMachineScaleSetName != v.Expected.VirtualMachineScaleSetName { + t.Fatalf("Expected %q but got %q for VirtualMachineScaleSetName", v.Expected.VirtualMachineScaleSetName, actual.VirtualMachineScaleSetName) + } + if actual.VirtualMachineName != v.Expected.VirtualMachineName { + t.Fatalf("Expected %q but got %q for VirtualMachineName", v.Expected.VirtualMachineName, actual.VirtualMachineName) + } + } +} diff --git a/internal/services/network/resourceids.go b/internal/services/network/resourceids.go index 2771982832a5..91c484faa42c 100644 --- a/internal/services/network/resourceids.go +++ b/internal/services/network/resourceids.go @@ -52,6 +52,7 @@ package network //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=NetworkWatcher -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=PacketCapture -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1/packetCaptures/capture1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FlowLog -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1/flowLogs/log1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=VMSSInstance -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1 // Private Link //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=PrivateEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateEndpoints/endpoint1 diff --git a/internal/services/network/validate/vmss_instance_id.go b/internal/services/network/validate/vmss_instance_id.go new file mode 100644 index 000000000000..cad9662fc60f --- /dev/null +++ b/internal/services/network/validate/vmss_instance_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" +) + +func VMSSInstanceID(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 := parse.VMSSInstanceID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/network/validate/vmss_instance_id_test.go b/internal/services/network/validate/vmss_instance_id_test.go new file mode 100644 index 000000000000..7cbca58119c6 --- /dev/null +++ b/internal/services/network/validate/vmss_instance_id_test.go @@ -0,0 +1,88 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestVMSSInstanceID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing VirtualMachineScaleSetName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/", + Valid: false, + }, + + { + // missing value for VirtualMachineScaleSetName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/", + Valid: false, + }, + + { + // missing VirtualMachineName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/", + Valid: false, + }, + + { + // missing value for VirtualMachineName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/VMSS1/VIRTUALMACHINES/VM1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := VMSSInstanceID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} From 670691e3d358eb9973a4b613cbb00ff5f3a8cc11 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Wed, 30 Nov 2022 10:12:24 +0800 Subject: [PATCH 05/12] update code --- .../parse/vmss_instance.go | 0 .../parse/vmss_instance_test.go | 0 internal/services/compute/resourceids.go | 1 + .../validate/vmss_instance_id.go | 2 +- .../validate/vmss_instance_id_test.go | 0 .../migration/network_packet_capture.go | 36 ---------------- .../network_packet_capture_resource.go | 42 ++++++++++++------- .../network_packet_capture_resource_test.go | 37 ++++++---------- .../network/network_watcher_resource_test.go | 2 +- internal/services/network/resourceids.go | 1 - .../r/network_packet_capture.html.markdown | 12 +++--- 11 files changed, 49 insertions(+), 84 deletions(-) rename internal/services/{network => compute}/parse/vmss_instance.go (100%) rename internal/services/{network => compute}/parse/vmss_instance_test.go (100%) rename internal/services/{network => compute}/validate/vmss_instance_id.go (96%) rename internal/services/{network => compute}/validate/vmss_instance_id_test.go (100%) diff --git a/internal/services/network/parse/vmss_instance.go b/internal/services/compute/parse/vmss_instance.go similarity index 100% rename from internal/services/network/parse/vmss_instance.go rename to internal/services/compute/parse/vmss_instance.go diff --git a/internal/services/network/parse/vmss_instance_test.go b/internal/services/compute/parse/vmss_instance_test.go similarity index 100% rename from internal/services/network/parse/vmss_instance_test.go rename to internal/services/compute/parse/vmss_instance_test.go diff --git a/internal/services/compute/resourceids.go b/internal/services/compute/resourceids.go index 03d28cd95b18..2d2d9f172c2c 100644 --- a/internal/services/compute/resourceids.go +++ b/internal/services/compute/resourceids.go @@ -19,3 +19,4 @@ package compute //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=DataDisk -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.Compute/virtualMachines/machine1/dataDisks/disk1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Plan -id=/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.MarketplaceOrdering/agreements/agreement1/offers/offer1/plans/hourly //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HostGroup -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/group1/providers/Microsoft.Compute/hostGroups/hostgroup1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=VMSSInstance -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1 diff --git a/internal/services/network/validate/vmss_instance_id.go b/internal/services/compute/validate/vmss_instance_id.go similarity index 96% rename from internal/services/network/validate/vmss_instance_id.go rename to internal/services/compute/validate/vmss_instance_id.go index cad9662fc60f..9e4268d00370 100644 --- a/internal/services/network/validate/vmss_instance_id.go +++ b/internal/services/compute/validate/vmss_instance_id.go @@ -5,7 +5,7 @@ package validate import ( "fmt" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" ) func VMSSInstanceID(input interface{}, key string) (warnings []string, errors []error) { diff --git a/internal/services/network/validate/vmss_instance_id_test.go b/internal/services/compute/validate/vmss_instance_id_test.go similarity index 100% rename from internal/services/network/validate/vmss_instance_id_test.go rename to internal/services/compute/validate/vmss_instance_id_test.go diff --git a/internal/services/network/migration/network_packet_capture.go b/internal/services/network/migration/network_packet_capture.go index cb0525c20c5a..58197a333965 100644 --- a/internal/services/network/migration/network_packet_capture.go +++ b/internal/services/network/migration/network_packet_capture.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/tombuildsstuff/kermit/sdk/network/2022-05-01/network" ) var _ pluginsdk.StateUpgrade = NetworkPacketCaptureV0ToV1{} @@ -39,13 +38,6 @@ func (NetworkPacketCaptureV0ToV1) Schema() map[string]*pluginsdk.Schema { ForceNew: true, }, - "target_type": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - Default: string(network.PacketCaptureTargetTypeAzureVM), - }, - "maximum_bytes_per_packet": { Type: pluginsdk.TypeInt, Optional: true, @@ -131,34 +123,6 @@ func (NetworkPacketCaptureV0ToV1) Schema() map[string]*pluginsdk.Schema { }, }, }, - - "scope": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "exclude": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - }, - }, - - "include": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - }, - }, - }, - }, - }, } } diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 19eed2e89c0b..d3e9e42811c7 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -8,6 +8,8 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + computeParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" + computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" @@ -58,6 +60,10 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, + ValidateFunc: validation.Any( + computeValidate.VirtualMachineID, + computeValidate.VirtualMachineScaleSetID, + ), }, "target_type": { @@ -158,14 +164,14 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { }, }, - "scope": { + "machine_scope": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "exclude": { + "exclude_instance_ids": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, @@ -175,7 +181,7 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { }, }, - "include": { + "include_instance_ids": { Type: pluginsdk.TypeList, Optional: true, ForceNew: true, @@ -235,8 +241,8 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac properties.PacketCaptureParameters.TargetType = network.PacketCaptureTargetType(v.(string)) } - if v, ok := d.GetOk("scope"); ok { - properties.PacketCaptureParameters.Scope = expandNetworkPacketCaptureScope(v.([]interface{})) + if v, ok := d.GetOk("machine_scope"); ok { + properties.PacketCaptureParameters.Scope = expandNetworkPacketCaptureMachineScope(v.([]interface{})) } future, err := client.Create(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name, properties) @@ -295,13 +301,19 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ return fmt.Errorf("setting `filter`: %+v", err) } - scope, err := flattenNetworkPacketCaptureScope(props.Scope) + scope, err := flattenNetworkPacketCaptureMachineScope(props.Scope) if err != nil { return err } - if err := d.Set("scope", scope); err != nil { - return fmt.Errorf(`setting "scope": %+v`, err) + if err := d.Set("machine_scope", scope); err != nil { + return fmt.Errorf(`setting "machine_scope": %+v`, err) } + + targetType := network.PacketCaptureTargetTypeAzureVM + if props.TargetType != "" { + targetType = props.TargetType + } + d.Set("target_type", targetType) } return nil @@ -433,7 +445,7 @@ func flattenNetworkPacketCaptureFilters(input *[]network.PacketCaptureFilter) [] return filters } -func expandNetworkPacketCaptureScope(input []interface{}) *network.PacketCaptureMachineScope { +func expandNetworkPacketCaptureMachineScope(input []interface{}) *network.PacketCaptureMachineScope { if len(input) == 0 || input[0] == nil { return nil } @@ -441,18 +453,18 @@ func expandNetworkPacketCaptureScope(input []interface{}) *network.PacketCapture raw := input[0].(map[string]interface{}) output := &network.PacketCaptureMachineScope{} - if exclude := raw["exclude"].([]interface{}); len(exclude) > 0 { + if exclude := raw["exclude_instance_ids"].([]interface{}); len(exclude) > 0 { output.Exclude = utils.ExpandStringSlice(exclude) } - if include := raw["include"].([]interface{}); len(include) > 0 { + if include := raw["include_instance_ids"].([]interface{}); len(include) > 0 { output.Include = utils.ExpandStringSlice(include) } return output } -func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) ([]interface{}, error) { +func flattenNetworkPacketCaptureMachineScope(input *network.PacketCaptureMachineScope) ([]interface{}, error) { outputs := make([]interface{}, 0) if input == nil || (input.Exclude == nil && input.Include == nil) || (len(*input.Exclude) == 0 && len(*input.Include) == 0) { return outputs, nil @@ -464,13 +476,13 @@ func flattenNetworkPacketCaptureScope(input *network.PacketCaptureMachineScope) if err != nil { return nil, err } - output["exclude"] = excludedInstanceIds + output["exclude_instance_ids"] = excludedInstanceIds includedInstanceIds, err := flattenNetworkPacketCaptureScopeInstanceIds(input.Include) if err != nil { return nil, err } - output["include"] = includedInstanceIds + output["include_instance_ids"] = includedInstanceIds outputs = append(outputs, output) @@ -484,7 +496,7 @@ func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) ([]string, err } for _, instance := range *input { - instance, err := parse.VMSSInstanceID(instance) + instance, err := computeParse.VMSSInstanceID(instance) if err != nil { return nil, err } diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index f29522dc0a2f..d7f61a873bb3 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -93,13 +93,13 @@ func testAccNetworkPacketCapture_withFilters(t *testing.T) { }) } -func testAccNetworkPacketCapture_scope(t *testing.T) { +func testAccNetworkPacketCapture_machineScope(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} data.ResourceSequentialTest(t, r, []acceptance.TestStep{ { - Config: r.scope(data), + Config: r.machineScope(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -197,10 +197,6 @@ resource "azurerm_virtual_machine" "test" { os_profile_linux_config { disable_password_authentication = false } - - lifecycle { - ignore_changes = [tags] - } } resource "azurerm_virtual_machine_extension" "test" { @@ -338,7 +334,7 @@ resource "azurerm_network_packet_capture" "test" { `, r.base(data), data.RandomString, data.RandomInteger) } -func (NetworkPacketCaptureResource) scope(data acceptance.TestData) string { +func (NetworkPacketCaptureResource) machineScope(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -405,21 +401,16 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { } } - lifecycle { - ignore_changes = [identity, tags] + extension { + name = "network-watcher" + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true + automatic_upgrade_enabled = true } } -resource "azurerm_virtual_machine_scale_set_extension" "test" { - name = "network-watcher" - virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id - publisher = "Microsoft.Azure.NetworkWatcher" - type = "NetworkWatcherAgentLinux" - type_handler_version = "1.4" - auto_upgrade_minor_version = true - automatic_upgrade_enabled = true -} - resource "azurerm_network_packet_capture" "test" { name = "acctestpc-%d" network_watcher_name = azurerm_network_watcher.test.name @@ -432,12 +423,10 @@ resource "azurerm_network_packet_capture" "test" { target_type = "AzureVMSS" - scope { - include = ["0", "1"] - exclude = ["2", "3"] + machine_scope { + include_instance_ids = ["0", "1"] + exclude_instance_ids = ["2", "3"] } - - depends_on = [azurerm_virtual_machine_scale_set_extension.test] } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/internal/services/network/network_watcher_resource_test.go b/internal/services/network/network_watcher_resource_test.go index f1786fce98e9..bfa438090c37 100644 --- a/internal/services/network/network_watcher_resource_test.go +++ b/internal/services/network/network_watcher_resource_test.go @@ -57,7 +57,7 @@ func TestAccNetworkWatcher(t *testing.T) { "storageAccountAndLocalDisk": testAccNetworkPacketCapture_storageAccountAndLocalDisk, "withFilters": testAccNetworkPacketCapture_withFilters, "requiresImport": testAccNetworkPacketCapture_requiresImport, - "scope": testAccNetworkPacketCapture_scope, + "machineScope": testAccNetworkPacketCapture_machineScope, }, "FlowLog": { "basic": testAccNetworkWatcherFlowLog_basic, diff --git a/internal/services/network/resourceids.go b/internal/services/network/resourceids.go index 91c484faa42c..2771982832a5 100644 --- a/internal/services/network/resourceids.go +++ b/internal/services/network/resourceids.go @@ -52,7 +52,6 @@ package network //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=NetworkWatcher -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=PacketCapture -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1/packetCaptures/capture1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FlowLog -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/networkWatchers/watcher1/flowLogs/log1 -//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=VMSSInstance -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1/virtualMachines/vm1 // Private Link //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=PrivateEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateEndpoints/endpoint1 diff --git a/website/docs/r/network_packet_capture.html.markdown b/website/docs/r/network_packet_capture.html.markdown index 6f1d83919812..8feaf3004110 100644 --- a/website/docs/r/network_packet_capture.html.markdown +++ b/website/docs/r/network_packet_capture.html.markdown @@ -114,7 +114,7 @@ resource "azurerm_network_packet_capture" "example" { } ``` -~> **NOTE:** This Resource requires that [the Network Watcher Virtual Machine Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_extension` resource](virtual_machine_extension.html). +~> **NOTE:** This Resource requires that [the Network Watcher Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine or Virtual Machine Scale Set before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_extension` resource](virtual_machine_extension.html) or [the `azurerm_virtual_machine_scale_set_extension` resource](virtual_machine_scale_set_extension.html). ## Argument Reference @@ -128,7 +128,7 @@ The following arguments are supported: * `target_resource_id` - (Required) The ID of the Resource to capture packets from. Changing this forces a new resource to be created. -~> **NOTE:** Currently only Virtual Machines IDs are supported. +~> **NOTE:** Currently only Virtual Machines IDs and Virtual Machine Scale Set IDs are supported. * `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. @@ -142,7 +142,7 @@ The following arguments are supported: * `target_type` - (Optional) The target type of the resource provided. Possible values are `AzureVM` and `AzureVMSS`. Defaults to `AzureVM`. Changing this forces a new resource to be created. -* `scope` - (Optional) A `scope` block as defined below. Changing this forces a new resource to be created. +* `machine_scope` - (Optional) A `machine_scope` block as defined below. Changing this forces a new resource to be created. --- @@ -168,11 +168,11 @@ A `filter` block contains: --- -A `scope` block contains: +A `machine_scope` block contains: -* `exclude` - (Optional) A list of Azure VMSS instance IDs which has to be excluded from Azure VMSS from running Packet Capture. Changing this forces a new resource to be created. +* `exclude_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be excluded from running Packet Capture, e.g. `["0", "2"]`. Changing this forces a new resource to be created. -* `include` - (Optional) A list of Azure VMSS instance IDs to run Packet Capture on. Changing this forces a new resource to be created. +* `include_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be included for Packet Capture, e.g. `["1", "3"]`. Changing this forces a new resource to be created. ## Attributes Reference From 41e0b3db2ffe540b1ed404d13a5bfc9cef297c71 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Wed, 30 Nov 2022 10:18:03 +0800 Subject: [PATCH 06/12] update code --- internal/services/network/network_packet_capture_resource.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index d3e9e42811c7..812ce71316b1 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -286,7 +286,6 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ if props := resp.PacketCaptureResultProperties; props != nil { d.Set("target_resource_id", props.Target) - d.Set("target_type", props.TargetType) d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) From 9fc570641d08563b59a0906e4f8771ec0bf8cf32 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Wed, 30 Nov 2022 11:19:54 +0800 Subject: [PATCH 07/12] update code --- .../network_packet_capture_resource_test.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index d7f61a873bb3..ac0c36114447 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -400,15 +400,16 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" { subnet_id = azurerm_subnet.test.id } } +} - extension { - name = "network-watcher" - publisher = "Microsoft.Azure.NetworkWatcher" - type = "NetworkWatcherAgentLinux" - type_handler_version = "1.4" - auto_upgrade_minor_version = true - automatic_upgrade_enabled = true - } +resource "azurerm_virtual_machine_scale_set_extension" "test" { + name = "network-watcher" + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true + automatic_upgrade_enabled = true } resource "azurerm_network_packet_capture" "test" { @@ -427,6 +428,8 @@ resource "azurerm_network_packet_capture" "test" { include_instance_ids = ["0", "1"] exclude_instance_ids = ["2", "3"] } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } From 349fe33d4dbb99fa802582e5f31ef9114adaa1a0 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 1 Dec 2022 11:33:34 +0800 Subject: [PATCH 08/12] update code --- .../network_packet_capture_resource.go | 34 +++++++------------ .../network_packet_capture_resource_test.go | 2 -- .../r/network_packet_capture.html.markdown | 2 -- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 812ce71316b1..0f5d2b4b80f6 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -66,17 +66,6 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { ), }, - "target_type": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - Default: string(network.PacketCaptureTargetTypeAzureVM), - ValidateFunc: validation.StringInSlice([]string{ - string(network.PacketCaptureTargetTypeAzureVM), - string(network.PacketCaptureTargetTypeAzureVMSS), - }, false), - }, - "maximum_bytes_per_packet": { Type: pluginsdk.TypeInt, Optional: true, @@ -229,6 +218,7 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac properties := network.PacketCapture{ PacketCaptureParameters: &network.PacketCaptureParameters{ Target: utils.String(targetResourceId), + TargetType: getNetworkPacketCaptureTargetType(targetResourceId), StorageLocation: storageLocation, BytesToCapturePerPacket: utils.Int64(int64(bytesToCapturePerPacket)), TimeLimitInSeconds: utils.Int32(int32(timeLimitInSeconds)), @@ -237,10 +227,6 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac }, } - if v, ok := d.GetOk("target_type"); ok { - properties.PacketCaptureParameters.TargetType = network.PacketCaptureTargetType(v.(string)) - } - if v, ok := d.GetOk("machine_scope"); ok { properties.PacketCaptureParameters.Scope = expandNetworkPacketCaptureMachineScope(v.([]interface{})) } @@ -307,12 +293,6 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ if err := d.Set("machine_scope", scope); err != nil { return fmt.Errorf(`setting "machine_scope": %+v`, err) } - - targetType := network.PacketCaptureTargetTypeAzureVM - if props.TargetType != "" { - targetType = props.TargetType - } - d.Set("target_type", targetType) } return nil @@ -505,3 +485,15 @@ func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) ([]string, err return instances, nil } + +func getNetworkPacketCaptureTargetType(targetResourceId string) network.PacketCaptureTargetType { + var targetType network.PacketCaptureTargetType + + if _, err := computeParse.VirtualMachineID(targetResourceId); err == nil { + targetType = network.PacketCaptureTargetTypeAzureVM + } else if _, err := computeParse.VirtualMachineScaleSetID(targetResourceId); err == nil { + targetType = network.PacketCaptureTargetTypeAzureVMSS + } + + return targetType +} diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index ac0c36114447..8d725b01d846 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -422,8 +422,6 @@ resource "azurerm_network_packet_capture" "test" { file_path = "/var/captures/packet.cap" } - target_type = "AzureVMSS" - machine_scope { include_instance_ids = ["0", "1"] exclude_instance_ids = ["2", "3"] diff --git a/website/docs/r/network_packet_capture.html.markdown b/website/docs/r/network_packet_capture.html.markdown index 8feaf3004110..1a73cfb1d47b 100644 --- a/website/docs/r/network_packet_capture.html.markdown +++ b/website/docs/r/network_packet_capture.html.markdown @@ -140,8 +140,6 @@ The following arguments are supported: * `filter` - (Optional) One or more `filter` blocks as defined below. Changing this forces a new resource to be created. -* `target_type` - (Optional) The target type of the resource provided. Possible values are `AzureVM` and `AzureVMSS`. Defaults to `AzureVM`. Changing this forces a new resource to be created. - * `machine_scope` - (Optional) A `machine_scope` block as defined below. Changing this forces a new resource to be created. --- From bd2f8909a818fae14914f1415339b82b7912c78d Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 8 Dec 2022 11:09:42 +0800 Subject: [PATCH 09/12] update code --- .../network_packet_capture_resource.go | 131 +---- .../network_packet_capture_resource_test.go | 134 +---- .../network/network_watcher_resource_test.go | 16 +- internal/services/network/registration.go | 2 + ...virtual_machine_packet_capture_resource.go | 381 ++++++++++++++ ...al_machine_packet_capture_resource_test.go | 317 ++++++++++++ ...chine_scale_set_packet_capture_resource.go | 486 ++++++++++++++++++ ..._scale_set_packet_capture_resource_test.go | 348 +++++++++++++ .../r/network_packet_capture.html.markdown | 18 +- ...rtual_machine_packet_capture.html.markdown | 191 +++++++ ...ine_scale_set_packet_capture.html.markdown | 192 +++++++ 11 files changed, 1963 insertions(+), 253 deletions(-) create mode 100644 internal/services/network/virtual_machine_packet_capture_resource.go create mode 100644 internal/services/network/virtual_machine_packet_capture_resource_test.go create mode 100644 internal/services/network/virtual_machine_scale_set_packet_capture_resource.go create mode 100644 internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go create mode 100644 website/docs/r/virtual_machine_packet_capture.html.markdown create mode 100644 website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index 0f5d2b4b80f6..b6007ecb1a24 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -8,8 +8,6 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - computeParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" - computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" @@ -21,9 +19,11 @@ import ( func resourceNetworkPacketCapture() *pluginsdk.Resource { return &pluginsdk.Resource{ - Create: resourceNetworkPacketCaptureCreate, - Read: resourceNetworkPacketCaptureRead, - Delete: resourceNetworkPacketCaptureDelete, + Create: resourceNetworkPacketCaptureCreate, + Read: resourceNetworkPacketCaptureRead, + Delete: resourceNetworkPacketCaptureDelete, + DeprecationMessage: "The \"azurerm_network_packet_capture\" resource is deprecated and will be removed in favour of `azurerm_virtual_machine_packet_capture` and `azurerm_virtual_machine_scale_set_packet_capture` in version 4.0 of the AzureRM Provider.", + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { _, err := parse.PacketCaptureID(id) return err @@ -60,10 +60,6 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.Any( - computeValidate.VirtualMachineID, - computeValidate.VirtualMachineScaleSetID, - ), }, "maximum_bytes_per_packet": { @@ -152,36 +148,6 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { }, }, }, - - "machine_scope": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "exclude_instance_ids": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringIsNotEmpty, - }, - }, - - "include_instance_ids": { - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringIsNotEmpty, - }, - }, - }, - }, - }, }, } } @@ -218,7 +184,6 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac properties := network.PacketCapture{ PacketCaptureParameters: &network.PacketCaptureParameters{ Target: utils.String(targetResourceId), - TargetType: getNetworkPacketCaptureTargetType(targetResourceId), StorageLocation: storageLocation, BytesToCapturePerPacket: utils.Int64(int64(bytesToCapturePerPacket)), TimeLimitInSeconds: utils.Int32(int32(timeLimitInSeconds)), @@ -227,10 +192,6 @@ func resourceNetworkPacketCaptureCreate(d *pluginsdk.ResourceData, meta interfac }, } - if v, ok := d.GetOk("machine_scope"); ok { - properties.PacketCaptureParameters.Scope = expandNetworkPacketCaptureMachineScope(v.([]interface{})) - } - future, err := client.Create(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name, properties) if err != nil { return fmt.Errorf("creating %s: %+v", id, err) @@ -285,14 +246,6 @@ func resourceNetworkPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{ if err := d.Set("filter", filters); err != nil { return fmt.Errorf("setting `filter`: %+v", err) } - - scope, err := flattenNetworkPacketCaptureMachineScope(props.Scope) - if err != nil { - return err - } - if err := d.Set("machine_scope", scope); err != nil { - return fmt.Errorf(`setting "machine_scope": %+v`, err) - } } return nil @@ -423,77 +376,3 @@ func flattenNetworkPacketCaptureFilters(input *[]network.PacketCaptureFilter) [] return filters } - -func expandNetworkPacketCaptureMachineScope(input []interface{}) *network.PacketCaptureMachineScope { - if len(input) == 0 || input[0] == nil { - return nil - } - - raw := input[0].(map[string]interface{}) - output := &network.PacketCaptureMachineScope{} - - if exclude := raw["exclude_instance_ids"].([]interface{}); len(exclude) > 0 { - output.Exclude = utils.ExpandStringSlice(exclude) - } - - if include := raw["include_instance_ids"].([]interface{}); len(include) > 0 { - output.Include = utils.ExpandStringSlice(include) - } - - return output -} - -func flattenNetworkPacketCaptureMachineScope(input *network.PacketCaptureMachineScope) ([]interface{}, error) { - outputs := make([]interface{}, 0) - if input == nil || (input.Exclude == nil && input.Include == nil) || (len(*input.Exclude) == 0 && len(*input.Include) == 0) { - return outputs, nil - } - - output := make(map[string]interface{}, 0) - - excludedInstanceIds, err := flattenNetworkPacketCaptureScopeInstanceIds(input.Exclude) - if err != nil { - return nil, err - } - output["exclude_instance_ids"] = excludedInstanceIds - - includedInstanceIds, err := flattenNetworkPacketCaptureScopeInstanceIds(input.Include) - if err != nil { - return nil, err - } - output["include_instance_ids"] = includedInstanceIds - - outputs = append(outputs, output) - - return outputs, nil -} - -func flattenNetworkPacketCaptureScopeInstanceIds(input *[]string) ([]string, error) { - instances := make([]string, 0) - if input == nil { - return instances, nil - } - - for _, instance := range *input { - instance, err := computeParse.VMSSInstanceID(instance) - if err != nil { - return nil, err - } - - instances = append(instances, instance.VirtualMachineName) - } - - return instances, nil -} - -func getNetworkPacketCaptureTargetType(targetResourceId string) network.PacketCaptureTargetType { - var targetType network.PacketCaptureTargetType - - if _, err := computeParse.VirtualMachineID(targetResourceId); err == nil { - targetType = network.PacketCaptureTargetTypeAzureVM - } else if _, err := computeParse.VirtualMachineScaleSetID(targetResourceId); err == nil { - targetType = network.PacketCaptureTargetTypeAzureVMSS - } - - return targetType -} diff --git a/internal/services/network/network_packet_capture_resource_test.go b/internal/services/network/network_packet_capture_resource_test.go index 8d725b01d846..ff3170fdf4b9 100644 --- a/internal/services/network/network_packet_capture_resource_test.go +++ b/internal/services/network/network_packet_capture_resource_test.go @@ -8,6 +8,7 @@ import ( "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/features" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" @@ -15,7 +16,11 @@ import ( type NetworkPacketCaptureResource struct{} +// todo remove for 4.0 func testAccNetworkPacketCapture_localDisk(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} @@ -30,7 +35,11 @@ func testAccNetworkPacketCapture_localDisk(t *testing.T) { }) } +// todo remove for 4.0 func testAccNetworkPacketCapture_requiresImport(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} @@ -48,7 +57,11 @@ func testAccNetworkPacketCapture_requiresImport(t *testing.T) { }) } +// todo remove for 4.0 func testAccNetworkPacketCapture_storageAccount(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} @@ -63,7 +76,11 @@ func testAccNetworkPacketCapture_storageAccount(t *testing.T) { }) } +// todo remove for 4.0 func testAccNetworkPacketCapture_storageAccountAndLocalDisk(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} @@ -78,7 +95,11 @@ func testAccNetworkPacketCapture_storageAccountAndLocalDisk(t *testing.T) { }) } +// todo remove for 4.0 func testAccNetworkPacketCapture_withFilters(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("this test requires 3.0 mode") + } data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") r := NetworkPacketCaptureResource{} @@ -93,21 +114,6 @@ func testAccNetworkPacketCapture_withFilters(t *testing.T) { }) } -func testAccNetworkPacketCapture_machineScope(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_network_packet_capture", "test") - r := NetworkPacketCaptureResource{} - - data.ResourceSequentialTest(t, r, []acceptance.TestStep{ - { - Config: r.machineScope(data), - Check: acceptance.ComposeTestCheckFunc( - check.That(data.ResourceName).ExistsInAzure(r), - ), - }, - data.ImportStep(), - }) -} - func (t NetworkPacketCaptureResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := parse.PacketCaptureID(state.ID) if err != nil { @@ -333,101 +339,3 @@ resource "azurerm_network_packet_capture" "test" { } `, r.base(data), data.RandomString, data.RandomInteger) } - -func (NetworkPacketCaptureResource) machineScope(data acceptance.TestData) string { - return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-watcher-%d" - location = "%s" -} - -resource "azurerm_network_watcher" "test" { - name = "acctestnw-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name -} - -resource "azurerm_virtual_network" "test" { - name = "acctvn-%d" - address_space = ["10.0.0.0/16"] - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name -} - -resource "azurerm_subnet" "test" { - name = "internal" - resource_group_name = azurerm_resource_group.test.name - virtual_network_name = azurerm_virtual_network.test.name - address_prefixes = ["10.0.2.0/24"] -} - -resource "azurerm_linux_virtual_machine_scale_set" "test" { - name = "acctestvmss-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - sku = "Standard_F2" - instances = 4 - admin_username = "adminuser" - admin_password = "P@ssword1234!" - computer_name_prefix = "my-linux-computer-name-prefix" - upgrade_mode = "Automatic" - - disable_password_authentication = false - - source_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - os_disk { - storage_account_type = "Standard_LRS" - caching = "ReadWrite" - } - - network_interface { - name = "example" - primary = true - - ip_configuration { - name = "internal" - primary = true - subnet_id = azurerm_subnet.test.id - } - } -} - -resource "azurerm_virtual_machine_scale_set_extension" "test" { - name = "network-watcher" - virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id - publisher = "Microsoft.Azure.NetworkWatcher" - type = "NetworkWatcherAgentLinux" - type_handler_version = "1.4" - auto_upgrade_minor_version = true - automatic_upgrade_enabled = true -} - -resource "azurerm_network_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id - - storage_location { - file_path = "/var/captures/packet.cap" - } - - machine_scope { - include_instance_ids = ["0", "1"] - exclude_instance_ids = ["2", "3"] - } - - depends_on = [azurerm_virtual_machine_scale_set_extension.test] -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} diff --git a/internal/services/network/network_watcher_resource_test.go b/internal/services/network/network_watcher_resource_test.go index bfa438090c37..5224d628fd23 100644 --- a/internal/services/network/network_watcher_resource_test.go +++ b/internal/services/network/network_watcher_resource_test.go @@ -57,7 +57,21 @@ func TestAccNetworkWatcher(t *testing.T) { "storageAccountAndLocalDisk": testAccNetworkPacketCapture_storageAccountAndLocalDisk, "withFilters": testAccNetworkPacketCapture_withFilters, "requiresImport": testAccNetworkPacketCapture_requiresImport, - "machineScope": testAccNetworkPacketCapture_machineScope, + }, + "VMPacketCapture": { + "localDisk": testAccVirtualMachinePacketCapture_localDisk, + "storageAccount": testAccVirtualMachinePacketCapture_storageAccount, + "storageAccountAndLocalDisk": testAccVirtualMachinePacketCapture_storageAccountAndLocalDisk, + "withFilters": testAccVirtualMachinePacketCapture_withFilters, + "requiresImport": testAccVirtualMachinePacketCapture_requiresImport, + }, + "VMSSPacketCapture": { + "localDisk": testAccVirtualMachineScaleSetPacketCapture_localDisk, + "storageAccount": testAccVirtualMachineScaleSetPacketCapture_storageAccount, + "storageAccountAndLocalDisk": testAccVirtualMachineScaleSetPacketCapture_storageAccountAndLocalDisk, + "withFilters": testAccVirtualMachineScaleSetPacketCapture_withFilters, + "requiresImport": testAccVirtualMachineScaleSetPacketCapture_requiresImport, + "machineScope": testAccVirtualMachineScaleSetPacketCapture_machineScope, }, "FlowLog": { "basic": testAccNetworkWatcherFlowLog_basic, diff --git a/internal/services/network/registration.go b/internal/services/network/registration.go index 87082130a4a8..7b5dfe0ea287 100644 --- a/internal/services/network/registration.go +++ b/internal/services/network/registration.go @@ -107,6 +107,8 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { "azurerm_virtual_hub_ip": resourceVirtualHubIP(), "azurerm_virtual_hub_route_table": resourceVirtualHubRouteTable(), "azurerm_virtual_hub_route_table_route": resourceVirtualHubRouteTableRoute(), + "azurerm_virtual_machine_packet_capture": resourceVirtualMachinePacketCapture(), + "azurerm_virtual_machine_scale_set_packet_capture": resourceVirtualMachineScaleSetPacketCapture(), "azurerm_virtual_network_dns_servers": resourceVirtualNetworkDnsServers(), "azurerm_virtual_network_gateway_connection": resourceVirtualNetworkGatewayConnection(), "azurerm_virtual_network_gateway_nat_rule": resourceVirtualNetworkGatewayNatRule(), diff --git a/internal/services/network/virtual_machine_packet_capture_resource.go b/internal/services/network/virtual_machine_packet_capture_resource.go new file mode 100644 index 000000000000..a8fe962c926f --- /dev/null +++ b/internal/services/network/virtual_machine_packet_capture_resource.go @@ -0,0 +1,381 @@ +package network + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "github.com/tombuildsstuff/kermit/sdk/network/2022-05-01/network" +) + +func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceVirtualMachinePacketCaptureCreate, + Read: resourceVirtualMachinePacketCaptureRead, + Delete: resourceVirtualMachinePacketCaptureDelete, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.PacketCaptureID(id) + return err + }), + + SchemaVersion: 1, + StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{ + 0: migration.NetworkPacketCaptureV0ToV1{}, + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "network_watcher_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "target_resource_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.Any( + computeValidate.VirtualMachineID, + ), + }, + + "maximum_bytes_per_packet": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + }, + + "maximum_bytes_per_session": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 1073741824, + }, + + "maximum_capture_duration": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 18000, + ValidateFunc: validation.IntBetween(1, 18000), + }, + + "storage_location": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "file_path": { + Type: pluginsdk.TypeString, + Optional: true, + AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, + }, + "storage_account_id": { + Type: pluginsdk.TypeString, + Optional: true, + AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, + }, + "storage_path": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "filter": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "local_ip_address": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "local_port": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "protocol": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.PcProtocolAny), + string(network.PcProtocolTCP), + string(network.PcProtocolUDP), + }, false), + }, + "remote_ip_address": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "remote_port": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + }, + } +} + +func resourceVirtualMachinePacketCaptureCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) + + targetResourceId := d.Get("target_resource_id").(string) + bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) + totalBytesPerSession := d.Get("maximum_bytes_per_session").(int) + timeLimitInSeconds := d.Get("maximum_capture_duration").(int) + + existing, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) + } + } + + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_virtual_machine_packet_capture", id.ID()) + } + + storageLocation, err := expandVirtualMachinePacketCaptureStorageLocation(d) + if err != nil { + return err + } + + properties := network.PacketCapture{ + PacketCaptureParameters: &network.PacketCaptureParameters{ + Target: utils.String(targetResourceId), + TargetType: network.PacketCaptureTargetTypeAzureVM, + StorageLocation: storageLocation, + BytesToCapturePerPacket: utils.Int64(int64(bytesToCapturePerPacket)), + TimeLimitInSeconds: utils.Int32(int32(timeLimitInSeconds)), + TotalBytesPerSession: utils.Int64(int64(totalBytesPerSession)), + Filters: expandVirtualMachinePacketCaptureFilters(d), + }, + } + + future, err := client.Create(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name, properties) + if err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for creation of %s: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceVirtualMachinePacketCaptureRead(d, meta) +} + +func resourceVirtualMachinePacketCaptureRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.PacketCaptureID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[WARN] %s not found - removing from state", *id) + d.SetId("") + return nil + } + + return fmt.Errorf("reading %s: %+v", *id, err) + } + + d.Set("name", id.Name) + d.Set("network_watcher_name", id.NetworkWatcherName) + d.Set("resource_group_name", id.ResourceGroup) + + if props := resp.PacketCaptureResultProperties; props != nil { + d.Set("target_resource_id", props.Target) + d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) + d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) + d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) + + location := flattenVirtualMachinePacketCaptureStorageLocation(props.StorageLocation) + if err := d.Set("storage_location", location); err != nil { + return fmt.Errorf("setting `storage_location`: %+v", err) + } + + filters := flattenVirtualMachinePacketCaptureFilters(props.Filters) + if err := d.Set("filter", filters); err != nil { + return fmt.Errorf("setting `filter`: %+v", err) + } + } + + return nil +} + +func resourceVirtualMachinePacketCaptureDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.PacketCaptureID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for the deletion of %s: %+v", *id, err) + } + + return nil +} + +func expandVirtualMachinePacketCaptureStorageLocation(d *pluginsdk.ResourceData) (*network.PacketCaptureStorageLocation, error) { + locations := d.Get("storage_location").([]interface{}) + if len(locations) == 0 { + return nil, fmt.Errorf("expandng `storage_location`: not found") + } + + location := locations[0].(map[string]interface{}) + + storageLocation := network.PacketCaptureStorageLocation{} + + if v := location["file_path"]; v != "" { + storageLocation.FilePath = utils.String(v.(string)) + } + if v := location["storage_account_id"]; v != "" { + storageLocation.StorageID = utils.String(v.(string)) + } + + return &storageLocation, nil +} + +func flattenVirtualMachinePacketCaptureStorageLocation(input *network.PacketCaptureStorageLocation) []interface{} { + if input == nil { + return []interface{}{} + } + + output := make(map[string]interface{}) + + if path := input.FilePath; path != nil { + output["file_path"] = *path + } + + if account := input.StorageID; account != nil { + output["storage_account_id"] = *account + } + + if path := input.StoragePath; path != nil { + output["storage_path"] = *path + } + + return []interface{}{output} +} + +func expandVirtualMachinePacketCaptureFilters(d *pluginsdk.ResourceData) *[]network.PacketCaptureFilter { + inputFilters := d.Get("filter").([]interface{}) + if len(inputFilters) == 0 { + return nil + } + + filters := make([]network.PacketCaptureFilter, 0) + + for _, v := range inputFilters { + inputFilter := v.(map[string]interface{}) + + localIPAddress := inputFilter["local_ip_address"].(string) + localPort := inputFilter["local_port"].(string) // TODO: should this be an int? + protocol := inputFilter["protocol"].(string) + remoteIPAddress := inputFilter["remote_ip_address"].(string) + remotePort := inputFilter["remote_port"].(string) + + filter := network.PacketCaptureFilter{ + LocalIPAddress: utils.String(localIPAddress), + LocalPort: utils.String(localPort), + Protocol: network.PcProtocol(protocol), + RemoteIPAddress: utils.String(remoteIPAddress), + RemotePort: utils.String(remotePort), + } + filters = append(filters, filter) + } + + return &filters +} + +func flattenVirtualMachinePacketCaptureFilters(input *[]network.PacketCaptureFilter) []interface{} { + filters := make([]interface{}, 0) + + if inFilter := input; inFilter != nil { + for _, v := range *inFilter { + filter := make(map[string]interface{}) + + if address := v.LocalIPAddress; address != nil { + filter["local_ip_address"] = *address + } + + if port := v.LocalPort; port != nil { + filter["local_port"] = *port + } + + filter["protocol"] = string(v.Protocol) + + if address := v.RemoteIPAddress; address != nil { + filter["remote_ip_address"] = *address + } + + if port := v.RemotePort; port != nil { + filter["remote_port"] = *port + } + + filters = append(filters, filter) + } + } + + return filters +} diff --git a/internal/services/network/virtual_machine_packet_capture_resource_test.go b/internal/services/network/virtual_machine_packet_capture_resource_test.go new file mode 100644 index 000000000000..3944e819d880 --- /dev/null +++ b/internal/services/network/virtual_machine_packet_capture_resource_test.go @@ -0,0 +1,317 @@ +package network_test + +import ( + "context" + "fmt" + "testing" + + "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/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type VirtualMachinePacketCaptureResource struct{} + +func testAccVirtualMachinePacketCapture_localDisk(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_packet_capture", "test") + r := VirtualMachinePacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachinePacketCapture_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_packet_capture", "test") + r := VirtualMachinePacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.localDiskConfig_requiresImport), + }) +} + +func testAccVirtualMachinePacketCapture_storageAccount(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_packet_capture", "test") + r := VirtualMachinePacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.storageAccountConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachinePacketCapture_storageAccountAndLocalDisk(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_packet_capture", "test") + r := VirtualMachinePacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.storageAccountAndLocalDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachinePacketCapture_withFilters(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_packet_capture", "test") + r := VirtualMachinePacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfigWithFilters(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (t VirtualMachinePacketCaptureResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.PacketCaptureID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Network.PacketCapturesClient.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + return nil, fmt.Errorf("reading Virtual Machine Packet Capture (%s): %+v", id, err) + } + + return utils.Bool(resp.ID != nil), nil +} + +func (VirtualMachinePacketCaptureResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-watcher-%d" + location = "%s" +} + +resource "azurerm_network_watcher" "test" { + name = "acctestnw-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_network_interface" "test" { + name = "acctni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_virtual_machine" "test" { + name = "acctvm-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + network_interface_ids = [azurerm_network_interface.test.id] + vm_size = "Standard_F2" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + delete_os_disk_on_termination = true + + os_profile { + computer_name = "hostname%d" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } +} + +resource "azurerm_virtual_machine_extension" "test" { + name = "network-watcher" + virtual_machine_id = azurerm_virtual_machine.test.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func (r VirtualMachinePacketCaptureResource) localDiskConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_virtual_machine.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + depends_on = [azurerm_virtual_machine_extension.test] +} +`, r.template(data), data.RandomInteger) +} + +func (r VirtualMachinePacketCaptureResource) localDiskConfig_requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_packet_capture" "import" { + name = azurerm_virtual_machine_packet_capture.test.name + network_watcher_name = azurerm_virtual_machine_packet_capture.test.network_watcher_name + resource_group_name = azurerm_virtual_machine_packet_capture.test.resource_group_name + target_resource_id = azurerm_virtual_machine_packet_capture.test.target_resource_id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + depends_on = [azurerm_virtual_machine_extension.test] +} +`, r.localDiskConfig(data)) +} + +func (r VirtualMachinePacketCaptureResource) localDiskConfigWithFilters(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_virtual_machine.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + filter { + local_ip_address = "127.0.0.1" + local_port = "8080;9020;" + protocol = "TCP" + } + + filter { + local_ip_address = "127.0.0.1" + local_port = "80;443;" + protocol = "UDP" + } + + depends_on = [azurerm_virtual_machine_extension.test] +} +`, r.template(data), data.RandomInteger) +} + +func (r VirtualMachinePacketCaptureResource) storageAccountConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_virtual_machine.test.id + + storage_location { + storage_account_id = azurerm_storage_account.test.id + } + + depends_on = [azurerm_virtual_machine_extension.test] +} +`, r.template(data), data.RandomString, data.RandomInteger) +} + +func (r VirtualMachinePacketCaptureResource) storageAccountAndLocalDiskConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_virtual_machine.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + storage_account_id = azurerm_storage_account.test.id + } + + depends_on = [azurerm_virtual_machine_extension.test] +} +`, r.template(data), data.RandomString, data.RandomInteger) +} diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go new file mode 100644 index 000000000000..95e4e63d477e --- /dev/null +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go @@ -0,0 +1,486 @@ +package network + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + computeParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" + computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "github.com/tombuildsstuff/kermit/sdk/network/2022-05-01/network" +) + +func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceVirtualMachineScaleSetPacketCaptureCreate, + Read: resourceVirtualMachineScaleSetPacketCaptureRead, + Delete: resourceVirtualMachineScaleSetPacketCaptureDelete, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.PacketCaptureID(id) + return err + }), + + SchemaVersion: 1, + StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{ + 0: migration.NetworkPacketCaptureV0ToV1{}, + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "network_watcher_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "target_resource_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.Any( + computeValidate.VirtualMachineScaleSetID, + ), + }, + + "maximum_bytes_per_packet": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 0, + }, + + "maximum_bytes_per_session": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 1073741824, + }, + + "maximum_capture_duration": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + Default: 18000, + ValidateFunc: validation.IntBetween(1, 18000), + }, + + "storage_location": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "file_path": { + Type: pluginsdk.TypeString, + Optional: true, + AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, + }, + "storage_account_id": { + Type: pluginsdk.TypeString, + Optional: true, + AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, + }, + "storage_path": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "filter": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "local_ip_address": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "local_port": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "protocol": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.PcProtocolAny), + string(network.PcProtocolTCP), + string(network.PcProtocolUDP), + }, false), + }, + "remote_ip_address": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + "remote_port": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + }, + }, + }, + + "machine_scope": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "exclude_instance_ids": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + + "include_instance_ids": { + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + }, + }, + } +} + +func resourceVirtualMachineScaleSetPacketCaptureCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) + + targetResourceId := d.Get("target_resource_id").(string) + bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) + totalBytesPerSession := d.Get("maximum_bytes_per_session").(int) + timeLimitInSeconds := d.Get("maximum_capture_duration").(int) + + existing, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) + } + } + + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_virtual_machine_scale_set_packet_capture", id.ID()) + } + + storageLocation, err := expandVirtualMachineScaleSetPacketCaptureStorageLocation(d) + if err != nil { + return err + } + + properties := network.PacketCapture{ + PacketCaptureParameters: &network.PacketCaptureParameters{ + Target: utils.String(targetResourceId), + TargetType: network.PacketCaptureTargetTypeAzureVMSS, + StorageLocation: storageLocation, + BytesToCapturePerPacket: utils.Int64(int64(bytesToCapturePerPacket)), + TimeLimitInSeconds: utils.Int32(int32(timeLimitInSeconds)), + TotalBytesPerSession: utils.Int64(int64(totalBytesPerSession)), + Filters: expandVirtualMachineScaleSetPacketCaptureFilters(d), + }, + } + + if v, ok := d.GetOk("machine_scope"); ok { + properties.PacketCaptureParameters.Scope = expandVirtualMachineScaleSetPacketCaptureMachineScope(v.([]interface{})) + } + + future, err := client.Create(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name, properties) + if err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for creation of %s: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceVirtualMachineScaleSetPacketCaptureRead(d, meta) +} + +func resourceVirtualMachineScaleSetPacketCaptureRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.PacketCaptureID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[WARN] %s not found - removing from state", *id) + d.SetId("") + return nil + } + + return fmt.Errorf("reading %s: %+v", *id, err) + } + + d.Set("name", id.Name) + d.Set("network_watcher_name", id.NetworkWatcherName) + d.Set("resource_group_name", id.ResourceGroup) + + if props := resp.PacketCaptureResultProperties; props != nil { + d.Set("target_resource_id", props.Target) + d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) + d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) + d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) + + location := flattenVirtualMachineScaleSetPacketCaptureStorageLocation(props.StorageLocation) + if err := d.Set("storage_location", location); err != nil { + return fmt.Errorf("setting `storage_location`: %+v", err) + } + + filters := flattenVirtualMachineScaleSetPacketCaptureFilters(props.Filters) + if err := d.Set("filter", filters); err != nil { + return fmt.Errorf("setting `filter`: %+v", err) + } + + scope, err := flattenVirtualMachineScaleSetPacketCaptureMachineScope(props.Scope) + if err != nil { + return err + } + if err := d.Set("machine_scope", scope); err != nil { + return fmt.Errorf(`setting "machine_scope": %+v`, err) + } + } + + return nil +} + +func resourceVirtualMachineScaleSetPacketCaptureDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.PacketCapturesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.PacketCaptureID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for the deletion of %s: %+v", *id, err) + } + + return nil +} + +func expandVirtualMachineScaleSetPacketCaptureStorageLocation(d *pluginsdk.ResourceData) (*network.PacketCaptureStorageLocation, error) { + locations := d.Get("storage_location").([]interface{}) + if len(locations) == 0 { + return nil, fmt.Errorf("expandng `storage_location`: not found") + } + + location := locations[0].(map[string]interface{}) + + storageLocation := network.PacketCaptureStorageLocation{} + + if v := location["file_path"]; v != "" { + storageLocation.FilePath = utils.String(v.(string)) + } + if v := location["storage_account_id"]; v != "" { + storageLocation.StorageID = utils.String(v.(string)) + } + + return &storageLocation, nil +} + +func flattenVirtualMachineScaleSetPacketCaptureStorageLocation(input *network.PacketCaptureStorageLocation) []interface{} { + if input == nil { + return []interface{}{} + } + + output := make(map[string]interface{}) + + if path := input.FilePath; path != nil { + output["file_path"] = *path + } + + if account := input.StorageID; account != nil { + output["storage_account_id"] = *account + } + + if path := input.StoragePath; path != nil { + output["storage_path"] = *path + } + + return []interface{}{output} +} + +func expandVirtualMachineScaleSetPacketCaptureFilters(d *pluginsdk.ResourceData) *[]network.PacketCaptureFilter { + inputFilters := d.Get("filter").([]interface{}) + if len(inputFilters) == 0 { + return nil + } + + filters := make([]network.PacketCaptureFilter, 0) + + for _, v := range inputFilters { + inputFilter := v.(map[string]interface{}) + + localIPAddress := inputFilter["local_ip_address"].(string) + localPort := inputFilter["local_port"].(string) // TODO: should this be an int? + protocol := inputFilter["protocol"].(string) + remoteIPAddress := inputFilter["remote_ip_address"].(string) + remotePort := inputFilter["remote_port"].(string) + + filter := network.PacketCaptureFilter{ + LocalIPAddress: utils.String(localIPAddress), + LocalPort: utils.String(localPort), + Protocol: network.PcProtocol(protocol), + RemoteIPAddress: utils.String(remoteIPAddress), + RemotePort: utils.String(remotePort), + } + filters = append(filters, filter) + } + + return &filters +} + +func flattenVirtualMachineScaleSetPacketCaptureFilters(input *[]network.PacketCaptureFilter) []interface{} { + filters := make([]interface{}, 0) + + if inFilter := input; inFilter != nil { + for _, v := range *inFilter { + filter := make(map[string]interface{}) + + if address := v.LocalIPAddress; address != nil { + filter["local_ip_address"] = *address + } + + if port := v.LocalPort; port != nil { + filter["local_port"] = *port + } + + filter["protocol"] = string(v.Protocol) + + if address := v.RemoteIPAddress; address != nil { + filter["remote_ip_address"] = *address + } + + if port := v.RemotePort; port != nil { + filter["remote_port"] = *port + } + + filters = append(filters, filter) + } + } + + return filters +} + +func expandVirtualMachineScaleSetPacketCaptureMachineScope(input []interface{}) *network.PacketCaptureMachineScope { + if len(input) == 0 || input[0] == nil { + return nil + } + + raw := input[0].(map[string]interface{}) + output := &network.PacketCaptureMachineScope{} + + if exclude := raw["exclude_instance_ids"].([]interface{}); len(exclude) > 0 { + output.Exclude = utils.ExpandStringSlice(exclude) + } + + if include := raw["include_instance_ids"].([]interface{}); len(include) > 0 { + output.Include = utils.ExpandStringSlice(include) + } + + return output +} + +func flattenVirtualMachineScaleSetPacketCaptureMachineScope(input *network.PacketCaptureMachineScope) ([]interface{}, error) { + outputs := make([]interface{}, 0) + if input == nil || (input.Exclude == nil && input.Include == nil) || (len(*input.Exclude) == 0 && len(*input.Include) == 0) { + return outputs, nil + } + + output := make(map[string]interface{}, 0) + + excludedInstanceIds, err := flattenVirtualMachineScaleSetPacketCaptureScopeInstanceIds(input.Exclude) + if err != nil { + return nil, err + } + output["exclude_instance_ids"] = excludedInstanceIds + + includedInstanceIds, err := flattenVirtualMachineScaleSetPacketCaptureScopeInstanceIds(input.Include) + if err != nil { + return nil, err + } + output["include_instance_ids"] = includedInstanceIds + + outputs = append(outputs, output) + + return outputs, nil +} + +func flattenVirtualMachineScaleSetPacketCaptureScopeInstanceIds(input *[]string) ([]string, error) { + instances := make([]string, 0) + if input == nil { + return instances, nil + } + + for _, instance := range *input { + instance, err := computeParse.VMSSInstanceID(instance) + if err != nil { + return nil, err + } + + instances = append(instances, instance.VirtualMachineName) + } + + return instances, nil +} diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go new file mode 100644 index 000000000000..9f47fd035500 --- /dev/null +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go @@ -0,0 +1,348 @@ +package network_test + +import ( + "context" + "fmt" + "testing" + + "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/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type VirtualMachineScaleSetPacketCaptureResource struct{} + +func testAccVirtualMachineScaleSetPacketCapture_localDisk(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachineScaleSetPacketCapture_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.localDiskConfig_requiresImport), + }) +} + +func testAccVirtualMachineScaleSetPacketCapture_storageAccount(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.storageAccountConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachineScaleSetPacketCapture_storageAccountAndLocalDisk(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.storageAccountAndLocalDiskConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachineScaleSetPacketCapture_withFilters(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.localDiskConfigWithFilters(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func testAccVirtualMachineScaleSetPacketCapture_machineScope(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_virtual_machine_scale_set_packet_capture", "test") + r := VirtualMachineScaleSetPacketCaptureResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.machineScope(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (t VirtualMachineScaleSetPacketCaptureResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.PacketCaptureID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Network.PacketCapturesClient.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) + if err != nil { + return nil, fmt.Errorf("reading Virtual Machine Scale Set Packet Capture (%s): %+v", id, err) + } + + return utils.Bool(resp.ID != nil), nil +} + +func (VirtualMachineScaleSetPacketCaptureResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-watcher-%d" + location = "%s" +} + +resource "azurerm_network_watcher" "test" { + name = "acctestnw-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_linux_virtual_machine_scale_set" "test" { + name = "acctestvmss-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 4 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + computer_name_prefix = "my-linux-computer-name-prefix" + upgrade_mode = "Automatic" + + disable_password_authentication = false + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + } + } +} + +resource "azurerm_virtual_machine_scale_set_extension" "test" { + name = "network-watcher" + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true + automatic_upgrade_enabled = true +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.template(data), data.RandomInteger) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig_requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_scale_set_packet_capture" "import" { + name = azurerm_virtual_machine_scale_set_packet_capture.test.name + network_watcher_name = azurerm_virtual_machine_scale_set_packet_capture.test.network_watcher_name + resource_group_name = azurerm_virtual_machine_scale_set_packet_capture.test.resource_group_name + target_resource_id = azurerm_virtual_machine_scale_set_packet_capture.test.target_resource_id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.localDiskConfig(data)) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfigWithFilters(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + filter { + local_ip_address = "127.0.0.1" + local_port = "8080;9020;" + protocol = "TCP" + } + + filter { + local_ip_address = "127.0.0.1" + local_port = "80;443;" + protocol = "UDP" + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.template(data), data.RandomInteger) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) storageAccountConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + storage_account_id = azurerm_storage_account.test.id + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.template(data), data.RandomString, data.RandomInteger) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) storageAccountAndLocalDiskConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + storage_account_id = azurerm_storage_account.test.id + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.template(data), data.RandomString, data.RandomInteger) +} + +func (r VirtualMachineScaleSetPacketCaptureResource) machineScope(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + machine_scope { + include_instance_ids = ["0", "1"] + exclude_instance_ids = ["2", "3"] + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.test] +} +`, r.template(data), data.RandomInteger) +} diff --git a/website/docs/r/network_packet_capture.html.markdown b/website/docs/r/network_packet_capture.html.markdown index 1a73cfb1d47b..58f2199c4b9d 100644 --- a/website/docs/r/network_packet_capture.html.markdown +++ b/website/docs/r/network_packet_capture.html.markdown @@ -7,10 +7,12 @@ description: |- --- -# azurerm_packet_capture +# azurerm_network_packet_capture Configures Network Packet Capturing against a Virtual Machine using a Network Watcher. +!> **NOTE:** The `azurerm_network_packet_capture` resource is deprecated and will be removed in favour of `azurerm_virtual_machine_packet_capture` and `azurerm_virtual_machine_scale_set_packet_capture` in version 4.0 of the AzureRM Provider. + ## Example Usage ```hcl @@ -114,7 +116,7 @@ resource "azurerm_network_packet_capture" "example" { } ``` -~> **NOTE:** This Resource requires that [the Network Watcher Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine or Virtual Machine Scale Set before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_extension` resource](virtual_machine_extension.html) or [the `azurerm_virtual_machine_scale_set_extension` resource](virtual_machine_scale_set_extension.html). +~> **NOTE:** This Resource requires that [the Network Watcher Virtual Machine Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_extension` resource](virtual_machine_extension.html). ## Argument Reference @@ -128,7 +130,7 @@ The following arguments are supported: * `target_resource_id` - (Required) The ID of the Resource to capture packets from. Changing this forces a new resource to be created. -~> **NOTE:** Currently only Virtual Machines IDs and Virtual Machine Scale Set IDs are supported. +~> **NOTE:** Currently only Virtual Machines IDs are supported. * `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. @@ -140,8 +142,6 @@ The following arguments are supported: * `filter` - (Optional) One or more `filter` blocks as defined below. Changing this forces a new resource to be created. -* `machine_scope` - (Optional) A `machine_scope` block as defined below. Changing this forces a new resource to be created. - --- A `storage_location` block contains: @@ -164,14 +164,6 @@ A `filter` block contains: * `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. ---- - -A `machine_scope` block contains: - -* `exclude_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be excluded from running Packet Capture, e.g. `["0", "2"]`. Changing this forces a new resource to be created. - -* `include_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be included for Packet Capture, e.g. `["1", "3"]`. Changing this forces a new resource to be created. - ## Attributes Reference The following attributes are exported: diff --git a/website/docs/r/virtual_machine_packet_capture.html.markdown b/website/docs/r/virtual_machine_packet_capture.html.markdown new file mode 100644 index 000000000000..dacfd9a61c25 --- /dev/null +++ b/website/docs/r/virtual_machine_packet_capture.html.markdown @@ -0,0 +1,191 @@ +--- +subcategory: "Network" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_virtual_machine_packet_capture" +description: |- + Configures Packet Capturing against a Virtual Machine using a Network Watcher. + +--- + +# azurerm_virtual_machine_packet_capture + +Configures Network Packet Capturing against a Virtual Machine using a Network Watcher. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_network_watcher" "example" { + name = "example-nw" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_virtual_network" "example" { + name = "example-network" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_subnet" "example" { + name = "internal" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_network_interface" "example" { + name = "example-nic" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.example.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_virtual_machine" "example" { + name = "example-vm" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + network_interface_ids = [azurerm_network_interface.example.id] + vm_size = "Standard_F2" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "osdisk" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } + + os_profile { + computer_name = "pctest-vm" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } +} + +resource "azurerm_virtual_machine_extension" "example" { + name = "network-watcher" + virtual_machine_id = azurerm_virtual_machine.example.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true +} + +resource "azurerm_storage_account" "example" { + name = "examplesa" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_virtual_machine_packet_capture" "example" { + name = "example-pc" + network_watcher_name = azurerm_network_watcher.example.name + resource_group_name = azurerm_resource_group.example.name + target_resource_id = azurerm_virtual_machine.example.id + + storage_location { + storage_account_id = azurerm_storage_account.example.id + } + + depends_on = [azurerm_virtual_machine_extension.example] +} +``` + +~> **NOTE:** This Resource requires that [the Network Watcher Virtual Machine Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_extension` resource](virtual_machine_extension.html). + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name to use for this Network Packet Capture. Changing this forces a new resource to be created. + +* `network_watcher_name` - (Required) The name of the Network Watcher. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. + +* `target_resource_id` - (Required) The resource ID of the Virtual Machine to capture packets from. Changing this forces a new resource to be created. + +* `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. + +* `maximum_bytes_per_session` - (Optional) Maximum size of the capture in Bytes. Defaults to `1073741824` (1GB). Changing this forces a new resource to be created. + +* `maximum_capture_duration` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. + +* `storage_location` - (Required) A `storage_location` block as defined below. Changing this forces a new resource to be created. + +* `filter` - (Optional) One or more `filter` blocks as defined below. Changing this forces a new resource to be created. + +--- + +A `storage_location` block contains: + +* `file_path` - (Optional) A valid local path on the targeting VM. Must include the name of the capture file (*.cap). For Linux virtual machine it must start with `/var/captures`. + +* `storage_account_id` - (Optional) The ID of the storage account to save the packet capture session + +~> **NOTE:** At least one of `file_path` or `storage_account_id` must be specified. + +A `filter` block contains: + +* `local_ip_address` - (Optional) The local IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +* `local_port` - (Optional) The local port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +* `protocol` - (Required) The Protocol to be filtered on. Possible values include `Any`, `TCP` and `UDP`. Changing this forces a new resource to be created. + +* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported.. Changing this forces a new resource to be created. + +* `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Virtual Machine Packet Capture ID. + +* `storage_location` - (Required) A `storage_location` block as defined below. + +--- + +A `storage_location` block contains: + +* `storage_path` - The URI of the storage path to save the packet capture. + +## 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 Virtual Machine Packet Capture. +* `read` - (Defaults to 5 minutes) Used when retrieving the Virtual Machine Packet Capture. +* `delete` - (Defaults to 30 minutes) Used when deleting the Virtual Machine Packet Capture. + +## Import + +Virtual Machine Packet Captures can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_virtual_machine_packet_capture.capture1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/networkWatchers/watcher1/packetCaptures/capture1 +``` diff --git a/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown new file mode 100644 index 000000000000..4e39634845a5 --- /dev/null +++ b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown @@ -0,0 +1,192 @@ +--- +subcategory: "Network" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_virtual_machine_scale_set_packet_capture" +description: |- + Configures Packet Capturing against a Virtual Machine Scale Set using a Network Watcher. + +--- + +# azurerm_virtual_machine_scale_set_packet_capture + +Configures Network Packet Capturing against a Virtual Machine Scale Set using a Network Watcher. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_network_watcher" "example" { + name = "example-nw" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_virtual_network" "example" { + name = "example-vn" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_subnet" "example" { + name = "internal" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_linux_virtual_machine_scale_set" "example" { + name = "example-vmss" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku = "Standard_F2" + instances = 4 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + computer_name_prefix = "my-linux-computer-name-prefix" + upgrade_mode = "Automatic" + + disable_password_authentication = false + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.example.id + } + } +} + +resource "azurerm_virtual_machine_scale_set_extension" "example" { + name = "network-watcher" + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.example.id + publisher = "Microsoft.Azure.NetworkWatcher" + type = "NetworkWatcherAgentLinux" + type_handler_version = "1.4" + auto_upgrade_minor_version = true + automatic_upgrade_enabled = true +} + +resource "azurerm_virtual_machine_scale_set_packet_capture" "example" { + name = "example-pc" + network_watcher_name = azurerm_network_watcher.example.name + resource_group_name = azurerm_resource_group.example.name + target_resource_id = azurerm_linux_virtual_machine_scale_set.example.id + + storage_location { + file_path = "/var/captures/packet.cap" + } + + machine_scope { + include_instance_ids = ["0"] + exclude_instance_ids = ["1"] + } + + depends_on = [azurerm_virtual_machine_scale_set_extension.example] +} +``` + +~> **NOTE:** This Resource requires that [the Network Watcher Extension](https://docs.microsoft.com/azure/network-watcher/network-watcher-packet-capture-manage-portal#before-you-begin) is installed on the Virtual Machine Scale Set before capturing can be enabled which can be installed via [the `azurerm_virtual_machine_scale_set_extension` resource](virtual_machine_scale_set_extension.html). + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name to use for this Network Packet Capture. Changing this forces a new resource to be created. + +* `network_watcher_name` - (Required) The name of the Network Watcher. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. + +* `target_resource_id` - (Required) The resource ID of the Virtual Machine Scale Set to capture packets from. Changing this forces a new resource to be created. + +* `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. + +* `maximum_bytes_per_session` - (Optional) Maximum size of the capture in Bytes. Defaults to `1073741824` (1GB). Changing this forces a new resource to be created. + +* `maximum_capture_duration` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. + +* `storage_location` - (Required) A `storage_location` block as defined below. Changing this forces a new resource to be created. + +* `filter` - (Optional) One or more `filter` blocks as defined below. Changing this forces a new resource to be created. + +* `machine_scope` - (Optional) A `machine_scope` block as defined below. Changing this forces a new resource to be created. + +--- + +A `storage_location` block contains: + +* `file_path` - (Optional) A valid local path on the targeting VM. Must include the name of the capture file (*.cap). For Linux virtual machine it must start with `/var/captures`. + +* `storage_account_id` - (Optional) The ID of the storage account to save the packet capture session + +~> **NOTE:** At least one of `file_path` or `storage_account_id` must be specified. + +A `filter` block contains: + +* `local_ip_address` - (Optional) The local IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +* `local_port` - (Optional) The local port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +* `protocol` - (Required) The Protocol to be filtered on. Possible values include `Any`, `TCP` and `UDP`. Changing this forces a new resource to be created. + +* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported.. Changing this forces a new resource to be created. + +* `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. + +--- + +A `machine_scope` block contains: + +* `exclude_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be excluded from running Packet Capture, e.g. `["0", "2"]`. Changing this forces a new resource to be created. + +* `include_instance_ids` - (Optional) A list of Virtual Machine Scale Set instance IDs which should be included for Packet Capture, e.g. `["1", "3"]`. Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Virtual Machine Scale Set Packet Capture ID. + +* `storage_location` - (Required) A `storage_location` block as defined below. + +--- + +A `storage_location` block contains: + +* `storage_path` - The URI of the storage path to save the packet capture. + +## 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 Virtual Machine Scale Set Packet Capture. +* `read` - (Defaults to 5 minutes) Used when retrieving the Virtual Machine Scale Set Packet Capture. +* `delete` - (Defaults to 30 minutes) Used when deleting the Virtual Machine Scale Set Packet Capture. + +## Import + +Virtual Machine Scale Set Packet Captures can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_virtual_machine_scale_set_packet_capture.capture1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/networkWatchers/watcher1/packetCaptures/capture1 +``` From cbd9996438acc5d0bbdf13dae5f8cb41617f082d Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 8 Dec 2022 14:46:16 +0800 Subject: [PATCH 10/12] update code --- .../network/virtual_machine_packet_capture_resource.go | 6 ------ .../virtual_machine_scale_set_packet_capture_resource.go | 6 ------ 2 files changed, 12 deletions(-) diff --git a/internal/services/network/virtual_machine_packet_capture_resource.go b/internal/services/network/virtual_machine_packet_capture_resource.go index a8fe962c926f..0e69dd9a5cad 100644 --- a/internal/services/network/virtual_machine_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_packet_capture_resource.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" @@ -29,11 +28,6 @@ func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { return err }), - SchemaVersion: 1, - StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{ - 0: migration.NetworkPacketCaptureV0ToV1{}, - }), - Timeouts: &pluginsdk.ResourceTimeout{ Create: pluginsdk.DefaultTimeout(30 * time.Minute), Read: pluginsdk.DefaultTimeout(5 * time.Minute), diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go index 95e4e63d477e..fab330622843 100644 --- a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/clients" computeParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/migration" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" @@ -30,11 +29,6 @@ func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { return err }), - SchemaVersion: 1, - StateUpgraders: pluginsdk.StateUpgrades(map[int]pluginsdk.StateUpgrade{ - 0: migration.NetworkPacketCaptureV0ToV1{}, - }), - Timeouts: &pluginsdk.ResourceTimeout{ Create: pluginsdk.DefaultTimeout(30 * time.Minute), Read: pluginsdk.DefaultTimeout(5 * time.Minute), From ae6d93ff6bc2b2343278195a8d9fc4481d780d7a Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 9 Dec 2022 10:46:01 +0800 Subject: [PATCH 11/12] update code --- .../network_packet_capture_resource.go | 2 +- ...virtual_machine_packet_capture_resource.go | 12 ++--- ...al_machine_packet_capture_resource_test.go | 12 ++--- ...chine_scale_set_packet_capture_resource.go | 12 ++--- ..._scale_set_packet_capture_resource_test.go | 50 +++++++++---------- ...rtual_machine_packet_capture.html.markdown | 20 ++++---- ...ine_scale_set_packet_capture.html.markdown | 22 ++++---- 7 files changed, 65 insertions(+), 65 deletions(-) diff --git a/internal/services/network/network_packet_capture_resource.go b/internal/services/network/network_packet_capture_resource.go index b6007ecb1a24..cf9042ec0440 100644 --- a/internal/services/network/network_packet_capture_resource.go +++ b/internal/services/network/network_packet_capture_resource.go @@ -22,7 +22,7 @@ func resourceNetworkPacketCapture() *pluginsdk.Resource { Create: resourceNetworkPacketCaptureCreate, Read: resourceNetworkPacketCaptureRead, Delete: resourceNetworkPacketCaptureDelete, - DeprecationMessage: "The \"azurerm_network_packet_capture\" resource is deprecated and will be removed in favour of `azurerm_virtual_machine_packet_capture` and `azurerm_virtual_machine_scale_set_packet_capture` in version 4.0 of the AzureRM Provider.", + DeprecationMessage: "The \"azurerm_network_packet_capture\" resource is deprecated and will be removed in favour of the `azurerm_virtual_machine_packet_capture` and `azurerm_virtual_machine_scale_set_packet_capture` resources in version 4.0 of the AzureRM Provider.", Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { _, err := parse.PacketCaptureID(id) diff --git a/internal/services/network/virtual_machine_packet_capture_resource.go b/internal/services/network/virtual_machine_packet_capture_resource.go index 0e69dd9a5cad..24e43c8c05d1 100644 --- a/internal/services/network/virtual_machine_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_packet_capture_resource.go @@ -49,7 +49,7 @@ func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { ForceNew: true, }, - "target_resource_id": { + "virtual_machine_id": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -72,7 +72,7 @@ func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { Default: 1073741824, }, - "maximum_capture_duration": { + "maximum_capture_duration_in_seconds": { Type: pluginsdk.TypeInt, Optional: true, ForceNew: true, @@ -156,10 +156,10 @@ func resourceVirtualMachinePacketCaptureCreate(d *pluginsdk.ResourceData, meta i id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) - targetResourceId := d.Get("target_resource_id").(string) + targetResourceId := d.Get("virtual_machine_id").(string) bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) totalBytesPerSession := d.Get("maximum_bytes_per_session").(int) - timeLimitInSeconds := d.Get("maximum_capture_duration").(int) + timeLimitInSeconds := d.Get("maximum_capture_duration_in_seconds").(int) existing, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) if err != nil { @@ -229,10 +229,10 @@ func resourceVirtualMachinePacketCaptureRead(d *pluginsdk.ResourceData, meta int d.Set("resource_group_name", id.ResourceGroup) if props := resp.PacketCaptureResultProperties; props != nil { - d.Set("target_resource_id", props.Target) + d.Set("virtual_machine_id", props.Target) d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) - d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) + d.Set("maximum_capture_duration_in_seconds", int(*props.TimeLimitInSeconds)) location := flattenVirtualMachinePacketCaptureStorageLocation(props.StorageLocation) if err := d.Set("storage_location", location); err != nil { diff --git a/internal/services/network/virtual_machine_packet_capture_resource_test.go b/internal/services/network/virtual_machine_packet_capture_resource_test.go index 3944e819d880..6ddedc84f7e4 100644 --- a/internal/services/network/virtual_machine_packet_capture_resource_test.go +++ b/internal/services/network/virtual_machine_packet_capture_resource_test.go @@ -98,7 +98,7 @@ func (t VirtualMachinePacketCaptureResource) Exists(ctx context.Context, clients resp, err := clients.Network.PacketCapturesClient.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) if err != nil { - return nil, fmt.Errorf("reading Virtual Machine Packet Capture (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id, err) } return utils.Bool(resp.ID != nil), nil @@ -200,7 +200,7 @@ resource "azurerm_virtual_machine_packet_capture" "test" { name = "acctestpc-%d" network_watcher_name = azurerm_network_watcher.test.name resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_virtual_machine.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -219,7 +219,7 @@ resource "azurerm_virtual_machine_packet_capture" "import" { name = azurerm_virtual_machine_packet_capture.test.name network_watcher_name = azurerm_virtual_machine_packet_capture.test.network_watcher_name resource_group_name = azurerm_virtual_machine_packet_capture.test.resource_group_name - target_resource_id = azurerm_virtual_machine_packet_capture.test.target_resource_id + virtual_machine_id = azurerm_virtual_machine_packet_capture.test.virtual_machine_id storage_location { file_path = "/var/captures/packet.cap" @@ -238,7 +238,7 @@ resource "azurerm_virtual_machine_packet_capture" "test" { name = "acctestpc-%d" network_watcher_name = azurerm_network_watcher.test.name resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_virtual_machine.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -277,7 +277,7 @@ resource "azurerm_virtual_machine_packet_capture" "test" { name = "acctestpc-%d" network_watcher_name = azurerm_network_watcher.test.name resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_virtual_machine.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { storage_account_id = azurerm_storage_account.test.id @@ -304,7 +304,7 @@ resource "azurerm_virtual_machine_packet_capture" "test" { name = "acctestpc-%d" network_watcher_name = azurerm_network_watcher.test.name resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_virtual_machine.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go index fab330622843..97b896ffb0c2 100644 --- a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go @@ -50,7 +50,7 @@ func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { ForceNew: true, }, - "target_resource_id": { + "virtual_machine_scale_set_id": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, @@ -73,7 +73,7 @@ func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { Default: 1073741824, }, - "maximum_capture_duration": { + "maximum_capture_duration_in_seconds": { Type: pluginsdk.TypeInt, Optional: true, ForceNew: true, @@ -187,10 +187,10 @@ func resourceVirtualMachineScaleSetPacketCaptureCreate(d *pluginsdk.ResourceData id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) - targetResourceId := d.Get("target_resource_id").(string) + targetResourceId := d.Get("virtual_machine_scale_set_id").(string) bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) totalBytesPerSession := d.Get("maximum_bytes_per_session").(int) - timeLimitInSeconds := d.Get("maximum_capture_duration").(int) + timeLimitInSeconds := d.Get("maximum_capture_duration_in_seconds").(int) existing, err := client.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) if err != nil { @@ -264,10 +264,10 @@ func resourceVirtualMachineScaleSetPacketCaptureRead(d *pluginsdk.ResourceData, d.Set("resource_group_name", id.ResourceGroup) if props := resp.PacketCaptureResultProperties; props != nil { - d.Set("target_resource_id", props.Target) + d.Set("virtual_machine_scale_set_id", props.Target) d.Set("maximum_bytes_per_packet", int(*props.BytesToCapturePerPacket)) d.Set("maximum_bytes_per_session", int(*props.TotalBytesPerSession)) - d.Set("maximum_capture_duration", int(*props.TimeLimitInSeconds)) + d.Set("maximum_capture_duration_in_seconds", int(*props.TimeLimitInSeconds)) location := flattenVirtualMachineScaleSetPacketCaptureStorageLocation(props.StorageLocation) if err := d.Set("storage_location", location); err != nil { diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go index 9f47fd035500..1140b5cdacfd 100644 --- a/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go @@ -113,7 +113,7 @@ func (t VirtualMachineScaleSetPacketCaptureResource) Exists(ctx context.Context, resp, err := clients.Network.PacketCapturesClient.Get(ctx, id.ResourceGroup, id.NetworkWatcherName, id.Name) if err != nil { - return nil, fmt.Errorf("reading Virtual Machine Scale Set Packet Capture (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id, err) } return utils.Bool(resp.ID != nil), nil @@ -204,10 +204,10 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig(data accept %s resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -223,10 +223,10 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig_requiresImp %s resource "azurerm_virtual_machine_scale_set_packet_capture" "import" { - name = azurerm_virtual_machine_scale_set_packet_capture.test.name - network_watcher_name = azurerm_virtual_machine_scale_set_packet_capture.test.network_watcher_name - resource_group_name = azurerm_virtual_machine_scale_set_packet_capture.test.resource_group_name - target_resource_id = azurerm_virtual_machine_scale_set_packet_capture.test.target_resource_id + name = azurerm_virtual_machine_scale_set_packet_capture.test.name + network_watcher_name = azurerm_virtual_machine_scale_set_packet_capture.test.network_watcher_name + resource_group_name = azurerm_virtual_machine_scale_set_packet_capture.test.resource_group_name + virtual_machine_scale_set_id = azurerm_virtual_machine_scale_set_packet_capture.test.virtual_machine_scale_set_id storage_location { file_path = "/var/captures/packet.cap" @@ -242,10 +242,10 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfigWithFilters( %s resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -281,10 +281,10 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { storage_account_id = azurerm_storage_account.test.id @@ -308,10 +308,10 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -328,10 +328,10 @@ func (r VirtualMachineScaleSetPacketCaptureResource) machineScope(data acceptanc %s resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.test.id + name = "acctestpc-%d" + network_watcher_name = azurerm_network_watcher.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { file_path = "/var/captures/packet.cap" diff --git a/website/docs/r/virtual_machine_packet_capture.html.markdown b/website/docs/r/virtual_machine_packet_capture.html.markdown index dacfd9a61c25..0905a4328651 100644 --- a/website/docs/r/virtual_machine_packet_capture.html.markdown +++ b/website/docs/r/virtual_machine_packet_capture.html.markdown @@ -104,7 +104,7 @@ resource "azurerm_virtual_machine_packet_capture" "example" { name = "example-pc" network_watcher_name = azurerm_network_watcher.example.name resource_group_name = azurerm_resource_group.example.name - target_resource_id = azurerm_virtual_machine.example.id + virtual_machine_id = azurerm_virtual_machine.example.id storage_location { storage_account_id = azurerm_storage_account.example.id @@ -126,13 +126,13 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. -* `target_resource_id` - (Required) The resource ID of the Virtual Machine to capture packets from. Changing this forces a new resource to be created. +* `virtual_machine_id` - (Required) The resource ID of the target Virtual Machine to capture packets from. Changing this forces a new resource to be created. * `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. * `maximum_bytes_per_session` - (Optional) Maximum size of the capture in Bytes. Defaults to `1073741824` (1GB). Changing this forces a new resource to be created. -* `maximum_capture_duration` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. +* `maximum_capture_duration_in_seconds` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. * `storage_location` - (Required) A `storage_location` block as defined below. Changing this forces a new resource to be created. @@ -142,23 +142,23 @@ The following arguments are supported: A `storage_location` block contains: -* `file_path` - (Optional) A valid local path on the targeting VM. Must include the name of the capture file (*.cap). For Linux virtual machine it must start with `/var/captures`. +* `file_path` - (Optional) A valid local path on the target Virtual Machine. Must include the name of the capture file (*.cap). For Linux Virtual Machines it must start with `/var/captures`. -* `storage_account_id` - (Optional) The ID of the storage account to save the packet capture session +* `storage_account_id` - (Optional) The ID of the storage account where the packet capture sessions should be saved to. ~> **NOTE:** At least one of `file_path` or `storage_account_id` must be specified. A `filter` block contains: -* `local_ip_address` - (Optional) The local IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `local_ip_address` - (Optional) The local IP Address to be filtered on. Specify `127.0.0.1` for a single address entry, `127.0.0.1-127.0.0.255` for a range and `127.0.0.1;127.0.0.5` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. -* `local_port` - (Optional) The local port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `local_port` - (Optional) The local port to be filtered on. Specify `80` for single port entry, `80-85` for a range and `80;443;` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. * `protocol` - (Required) The Protocol to be filtered on. Possible values include `Any`, `TCP` and `UDP`. Changing this forces a new resource to be created. -* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported.. Changing this forces a new resource to be created. +* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Specify `127.0.0.1` for a single address entry, `127.0.0.1-127.0.0.255` for a range and `127.0.0.1;127.0.0.5` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. -* `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `remote_port` - (Optional) The remote port to be filtered on. Specify `80` for single port entry, `80-85` for a range and `80;443;` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. ## Attributes Reference @@ -172,7 +172,7 @@ The following attributes are exported: A `storage_location` block contains: -* `storage_path` - The URI of the storage path to save the packet capture. +* `storage_path` - The URI of the storage path where the packet capture sessions are saved to. ## Timeouts diff --git a/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown index 4e39634845a5..9fc2e6e28f5e 100644 --- a/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown +++ b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown @@ -87,10 +87,10 @@ resource "azurerm_virtual_machine_scale_set_extension" "example" { } resource "azurerm_virtual_machine_scale_set_packet_capture" "example" { - name = "example-pc" - network_watcher_name = azurerm_network_watcher.example.name - resource_group_name = azurerm_resource_group.example.name - target_resource_id = azurerm_linux_virtual_machine_scale_set.example.id + name = "example-pc" + network_watcher_name = azurerm_network_watcher.example.name + resource_group_name = azurerm_resource_group.example.name + virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.example.id storage_location { file_path = "/var/captures/packet.cap" @@ -117,13 +117,13 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. -* `target_resource_id` - (Required) The resource ID of the Virtual Machine Scale Set to capture packets from. Changing this forces a new resource to be created. +* `virtual_machine_scale_set_id` - (Required) The resource ID of the Virtual Machine Scale Set to capture packets from. Changing this forces a new resource to be created. * `maximum_bytes_per_packet` - (Optional) The number of bytes captured per packet. The remaining bytes are truncated. Defaults to `0` (Entire Packet Captured). Changing this forces a new resource to be created. * `maximum_bytes_per_session` - (Optional) Maximum size of the capture in Bytes. Defaults to `1073741824` (1GB). Changing this forces a new resource to be created. -* `maximum_capture_duration` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. +* `maximum_capture_duration_in_seconds` - (Optional) The maximum duration of the capture session in seconds. Defaults to `18000` (5 hours). Changing this forces a new resource to be created. * `storage_location` - (Required) A `storage_location` block as defined below. Changing this forces a new resource to be created. @@ -143,15 +143,15 @@ A `storage_location` block contains: A `filter` block contains: -* `local_ip_address` - (Optional) The local IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `local_ip_address` - (Optional) The local IP Address to be filtered on. Specify `127.0.0.1` for a single address entry, `127.0.0.1-127.0.0.255` for a range and `127.0.0.1;127.0.0.5` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. -* `local_port` - (Optional) The local port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `local_port` - (Optional) The local port to be filtered on. Specify `80` for single port entry, `80-85` for a range and `80;443;` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. * `protocol` - (Required) The Protocol to be filtered on. Possible values include `Any`, `TCP` and `UDP`. Changing this forces a new resource to be created. -* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Notation: "127.0.0.1" for single address entry. "127.0.0.1-127.0.0.255" for range. "127.0.0.1;127.0.0.5;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported.. Changing this forces a new resource to be created. +* `remote_ip_address` - (Optional) The remote IP Address to be filtered on. Specify `127.0.0.1` for a single address entry, `127.0.0.1-127.0.0.255` for a range and `127.0.0.1;127.0.0.5` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. -* `remote_port` - (Optional) The remote port to be filtered on. Notation: "80" for single port entry."80-85" for range. "80;443;" for multiple entries. Multiple ranges not currently supported. Mixing ranges with multiple entries not currently supported. Changing this forces a new resource to be created. +* `remote_port` - (Optional) The remote port to be filtered on. Specify `80` for single port entry, `80-85` for a range and `80;443;` for multiple entries. Multiple ranges and mixing ranges with multiple entries are currently not supported. Changing this forces a new resource to be created. --- @@ -173,7 +173,7 @@ The following attributes are exported: A `storage_location` block contains: -* `storage_path` - The URI of the storage path to save the packet capture. +* `storage_path` - The URI of the storage path where the packet capture sessions are saved to. ## Timeouts From 31ebf62d2d5a0e750b3a7333a67d8b4e31e2d679 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Fri, 9 Dec 2022 13:02:29 +0800 Subject: [PATCH 12/12] update code --- .../services/network/validate/file_path.go | 16 ++++++++ .../network/validate/file_path_test.go | 37 +++++++++++++++++++ ...virtual_machine_packet_capture_resource.go | 35 +++++++++++------- ...al_machine_packet_capture_resource_test.go | 35 ++++++++---------- ...chine_scale_set_packet_capture_resource.go | 35 +++++++++++------- ..._scale_set_packet_capture_resource_test.go | 18 +++------ ...rtual_machine_packet_capture.html.markdown | 11 ++---- ...ine_scale_set_packet_capture.html.markdown | 7 +--- 8 files changed, 124 insertions(+), 70 deletions(-) create mode 100644 internal/services/network/validate/file_path.go create mode 100644 internal/services/network/validate/file_path_test.go diff --git a/internal/services/network/validate/file_path.go b/internal/services/network/validate/file_path.go new file mode 100644 index 000000000000..1475ad9e1efd --- /dev/null +++ b/internal/services/network/validate/file_path.go @@ -0,0 +1,16 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func FilePath(v interface{}, k string) (warnings []string, errors []error) { + value := v.(string) + + if !regexp.MustCompile(`^(.)+.cap$`).MatchString(value) { + errors = append(errors, fmt.Errorf("%s must end with extension name '.cap'", k)) + } + + return warnings, errors +} diff --git a/internal/services/network/validate/file_path_test.go b/internal/services/network/validate/file_path_test.go new file mode 100644 index 000000000000..910371f02518 --- /dev/null +++ b/internal/services/network/validate/file_path_test.go @@ -0,0 +1,37 @@ +package validate + +import "testing" + +func TestFilePath(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + { + Input: "", + Valid: false, + }, + { + Input: "testfilepath", + Valid: false, + }, + { + Input: "testfilepath.", + Valid: false, + }, + { + Input: "testfilepath.cap", + Valid: true, + }, + } + + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := FilePath(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/internal/services/network/virtual_machine_packet_capture_resource.go b/internal/services/network/virtual_machine_packet_capture_resource.go index 24e43c8c05d1..22a84ee2a696 100644 --- a/internal/services/network/virtual_machine_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_packet_capture_resource.go @@ -5,11 +5,12 @@ import ( "log" "time" - "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" + storageValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" @@ -36,17 +37,17 @@ func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "name": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, }, - "resource_group_name": commonschema.ResourceGroupName(), - - "network_watcher_name": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, + "network_watcher_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.NetworkWatcherID, }, "virtual_machine_id": { @@ -90,11 +91,13 @@ func resourceVirtualMachinePacketCapture() *pluginsdk.Resource { "file_path": { Type: pluginsdk.TypeString, Optional: true, + ValidateFunc: networkValidate.FilePath, AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, }, "storage_account_id": { Type: pluginsdk.TypeString, Optional: true, + ValidateFunc: storageValidate.StorageAccountID, AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, }, "storage_path": { @@ -154,7 +157,12 @@ func resourceVirtualMachinePacketCaptureCreate(d *pluginsdk.ResourceData, meta i ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) + watcherId, err := parse.NetworkWatcherID(d.Get("network_watcher_id").(string)) + if err != nil { + return err + } + + id := parse.NewPacketCaptureID(subscriptionId, watcherId.ResourceGroup, watcherId.Name, d.Get("name").(string)) targetResourceId := d.Get("virtual_machine_id").(string) bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) @@ -225,8 +233,9 @@ func resourceVirtualMachinePacketCaptureRead(d *pluginsdk.ResourceData, meta int } d.Set("name", id.Name) - d.Set("network_watcher_name", id.NetworkWatcherName) - d.Set("resource_group_name", id.ResourceGroup) + + networkWatcherId := parse.NewNetworkWatcherID(id.SubscriptionId, id.ResourceGroup, id.NetworkWatcherName) + d.Set("network_watcher_id", networkWatcherId.ID()) if props := resp.PacketCaptureResultProperties; props != nil { d.Set("virtual_machine_id", props.Target) diff --git a/internal/services/network/virtual_machine_packet_capture_resource_test.go b/internal/services/network/virtual_machine_packet_capture_resource_test.go index 6ddedc84f7e4..595ef7f7fa36 100644 --- a/internal/services/network/virtual_machine_packet_capture_resource_test.go +++ b/internal/services/network/virtual_machine_packet_capture_resource_test.go @@ -197,10 +197,9 @@ func (r VirtualMachinePacketCaptureResource) localDiskConfig(data acceptance.Tes %s resource "azurerm_virtual_machine_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - virtual_machine_id = azurerm_virtual_machine.test.id + name = "acctestpc-%d" + network_watcher_id = azurerm_network_watcher.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -216,10 +215,9 @@ func (r VirtualMachinePacketCaptureResource) localDiskConfig_requiresImport(data %s resource "azurerm_virtual_machine_packet_capture" "import" { - name = azurerm_virtual_machine_packet_capture.test.name - network_watcher_name = azurerm_virtual_machine_packet_capture.test.network_watcher_name - resource_group_name = azurerm_virtual_machine_packet_capture.test.resource_group_name - virtual_machine_id = azurerm_virtual_machine_packet_capture.test.virtual_machine_id + name = azurerm_virtual_machine_packet_capture.test.name + network_watcher_id = azurerm_virtual_machine_packet_capture.test.network_watcher_id + virtual_machine_id = azurerm_virtual_machine_packet_capture.test.virtual_machine_id storage_location { file_path = "/var/captures/packet.cap" @@ -235,10 +233,9 @@ func (r VirtualMachinePacketCaptureResource) localDiskConfigWithFilters(data acc %s resource "azurerm_virtual_machine_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - virtual_machine_id = azurerm_virtual_machine.test.id + name = "acctestpc-%d" + network_watcher_id = azurerm_network_watcher.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" @@ -274,10 +271,9 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_virtual_machine_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - virtual_machine_id = azurerm_virtual_machine.test.id + name = "acctestpc-%d" + network_watcher_id = azurerm_network_watcher.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { storage_account_id = azurerm_storage_account.test.id @@ -301,10 +297,9 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_virtual_machine_packet_capture" "test" { - name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name - virtual_machine_id = azurerm_virtual_machine.test.id + name = "acctestpc-%d" + network_watcher_id = azurerm_network_watcher.test.id + virtual_machine_id = azurerm_virtual_machine.test.id storage_location { file_path = "/var/captures/packet.cap" diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go index 97b896ffb0c2..d8ae20f54414 100644 --- a/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource.go @@ -5,12 +5,13 @@ import ( "log" "time" - "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" computeParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" + storageValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" @@ -37,17 +38,17 @@ func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "name": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, }, - "resource_group_name": commonschema.ResourceGroupName(), - - "network_watcher_name": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, + "network_watcher_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.NetworkWatcherID, }, "virtual_machine_scale_set_id": { @@ -91,11 +92,13 @@ func resourceVirtualMachineScaleSetPacketCapture() *pluginsdk.Resource { "file_path": { Type: pluginsdk.TypeString, Optional: true, + ValidateFunc: networkValidate.FilePath, AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, }, "storage_account_id": { Type: pluginsdk.TypeString, Optional: true, + ValidateFunc: storageValidate.StorageAccountID, AtLeastOneOf: []string{"storage_location.0.file_path", "storage_location.0.storage_account_id"}, }, "storage_path": { @@ -185,7 +188,12 @@ func resourceVirtualMachineScaleSetPacketCaptureCreate(d *pluginsdk.ResourceData ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewPacketCaptureID(subscriptionId, d.Get("resource_group_name").(string), d.Get("network_watcher_name").(string), d.Get("name").(string)) + watcherId, err := parse.NetworkWatcherID(d.Get("network_watcher_id").(string)) + if err != nil { + return err + } + + id := parse.NewPacketCaptureID(subscriptionId, watcherId.ResourceGroup, watcherId.Name, d.Get("name").(string)) targetResourceId := d.Get("virtual_machine_scale_set_id").(string) bytesToCapturePerPacket := d.Get("maximum_bytes_per_packet").(int) @@ -260,8 +268,9 @@ func resourceVirtualMachineScaleSetPacketCaptureRead(d *pluginsdk.ResourceData, } d.Set("name", id.Name) - d.Set("network_watcher_name", id.NetworkWatcherName) - d.Set("resource_group_name", id.ResourceGroup) + + networkWatcherId := parse.NewNetworkWatcherID(id.SubscriptionId, id.ResourceGroup, id.NetworkWatcherName) + d.Set("network_watcher_id", networkWatcherId.ID()) if props := resp.PacketCaptureResultProperties; props != nil { d.Set("virtual_machine_scale_set_id", props.Target) diff --git a/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go index 1140b5cdacfd..48d5be0120be 100644 --- a/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go +++ b/internal/services/network/virtual_machine_scale_set_packet_capture_resource_test.go @@ -205,8 +205,7 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig(data accept resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name + network_watcher_id = azurerm_network_watcher.test.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { @@ -224,8 +223,7 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfig_requiresImp resource "azurerm_virtual_machine_scale_set_packet_capture" "import" { name = azurerm_virtual_machine_scale_set_packet_capture.test.name - network_watcher_name = azurerm_virtual_machine_scale_set_packet_capture.test.network_watcher_name - resource_group_name = azurerm_virtual_machine_scale_set_packet_capture.test.resource_group_name + network_watcher_id = azurerm_virtual_machine_scale_set_packet_capture.test.network_watcher_id virtual_machine_scale_set_id = azurerm_virtual_machine_scale_set_packet_capture.test.virtual_machine_scale_set_id storage_location { @@ -243,8 +241,7 @@ func (r VirtualMachineScaleSetPacketCaptureResource) localDiskConfigWithFilters( resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name + network_watcher_id = azurerm_network_watcher.test.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { @@ -282,8 +279,7 @@ resource "azurerm_storage_account" "test" { resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name + network_watcher_id = azurerm_network_watcher.test.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { @@ -309,8 +305,7 @@ resource "azurerm_storage_account" "test" { resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name + network_watcher_id = azurerm_network_watcher.test.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { @@ -329,8 +324,7 @@ func (r VirtualMachineScaleSetPacketCaptureResource) machineScope(data acceptanc resource "azurerm_virtual_machine_scale_set_packet_capture" "test" { name = "acctestpc-%d" - network_watcher_name = azurerm_network_watcher.test.name - resource_group_name = azurerm_resource_group.test.name + network_watcher_id = azurerm_network_watcher.test.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.test.id storage_location { diff --git a/website/docs/r/virtual_machine_packet_capture.html.markdown b/website/docs/r/virtual_machine_packet_capture.html.markdown index 0905a4328651..de467da3871c 100644 --- a/website/docs/r/virtual_machine_packet_capture.html.markdown +++ b/website/docs/r/virtual_machine_packet_capture.html.markdown @@ -101,10 +101,9 @@ resource "azurerm_storage_account" "example" { } resource "azurerm_virtual_machine_packet_capture" "example" { - name = "example-pc" - network_watcher_name = azurerm_network_watcher.example.name - resource_group_name = azurerm_resource_group.example.name - virtual_machine_id = azurerm_virtual_machine.example.id + name = "example-pc" + network_watcher_id = azurerm_network_watcher.example.id + virtual_machine_id = azurerm_virtual_machine.example.id storage_location { storage_account_id = azurerm_storage_account.example.id @@ -122,9 +121,7 @@ The following arguments are supported: * `name` - (Required) The name to use for this Network Packet Capture. Changing this forces a new resource to be created. -* `network_watcher_name` - (Required) The name of the Network Watcher. Changing this forces a new resource to be created. - -* `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. +* `network_watcher_id` - (Required) The resource ID of the Network Watcher. Changing this forces a new resource to be created. * `virtual_machine_id` - (Required) The resource ID of the target Virtual Machine to capture packets from. Changing this forces a new resource to be created. diff --git a/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown index 9fc2e6e28f5e..b0727a36e8c3 100644 --- a/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown +++ b/website/docs/r/virtual_machine_scale_set_packet_capture.html.markdown @@ -88,8 +88,7 @@ resource "azurerm_virtual_machine_scale_set_extension" "example" { resource "azurerm_virtual_machine_scale_set_packet_capture" "example" { name = "example-pc" - network_watcher_name = azurerm_network_watcher.example.name - resource_group_name = azurerm_resource_group.example.name + network_watcher_id = azurerm_network_watcher.example.id virtual_machine_scale_set_id = azurerm_linux_virtual_machine_scale_set.example.id storage_location { @@ -113,9 +112,7 @@ The following arguments are supported: * `name` - (Required) The name to use for this Network Packet Capture. Changing this forces a new resource to be created. -* `network_watcher_name` - (Required) The name of the Network Watcher. Changing this forces a new resource to be created. - -* `resource_group_name` - (Required) The name of the resource group in which the Network Watcher exists. Changing this forces a new resource to be created. +* `network_watcher_id` - (Required) The resource ID of the Network Watcher. Changing this forces a new resource to be created. * `virtual_machine_scale_set_id` - (Required) The resource ID of the Virtual Machine Scale Set to capture packets from. Changing this forces a new resource to be created.