/
mock.go
158 lines (130 loc) · 3.37 KB
/
mock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2014 ALTOROS
// Licensed under the AGPLv3, see LICENSE file for details.
package mock
import (
"encoding/base64"
"net/http"
"net/http/httptest"
"strings"
"github.com/Altoros/gosigma/https"
)
//
// Implementation of CloudSigma server mock object for testing purposes.
//
// Username: test@example.com
// Password: test
//
const serverBase = "/api/2.0/"
const (
// TestUser contains account name for log into mock server
TestUser = "test@example.com"
// TestPassword contains password for log into mock server
TestPassword = "test"
)
var pServer *httptest.Server
// Start mock server for testing CloudSigma endpoint communication.
// If server is already started, this function does nothing.
func Start() {
if IsStarted() {
return
}
mux := http.NewServeMux()
mux.HandleFunc(makeHandler("capabilities", capsHandler))
mux.HandleFunc(makeHandler("drives", Drives.handleRequest))
mux.HandleFunc(makeHandler("libdrives", LibDrives.handleRequest))
mux.HandleFunc(makeHandler("servers", serversHandler))
mux.HandleFunc(makeHandler("jobs", Jobs.handleRequest))
pServer = httptest.NewUnstartedServer(mux)
pServer.StartTLS()
}
type handlerType func(http.ResponseWriter, *http.Request)
func makeHandler(name string, f handlerType) (string, handlerType) {
url := serverBase + name + "/"
handler := func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
rec := httptest.NewRecorder()
if isValidAuth(r) {
f(rec, r)
} else {
rec.WriteHeader(401)
rec.Write([]byte("401 Unauthorized\n"))
}
recordJournal(name, r, rec)
hdr := w.Header()
for k, v := range rec.HeaderMap {
hdr[k] = v
}
w.WriteHeader(rec.Code)
w.Write(rec.Body.Bytes())
}
return url, handler
}
func isValidAuth(r *http.Request) bool {
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(s) < 2 {
return false
}
switch s[0] {
case "Basic":
return isValidBasicAuth(s[1])
case "Digest":
return isValidDigestAuth(s[1])
}
return false
}
func isValidBasicAuth(auth string) bool {
b, err := base64.StdEncoding.DecodeString(auth)
if err != nil {
return false
}
pair := strings.SplitN(string(b), ":", 2)
if len(pair) != 2 {
return false
}
if pair[0] != TestUser {
return false
}
if pair[1] != TestPassword {
return false
}
return true
}
func isValidDigestAuth(auth string) bool {
return false
}
// IsStarted checks the mock server is running
func IsStarted() bool {
if pServer == nil {
return false
}
return true
}
// Stop mock server.
// Panic if server is not started.
func Stop() {
pServer.CloseClientConnections()
pServer.Close()
pServer = nil
}
// Reset mock server
func Reset() {
Jobs.Reset()
Drives.Reset()
LibDrives.Reset()
ResetServers()
}
// Endpoint of mock server, represented as string in form
// 'https://host:port/api/{version}/{section}'. Panic if server is not started.
func Endpoint(section string) string {
return pServer.URL + serverBase + section
}
// GetAuth performs Get request to the given section of mock server with authentication
func GetAuth(section, username, password string) (*https.Response, error) {
client := https.NewAuthClient(username, password, nil)
url := Endpoint(section)
return client.Get(url, nil)
}
// Get performs Get request to the given section of mock server with default authentication
func Get(section string) (*https.Response, error) {
return GetAuth(section, TestUser, TestPassword)
}