Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add peering feature to google_compute_network. #242

Closed
wants to merge 1 commit into from

Conversation

rosbo
Copy link
Contributor

@rosbo rosbo commented Jul 25, 2017

issue #178

I added a few comments on my own PR to ask for the opinions of the reviewers on a few things

cc/ @danawillow @rileykarson

@rosbo rosbo requested review from danawillow and rileykarson July 25, 2017 22:34
Type: schema.TypeString,
Required: true,
ValidateFunc: validateRegexp(peerNetworkLinkRegex),
DiffSuppressFunc: peerNetworkLinkDiffSuppress,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could achieve the same thing by using a StateFunc that always saves the value to a canonical format. Any preferences?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no preferences here personally. I think that we could migrate between the two at will without even using a MigrateFunc if we ever wanted to, too.

)

const peerNetworkLinkRegex = "projects/(" + projectRegex + ")/global/networks/((?:[a-z](?:[-a-z0-9]*[a-z0-9])?))$"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the peer network, full URL and partial URL are supported:

  1. https://www.googleapis.com/compute/v1/projects/my-project/global/networks/network-1 OK
  2. projects/my-project/global/networks/network-1 OK
  3. global/networks/network-1 ACCEPTED by GCP but REJECTED by my implementation
  4. network-1 WRONG

The reason why I am rejecting (3) even though GCP considers it valid is because I can't properly detect changes if I don't require the project in the URL. GCP, if the project is missing from the URL uses the default project.

If I have this configuration:

resource "google_compute_network" "default" {
  name = "default"  

  peering {
    name = "foo"
    network = "global/networks/other-network"
  }
}

After the first terraform apply, the network is created and the peering.0.network field containshttps://www.googleapis.com/compute/v1/projects/my-project/global/networks/other-network (this value is read from the GCP and GCP always return a full url.

If I call terraform plan. I should not see a diff. However, I have the following two strings for the network field:

  • old https://www.googleapis.com/compute/v1/projects/my-project/global/networks/other-network
  • new global/networks/other-network
    I could suppress the diff by only comparing the network name. However, this would introduce a new bug, if I change the network from /my-project/global/networks/other-network to ANOTHER-PROJECT/global/networks/other-network, I would detect the diff because both network have the same name.

If I try using the StateFunc, I don't have access to the current project in a StateFunc in order to transform global/networks/other-network to its canonical form.

Anybody have a solution for this?
Or are we fine with not supporting the "project-less" version. This is a new field so we are not breaking anybody. We are only forcing them to be more explicit from the start.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'm OK with only accepting the first two forms. Terraform self links will always be using full or relative partial URLs, and while omitting the project is a nice shorthand, it's information that users will always have.

I'd be interested if we could file/bump an issue against Terraform itself for getting more information inside a StateFunc/DiffSuppressFunc; if we knew the project in either, we could allow the shorthand as well.

Copy link
Collaborator

@rileykarson rileykarson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good! I want to make it more clear in tests/the example in the docs that peering requires both networks to opt-in, and have a few minor nits otherwise.

@@ -6,6 +6,8 @@ import (
"regexp"
)

const projectRegex = "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Let's use a capital P here as if this variable was exported. We are in the same google package as the rest of the provider so it's not a necessary change, but imo it makes it more clear that the value comes from another file when used.


The `peering` block supports:

* `name` - (Required) Name of the peering.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Add a new line between each attribute.

@@ -71,6 +71,38 @@ func TestAccComputeNetwork_custom_subnet(t *testing.T) {
})
}

func TestAccComputeNetwork_peering(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of these test cases handle one network requesting a peering with the other, but these networks won't connect since each network has to define the peering. Can we add a test that successfully sets up a peered network?

We'll probably need to define subnetworks with different CIDR rules to do that instead of automatically creating them, since their IP ranges can't overlap; I connected two networks in the Cloud Console using 192.168.0.0/24 and 10.0.0.0/9 if I remember right.


d.Partial(true)

if d.HasChange("peering") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a lot of code dedicated to working with changing a set of peerings, but our tests only have 1 or 0 on each network. Let's test that code by adding a test that has several peerings, and updates keeping some but removing/adding others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, since I am changing the name of the peering, it does one add and one remove. I will add more coverage though. One problem is that I can't add more than 3 networks because by default, GCD account have a default network and a cap of 5 on the maximum number of networks. I like to leave at least one open to be able to allow some level of manual testing while my test run.

return add, remove
}

