Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type RobotClient interface {
ServerReverse(id int) (*models.Cancellation, error)
KeyGetList() ([]models.Key, error)
KeySet(input *models.KeySetInput) (*models.Key, error)
KeyDelete(fingerprint string) error
IPGetList() ([]models.IP, error)
RDnsGetList() ([]models.Rdns, error)
RDnsGet(ip string) (*models.Rdns, error)
Expand All @@ -28,4 +29,9 @@ type RobotClient interface {
ResetSet(id int, input *models.ResetSetInput) (*models.ResetPost, error)
FailoverGetList() ([]models.Failover, error)
FailoverGet(ip string) (*models.Failover, error)
VSwitchGetList() ([]models.VSwitch, error)
VSwitchGet(id int) (*models.VSwitch, error)
VSwitchCreate(input *models.VSwitchCreateInput) (*models.VSwitch, error)
VSwitchAddServer(vswitchID, serverNumber int) error
VSwitchRemoveServer(vswitchID, serverNumber int) error
}
9 changes: 9 additions & 0 deletions key.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,12 @@ func (c *Client) KeySet(input *models.KeySetInput) (*models.Key, error) {

return &keyResp.Key, nil
}

func (c *Client) KeyDelete(fingerprint string) error {
url := fmt.Sprintf(c.baseURL+"/key/%s", fingerprint)
_, err := c.doDeleteRequest(url)
if err != nil {
return err
}
return nil
}
47 changes: 47 additions & 0 deletions key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,50 @@ func (s *ClientSuite) TestKeySetSuccess(c *C) {
c.Assert(linux.Name, Equals, "NewKey")
c.Assert(linux.Data, Equals, "ssh-rsa AAAAB3NzaC1yc+...")
}

func (s *ClientSuite) TestKeyDeleteSuccess(c *C) {
testFingerprint := "fi:ng:er:pr:in:t0:00:00:00:00:00:00:00:00:00:00"
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c.Assert(r.Method, Equals, http.MethodDelete)
c.Assert(r.URL.Path, Equals, "/key/"+testFingerprint)
w.WriteHeader(http.StatusOK)
}))
defer ts.Close()

robotClient := client.NewBasicAuthClient("user", "pass")
robotClient.SetBaseURL(ts.URL)

err := robotClient.KeyDelete(testFingerprint)
c.Assert(err, IsNil)
}

func (s *ClientSuite) TestKeyDeleteNotFound(c *C) {
testFingerprint := "nonexistent:fingerprint"
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
_, err := w.Write([]byte(`{"error":{"status":404,"code":"NOT_FOUND","message":"SSH key not found"}}`))
c.Assert(err, IsNil)
}))
defer ts.Close()

robotClient := client.NewBasicAuthClient("user", "pass")
robotClient.SetBaseURL(ts.URL)

err := robotClient.KeyDelete(testFingerprint)
c.Assert(err, Not(IsNil))
}

func (s *ClientSuite) TestKeyDeleteServerError(c *C) {
testFingerprint := "fi:ng:er:pr:in:t0:00:00:00:00:00:00:00:00:00:00"
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer ts.Close()

robotClient := client.NewBasicAuthClient("user", "pass")
robotClient.SetBaseURL(ts.URL)

err := robotClient.KeyDelete(testFingerprint)
c.Assert(err, Not(IsNil))
}
46 changes: 46 additions & 0 deletions models/vswitch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package models

// VSwitchResponse wraps a single vSwitch response.
type VSwitchResponse struct {
VSwitch VSwitch `json:"vswitch"`
}

// VSwitch represents a Hetzner vSwitch.
type VSwitch struct {
ID int `json:"id"`
Name string `json:"name"`
Vlan int `json:"vlan"`
Cancelled bool `json:"cancelled"`
Server []VSwitchServer `json:"server,omitempty"`
Subnet []VSwitchSubnet `json:"subnet,omitempty"`
CloudNetwork []VSwitchCloudNet `json:"cloud_network,omitempty"`
}

// VSwitchServer represents a server attached to a vSwitch.
type VSwitchServer struct {
ServerIP string `json:"server_ip"`
ServerIPv6Net string `json:"server_ipv6_net"`
ServerNumber int `json:"server_number"`
Status string `json:"status"`
}

// VSwitchSubnet represents a subnet attached to a vSwitch.
type VSwitchSubnet struct {
IP string `json:"ip"`
Mask string `json:"mask"`
Gateway string `json:"gateway"`
}

// VSwitchCloudNet represents a cloud network attached to a vSwitch.
type VSwitchCloudNet struct {
ID int `json:"id"`
IP string `json:"ip"`
Mask int `json:"mask"`
Gateway string `json:"gateway"`
}

// VSwitchCreateInput is the input for creating a vSwitch.
type VSwitchCreateInput struct {
Name string `json:"name"`
VlanID int `json:"vlan"`
}
96 changes: 96 additions & 0 deletions vswitch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package client

import (
"encoding/json"
"fmt"
"net/http"
neturl "net/url"
"strconv"
"strings"

"github.com/syself/hrobot-go/models"
)

// VSwitchGetList returns all vSwitches.
func (c *Client) VSwitchGetList() ([]models.VSwitch, error) {
url := c.baseURL + "/vswitch"
bytes, err := c.doGetRequest(url)
if err != nil {
return nil, err
}

var vswitches []models.VSwitch
err = json.Unmarshal(bytes, &vswitches)
if err != nil {
return nil, err
}

return vswitches, nil
}

// VSwitchGet returns a vSwitch by ID.
func (c *Client) VSwitchGet(id int) (*models.VSwitch, error) {
url := fmt.Sprintf(c.baseURL+"/vswitch/%d", id)
bytes, err := c.doGetRequest(url)
if err != nil {
return nil, err
}

var vswitch models.VSwitch
err = json.Unmarshal(bytes, &vswitch)
if err != nil {
return nil, err
}

return &vswitch, nil
}

// VSwitchCreate creates a new vSwitch.
func (c *Client) VSwitchCreate(input *models.VSwitchCreateInput) (*models.VSwitch, error) {
url := c.baseURL + "/vswitch"

formData := neturl.Values{}
formData.Set("name", input.Name)
formData.Set("vlan", strconv.Itoa(input.VlanID))

bytes, err := c.doPostFormRequest(url, formData)
if err != nil {
return nil, err
}

var vswitch models.VSwitch
err = json.Unmarshal(bytes, &vswitch)
if err != nil {
return nil, err
}

return &vswitch, nil
}

// VSwitchAddServer adds a server to a vSwitch.
func (c *Client) VSwitchAddServer(vswitchID, serverNumber int) error {
url := fmt.Sprintf(c.baseURL+"/vswitch/%d/server", vswitchID)

formData := neturl.Values{}
formData.Add("server[]", strconv.Itoa(serverNumber))

_, err := c.doPostFormRequest(url, formData)
return err
}

// VSwitchRemoveServer removes a server from a vSwitch.
func (c *Client) VSwitchRemoveServer(vswitchID, serverNumber int) error {
url := fmt.Sprintf(c.baseURL+"/vswitch/%d/server", vswitchID)

formData := neturl.Values{}
formData.Add("server[]", strconv.Itoa(serverNumber))

req, err := http.NewRequest(http.MethodDelete, url, strings.NewReader(formData.Encode()))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

_, err = c.doRequest(req)
return err
}