Skip to content

Commit a3ac872

Browse files
authored
Merge pull request #58 from opencredo/master
New Host, Firewall, Network and Router resources
2 parents ca03c8c + d886d88 commit a3ac872

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+19073
-8287
lines changed

examples/upcloud-cli/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ func createServer(s *service.Service) error {
7878
Title: fmt.Sprintf("example-cli-server-%04d", rand.Int31n(1000)),
7979
Zone: "fi-hel2",
8080
Plan: "1xCPU-1GB",
81-
StorageDevices: []upcloud.CreateServerStorageDevice{
81+
StorageDevices: []request.CreateServerStorageDevice{
8282
{
83-
Action: upcloud.CreateServerStorageDeviceActionClone,
83+
Action: request.CreateServerStorageDeviceActionClone,
8484
Storage: "01000000-0000-4000-8000-000050010400",
8585
Title: "Centos8 from a template",
8686
Size: 50,
@@ -95,7 +95,7 @@ func createServer(s *service.Service) error {
9595
Family: upcloud.IPAddressFamilyIPv4,
9696
},
9797
},
98-
Type: upcloud.IPAddressAccessUtility,
98+
Type: upcloud.NetworkTypeUtility,
9999
},
100100
},
101101
},

upcloud/client/client.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@ func (c *Client) PerformJSONDeleteRequest(url string) error {
137137
return err
138138
}
139139