func addPeering(config *Config, project, network string, add []map[string]interface{}) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/addPeering/addPeerings

old, new := d.GetChange("peering")
add, remove := calcAddRemoveNetworkPeerings(old, new)

if len(remove) > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's factor this out into removePeerings as well, to mirror addPeering

)

const peerNetworkLinkRegex = "projects/(" + projectRegex + ")/global/networks/((?:[a-z](?:[-a-z0-9]*[a-z0-9])?))$"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'm OK with only accepting the first two forms. Terraform self links will always be using full or relative partial URLs, and while omitting the project is a nice shorthand, it's information that users will always have.

I'd be interested if we could file/bump an issue against Terraform itself for getting more information inside a StateFunc/DiffSuppressFunc; if we knew the project in either, we could allow the shorthand as well.

Type: schema.TypeString,
Required: true,
ValidateFunc: validateRegexp(peerNetworkLinkRegex),
DiffSuppressFunc: peerNetworkLinkDiffSuppress,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no preferences here personally. I think that we could migrate between the two at will without even using a MigrateFunc if we ever wanted to, too.

@@ -17,6 +17,16 @@ resource "google_compute_network" "default" {
name = "foobar"
auto_create_subnetworks = "true"
}

resource "google_compute_network" "other" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with the tests - let's make this example a valid network peering.

If we can have one network automatically create subnetworks and we manually define them for another & manage to peer successfully, we'd be able to show even more of how to use this resource to readers.

* `network` - (Required) Resource link of the peer network.
* `auto_create_routes` - (Optional) If set to true, the routes between the two networks will
be created and managed automatically.
* `state` - (Computed) State for the peering.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output-only attributes typically live under Attributes Reference, but I'm not sure exactly what it should look like because these are part of the peering block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, when I wrote these I wasn't sure where to put it because it is part of the peering block. @danawillow any preference?

@rosbo
Copy link
Contributor Author

rosbo commented Jul 26, 2017

After thinking more about it and also discussing with Riley, it may makes more sense to have the vpc peering feature be its own resource.

One problem comes with circular dependency when creating peer network:

resource "google_compute_network" "network1" {
  name = "network-1" 

  auto_create_subnetworks = false

  peering {
    name = "one-two-peering"
    # Error: cycle network1 depends on network2 and vice versa
    network = "${google_compute_network.network2.self_link}"
  } 
}

resource "google_compute_network" "network2" {
  name = "network-2"  

  auto_create_subnetworks = false

  peering {
    name = "one-two-peering"
    # Error: cycle network1 depends on network2 and vice versa
    network = "${google_compute_network.network1.self_link}"
  }
}

To go around this a user must set manually (w/o interpolations) the self link:

peering {
    name = "one-two-peering"
    network = "https://www.googleapis.com/compute/v1/projects/rosbo-personal/global/networks/network-2"
 } 

If we create a separate resource for peering. The config would look like:

resource "google_compute_network" "network1" {
  name = "network-1" 
  auto_create_subnetworks = false
}

resource "google_compute_network" "network2" {
  name = "network-2" 
  auto_create_subnetworks = false
}

resource "google_compute_network_peering" "peering1-2" {
   name = "one-two-peering"
   network = "${google_compute_network.network1.self_link}"
   peer_network = "${google_compute_network.network2.self_link}"
}

resource "google_compute_network_peering" "peering2-1" {
   name = "one-two-peering"
   network = "${google_compute_network.network2.self_link}"
   peer_network = "${google_compute_network.network1.self_link}"
}

And alternative for the google_compute_network_peering resource would be to support bidirectionality. This way, we remove the need for creating two peering resources.

resource "google_compute_network_peering" "peering" {
   name = "one-two-peering"
   network = "${google_compute_network.network2.self_link}"
   peer_network = "${google_compute_network.network1.self_link}"
   bidirectional = true  # Defaults to false. False means only a peering from `network` to `peer_network` is created.
}

@danawillow Any thoughts?

@rosbo
Copy link
Contributor Author

rosbo commented Jul 27, 2017

Closed in favor of #259 using more fine grained resources.

@rosbo rosbo closed this Jul 27, 2017
luis-silva pushed a commit to luis-silva/terraform-provider-google that referenced this pull request May 21, 2019
@ghost
Copy link

ghost commented Mar 31, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks!

@ghost ghost locked and limited conversation to collaborators Mar 31, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants