Skip to content

Commit

Permalink
handle inconsistent API responses for servers
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesClonk committed Jul 7, 2015
1 parent dae01a7 commit aacf00e
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 6 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ Everybody likes screenshots, even of command line tools.. :smile:
* Place the **vultr** binary somewhere into your PATH
* Export your Vultr API key into a VULTR_API_KEY env variable. You can get the API key from the [admin panel](https://my.vultr.com/settings)
```sh
$ export VULTR_API_KEY=89dFbb91rGjkL/12zJEQxS
$ export VULTR_API_KEY=87dFbC91rJjkL/18zJEQxS
```
* Run it
```sh
$ vultr version
Client version: v1.3
Client version: v1.4
Vultr API endpoint: https://api.vultr.com/
Vultr API version: v1
OS/Arch (client): linux/amd64
Expand All @@ -46,7 +46,7 @@ $ export VULTR_API_KEY=89dFbb91rGjkL/12zJEQxS
* Run it
```sh
$ vultr version
Client version: v1.3
Client version: v1.4
Vultr API endpoint: https://api.vultr.com/
Vultr API version: v1
OS/Arch (client): linux/amd64
Expand Down
2 changes: 1 addition & 1 deletion lib/account_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Client) GetAccountInfo() (info AccountInfo, err error) {
return
}

// UnmarshalJSON implements json.Unmarshaller.
// UnmarshalJSON implements json.Unmarshaller on AccountInfo.
// This is needed because the Vultr API is inconsistent in it's JSON responses for account info.
// Some fields can changed type, from JSON number to JSON string and vice-versa.
func (a *AccountInfo) UnmarshalJSON(data []byte) (err error) {
Expand Down
2 changes: 1 addition & 1 deletion lib/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

const (
// Version of this libary
Version = "v1.3"
Version = "v1.4"

// APIVersion of Vultr
APIVersion = "v1"
Expand Down
99 changes: 99 additions & 0 deletions lib/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package lib

import (
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strconv"
)

// Server (virtual machine) on Vultr account
Expand Down Expand Up @@ -48,6 +50,103 @@ type ServerOptions struct {
AutoBackups bool
}

// UnmarshalJSON implements json.Unmarshaller on Server.
// This is needed because the Vultr API is inconsistent in it's JSON responses for servers.
// Some fields can changed type, from JSON number to JSON string and vice-versa.
func (s *Server) UnmarshalJSON(data []byte) (err error) {
if s == nil {
*s = Server{}
}

var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}

value := fmt.Sprintf("%v", fields["vcpu_count"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
vcpu, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.VCpus = int(vcpu)

value = fmt.Sprintf("%v", fields["DCID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
region, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.RegionID = int(region)

value = fmt.Sprintf("%v", fields["VPSPLANID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
plan, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.PlanID = int(plan)

value = fmt.Sprintf("%v", fields["pending_charges"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
pc, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.PendingCharges = pc

value = fmt.Sprintf("%v", fields["current_bandwidth_gb"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
cb, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.CurrentBandwidth = cb

value = fmt.Sprintf("%v", fields["allowed_bandwidth_gb"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
ab, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.AllowedBandwidth = ab

s.ID = fmt.Sprintf("%v", fields["SUBID"])
s.Name = fmt.Sprintf("%v", fields["label"])
s.OS = fmt.Sprintf("%v", fields["os"])
s.RAM = fmt.Sprintf("%v", fields["ram"])
s.Disk = fmt.Sprintf("%v", fields["disk"])
s.MainIP = fmt.Sprintf("%v", fields["main_ip"])
s.Location = fmt.Sprintf("%v", fields["location"])
s.DefaultPassword = fmt.Sprintf("%v", fields["default_password"])
s.Created = fmt.Sprintf("%v", fields["date_created"])
s.Status = fmt.Sprintf("%v", fields["status"])
s.Cost = fmt.Sprintf("%v", fields["cost_per_month"])
s.NetmaskV4 = fmt.Sprintf("%v", fields["netmask_v4"])
s.GatewayV4 = fmt.Sprintf("%v", fields["gateway_v4"])
s.PowerStatus = fmt.Sprintf("%v", fields["power_status"])
s.NetworkV6 = fmt.Sprintf("%v", fields["v6_network"])
s.MainIPV6 = fmt.Sprintf("%v", fields["v6_main_ip"])
s.NetworkSizeV6 = fmt.Sprintf("%v", fields["v6_network_size"])
s.InternalIP = fmt.Sprintf("%v", fields["internal_ip"])
s.KVMUrl = fmt.Sprintf("%v", fields["kvm_url"])
s.AutoBackups = fmt.Sprintf("%v", fields["auto_backups"])

return
}

func (c *Client) GetServers() (servers []Server, err error) {
var serverMap map[string]Server
if err := c.get(`server/list`, &serverMap); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion lib/servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ func Test_Servers_CreateServer_NoServer(t *testing.T) {
}

func Test_Servers_CreateServer_OK(t *testing.T) {
server, client := getTestServerAndClient(http.StatusOK, `{"SUBID":"123456789"}`)
server, client := getTestServerAndClient(http.StatusOK, `{"SUBID":"123456789",
"vcpu_count":"1",
"DCID":17,
"VPSPLANID":"29"}`)
defer server.Close()

s, err := client.CreateServer("test", 1, 2, 3, nil)
Expand Down

0 comments on commit aacf00e

Please sign in to comment.