Repository: hetznercloud/hcloud-go
Pull request #271 (2023-06-15 13:02:09)

deps: update golangci/golangci-lint docker tag to v1.53.3
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| golangci/golangci-lint | image | patch | `v1.53.2` -> `v1.53.3` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/hetznercloud/hcloud-go).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS4xMTcuMyIsInVwZGF0ZWRJblZlciI6IjM1LjEzMS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->



Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2cbf73f..f848f02 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ variables:
 
 test:golangci-lint:
   stage: test
-  image: golangci/golangci-lint:v1.53.2
+  image: golangci/golangci-lint:v1.53.3
   script:
     - golangci-lint run -v
   except:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 168fa65..47c52e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## [1.46.1](https://github.com/hetznercloud/hcloud-go/compare/v1.46.0...v1.46.1) (2023-06-16)
+
+
+### Bug Fixes
+
+* adjust label validation for max length of 63 characters ([#273](https://github.com/hetznercloud/hcloud-go/issues/273)) ([6382808](https://github.com/hetznercloud/hcloud-go/commit/63828086e89413115f4f5ee326835f93752cbb51))
+* **deps:** update module golang.org/x/net to v0.11.0 ([#258](https://github.com/hetznercloud/hcloud-go/issues/258)) ([7918f21](https://github.com/hetznercloud/hcloud-go/commit/7918f2172ac000f72a6ed52a2c69ae03c7b6513f))
+
 ## [1.46.0](https://github.com/hetznercloud/hcloud-go/compare/v1.45.1...v1.46.0) (2023-06-13)
 
 
diff --git a/go.mod b/go.mod
index 1b8670f..6eb3837 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
 require (
 	github.com/google/go-cmp v0.5.9
 	github.com/prometheus/client_golang v1.15.1
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.4
 	golang.org/x/net v0.11.0
 )
 
diff --git a/go.sum b/go.sum
index beea5ed..6a17b17 100644
--- a/go.sum
+++ b/go.sum
@@ -225,6 +225,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/hcloud/hcloud.go b/hcloud/hcloud.go
index 7a45724..bc4bcba 100644
--- a/hcloud/hcloud.go
+++ b/hcloud/hcloud.go
@@ -2,4 +2,4 @@
 package hcloud
 
 // Version is the library's version following Semantic Versioning.
-const Version = "1.46.0" // x-release-please-version
+const Version = "1.46.1" // x-release-please-version
diff --git a/hcloud/labels.go b/hcloud/labels.go
index e22000a..3dc7d78 100644
--- a/hcloud/labels.go
+++ b/hcloud/labels.go
@@ -6,8 +6,8 @@ import (
 )
 
 var keyRegexp = regexp.MustCompile(
-	`^([a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]){0,253}[a-z0-9A-Z])?/)?[a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]|){0,62}[a-z0-9A-Z])?$`)
-var valueRegexp = regexp.MustCompile(`^(([a-z0-9A-Z](?:[\-_.]|[a-z0-9A-Z]){0,62})?[a-z0-9A-Z]$|$)`)
+	`^([a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]){0,253}[a-z0-9A-Z])?/)?[a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]|){0,61}[a-z0-9A-Z])?$`)
+var valueRegexp = regexp.MustCompile(`^(([a-z0-9A-Z](?:[\-_.]|[a-z0-9A-Z]){0,61})?[a-z0-9A-Z]$|$)`)
 
 func ValidateResourceLabels(labels map[string]interface{}) (bool, error) {
 	for k, v := range labels {
diff --git a/hcloud/network.go b/hcloud/network.go
index 5a19681..cf85a55 100644
--- a/hcloud/network.go
+++ b/hcloud/network.go
@@ -45,6 +45,9 @@ type Network struct {
 	Servers    []*Server
 	Protection NetworkProtection
 	Labels     map[string]string
+
+	// ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection.
+	ExposeRoutesToVSwitch bool
 }
 
 // NetworkSubnet represents a subnet of a network in the Hetzner Cloud.
@@ -190,6 +193,9 @@ func (c *NetworkClient) Delete(ctx context.Context, network *Network) (*Response
 type NetworkUpdateOpts struct {
 	Name   string
 	Labels map[string]string
+	// ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection.
+	// The exposing only takes effect if a vSwitch connection is active.
+	ExposeRoutesToVSwitch *bool
 }
 
 // Update updates a network.
@@ -200,6 +206,10 @@ func (c *NetworkClient) Update(ctx context.Context, network *Network, opts Netwo
 	if opts.Labels != nil {
 		reqBody.Labels = &opts.Labels
 	}
+	if opts.ExposeRoutesToVSwitch != nil {
+		reqBody.ExposeRoutesToVSwitch = opts.ExposeRoutesToVSwitch
+	}
+
 	reqBodyData, err := json.Marshal(reqBody)
 	if err != nil {
 		return nil, nil, err
@@ -226,6 +236,9 @@ type NetworkCreateOpts struct {
 	Subnets []NetworkSubnet
 	Routes  []NetworkRoute
 	Labels  map[string]string
+	// ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection.
+	// The exposing only takes effect if a vSwitch connection is active.
+	ExposeRoutesToVSwitch bool
 }
 
 // Validate checks if options are valid.
@@ -245,8 +258,9 @@ func (c *NetworkClient) Create(ctx context.Context, opts NetworkCreateOpts) (*Ne
 		return nil, nil, err
 	}
 	reqBody := schema.NetworkCreateRequest{
-		Name:    opts.Name,
-		IPRange: opts.IPRange.String(),
+		Name:                  opts.Name,
+		IPRange:               opts.IPRange.String(),
+		ExposeRoutesToVSwitch: opts.ExposeRoutesToVSwitch,
 	}
 	for _, subnet := range opts.Subnets {
 		s := schema.NetworkSubnet{
diff --git a/hcloud/schema.go b/hcloud/schema.go
index c76d7de..f4a9366 100644
--- a/hcloud/schema.go
+++ b/hcloud/schema.go
@@ -403,7 +403,8 @@ func NetworkFromSchema(s schema.Network) *Network {
 		Protection: NetworkProtection{
 			Delete: s.Protection.Delete,
 		},
-		Labels: map[string]string{},
+		Labels:                map[string]string{},
+		ExposeRoutesToVSwitch: s.ExposeRoutesToVSwitch,
 	}
 
 	_, n.IPRange, _ = net.ParseCIDR(s.IPRange)
diff --git a/hcloud/schema/network.go b/hcloud/schema/network.go
index 87e184d..56bcbea 100644
--- a/hcloud/schema/network.go
+++ b/hcloud/schema/network.go
@@ -4,15 +4,16 @@ import "time"
 
 // Network defines the schema of a network.
 type Network struct {
-	ID         int               `json:"id"`
-	Name       string            `json:"name"`
-	Created    time.Time         `json:"created"`
-	IPRange    string            `json:"ip_range"`
-	Subnets    []NetworkSubnet   `json:"subnets"`
-	Routes     []NetworkRoute    `json:"routes"`
-	Servers    []int             `json:"servers"`
-	Protection NetworkProtection `json:"protection"`
-	Labels     map[string]string `json:"labels"`
+	ID                    int               `json:"id"`
+	Name                  string            `json:"name"`
+	Created               time.Time         `json:"created"`
+	IPRange               string            `json:"ip_range"`
+	Subnets               []NetworkSubnet   `json:"subnets"`
+	Routes                []NetworkRoute    `json:"routes"`
+	Servers               []int             `json:"servers"`
+	Protection            NetworkProtection `json:"protection"`
+	Labels                map[string]string `json:"labels"`
+	ExposeRoutesToVSwitch bool              `json:"expose_routes_to_vswitch"`
 }
 
 // NetworkSubnet represents a subnet of a network.
@@ -37,8 +38,9 @@ type NetworkProtection struct {
 
 // NetworkUpdateRequest defines the schema of the request to update a network.
 type NetworkUpdateRequest struct {
-	Name   string             `json:"name,omitempty"`
-	Labels *map[string]string `json:"labels,omitempty"`
+	Name                  string             `json:"name,omitempty"`
+	Labels                *map[string]string `json:"labels,omitempty"`
+	ExposeRoutesToVSwitch *bool              `json:"expose_routes_to_vswitch,omitempty"`
 }
 
 // NetworkUpdateResponse defines the schema of the response when updating a network.
@@ -60,11 +62,12 @@ type NetworkGetResponse struct {
 
 // NetworkCreateRequest defines the schema of the request to create a network.
 type NetworkCreateRequest struct {
-	Name    string             `json:"name"`
-	IPRange string             `json:"ip_range"`
-	Subnets []NetworkSubnet    `json:"subnets,omitempty"`
-	Routes  []NetworkRoute     `json:"routes,omitempty"`
-	Labels  *map[string]string `json:"labels,omitempty"`
+	Name                  string             `json:"name"`
+	IPRange               string             `json:"ip_range"`
+	Subnets               []NetworkSubnet    `json:"subnets,omitempty"`
+	Routes                []NetworkRoute     `json:"routes,omitempty"`
+	Labels                *map[string]string `json:"labels,omitempty"`
+	ExposeRoutesToVSwitch bool               `json:"expose_routes_to_vswitch"`
 }
 
 // NetworkCreateResponse defines the schema of the response when
diff --git a/renovate.json b/renovate.json
deleted file mode 100644
index 39a2b6e..0000000
--- a/renovate.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
-  "extends": [
-    "config:base"
-  ]
-}
diff --git a/renovate.json5 b/renovate.json5
new file mode 100644
index 0000000..5dca7dc
--- /dev/null
+++ b/renovate.json5
@@ -0,0 +1,11 @@
+{
+  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+  "extends": [
+    "config:base",
+
+    // Generate commits compatible with release-please changelog
+    // => "deps: update module github.com/prometheus/client_golang to v1.15.1"
+    ":semanticCommitTypeAll(deps)",
+    ":semanticCommitScopeDisabled"
+  ]
+}


Test patch:
diff --git a/hcloud/labels_test.go b/hcloud/labels_test.go
index 0c43d7f..48ffe40 100644
--- a/hcloud/labels_test.go
+++ b/hcloud/labels_test.go
@@ -29,6 +29,7 @@ func TestCheckLabels(t *testing.T) {
 			"incorrect.com-",
 			"incorr,ect.com-",
 			"incorrect-111111111111111111111111111111111111111111111111111111111111.com",
+			"63-characters-are-allowed-in-a-label__this-is-one-character-more",
 		}
 
 		for _, label := range incorrectLabels {
diff --git a/hcloud/network_test.go b/hcloud/network_test.go
index d5f5d00..b06f334 100644
--- a/hcloud/network_test.go
+++ b/hcloud/network_test.go
@@ -213,6 +213,36 @@ func TestNetworkCreate(t *testing.T) {
 			t.Fatal(err)
 		}
 	})
+
+	t.Run("optional fields", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/networks", func(w http.ResponseWriter, r *http.Request) {
+			var reqBody schema.NetworkCreateRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if reqBody.ExposeRoutesToVSwitch != true {
+				t.Errorf("unexpected ExposeRoutesToVSwitch: %v", reqBody.ExposeRoutesToVSwitch)
+			}
+
+			json.NewEncoder(w).Encode(schema.NetworkCreateResponse{
+				Network: schema.Network{
+					ID: 1,
+				},
+			})
+		})
+		opts := NetworkCreateOpts{
+			Name:                  "my-network",
+			IPRange:               ipRange,
+			ExposeRoutesToVSwitch: true,
+		}
+		_, _, err := env.Client.Network.Create(ctx, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+	})
 }
 
 func TestNetworkDelete(t *testing.T) {
@@ -245,7 +275,7 @@ func TestNetworkClientUpdate(t *testing.T) {
 			if r.Method != "PUT" {
 				t.Error("expected PUT")
 			}
-			var reqBody schema.ServerUpdateRequest
+			var reqBody schema.NetworkUpdateRequest
 			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
 				t.Fatal(err)
 			}
@@ -280,7 +310,7 @@ func TestNetworkClientUpdate(t *testing.T) {
 			if r.Method != "PUT" {
 				t.Error("expected PUT")
 			}
-			var reqBody schema.ServerUpdateRequest
+			var reqBody schema.NetworkUpdateRequest
 			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
 				t.Fatal(err)
 			}
@@ -307,6 +337,41 @@ func TestNetworkClientUpdate(t *testing.T) {
 		}
 	})
 
+	t.Run("update expose routes to vswitch", func(t *testing.T) {
+		env := newTestEnv()
+		defer env.Teardown()
+
+		env.Mux.HandleFunc("/networks/1", func(w http.ResponseWriter, r *http.Request) {
+			if r.Method != "PUT" {
+				t.Error("expected PUT")
+			}
+			var reqBody schema.NetworkUpdateRequest
+			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
+				t.Fatal(err)
+			}
+			if reqBody.ExposeRoutesToVSwitch == nil || *reqBody.ExposeRoutesToVSwitch != true {
+				t.Errorf("unexpected field in request: %v", reqBody.ExposeRoutesToVSwitch)
+			}
+			json.NewEncoder(w).Encode(schema.NetworkUpdateResponse{
+				Network: schema.Network{
+					ID: 1,
+				},
+			})
+		})
+
+		opts := NetworkUpdateOpts{
+			ExposeRoutesToVSwitch: Ptr(true),
+		}
+		updatedNetwork, _, err := env.Client.Network.Update(ctx, network, opts)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if updatedNetwork.ID != 1 {
+			t.Errorf("unexpected network ID: %v", updatedNetwork.ID)
+		}
+	})
+
 	t.Run("no updates", func(t *testing.T) {
 		env := newTestEnv()
 		defer env.Teardown()
@@ -315,7 +380,7 @@ func TestNetworkClientUpdate(t *testing.T) {
 			if r.Method != "PUT" {
 				t.Error("expected PUT")
 			}
-			var reqBody schema.ServerUpdateRequest
+			var reqBody schema.NetworkUpdateRequest
 			if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
 				t.Fatal(err)
 			}