Skip to content

Commit

Permalink
feat(network): add field expose_routes_to_vswitch (#277)
Browse files Browse the repository at this point in the history
Feature was released today.
  • Loading branch information
apricote committed Jun 21, 2023
1 parent a744f31 commit e73c52d
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 22 deletions.
18 changes: 16 additions & 2 deletions hcloud/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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{
Expand Down
71 changes: 68 additions & 3 deletions hcloud/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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()
Expand All @@ -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)
}
Expand Down
3 changes: 2 additions & 1 deletion hcloud/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
35 changes: 19 additions & 16 deletions hcloud/schema/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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
Expand Down

0 comments on commit e73c52d

Please sign in to comment.