Repository: cloudflare/cloudflare-go (go)

Issue:
Add vnet (virtual network) param for routes
### Current cloudflare-go version

v0.40.0

### Description

Hi team.

Need to extend [TunnelRoutes model](https://github.com/cloudflare/cloudflare-go/blob/b3795adaff979c172719bc524039a48e8b3f898d/tunnel_routes.go#L35) to include virtual network param.
This is blocking [this terraform feature request](https://github.com/cloudflare/terraform-provider-cloudflare/issues/1605).

Cloudflare CLI is already using it [here](https://github.com/cloudflare/cloudflared/blob/ec509e114a015cf191881611b3305e68bd8edd08/cfapi/ip_route.go#L80).




### Use cases

Cloudflared CLI is useless when you want to automate it with Terraform or Pulumi. We need to unblock this feature in terraform.

### Potential cloudflare-go usage

```go
-
```


### References

https://github.com/cloudflare/terraform-provider-cloudflare/issues/1605

Pull request:
Add vnet param to routes
## Description

I'm trying to build VPN for my company based on Cloudflare, but cloudflare terraform package is missing vnet param. I need to add it here first to update cloudflare terraform package.

## Has your change been tested?

Covered with unit tests. Have not tried to run it yet. But will run as soon as we merge it. Cloudlare has no docs for this yet. I tested in Insomnia that all calls work correctly.

## Types of changes

What sort of change does your code introduce/modify?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly. **How to do it??? Could you please give me the link when the docs are stored?**
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [ ] This change is using publicly documented (api.cloudflare.com or developers.cloudflare.com) and stable APIs. **It's not documented. But cloudflared CLI is already using it.**

Resolves #911 
Unblocks cloudflare/terraform-provider-cloudflare#1605


Patch:
diff --git a/tunnel_routes.go b/tunnel_routes.go
index 02103bb56..3ba73c789 100644
--- a/tunnel_routes.go
+++ b/tunnel_routes.go
@@ -19,47 +19,53 @@ var (
 
 // TunnelRoute is the full record for a route.
 type TunnelRoute struct {
-	Network    string     `json:"network"`
-	TunnelID   string     `json:"tunnel_id"`
-	TunnelName string     `json:"tunnel_name"`
-	Comment    string     `json:"comment"`
-	CreatedAt  *time.Time `json:"created_at"`
-	DeletedAt  *time.Time `json:"deleted_at"`
+	Network          string     `json:"network"`
+	TunnelID         string     `json:"tunnel_id"`
+	TunnelName       string     `json:"tunnel_name"`
+	Comment          string     `json:"comment"`
+	CreatedAt        *time.Time `json:"created_at"`
+	DeletedAt        *time.Time `json:"deleted_at"`
+	VirtualNetworkID string     `json:"virtual_network_id"`
 }
 
 type TunnelRoutesListParams struct {
-	AccountID       string     `url:"-"`
-	TunnelID        string     `url:"tunnel_id,omitempty"`
-	Comment         string     `url:"comment,omitempty"`
-	IsDeleted       *bool      `url:"is_deleted,omitempty"`
-	NetworkSubset   string     `url:"network_subset,omitempty"`
-	NetworkSuperset string     `url:"network_superset,omitempty"`
-	ExistedAt       *time.Time `url:"existed_at,omitempty"`
+	AccountID        string     `url:"-"`
+	TunnelID         string     `url:"tunnel_id,omitempty"`
+	Comment          string     `url:"comment,omitempty"`
+	IsDeleted        *bool      `url:"is_deleted,omitempty"`
+	NetworkSubset    string     `url:"network_subset,omitempty"`
+	NetworkSuperset  string     `url:"network_superset,omitempty"`
+	ExistedAt        *time.Time `url:"existed_at,omitempty"`
+	VirtualNetworkID string     `url:"virtual_network_id,omitempty"`
 	PaginationOptions
 }
 
 type TunnelRoutesCreateParams struct {
-	AccountID string `json:"-"`
-	Network   string `json:"-"`
-	TunnelID  string `json:"tunnel_id"`
-	Comment   string `json:"comment,omitempty"`
+	AccountID        string `json:"-"`
+	Network          string `json:"-"`
+	TunnelID         string `json:"tunnel_id"`
+	Comment          string `json:"comment,omitempty"`
+	VirtualNetworkID string `json:"virtual_network_id,omitempty"`
 }
 
 type TunnelRoutesUpdateParams struct {
-	AccountID string `json:"-"`
-	Network   string `json:"network"`
-	TunnelID  string `json:"tunnel_id"`
-	Comment   string `json:"comment,omitempty"`
+	AccountID        string `json:"-"`
+	Network          string `json:"network"`
+	TunnelID         string `json:"tunnel_id"`
+	Comment          string `json:"comment,omitempty"`
+	VirtualNetworkID string `json:"virtual_network_id,omitempty"`
 }
 
 type TunnelRoutesForIPParams struct {
-	AccountID string `json:"-"`
-	Network   string `json:"-"`
+	AccountID        string `url:"-"`
+	Network          string `url:"-"`
+	VirtualNetworkID string `url:"virtual_network_id,omitempty"`
 }
 
 type TunnelRoutesDeleteParams struct {
-	AccountID string `json:"-"`
-	Network   string `json:"-"`
+	AccountID        string `json:"-"`
+	Network          string `json:"-"`
+	VirtualNetworkID string `url:"virtual_network_id,omitempty"`
 }
 
 // tunnelRouteListResponse is the API response for listing tunnel routes.
@@ -112,7 +118,7 @@ func (api *API) GetTunnelRouteForIP(ctx context.Context, params TunnelRoutesForI
 		return TunnelRoute{}, ErrInvalidNetworkValue
 	}
 
-	uri := fmt.Sprintf("/%s/%s/teamnet/routes/ip/%s", AccountRouteRoot, params.AccountID, params.Network)
+	uri := buildURI(fmt.Sprintf("/%s/%s/teamnet/routes/ip/%s", AccountRouteRoot, params.AccountID, params.Network), params)
 
 	responseBody, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
 	if err != nil {


Test patch:
diff --git a/tunnel_routes_test.go b/tunnel_routes_test.go
index 13d7cb5fd..df6174a42 100644
--- a/tunnel_routes_test.go
+++ b/tunnel_routes_test.go
@@ -29,7 +29,8 @@ func TestListTunnelRoutes(t *testing.T) {
 				"tunnel_name": "blog",
 				"comment": "Example comment for this route",
 				"created_at": "2021-01-25T18:22:34.317854Z",
-				"deleted_at": "2021-01-25T18:22:34.317854Z"
+				"deleted_at": "2021-01-25T18:22:34.317854Z",
+				"virtual_network_id": "9f322de4-5988-4945-b770-f1d6ac200f86"
               }
             ]
           }`)
@@ -46,6 +47,7 @@ func TestListTunnelRoutes(t *testing.T) {
 			"Example comment for this route",
 			&ts,
 			&ts,
+			"9f322de4-5988-4945-b770-f1d6ac200f86",
 		},
 	}
 
@@ -74,7 +76,8 @@ func TestTunnelRouteForIP(t *testing.T) {
 			  "tunnel_name": "blog",
 			  "comment": "Example comment for this route",
 			  "created_at": "2021-01-25T18:22:34.317854Z",
-			  "deleted_at": "2021-01-25T18:22:34.317854Z"
+			  "deleted_at": "2021-01-25T18:22:34.317854Z",
+			  "virtual_network_id": "9f322de4-5988-4945-b770-f1d6ac200f86"
             }
           }`)
 	}
@@ -83,12 +86,13 @@ func TestTunnelRouteForIP(t *testing.T) {
 
 	ts, _ := time.Parse(time.RFC3339Nano, "2021-01-25T18:22:34.317854Z")
 	want := TunnelRoute{
-		Network:    "ff01::/32",
-		TunnelID:   "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
-		TunnelName: "blog",
-		Comment:    "Example comment for this route",
-		CreatedAt:  &ts,
-		DeletedAt:  &ts,
+		Network:          "ff01::/32",
+		TunnelID:         "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
+		TunnelName:       "blog",
+		Comment:          "Example comment for this route",
+		CreatedAt:        &ts,
+		DeletedAt:        &ts,
+		VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86",
 	}
 
 	got, err := client.GetTunnelRouteForIP(context.Background(), TunnelRoutesForIPParams{AccountID: testAccountID, Network: "10.1.0.137"})
@@ -115,7 +119,8 @@ func TestCreateTunnelRoute(t *testing.T) {
 			  "tunnel_name": "blog",
 			  "comment": "Example comment for this route",
 			  "created_at": "2021-01-25T18:22:34.317854Z",
-			  "deleted_at": "2021-01-25T18:22:34.317854Z"
+			  "deleted_at": "2021-01-25T18:22:34.317854Z",
+			  "virtual_network_id": "9f322de4-5988-4945-b770-f1d6ac200f86"
             }
           }`)
 	}
@@ -124,15 +129,16 @@ func TestCreateTunnelRoute(t *testing.T) {
 
 	ts, _ := time.Parse(time.RFC3339Nano, "2021-01-25T18:22:34.317854Z")
 	want := TunnelRoute{
-		Network:    "10.0.0.0/16",
-		TunnelID:   "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
-		TunnelName: "blog",
-		Comment:    "Example comment for this route",
-		CreatedAt:  &ts,
-		DeletedAt:  &ts,
+		Network:          "10.0.0.0/16",
+		TunnelID:         "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
+		TunnelName:       "blog",
+		Comment:          "Example comment for this route",
+		CreatedAt:        &ts,
+		DeletedAt:        &ts,
+		VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86",
 	}
 
-	tunnel, err := client.CreateTunnelRoute(context.Background(), TunnelRoutesCreateParams{AccountID: testAccountID, TunnelID: testTunnelID, Network: "10.0.0.0/16", Comment: "foo"})
+	tunnel, err := client.CreateTunnelRoute(context.Background(), TunnelRoutesCreateParams{AccountID: testAccountID, TunnelID: testTunnelID, Network: "10.0.0.0/16", Comment: "foo", VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86"})
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, tunnel)
 	}
@@ -161,23 +167,25 @@ func TestUpdateTunnelRoute(t *testing.T) {
 			  "tunnel_name": "blog",
 			  "comment": "Example comment for this route",
 			  "created_at": "2021-01-25T18:22:34.317854Z",
-			  "deleted_at": "2021-01-25T18:22:34.317854Z"
+			  "deleted_at": "2021-01-25T18:22:34.317854Z",
+			  "virtual_network_id": "9f322de4-5988-4945-b770-f1d6ac200f86"
             }
           }`)
 	}
 
 	ts, _ := time.Parse(time.RFC3339Nano, "2021-01-25T18:22:34.317854Z")
 	want := TunnelRoute{
-		Network:    "10.0.0.0/16",
-		TunnelID:   "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
-		TunnelName: "blog",
-		Comment:    "Example comment for this route",
-		CreatedAt:  &ts,
-		DeletedAt:  &ts,
+		Network:          "10.0.0.0/16",
+		TunnelID:         "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415",
+		TunnelName:       "blog",
+		Comment:          "Example comment for this route",
+		CreatedAt:        &ts,
+		DeletedAt:        &ts,
+		VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86",
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/teamnet/routes/network/10.0.0.0/16", handler)
-	tunnel, err := client.UpdateTunnelRoute(context.Background(), TunnelRoutesUpdateParams{AccountID: testAccountID, TunnelID: testTunnelID, Network: "10.0.0.0/16", Comment: "foo"})
+	tunnel, err := client.UpdateTunnelRoute(context.Background(), TunnelRoutesUpdateParams{AccountID: testAccountID, TunnelID: testTunnelID, Network: "10.0.0.0/16", Comment: "foo", VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86"})
 
 	if assert.NoError(t, err) {
 		assert.Equal(t, want, tunnel)
@@ -202,12 +210,13 @@ func TestDeleteTunnelRoute(t *testing.T) {
 			  "tunnel_name": "blog",
 			  "comment": "Example comment for this route",
 			  "created_at": "2021-01-25T18:22:34.317854Z",
-			  "deleted_at": "2021-01-25T18:22:34.317854Z"
+			  "deleted_at": "2021-01-25T18:22:34.317854Z",
+			  "virtual_network_id": "9f322de4-5988-4945-b770-f1d6ac200f86"
             }
           }`)
 	}
 
 	mux.HandleFunc("/accounts/"+testAccountID+"/teamnet/routes/network/10.0.0.0/16", handler)
-	err := client.DeleteTunnelRoute(context.Background(), TunnelRoutesDeleteParams{AccountID: testAccountID, Network: "10.0.0.0/16"})
+	err := client.DeleteTunnelRoute(context.Background(), TunnelRoutesDeleteParams{AccountID: testAccountID, Network: "10.0.0.0/16", VirtualNetworkID: "9f322de4-5988-4945-b770-f1d6ac200f86"})
 	assert.NoError(t, err)
 }