140+
// PerformJSONPutUploadRequest performs a PUT request to the specified URL with an io.Reader
141+
// and returns the response body and eventual errors
142+
func (c *Client) PerformJSONPutUploadRequest(url string, requestBody io.Reader) ([]byte, error) {
143+
144+
request, err := http.NewRequest(http.MethodPut, url, requestBody)
145+
146+
if err != nil {
147+
return nil, err
148+
}
149+
150+
return c.performJSONRequest(request)
151+
}
152+
140153
// Adds common headers to the specified request
141154
func (c *Client) addJSONRequestHeaders(request *http.Request) *http.Request {
142155
request.SetBasicAuth(c.userName, c.password)

upcloud/firewall.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type FirewallRule struct {
5555
Direction string `json:"direction"`
5656
Family string `json:"family"`
5757
ICMPType string `json:"icmp_type,omitempty"`
58-
Position int `json:"position,string"`
58+
Position int `json:"position,string,omitempty"`
5959
Protocol string `json:"protocol,omitempty"`
6060
SourceAddressStart string `json:"source_address_start,omitempty"`
6161
SourceAddressEnd string `json:"source_address_end,omitempty"`

upcloud/hosts.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package upcloud
2+
3+
import (
4+
"encoding/json"
5+
"time"
6+
)
7+
8+
// Hosts represents a GetHosts response
9+
type Hosts struct {
10+
Hosts []Host `json:"hosts"`
11+
}
12+
13+
// UnmarshalJSON is a custom unmarshaller that deals with
14+
// deeply embedded values.
15+
func (n *Hosts) UnmarshalJSON(b []byte) error {
16+
type localHost Host
17+
type hostWrapper struct {
18+
Hosts []localHost `json:"host"`
19+
}
20+
21+
v := struct {
22+
Hosts hostWrapper `json:"hosts"`
23+
}{}
24+
err := json.Unmarshal(b, &v)
25+
if err != nil {
26+
return err
27+
}
28+
29+
for _, ln := range v.Hosts.Hosts {
30+
n.Hosts = append(n.Hosts, Host(ln))
31+
}
32+
33+
return nil
34+
}
35+
36+
// StatSlice is a slice of Stat structs
37+
// This exsits to support a custom unmarshaller
38+
type StatSlice []Stat
39+
40+
// UnmarshalJSON is a custom unmarshaller that deals with
41+
// deeply embedded values.
42+
func (t *StatSlice) UnmarshalJSON(b []byte) error {
43+
v := struct {
44+
Networks []Stat `json:"stat"`
45+
}{}
46+
err := json.Unmarshal(b, &v)
47+
if err != nil {
48+
return err
49+
}
50+
51+
(*t) = v.Networks
52+
53+
return nil
54+
}
55+
56+
// Host represents an individual Host in a response
57+
type Host struct {
58+
ID int `json:"id"`
59+
Description string `json:"description"`
60+
Zone string `json:"zone"`
61+
WindowsEnabled Boolean `json:"windows_enabled"`
62+
Stats StatSlice `json:"stats"`
63+
}
64+
65+
// UnmarshalJSON is a custom unmarshaller that deals with
66+
// deeply embedded values.
67+
func (s *Host) UnmarshalJSON(b []byte) error {
68+
type localHost Host
69+
70+
v := struct {
71+
Host localHost `json:"host"`
72+
}{}
73+
err := json.Unmarshal(b, &v)
74+
if err != nil {
75+
return err
76+
}
77+
78+
(*s) = Host(v.Host)
79+
80+
return nil
81+
}
82+
83+
// Stat represents Host stats in a response
84+
type Stat struct {
85+
Name string `json:"name"`
86+
Timestamp time.Time `json:"timestamp"`
87+
Value float64 `json:"value"`
88+
}

upcloud/hosts_test.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package upcloud
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func timeParse(s string) time.Time {
12+
t, _ := time.Parse(time.RFC3339, s)
13+
return t
14+
}
15+
16+
// TestUnmarshalHosts tests that multiple Host and Stat are unmarshalled correcltly.
17+
func TestUnmarshalHosts(t *testing.T) {
18+
originalJSON := `
19+
{
20+
"hosts": {
21+
"host": [
22+
{
23+
"id": 7653311107,
24+
"description": "My Host #1",
25+
"zone": "private-zone-id",
26+
"windows_enabled": "no",
27+
"stats": {
28+
"stat": [
29+
{
30+
"name": "cpu_idle",
31+
"timestamp": "2019-08-09T12:46:57Z",
32+
"value": 95.2
33+
},
34+
{
35+
"name": "memory_free",
36+
"timestamp": "2019-08-09T12:46:57Z",
37+
"value": 102
38+
}
39+
]
40+
}
41+
},
42+
{
43+
"id": 8055964291,
44+
"description": "My Host #2",
45+
"zone": "private-zone-id",
46+
"windows_enabled": "no",
47+
"stats": {
48+
"stat": [
49+
{
50+
"name": "cpu_idle",
51+
"timestamp": "2019-08-09T12:46:57Z",
52+
"value": 80.1
53+
},
54+
{
55+
"name": "memory_free",
56+
"timestamp": "2019-08-09T12:46:57Z",
57+
"value": 61
58+
}
59+
]
60+
}
61+
}
62+
]
63+
}
64+
}
65+
`
66+
67+
var hosts Hosts
68+
err := json.Unmarshal([]byte(originalJSON), &hosts)
69+
assert.NoError(t, err)
70+
71+
testsHosts := []Host{
72+
{
73+
ID: 7653311107,
74+
Description: "My Host #1",
75+
Zone: "private-zone-id",
76+
WindowsEnabled: false,
77+
Stats: []Stat{
78+
{
79+
Name: "cpu_idle",
80+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
81+
Value: 95.2,
82+
},
83+
{
84+
Name: "memory_free",
85+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
86+
Value: 102,
87+
},
88+
},
89+
},
90+
{
91+
ID: 8055964291,
92+
Description: "My Host #2",
93+
Zone: "private-zone-id",
94+
WindowsEnabled: false,
95+
Stats: []Stat{
96+
{
97+
Name: "cpu_idle",
98+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
99+
Value: 80.1,
100+
},
101+
{
102+
Name: "memory_free",
103+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
104+
Value: 61,
105+
},
106+
},
107+
},
108+
}
109+
110+
for i, h := range testsHosts {
111+
assert.Equal(t, h, hosts.Hosts[i])
112+
}
113+
}
114+
115+
// TestUnmarshalHosts tests that a single Host and Stat are unmarshalled correcltly.
116+
func TestUnmarshalHost(t *testing.T) {
117+
originalJSON := `
118+
{
119+
"host": {
120+
"id": 7653311107,
121+
"description": "My Host #1",
122+
"zone": "private-zone-id",
123+
"windows_enabled": "no",
124+
"stats": {
125+
"stat": [
126+
{
127+
"name": "cpu_idle",
128+
"timestamp": "2019-08-09T12:46:57Z",
129+
"value": 95.2
130+
},
131+
{
132+
"name": "memory_free",
133+
"timestamp": "2019-08-09T12:46:57Z",
134+
"value": 102
135+
}
136+
]
137+
}
138+
}
139+
}
140+
`
141+
142+
var host Host
143+
err := json.Unmarshal([]byte(originalJSON), &host)
144+
assert.NoError(t, err)
145+
146+
testHost := Host{
147+
ID: 7653311107,
148+
Description: "My Host #1",
149+
Zone: "private-zone-id",
150+
WindowsEnabled: false,
151+
Stats: []Stat{
152+
{
153+
Name: "cpu_idle",
154+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
155+
Value: 95.2,
156+
},
157+
{
158+
Name: "memory_free",
159+
Timestamp: timeParse("2019-08-09T12:46:57Z"),
160+
Value: 102,
161+
},
162+
},
163+
}
164+
165+
assert.Equal(t, testHost, host)
166+
}

0 commit comments

Comments
 (0)