Skip to content

Commit

Permalink
NCC Producer VPC Spoke resource added (#11934) (#19806)
Browse files Browse the repository at this point in the history
[upstream:aef29d4aee109af32f440e86c90c241d0e4a91b3]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Oct 10, 2024
1 parent 9690942 commit 62800c0
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .changelog/11934.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
networkconnectivity: added `linked_producer_vpc_network` field to `google_network_connectivity_spoke` resource
```
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,55 @@ The only allowed value for now is "ALL_IPV4_RANGES".`,
},
},
},
ConflictsWith: []string{"linked_vpn_tunnels", "linked_router_appliance_instances", "linked_vpc_network"},
ConflictsWith: []string{"linked_vpn_tunnels", "linked_router_appliance_instances", "linked_vpc_network", "linked_producer_vpc_network"},
},
"linked_producer_vpc_network": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `Producer VPC network that is associated with the spoke.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"network": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
Description: `The URI of the Service Consumer VPC that the Producer VPC is peered with.`,
},
"peering": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The name of the VPC peering between the Service Consumer VPC and the Producer VPC (defined in the Tenant project) which is added to the NCC hub. This peering must be in ACTIVE state.`,
},
"exclude_export_ranges": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `IP ranges encompassing the subnets to be excluded from peering.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"include_export_ranges": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `IP ranges allowed to be included from peering.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"producer_network": {
Type: schema.TypeString,
Computed: true,
Description: `The URI of the Producer VPC.`,
},
},
},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_router_appliance_instances", "linked_vpn_tunnels", "linked_vpc_network"},
},
"linked_router_appliance_instances": {
Type: schema.TypeList,
Expand Down Expand Up @@ -173,7 +221,7 @@ The only allowed value for now is "ALL_IPV4_RANGES".`,
},
},
},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_vpn_tunnels", "linked_vpc_network"},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_vpn_tunnels", "linked_vpc_network", "linked_producer_vpc_network"},
},
"linked_vpc_network": {
Type: schema.TypeList,
Expand Down Expand Up @@ -210,7 +258,7 @@ The only allowed value for now is "ALL_IPV4_RANGES".`,
},
},
},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_router_appliance_instances", "linked_vpn_tunnels"},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_router_appliance_instances", "linked_vpn_tunnels", "linked_producer_vpc_network"},
},
"linked_vpn_tunnels": {
Type: schema.TypeList,
Expand Down Expand Up @@ -246,7 +294,7 @@ The only allowed value for now is "ALL_IPV4_RANGES".`,
},
},
},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_router_appliance_instances", "linked_vpc_network"},
ConflictsWith: []string{"linked_interconnect_attachments", "linked_router_appliance_instances", "linked_vpc_network", "linked_producer_vpc_network"},
},
"create_time": {
Type: schema.TypeString,
Expand Down Expand Up @@ -343,6 +391,12 @@ func resourceNetworkConnectivitySpokeCreate(d *schema.ResourceData, meta interfa
} else if v, ok := d.GetOkExists("linked_vpc_network"); !tpgresource.IsEmptyValue(reflect.ValueOf(linkedVpcNetworkProp)) && (ok || !reflect.DeepEqual(v, linkedVpcNetworkProp)) {
obj["linkedVpcNetwork"] = linkedVpcNetworkProp
}
linkedProducerVpcNetworkProp, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetwork(d.Get("linked_producer_vpc_network"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("linked_producer_vpc_network"); !tpgresource.IsEmptyValue(reflect.ValueOf(linkedProducerVpcNetworkProp)) && (ok || !reflect.DeepEqual(v, linkedProducerVpcNetworkProp)) {
obj["linkedProducerVpcNetwork"] = linkedProducerVpcNetworkProp
}
labelsProp, err := expandNetworkConnectivitySpokeEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -478,6 +532,9 @@ func resourceNetworkConnectivitySpokeRead(d *schema.ResourceData, meta interface
if err := d.Set("linked_vpc_network", flattenNetworkConnectivitySpokeLinkedVpcNetwork(res["linkedVpcNetwork"], d, config)); err != nil {
return fmt.Errorf("Error reading Spoke: %s", err)
}
if err := d.Set("linked_producer_vpc_network", flattenNetworkConnectivitySpokeLinkedProducerVpcNetwork(res["linkedProducerVpcNetwork"], d, config)); err != nil {
return fmt.Errorf("Error reading Spoke: %s", err)
}
if err := d.Set("unique_id", flattenNetworkConnectivitySpokeUniqueId(res["uniqueId"], d, config)); err != nil {
return fmt.Errorf("Error reading Spoke: %s", err)
}
Expand Down Expand Up @@ -835,6 +892,47 @@ func flattenNetworkConnectivitySpokeLinkedVpcNetworkIncludeExportRanges(v interf
return v
}

func flattenNetworkConnectivitySpokeLinkedProducerVpcNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["network"] =
flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkNetwork(original["network"], d, config)
transformed["peering"] =
flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkPeering(original["peering"], d, config)
transformed["producer_network"] =
flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkProducerNetwork(original["producerNetwork"], d, config)
transformed["include_export_ranges"] =
flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkIncludeExportRanges(original["includeExportRanges"], d, config)
transformed["exclude_export_ranges"] =
flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkExcludeExportRanges(original["excludeExportRanges"], d, config)
return []interface{}{transformed}
}
func flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkPeering(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkProducerNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkIncludeExportRanges(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenNetworkConnectivitySpokeLinkedProducerVpcNetworkExcludeExportRanges(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenNetworkConnectivitySpokeUniqueId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
Expand Down Expand Up @@ -1087,6 +1185,73 @@ func expandNetworkConnectivitySpokeLinkedVpcNetworkIncludeExportRanges(v interfa
return v, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedNetwork, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetworkNetwork(original["network"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["network"] = transformedNetwork
}

transformedPeering, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetworkPeering(original["peering"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedPeering); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["peering"] = transformedPeering
}

transformedProducerNetwork, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetworkProducerNetwork(original["producer_network"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedProducerNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["producerNetwork"] = transformedProducerNetwork
}

transformedIncludeExportRanges, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetworkIncludeExportRanges(original["include_export_ranges"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedIncludeExportRanges); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["includeExportRanges"] = transformedIncludeExportRanges
}

transformedExcludeExportRanges, err := expandNetworkConnectivitySpokeLinkedProducerVpcNetworkExcludeExportRanges(original["exclude_export_ranges"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedExcludeExportRanges); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["excludeExportRanges"] = transformedExcludeExportRanges
}

return transformed, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetworkNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetworkPeering(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetworkProducerNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetworkIncludeExportRanges(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkConnectivitySpokeLinkedProducerVpcNetworkExcludeExportRanges(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkConnectivitySpokeEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,86 @@ resource "google_network_connectivity_spoke" "primary" {
`, context)
}

