diff --git a/go.mod b/go.mod index 2effbbf28c..d9db4e409b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.22.5 require ( github.com/IBM-Cloud/bluemix-go v0.0.0-20240719075425-078fcb3a55be github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113 - github.com/IBM-Cloud/power-go-client v1.7.0 + github.com/IBM-Cloud/power-go-client v1.8.0-beta17 github.com/IBM/apigateway-go-sdk v0.0.0-20210714141226-a5d5d49caaca github.com/IBM/appconfiguration-go-admin-sdk v0.3.0 github.com/IBM/appid-management-go-sdk v0.0.0-20210908164609-dd0e0eaf732f diff --git a/go.sum b/go.sum index c3a7916418..9279ffd06e 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,8 @@ github.com/IBM-Cloud/bluemix-go v0.0.0-20240719075425-078fcb3a55be/go.mod h1:/7h github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113 h1:f2Erqfea1dKpaTFagTJM6W/wnD3JGq/Vn9URh8nuRwk= github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113/go.mod h1:xUQL9SGAjoZFd4GNjrjjtEpjpkgU7RFXRyHesbKTjiY= github.com/IBM-Cloud/ibm-cloud-cli-sdk v0.5.3/go.mod h1:RiUvKuHKTBmBApDMUQzBL14pQUGKcx/IioKQPIcRQjs= -github.com/IBM-Cloud/power-go-client v1.7.0 h1:/GuGwPMTKoCZACfnwt7b6wKr4v32q1VO1AMFGNETRN4= -github.com/IBM-Cloud/power-go-client v1.7.0/go.mod h1:9izycYAmNQ+NAdVPXDC3fHYxqWLjlR2YiwqKYveMv5Y= +github.com/IBM-Cloud/power-go-client v1.8.0-beta17 h1:zL/qQUs/bb8L0FEazcBcpr7wTCpv0CJp/dbpg6351Qc= +github.com/IBM-Cloud/power-go-client v1.8.0-beta17/go.mod h1:oAkZiHX25cmr2Yun5V0q6CpnUemegvSrpcEy/oQcjzU= github.com/IBM-Cloud/softlayer-go v1.0.5-tf h1:koUAyF9b6X78lLLruGYPSOmrfY2YcGYKOj/Ug9nbKNw= github.com/IBM-Cloud/softlayer-go v1.0.5-tf/go.mod h1:6HepcfAXROz0Rf63krk5hPZyHT6qyx2MNvYyHof7ik4= github.com/IBM/apigateway-go-sdk v0.0.0-20210714141226-a5d5d49caaca h1:crniVcf+YcmgF03NmmfonXwSQ73oJF+IohFYBwknMxs= diff --git a/ibm/acctest/acctest.go b/ibm/acctest/acctest.go index 410539545e..d58b19c42c 100644 --- a/ibm/acctest/acctest.go +++ b/ibm/acctest/acctest.go @@ -203,39 +203,43 @@ var ( // For Power Colo var ( - Pi_auxiliary_volume_name string - Pi_cloud_instance_id string - Pi_dhcp_id string - Pi_host_group_id string - Pi_host_id string - Pi_image string - Pi_image_bucket_access_key string - Pi_image_bucket_file_name string - Pi_image_bucket_name string - Pi_image_bucket_region string - Pi_image_bucket_secret_key string - Pi_instance_name string - Pi_key_name string - Pi_network_name string - Pi_placement_group_name string - Pi_replication_volume_name string - Pi_resource_group_id string - Pi_sap_image string - Pi_shared_processor_pool_id string - Pi_snapshot_id string - Pi_spp_placement_group_id string - Pi_target_storage_tier string - Pi_volume_clone_task_id string - Pi_volume_group_id string - Pi_volume_group_name string - Pi_volume_id string - Pi_volume_name string - Pi_volume_onboarding_id string - Pi_volume_onboarding_source_crn string - PiCloudConnectionName string - PiSAPProfileID string - PiStoragePool string - PiStorageType string + Pi_auxiliary_volume_name string + Pi_cloud_instance_id string + Pi_dhcp_id string + Pi_host_group_id string + Pi_host_id string + Pi_image string + Pi_image_bucket_access_key string + Pi_image_bucket_file_name string + Pi_image_bucket_name string + Pi_image_bucket_region string + Pi_image_bucket_secret_key string + Pi_instance_name string + Pi_key_name string + Pi_network_name string + Pi_network_security_group_id string + Pi_network_security_group_rule_id string + Pi_placement_group_name string + Pi_remote_id string + Pi_remote_type string + Pi_replication_volume_name string + Pi_resource_group_id string + Pi_sap_image string + Pi_shared_processor_pool_id string + Pi_snapshot_id string + Pi_spp_placement_group_id string + Pi_target_storage_tier string + Pi_volume_clone_task_id string + Pi_volume_group_id string + Pi_volume_group_name string + Pi_volume_id string + Pi_volume_name string + Pi_volume_onboarding_id string + Pi_volume_onboarding_source_crn string + PiCloudConnectionName string + PiSAPProfileID string + PiStoragePool string + PiStorageType string ) var ( @@ -1061,6 +1065,18 @@ func init() { fmt.Println("[INFO] Set the environment variable PI_NETWORK_NAME for testing ibm_pi_network_name resource else it is set to default value 'terraform-test-power'") } + Pi_network_security_group_id = os.Getenv("PI_NETWORK_SECURITY_GROUP_ID") + if Pi_network_security_group_id == "" { + Pi_network_security_group_id = "terraform-test-power" + fmt.Println("[INFO] Set the environment variable PI_NETWORK_SECURITY_GROUP_ID for testing ibm_pi_network_security_group resource else it is set to default value 'terraform-test-power'") + } + + Pi_network_security_group_rule_id = os.Getenv("PI_NETWORK_SECURITY_GROUP_RULE_ID") + if Pi_network_security_group_rule_id == "" { + Pi_network_security_group_rule_id = "terraform-test-power" + fmt.Println("[INFO] Set the environment variable PI_NETWORK_SECURITY_GROUP_RULE_ID for testing ibm_pi_network_security_group resource else it is set to default value 'terraform-test-power'") + } + Pi_volume_name = os.Getenv("PI_VOLUME_NAME") if Pi_volume_name == "" { Pi_volume_name = "terraform-test-power" @@ -1150,6 +1166,19 @@ func init() { Pi_placement_group_name = "tf-pi-placement-group" fmt.Println("[WARN] Set the environment variable PI_PLACEMENT_GROUP_NAME for testing ibm_pi_placement_group resource else it is set to default value 'tf-pi-placement-group'") } + + Pi_remote_id = os.Getenv("PI_REMOTE_ID") + if Pi_remote_id == "" { + Pi_remote_id = "tf-pi-placement-group" + fmt.Println("[WARN] Set the environment variable PI_REMOTE_ID for testing ibm_pi_placement_group resource else it is set to default value 'tf-pi-placement-group'") + } + + Pi_remote_type = os.Getenv("PI_REMOTE_TYPE") + if Pi_remote_type == "" { + Pi_remote_type = "tf-pi-placement-group" + fmt.Println("[WARN] Set the environment variable PI_REMOTE_TYPE for testing ibm_pi_placement_group resource else it is set to default value 'tf-pi-placement-group'") + } + Pi_spp_placement_group_id = os.Getenv("PI_SPP_PLACEMENT_GROUP_ID") if Pi_spp_placement_group_id == "" { Pi_spp_placement_group_id = "tf-pi-spp-placement-group" diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index da354497e6..3aa1bbc5c2 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -127,6 +127,22 @@ func FlattenIntList(list []int) []interface{} { return vs } +func ExpandInt64List(input []interface{}) []int64 { + vs := make([]int64, len(input)) + for i, v := range input { + vs[i] = v.(int64) + } + return vs +} + +func FlattenInt64List(list []int64) []interface{} { + vs := make([]interface{}, len(list)) + for i, v := range list { + vs[i] = v + } + return vs +} + func NewStringSet(f schema.SchemaSetFunc, in []string) *schema.Set { var out = make([]interface{}, len(in), len(in)) for i, v := range in { diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index dc4a116869..676cbb12c5 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -1297,6 +1297,7 @@ func Provider() *schema.Provider { "ibm_pi_ipsec_policy": power.ResourceIBMPIIPSecPolicy(), "ibm_pi_key": power.ResourceIBMPIKey(), "ibm_pi_network_port_attach": power.ResourceIBMPINetworkPortAttach(), + "ibm_pi_network_security_group_rule": power.ResourceIBMPINetworkSecurityGroupRule(), "ibm_pi_network": power.ResourceIBMPINetwork(), "ibm_pi_placement_group": power.ResourceIBMPIPlacementGroup(), "ibm_pi_shared_processor_pool": power.ResourceIBMPISharedProcessorPool(), diff --git a/ibm/service/power/ibm_pi_constants.go b/ibm/service/power/ibm_pi_constants.go index 6f3fff8509..f197aba157 100644 --- a/ibm/service/power/ibm_pi_constants.go +++ b/ibm/service/power/ibm_pi_constants.go @@ -20,6 +20,7 @@ const ( Arg_DeploymentTarget = "pi_deployment_target" Arg_DeploymentType = "pi_deployment_type" Arg_Description = "pi_description" + Arg_DestinationPorts = "pi_destination_ports" Arg_DhcpID = "pi_dhcp_id" Arg_DhcpName = "pi_dhcp_name" Arg_DhcpSnatEnabled = "pi_dhcp_snat_enabled" @@ -46,6 +47,8 @@ const ( Arg_Name = "pi_name" Arg_Network = "pi_network" Arg_NetworkName = "pi_network_name" + Arg_NetworkSecurityGroupID = "pi_network_security_group_id" + Arg_NetworkSecurityGroupRuleID = "pi_network_security_group_rule_id" Arg_PinPolicy = "pi_pin_policy" Arg_PlacementGroupID = "pi_placement_group_id" Arg_PlacementGroupName = "pi_placement_group_name" @@ -53,9 +56,11 @@ const ( Arg_Plan = "pi_plan" Arg_Processors = "pi_processors" Arg_ProcType = "pi_proc_type" + Arg_Protocol = "pi_protocol" Arg_PVMInstanceActionType = "pi_action" Arg_PVMInstanceHealthStatus = "pi_health_status" Arg_PVMInstanceId = "pi_instance_id" + Arg_Remote = "pi_remote" Arg_Remove = "pi_remove" Arg_Replicants = "pi_replicants" Arg_ReplicationEnabled = "pi_replication_enabled" @@ -74,6 +79,7 @@ const ( Arg_SharedProcessorPoolReservedCores = "pi_shared_processor_pool_reserved_cores" Arg_SnapshotID = "pi_snapshot_id" Arg_SnapShotName = "pi_snap_shot_name" + Arg_SourcePorts = "pi_source_ports" Arg_SPPPlacementGroupID = "pi_spp_placement_group_id" Arg_SPPPlacementGroupName = "pi_spp_placement_group_name" Arg_SPPPlacementGroupPolicy = "pi_spp_placement_group_policy" @@ -160,6 +166,7 @@ const ( Attr_DeleteOnTermination = "delete_on_termination" Attr_DeploymentType = "deployment_type" Attr_Description = "description" + Attr_DestinationPort = "destination_port" Attr_Details = "details" Attr_DhcpID = "dhcp_id" Attr_DhcpManaged = "dhcp_managed" @@ -174,6 +181,7 @@ const ( Attr_FailureMessage = "failure_message" Attr_FailureReason = "failure_reason" Attr_Fault = "fault" + Attr_Flag = "flag" Attr_FlashCopyMappings = "flash_copy_mappings" Attr_FlashCopyName = "flash_copy_name" Attr_FreezeTime = "freeze_time" @@ -197,6 +205,7 @@ const ( Attr_IBMiPHA = "ibmi_pha" Attr_IBMiRDS = "ibmi_rds" Attr_IBMiRDSUsers = "ibmi_rds_users" + Attr_ICMPType = "icmp_type" Attr_ID = "id" Attr_ImageID = "image_id" Attr_ImageInfo = "image_info" @@ -235,6 +244,7 @@ const ( Attr_MaxAllocationSize = "max_allocation_size" Attr_MaxAvailable = "max_available" Attr_MaxCoresAvailable = "max_cores_available" + Attr_Maximum = "maximum" Attr_MaximumStorageAllocation = "max_storage_allocation" Attr_MaxMem = "maxmem" Attr_MaxMemory = "max_memory" @@ -242,12 +252,15 @@ const ( Attr_MaxProc = "maxproc" Attr_MaxProcessors = "max_processors" Attr_MaxVirtualCores = "max_virtual_cores" + Attr_MemberNetworkSecurityGroupID = "member_network_security_group_id" Attr_Members = "members" + Attr_MemberType = "member_type" Attr_Memory = "memory" Attr_Message = "message" Attr_Metered = "metered" Attr_MigrationStatus = "migration_status" Attr_Min = "min" + Attr_Minimum = "minimum" Attr_MinMem = "minmem" Attr_MinMemory = "min_memory" Attr_MinProc = "minproc" @@ -260,6 +273,8 @@ const ( Attr_NetworkName = "network_name" Attr_NetworkPorts = "network_ports" Attr_Networks = "networks" + Attr_NetworkSecurityGroupID = "network_security_group_id" + Attr_NetworkSecurityGroups = "network_security_groups" Attr_NumberOfVolumes = "number_of_volumes" Attr_Onboardings = "onboardings" Attr_OperatingSystem = "operating_system" @@ -282,11 +297,13 @@ const ( Attr_ProfileID = "profile_id" Attr_Profiles = "profiles" Attr_Progress = "progress" + Attr_Protocol = "protocol" Attr_PublicIP = "public_ip" Attr_PVMInstanceID = "pvm_instance_id" Attr_PVMInstances = "pvm_instances" Attr_PVMSnapshots = "pvm_snapshots" Attr_Region = "region" + Attr_Remote = "remote" Attr_RemoteCopyID = "remote_copy_id" Attr_RemoteCopyRelationshipNames = "remote_copy_relationship_names" Attr_RemoteCopyRelationships = "remote_copy_relationships" @@ -299,6 +316,7 @@ const ( Attr_ReservedMemory = "reserved_memory" Attr_ResultsOnboardedVolumes = "results_onboarded_volumes" Attr_ResultsVolumeOnboardingFailures = "results_volume_onboarding_failures" + Attr_Rules = "rules" Attr_SAPS = "saps" Attr_Secondaries = "secondaries" Attr_ServerName = "server_name" @@ -325,6 +343,7 @@ const ( Attr_SharedProcessorPoolStatusDetail = "status_detail" Attr_Size = "size" Attr_SnapshotID = "snapshot_id" + Attr_SourcePort = "source_port" Attr_SourceVolumeID = "source_volume_id" Attr_SourceVolumeName = "source_volume_name" Attr_Speed = "speed" @@ -351,8 +370,10 @@ const ( Attr_Systems = "systems" Attr_SysType = "sys_type" Attr_Systype = "systype" + Attr_Target = "target" Attr_TargetVolumeName = "target_volume_name" Attr_TaskID = "task_id" + Attr_TCPFlags = "tcp_flags" Attr_TenantID = "tenant_id" Attr_TenantName = "tenant_name" Attr_TotalCapacity = "total_capacity" @@ -371,6 +392,7 @@ const ( Attr_UsedIPPercent = "used_ip_percent" Attr_UsedMemory = "used_memory" Attr_UserIPAddress = "user_ip_address" + Attr_UserTags = "user_tags" Attr_VCPUs = "vcpus" Attr_Vendor = "vendor" Attr_VirtualCoresAssigned = "virtual_cores_assigned" @@ -417,6 +439,8 @@ const ( // Allowed Values Affinity = "affinity" + All = "all" + Allow = "allow" AntiAffinity = "anti-affinity" Attach = "attach" BYOL = "byol" @@ -424,15 +448,23 @@ const ( Critical = "CRITICAL" CUSTOM_VIRTUAL_CORES = "custom-virtualcores" Dedicated = "dedicated" + DefaultNAG = "default-network-address-group" + Deny = "deny" DeploymentTypeEpic = "EPIC" DeploymentTypeVMNoStorage = "VMNoStorage" + DestinationUnreach = "destination-unreach" DHCPVlan = "dhcp-vlan" + Echo = "echo" + EchoReply = "echo-reply" Hana = "Hana" Hard = "hard" Host = "host" HostGroup = "hostGroup" + ICMP = "icmp" + NAG = "network-address-group" Netweaver = "Netweaver" None = "none" + NSG = "network-security-group" OK = "OK" PER = "power-edge-router" Prefix = "prefix" @@ -442,7 +474,11 @@ const ( SAP = "SAP" Shared = "shared" Soft = "soft" + SourceQuench = "source-quench" Suffix = "suffix" + TCP = "tcp" + TimeExceeded = "time-exceeded" + UDP = "udp" Vlan = "vlan" vSCSI = "vSCSI" Warning = "WARNING" @@ -487,8 +523,8 @@ const ( State_RESIZE = "RESIZE" State_Retry = "retry" State_Shutoff = "shutoff" - State_Stopping = "stopping" State_SHUTOFF = "SHUTOFF" + State_Stopping = "stopping" State_Up = "up" State_Updating = "updating" State_VerifyResize = "verify_resize" diff --git a/ibm/service/power/resource_ibm_pi_network_security_group_rule.go b/ibm/service/power/resource_ibm_pi_network_security_group_rule.go new file mode 100644 index 0000000000..2a6d22c3f8 --- /dev/null +++ b/ibm/service/power/resource_ibm_pi_network_security_group_rule.go @@ -0,0 +1,646 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power + +import ( + "context" + "fmt" + "time" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/power/models" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func ResourceIBMPINetworkSecurityGroupRule() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMPINetworkSecurityGroupRuleCreate, + ReadContext: resourceIBMPINetworkSecurityGroupRuleRead, + DeleteContext: resourceIBMPINetworkSecurityGroupRuleDelete, + Importer: &schema.ResourceImporter{}, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + // Arguments + Arg_Action: { + ConflictsWith: []string{Arg_NetworkSecurityGroupRuleID}, + Description: "The action to take if the rule matches network traffic.", + ForceNew: true, + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{Allow, Deny}), + }, + Arg_CloudInstanceID: { + Description: "The GUID of the service instance associated with an account.", + ForceNew: true, + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, + }, + Arg_DestinationPorts: { + ConflictsWith: []string{Arg_NetworkSecurityGroupRuleID}, + Description: "Destination port ranges.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Maximum: { + Default: 65535, + Description: "The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number.", + Optional: true, + Type: schema.TypeInt, + }, + Attr_Minimum: { + Default: 1, + Description: "The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number.", + Optional: true, + Type: schema.TypeInt, + }, + }, + }, + ForceNew: true, + MaxItems: 1, + Optional: true, + Type: schema.TypeList, + }, + Arg_NetworkSecurityGroupID: { + Description: "The unique identifier of the network security group.", + ForceNew: true, + Required: true, + Type: schema.TypeString, + }, + Arg_NetworkSecurityGroupRuleID: { + ConflictsWith: []string{Arg_Action, Arg_DestinationPorts, Arg_Protocol, Arg_Remote, Arg_SourcePorts}, + Description: "The network security group rule id to remove.", + ForceNew: true, + Optional: true, + Type: schema.TypeString, + }, + Arg_Protocol: { + ConflictsWith: []string{Arg_NetworkSecurityGroupRuleID}, + Description: "The protocol of the network traffic.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_ICMPType: { + Description: "If icmp type, a ICMP packet type affected by ICMP rules and if not present then all types are matched.", + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{All, DestinationUnreach, Echo, EchoReply, SourceQuench, TimeExceeded}), + }, + Attr_TCPFlags: { + Description: "If tcp type, the list of TCP flags and if not present then all flags are matched.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Flag: { + Description: "TCP flag.", + Required: true, + Type: schema.TypeString, + }, + }, + }, + Optional: true, + Type: schema.TypeList, + }, + Attr_Type: { + Description: "The protocol of the network traffic.", + Required: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{All, ICMP, TCP, UDP}), + }, + }, + }, + ForceNew: true, + MaxItems: 1, + Optional: true, + Type: schema.TypeList, + }, + Arg_Remote: { + ConflictsWith: []string{Arg_NetworkSecurityGroupRuleID}, + Description: "The protocol of the network traffic.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_ID: { + Description: "The ID of the remote network address group or network security group the rules apply to. Not required for default-network-address-group.", + Optional: true, + Type: schema.TypeString, + }, + Attr_Type: { + Description: "The type of remote group (MAC addresses, IP addresses, CIDRs, external CIDRs) that are the originators of rule's network traffic to match.", + Optional: true, + Type: schema.TypeString, + ValidateFunc: validate.ValidateAllowedStringValues([]string{DefaultNAG, NAG, NSG}), + }, + }, + }, + ForceNew: true, + MaxItems: 1, + Optional: true, + Type: schema.TypeList, + }, + Arg_SourcePorts: { + ConflictsWith: []string{Arg_NetworkSecurityGroupRuleID}, + Description: "Source port ranges.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Maximum: { + Default: 65535, + Description: "The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number.", + Optional: true, + Type: schema.TypeInt, + }, + Attr_Minimum: { + Default: 1, + Description: "The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number.", + Optional: true, + Type: schema.TypeInt, + }, + }, + }, + ForceNew: true, + MaxItems: 1, + Optional: true, + Type: schema.TypeList, + }, + + // Attributes + Attr_CRN: { + Computed: true, + Description: "The network security group's crn.", + Type: schema.TypeString, + }, + Attr_Members: { + Computed: true, + Description: "The list of IPv4 addresses and, or network interfaces in the network security group.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_ID: { + Computed: true, + Description: "The ID of the member in a network security group.", + Type: schema.TypeString, + }, + Attr_MacAddress: { + Computed: true, + Description: "The mac address of a network interface included if the type is network-interface.", + Type: schema.TypeString, + }, + Attr_Target: { + Computed: true, + Description: "If ipv4-address type, then IPv4 address or if network-interface type, then network interface ID.", + Type: schema.TypeString, + }, + Attr_Type: { + Computed: true, + Description: "The type of member.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, + Attr_Name: { + Computed: true, + Description: "The name of the network security group.", + Type: schema.TypeString, + }, + Attr_NetworkSecurityGroupID: { + Computed: true, + Description: "The unique identifier of the network security group.", + Type: schema.TypeString, + }, + Attr_Rules: { + Computed: true, + Description: "The list of rules in the network security group.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Action: { + Computed: true, + Description: "The action to take if the rule matches network traffic.", + Type: schema.TypeString, + }, + Attr_DestinationPort: { + Computed: true, + Description: "Destination port ranges.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Maximum: { + Computed: true, + Description: "The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number.", + Type: schema.TypeFloat, + }, + Attr_Minimum: { + Computed: true, + Description: "The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number.", + Type: schema.TypeFloat, + }, + }, + }, + Type: schema.TypeList, + }, + Attr_ID: { + Computed: true, + Description: "The ID of the rule in a network security group.", + Type: schema.TypeString, + }, + Attr_Protocol: { + Computed: true, + Description: "The list of protocol.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_ICMPType: { + Computed: true, + Description: "If icmp type, a ICMP packet type affected by ICMP rules and if not present then all types are matched.", + Type: schema.TypeString, + }, + Attr_TCPFlags: { + Computed: true, + Description: "If tcp type, the list of TCP flags and if not present then all flags are matched.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Flag: { + Computed: true, + Description: "TCP flag.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, + Attr_Type: { + Computed: true, + Description: "The protocol of the network traffic.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, + Attr_Remote: { + Computed: true, + Description: "List of remote.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_ID: { + Computed: true, + Description: "The ID of the remote network address group or network security group the rules apply to. Not required for default-network-address-group.", + Type: schema.TypeString, + }, + Attr_Type: { + Computed: true, + Description: "The type of remote group the rules apply to.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, + Attr_SourcePort: { + Computed: true, + Description: "Source port ranges.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Maximum: { + Computed: true, + Description: "The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number.", + Type: schema.TypeFloat, + }, + Attr_Minimum: { + Computed: true, + Description: "The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number.", + Type: schema.TypeFloat, + }, + }, + }, + Type: schema.TypeList, + }, + }, + }, + Type: schema.TypeList, + }, + }, + } +} + +func resourceIBMPINetworkSecurityGroupRuleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + nsgClient := instance.NewIBMIPINetworkSecurityGroupClient(ctx, sess, cloudInstanceID) + nsgID := d.Get(Arg_NetworkSecurityGroupID).(string) + + if v, ok := d.GetOk(Arg_NetworkSecurityGroupRuleID); ok { + ruleID := v.(string) + err := nsgClient.DeleteRule(nsgID, ruleID) + if err != nil { + return diag.FromErr(err) + } + _, err = isWaitForIBMPINetworkSecurityGroupRuleRemove(ctx, nsgClient, nsgID, ruleID, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return diag.FromErr(err) + } + d.SetId(fmt.Sprintf("%s/%s", cloudInstanceID, nsgID)) + } else { + action := d.Get(Arg_Action).(string) + + networkSecurityGroupAddRule := models.NetworkSecurityGroupAddRule{ + Action: &action, + } + + // Add protocol + protocol := d.Get(Arg_Protocol + ".0").(map[string]interface{}) + networkSecurityGroupAddRule.Protocol = networkSecurityGroupRuleMapToProtocol(protocol) + + // Add remote + remote := d.Get(Arg_Remote + ".0").(map[string]interface{}) + networkSecurityGroupAddRule.Remote = networkSecurityGroupRuleMapToRemote(remote) + + // Optional fields + destinationPort := d.Get(Arg_DestinationPorts + ".0").(map[string]interface{}) + networkSecurityGroupAddRule.DestinationPorts = networkSecurityGroupRuleMapToPort(destinationPort) + + sourcePort := d.Get(Arg_SourcePorts + ".0").(map[string]interface{}) + networkSecurityGroupAddRule.SourcePorts = networkSecurityGroupRuleMapToPort(sourcePort) + + networkSecurityGroup, err := nsgClient.AddRule(nsgID, &networkSecurityGroupAddRule) + ruleID := *networkSecurityGroup.ID + if err != nil { + return diag.FromErr(err) + } + _, err = isWaitForIBMPINetworkSecurityGroupRuleAdd(ctx, nsgClient, nsgID, ruleID, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return diag.FromErr(err) + } + d.SetId(fmt.Sprintf("%s/%s/%s", cloudInstanceID, nsgID, ruleID)) + } + + return resourceIBMPINetworkSecurityGroupRuleRead(ctx, d, meta) +} + +func resourceIBMPINetworkSecurityGroupRuleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + cloudInstanceID, nsgID, err := splitID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + nsgClient := instance.NewIBMIPINetworkSecurityGroupClient(ctx, sess, cloudInstanceID) + networkSecurityGroup, err := nsgClient.Get(nsgID) + if err != nil { + return diag.FromErr(err) + } + d.Set(Attr_Name, networkSecurityGroup.Name) + d.Set(Attr_CRN, networkSecurityGroup.Crn) + + if len(networkSecurityGroup.Members) > 0 { + members := []map[string]interface{}{} + for _, mbr := range networkSecurityGroup.Members { + mbrMap := networkSecurityGroupMemberToMap(mbr) + members = append(members, mbrMap) + } + d.Set(Attr_Members, members) + } else { + d.Set(Attr_Members, []string{}) + } + + d.Set(Attr_NetworkSecurityGroupID, networkSecurityGroup.ID) + if len(networkSecurityGroup.Rules) > 0 { + rules := []map[string]interface{}{} + for _, rule := range networkSecurityGroup.Rules { + ruleMap := networkSecurityGroupRuleToMap(rule) + rules = append(rules, ruleMap) + } + d.Set(Attr_Rules, rules) + } else { + d.Set(Attr_Rules, []string{}) + } + return nil +} + +func resourceIBMPINetworkSecurityGroupRuleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + ids, err := flex.IdParts(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + if len(ids) == 3 { + cloudInstanceID := ids[0] + nsgID := ids[1] + ruleID := ids[2] + + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + nsgClient := instance.NewIBMIPINetworkSecurityGroupClient(ctx, sess, cloudInstanceID) + + err = nsgClient.DeleteRule(nsgID, ruleID) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForIBMPINetworkSecurityGroupRuleRemove(ctx, nsgClient, nsgID, ruleID, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return diag.FromErr(err) + } + } + d.SetId("") + return nil +} + +func isWaitForIBMPINetworkSecurityGroupRuleAdd(ctx context.Context, client *instance.IBMPINetworkSecurityGroupClient, id, ruleID string, timeout time.Duration) (interface{}, error) { + + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Pending}, + Target: []string{State_Available}, + Refresh: isIBMPINetworkSecurityGroupRuleAddRefreshFunc(client, id, ruleID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: time.Minute, + } + + return stateConf.WaitForStateContext(ctx) +} + +func isIBMPINetworkSecurityGroupRuleAddRefreshFunc(client *instance.IBMPINetworkSecurityGroupClient, id, ruleID string) retry.StateRefreshFunc { + + return func() (interface{}, string, error) { + networkSecurityGroup, err := client.Get(id) + if err != nil { + return nil, "", err + } + + if networkSecurityGroup.Rules != nil { + for _, rule := range networkSecurityGroup.Rules { + if *rule.ID == ruleID { + return networkSecurityGroup, State_Available, nil + } + + } + } + return networkSecurityGroup, State_Pending, nil + } +} + +func isWaitForIBMPINetworkSecurityGroupRuleRemove(ctx context.Context, client *instance.IBMPINetworkSecurityGroupClient, id, ruleID string, timeout time.Duration) (interface{}, error) { + + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Pending}, + Target: []string{State_Removed}, + Refresh: isIBMPINetworkSecurityGroupRuleRemoveRefreshFunc(client, id, ruleID), + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: time.Minute, + } + + return stateConf.WaitForStateContext(ctx) +} + +func isIBMPINetworkSecurityGroupRuleRemoveRefreshFunc(client *instance.IBMPINetworkSecurityGroupClient, id, ruleID string) retry.StateRefreshFunc { + + return func() (interface{}, string, error) { + networkSecurityGroup, err := client.Get(id) + if err != nil { + return nil, "", err + } + + if networkSecurityGroup.Rules != nil { + foundRule := false + for _, rule := range networkSecurityGroup.Rules { + if *rule.ID == ruleID { + foundRule = true + return networkSecurityGroup, State_Pending, nil + } + } + if !foundRule { + return networkSecurityGroup, State_Removed, nil + } + } + return networkSecurityGroup, State_Pending, nil + } +} + +func networkSecurityGroupMemberToMap(mbr *models.NetworkSecurityGroupMember) map[string]interface{} { + mbrMap := make(map[string]interface{}) + mbrMap[Attr_ID] = mbr.ID + if mbr.MacAddress != "" { + mbrMap[Attr_MacAddress] = mbr.MacAddress + } + mbrMap[Attr_Target] = mbr.Target + mbrMap[Attr_Type] = mbr.Type + return mbrMap +} + +func networkSecurityGroupRuleToMap(rule *models.NetworkSecurityGroupRule) map[string]interface{} { + ruleMap := make(map[string]interface{}) + ruleMap[Attr_Action] = rule.Action + if rule.DestinationPort != nil { + destinationPortMap := networkSecurityGroupRulePortToMap(rule.DestinationPort) + ruleMap[Attr_DestinationPort] = []map[string]interface{}{destinationPortMap} + } + + ruleMap[Attr_ID] = rule.ID + + protocolMap := networkSecurityGroupRuleProtocolToMap(rule.Protocol) + ruleMap[Attr_Protocol] = []map[string]interface{}{protocolMap} + + remoteMap := networkSecurityGroupRuleRemoteToMap(rule.Remote) + ruleMap[Attr_Remote] = []map[string]interface{}{remoteMap} + + if rule.SourcePort != nil { + sourcePortMap := networkSecurityGroupRulePortToMap(rule.SourcePort) + ruleMap[Attr_SourcePort] = []map[string]interface{}{sourcePortMap} + } + + return ruleMap +} + +func networkSecurityGroupRulePortToMap(port *models.NetworkSecurityGroupRulePort) map[string]interface{} { + portMap := make(map[string]interface{}) + portMap[Attr_Maximum] = port.Maximum + portMap[Attr_Minimum] = port.Minimum + return portMap +} + +func networkSecurityGroupRuleProtocolToMap(protocol *models.NetworkSecurityGroupRuleProtocol) map[string]interface{} { + protocolMap := make(map[string]interface{}) + if protocol.IcmpType != nil { + protocolMap[Attr_ICMPType] = protocol.IcmpType + } + if len(protocol.TCPFlags) > 0 { + tcpFlags := []map[string]interface{}{} + for _, tcpFlagsItem := range protocol.TCPFlags { + tcpFlagsItemMap := make(map[string]interface{}) + tcpFlagsItemMap[Attr_Flag] = tcpFlagsItem.Flag + tcpFlags = append(tcpFlags, tcpFlagsItemMap) + } + protocolMap[Attr_TCPFlags] = tcpFlags + } + if protocol.Type != "" { + protocolMap[Attr_Type] = protocol.Type + } + return protocolMap +} + +func networkSecurityGroupRuleRemoteToMap(remote *models.NetworkSecurityGroupRuleRemote) map[string]interface{} { + remoteMap := make(map[string]interface{}) + if remote.ID != "" { + remoteMap[Attr_ID] = remote.ID + } + if remote.Type != "" { + remoteMap[Attr_Type] = remote.Type + } + return remoteMap +} + +func networkSecurityGroupRuleMapToPort(portMap map[string]interface{}) *models.NetworkSecurityGroupRulePort { + networkSecurityGroupRulePort := models.NetworkSecurityGroupRulePort{} + if portMap[Attr_Maximum] != nil { + networkSecurityGroupRulePort.Maximum = int64(portMap[Attr_Maximum].(int)) + } + if portMap[Attr_Minimum] != nil { + networkSecurityGroupRulePort.Minimum = int64(portMap[Attr_Minimum].(int)) + } + return &networkSecurityGroupRulePort +} + +func networkSecurityGroupRuleMapToRemote(remoteMap map[string]interface{}) *models.NetworkSecurityGroupRuleRemote { + networkSecurityGroupRuleRemote := models.NetworkSecurityGroupRuleRemote{} + if remoteMap[Attr_ID].(string) != "" { + networkSecurityGroupRuleRemote.ID = remoteMap[Attr_ID].(string) + } + networkSecurityGroupRuleRemote.Type = remoteMap[Attr_Type].(string) + return &networkSecurityGroupRuleRemote +} + +func networkSecurityGroupRuleMapToProtocol(protocolMap map[string]interface{}) *models.NetworkSecurityGroupRuleProtocol { + networkSecurityGroupRuleProtocol := models.NetworkSecurityGroupRuleProtocol{} + networkSecurityGroupRuleProtocol.Type = protocolMap[Attr_Type].(string) + + if networkSecurityGroupRuleProtocol.Type == ICMP { + icmpType := protocolMap[Attr_ICMPType].(string) + networkSecurityGroupRuleProtocol.IcmpType = &icmpType + } else if networkSecurityGroupRuleProtocol.Type == TCP { + tcpMaps := protocolMap[Attr_TCPFlags].([]interface{}) + networkSecurityGroupRuleProtocolTCPFlagArray := []*models.NetworkSecurityGroupRuleProtocolTCPFlag{} + for _, tcpMap := range tcpMaps { + flag := tcpMap.(map[string]interface{}) + networkSecurityGroupRuleProtocolTCPFlag := models.NetworkSecurityGroupRuleProtocolTCPFlag{} + networkSecurityGroupRuleProtocolTCPFlag.Flag = flag[Attr_Flag].(string) + networkSecurityGroupRuleProtocolTCPFlagArray = append(networkSecurityGroupRuleProtocolTCPFlagArray, &networkSecurityGroupRuleProtocolTCPFlag) + } + networkSecurityGroupRuleProtocol.TCPFlags = networkSecurityGroupRuleProtocolTCPFlagArray + } + + return &networkSecurityGroupRuleProtocol +} diff --git a/ibm/service/power/resource_ibm_pi_network_security_group_rule_test.go b/ibm/service/power/resource_ibm_pi_network_security_group_rule_test.go new file mode 100644 index 0000000000..f6234b2abf --- /dev/null +++ b/ibm/service/power/resource_ibm_pi_network_security_group_rule_test.go @@ -0,0 +1,191 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/power" +) + +func TestAccIBMPINetworkSecurityGroupRuleBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPINetworkSecurityGroupRuleConfigAddRule(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMPINetworkSecurityGroupRuleExists("ibm_pi_network_security_group_rule.network_security_group_rule"), + resource.TestCheckResourceAttrSet("ibm_pi_network_security_group_rule.network_security_group_rule", power.Arg_NetworkSecurityGroupID), + ), + }, + }, + }) +} + +func TestAccIBMPINetworkSecurityGroupRuleTCP(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPINetworkSecurityGroupRuleConfigAddRuleTCP(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMPINetworkSecurityGroupRuleExists("ibm_pi_network_security_group_rule.network_security_group_rule"), + resource.TestCheckResourceAttrSet("ibm_pi_network_security_group_rule.network_security_group_rule", power.Arg_NetworkSecurityGroupID), + ), + }, + }, + }) +} + +func TestAccIBMPINetworkSecurityGroupRuleRemove(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPINetworkSecurityGroupRuleConfigRemoveRule(), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMPINetworkSecurityGroupRuleRemoved("ibm_pi_network_security_group_rule.network_security_group_rule", acc.Pi_network_security_group_rule_id), + resource.TestCheckResourceAttrSet("ibm_pi_network_security_group_rule.network_security_group_rule", power.Arg_NetworkSecurityGroupID), + ), + }, + }, + }) +} + +func testAccCheckIBMPINetworkSecurityGroupRuleConfigAddRule() string { + return fmt.Sprintf(` + resource "ibm_pi_network_security_group_rule" "network_security_group_rule" { + pi_cloud_instance_id = "%[1]s" + pi_network_security_group_id = "%[2]s" + pi_action = "allow" + pi_protocol { + type = "all" + } + pi_remote { + id = "%[3]s" + type = "%[4]s" + } + }`, acc.Pi_cloud_instance_id, acc.Pi_network_security_group_id, acc.Pi_remote_id, acc.Pi_remote_type) +} + +func testAccCheckIBMPINetworkSecurityGroupRuleConfigAddRuleTCP() string { + return fmt.Sprintf(` + resource "ibm_pi_network_security_group_rule" "network_security_group_rule" { + pi_cloud_instance_id = "%[1]s" + pi_network_security_group_id = "%[2]s" + pi_action = "allow" + pi_destination_ports { + minimum = 1200 + maximum = 37466 + } + pi_source_ports { + minimum = 1000 + maximum = 19500 + } + pi_protocol { + tcp_flags { + flag = "ack" + } + tcp_flags { + flag = "syn" + } + tcp_flags { + flag = "psh" + } + type = "tcp" + } + pi_remote { + id = "%[3]s" + type = "%[4]s" + } + }`, acc.Pi_cloud_instance_id, acc.Pi_network_security_group_id, acc.Pi_remote_id, acc.Pi_remote_type) +} + +func testAccCheckIBMPINetworkSecurityGroupRuleConfigRemoveRule() string { + return fmt.Sprintf(` + resource "ibm_pi_network_security_group_rule" "network_security_group_rule" { + pi_cloud_instance_id = "%[1]s" + pi_network_security_group_id = "%[2]s" + pi_network_security_group_rule_id = "%[3]s" + }`, acc.Pi_cloud_instance_id, acc.Pi_network_security_group_id, acc.Pi_network_security_group_rule_id) +} + +func testAccCheckIBMPINetworkSecurityGroupRuleExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Record ID is set") + } + sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession() + if err != nil { + return err + } + cloudInstanceID, nsgID, err := splitID(rs.Primary.ID) + if err != nil { + return err + } + nsgClient := instance.NewIBMIPINetworkSecurityGroupClient(context.Background(), sess, cloudInstanceID) + _, err = nsgClient.Get(nsgID) + if err != nil { + return err + } + return nil + } +} + +func testAccCheckIBMPINetworkSecurityGroupRuleRemoved(n string, ruleID string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Record ID is set") + } + sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession() + if err != nil { + return err + } + cloudInstanceID, nsgID, err := splitID(rs.Primary.ID) + if err != nil { + return err + } + nsgClient := instance.NewIBMIPINetworkSecurityGroupClient(context.Background(), sess, cloudInstanceID) + networkSecurityGroup, err := nsgClient.Get(nsgID) + if err != nil { + return err + } + foundRule := false + if networkSecurityGroup.Rules != nil { + for _, rule := range networkSecurityGroup.Rules { + if *rule.ID == ruleID { + foundRule = true + break + } + } + } + if foundRule { + return fmt.Errorf("NSG rule still exists") + } + return nil + } +} diff --git a/website/docs/r/pi_network_security_group_rule.html.markdown b/website/docs/r/pi_network_security_group_rule.html.markdown new file mode 100644 index 0000000000..376789a47b --- /dev/null +++ b/website/docs/r/pi_network_security_group_rule.html.markdown @@ -0,0 +1,136 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_pi_network_security_group_rule" +description: |- + Manages pi_network_security_group_rule. +subcategory: "Power Systems" +--- + +# ibm_pi_network_security_group_rule + +Add or remove a network security group rule. + +## Example Usage + +```terraform + resource "ibm_pi_network_security_group_rule" "network_security_group_rule" { + pi_cloud_instance_id = "" + pi_network_security_group_id = "" + pi_action = "allow" + pi_destination_ports { + minimum = 1200 + maximum = 37466 + } + pi_source_ports { + minimum = 1000 + maximum = 19500 + } + pi_protocol { + tcp_flags { + flag = "ack" + } + tcp_flags { + flag = "syn" + } + tcp_flags { + flag = "psh" + } + type = "tcp" + } + pi_remote { + id = "" + type = "network-security-group" + } + } +``` + +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` + +Example usage: + + ```terraform + provider "ibm" { + region = "lon" + zone = "lon04" + } + ``` + +## Argument Reference + +Review the argument references that you can specify for your resource. + +- `pi_action` - (Optional, String) The action to take if the rule matches network traffic. Supported values are: `allow`, `deny`. Required if `pi_network_security_group_rule_id` is not provided. +- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. +- `pi_destination_port` - (Optional, List) The list of destination port. + + Nested schema for `pi_destination_port`: + - `maximum` - (Optional, Int) The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number. + - `minimum` - (Optional, Int) The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number. +- `pi_network_security_group_id` - (Required, String) The unique identifier of the network security group. +- `pi_network_security_group_rule_id` - (Optional, String) The network security group rule id to remove. Required if none of the other optional fields are provided. +- `pi_protocol` - (Optional, List) The list of protocol. Required if `pi_network_security_group_rule_id` is not provided. + + Nested schema for `pi_protocol`: + - `icmp_type` - (Optional, String) If icmp type, a ICMP packet type affected by ICMP rules and if not present then all types are matched. Supported values are: `all`, `destination-unreach`, `echo`, `echo-reply`, `source-quench`, `time-exceeded`. + - `tcp_flags` - (Optional, String) If tcp type, the list of TCP flags and if not present then all flags are matched. Supported values are: `syn`, `ack`, `fin`, `rst`, `urg`, `psh`, `wnd`, `chk`, `seq`. + - `type` - (Required, String) The protocol of the network traffic. Supported values are: `icmp`, `tcp`, `udp`, `all`. +- `pi_remote` - (Optional, List) List of remote. Required if `pi_network_security_group_rule_id` is not provided. + + Nested schema for `pi_remote`: + - `id` - (Optional, String) The id of the remote network address group or network security group the rules apply to. Not required for default-network-address-group. + - `type` - (Optional, String) The type of remote group the rules apply to. Supported values are: `network-security-group`, `network-address-group`, `default-network-address-group`. +- `pi_source_port` - (Optional, List) List of source port + + Nested schema for `pi_source_port`: + - `maximum` - (Optional, Int) The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number. + - `minimum` - (Optional, Int) The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number. + +- `pi_name` - (Optional, String) The name of the network security group rule. Required if `pi_network_security_group_rule_id` is not provided. + +## Attribute Reference + +In addition to all argument reference list, you can access the following attribute reference after your resource is created. + +- `crn` - (String) The network security group's crn. + +- `members` - (List) The list of IPv4 addresses and\or network interfaces in the network security group. + + Nested schema for `members`: + - `id` - (String) The id of the member in a network security group. + - `mac_address` - (String) The mac address of a network interface included if the type is `network-interface`. + - `target` - (String) If `ipv4-address` type, then IPv4 address or if `network-interface` type, then network interface id. + - `type` - (String) The type of member. Supported values are: `ipv4-address`, `network-interface`. + +- `network_security_group_id` -(String) The unique identifier of the network security group. +- `rules` - (List) The list of rules in the network security group. + + Nested schema for `rules`: + - `action` - (String) The action to take if the rule matches network traffic. Supported values are: `allow`, `deny`. + - `destination_port` - (List) The list of destination port. + + Nested schema for `destination_port`: + - `maximum` - (Int) The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number. + - `minimum` - (Int) The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number. + - `id` - (String) The id of the rule in a network security group. + - `name` - (String) The unique name of the network security group rule. + - `protocol` - (List) The list of protocol. + + Nested schema for `protocol`: + - `icmp_type` - (String) If icmp type, a ICMP packet type affected by ICMP rules and if not present then all types are matched. Supported values are: `all`, `destination-unreach`, `echo`, `echo-reply`, `source-quench`, `time-exceeded`. + - `tcp_flags` - (String) If tcp type, the list of TCP flags and if not present then all flags are matched. Supported values are: `syn`, `ack`, `fin`, `rst`, `urg`, `psh`, `wnd`, `chk`, `seq`. + - `type` - (String) The protocol of the network traffic. Supported values are: `icmp`, `tcp`, `udp`, `all`. + - `remote` - (List) List of remote. + + Nested schema for `remote`: + - `id` - (String) The id of the remote network address group or network security group the rules apply to. Not required for default-network-address-group. + - `type` - (String) The type of remote group the rules apply to. Supported values are: `network-security-group`, `network-address-group`, `default-network-address-group`. + - `source_port` - (List) List of source port + + Nested schema for `source_port`: + - `maximum` - (Int) The end of the port range, if applicable. If the value is not present then the default value of 65535 will be the maximum port number. + - `minimum` - (Int) The start of the port range, if applicable. If the value is not present then the default value of 1 will be the minimum port number.