func TestAccNetworkConnectivitySpoke_networkConnectivitySpokeLinkedProducerVpcNetworkBasicExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckNetworkConnectivitySpokeDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccNetworkConnectivitySpoke_networkConnectivitySpokeLinkedProducerVpcNetworkBasicExample(context),
},
{
ResourceName: "google_network_connectivity_spoke.primary",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"hub", "labels", "location", "terraform_labels"},
},
},
})
}

func testAccNetworkConnectivitySpoke_networkConnectivitySpokeLinkedProducerVpcNetworkBasicExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_compute_network" "network" {
name = "tf-test-net-spoke%{random_suffix}"
auto_create_subnetworks = false
}
resource "google_compute_global_address" "address" {
name = "tf-test-test-address%{random_suffix}"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = google_compute_network.network.id
}
resource "google_service_networking_connection" "peering" {
network = google_compute_network.network.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.address.name]
}
resource "google_network_connectivity_hub" "basic_hub" {
name = "tf-test-hub-basic%{random_suffix}"
}
resource "google_network_connectivity_spoke" "linked_vpc_spoke" {
name = "tf-test-vpc-spoke%{random_suffix}"
location = "global"
hub = google_network_connectivity_hub.basic_hub.id
linked_vpc_network {
uri = google_compute_network.network.self_link
}
}
resource "google_network_connectivity_spoke" "primary" {
name = "tf-test-producer-spoke%{random_suffix}"
location = "global"
description = "A sample spoke with a linked router appliance instance"
labels = {
label-one = "value-one"
}
hub = google_network_connectivity_hub.basic_hub.id
linked_producer_vpc_network {
network = google_compute_network.network.name
peering = google_service_networking_connection.peering.peering
exclude_export_ranges = [
"198.51.100.0/24",
"10.10.0.0/16"
]
}
depends_on = [google_network_connectivity_spoke.linked_vpc_spoke]
}
`, context)
}

func testAccCheckNetworkConnectivitySpokeDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
Expand Down
Loading

0 comments on commit 62800c0

Please sign in to comment.