blob: e3a04d547c9bfe75dbd0bdcec4c0bdf6f3b0e08f [file] [log] [blame]
Serge Bazanskicaa12082023-02-16 14:54:04 +01001package manager
2
3import (
4 "context"
5 "net/http"
6 "sync"
7
8 "github.com/google/uuid"
9 "github.com/packethost/packngo"
10)
11
12// fakequinix implements a wrapngo.Client for testing. It starts out with a
13// number of made up hardware reservations, and allows for creating devices and
14// SSH keys.
15type fakequinix struct {
16 mu sync.Mutex
17
18 pid string
19 devices map[string]*packngo.Device
20 reservations map[string]*packngo.HardwareReservation
21 sshKeys map[string]*packngo.SSHKey
Serge Bazanskiae004682023-04-18 13:28:48 +020022 reboots map[string]int
Serge Bazanskicaa12082023-02-16 14:54:04 +010023}
24
25// newFakequinix makes a fakequinix with a given fake project ID and number of
26// hardware reservations to create.
27func newFakequinix(pid string, numReservations int) *fakequinix {
28 f := fakequinix{
29 pid: pid,
30 devices: make(map[string]*packngo.Device),
31 reservations: make(map[string]*packngo.HardwareReservation),
32 sshKeys: make(map[string]*packngo.SSHKey),
Serge Bazanskiae004682023-04-18 13:28:48 +020033 reboots: make(map[string]int),
Serge Bazanskicaa12082023-02-16 14:54:04 +010034 }
35
36 for i := 0; i < numReservations; i++ {
37 uid := uuid.New()
38 f.reservations[uid.String()] = &packngo.HardwareReservation{
39 ID: uid.String(),
40 ShortID: uid.String(),
41 Provisionable: true,
42 }
43 }
44
45 return &f
46}
47
48func (f *fakequinix) notFound() error {
49 return &packngo.ErrorResponse{
50 Response: &http.Response{
51 StatusCode: http.StatusNotFound,
52 },
53 }
54}
55
Serge Bazanski4969fd72023-04-19 17:43:12 +020056func (f *fakequinix) GetDevice(_ context.Context, pid, did string, _ *packngo.ListOptions) (*packngo.Device, error) {
Serge Bazanskicaa12082023-02-16 14:54:04 +010057 f.mu.Lock()
58 defer f.mu.Unlock()
59
Serge Bazanskicaa12082023-02-16 14:54:04 +010060 val := f.devices[did]
61 if val == nil {
62 return nil, f.notFound()
63 }
64 return val, nil
65}
66
67func (f *fakequinix) ListDevices(_ context.Context, pid string) ([]packngo.Device, error) {
68 f.mu.Lock()
69 defer f.mu.Unlock()
70
71 if pid != f.pid {
72 return nil, nil
73 }
74 var res []packngo.Device
75 for _, dev := range f.devices {
76 res = append(res, *dev)
77 }
78 return res, nil
79}
80
Tim Windelschmidt8180de92023-05-11 19:45:37 +020081// MoveReservation is not implemented in fakequinix
82func (f *fakequinix) MoveReservation(_ context.Context, hardwareReservationDID, projectID string) (*packngo.HardwareReservation, error) {
83 return nil, &packngo.ErrorResponse{
84 Response: &http.Response{
85 StatusCode: http.StatusNotImplemented,
86 },
87 }
88}
89
90func (f *fakequinix) DeleteDevice(_ context.Context, id string) error {
91 f.mu.Lock()
92 defer f.mu.Unlock()
93
94 if _, ok := f.devices[id]; !ok {
95 return f.notFound()
96 }
97
98 delete(f.devices, id)
99
100 return nil
101}
102
Serge Bazanskicaa12082023-02-16 14:54:04 +0100103func (f *fakequinix) CreateDevice(_ context.Context, request *packngo.DeviceCreateRequest) (*packngo.Device, error) {
104 f.mu.Lock()
105 defer f.mu.Unlock()
106
107 rid := request.HardwareReservationID
108 res := f.reservations[rid]
109 if res == nil {
110 return nil, f.notFound()
111 }
112 if res.Device != nil {
113 return nil, f.notFound()
114 }
115
116 dev := &packngo.Device{
Serge Bazanskiafd3cf82023-04-19 17:43:46 +0200117 ID: uuid.New().String(),
118 State: "active",
119 HardwareReservation: &packngo.HardwareReservation{
120 ID: rid,
121 },
122 Network: []*packngo.IPAddressAssignment{
123 {
124 IpAddressCommon: packngo.IpAddressCommon{
125 Public: true,
126 Address: "1.2.3.4",
127 },
128 },
129 },
130 Facility: &packngo.Facility{
131 Code: "wad",
132 },
Serge Bazanskicaa12082023-02-16 14:54:04 +0100133 Hostname: request.Hostname,
134 OS: &packngo.OS{
135 Name: request.OS,
136 Slug: request.OS,
137 },
138 }
139 res.Device = dev
140 res.Provisionable = false
141
142 f.devices[dev.ID] = dev
143 return dev, nil
144}
145
146func (f *fakequinix) ListReservations(_ context.Context, pid string) ([]packngo.HardwareReservation, error) {
147 f.mu.Lock()
148 defer f.mu.Unlock()
149
150 var res []packngo.HardwareReservation
151 for _, r := range f.reservations {
152 res = append(res, *r)
153 }
154
155 return res, nil
156}
157
158func (f *fakequinix) ListSSHKeys(_ context.Context) ([]packngo.SSHKey, error) {
159 f.mu.Lock()
160 defer f.mu.Unlock()
161
162 var res []packngo.SSHKey
163 for _, key := range f.sshKeys {
164 res = append(res, *key)
165 }
166
167 return res, nil
168}
169
170func (f *fakequinix) CreateSSHKey(_ context.Context, req *packngo.SSHKeyCreateRequest) (*packngo.SSHKey, error) {
171 f.mu.Lock()
172 defer f.mu.Unlock()
173
174 for _, k := range f.sshKeys {
175 if k.Key == req.Key {
176 return nil, f.notFound()
177 }
178 if k.Label == req.Label {
179 return nil, f.notFound()
180 }
181 }
182
183 uid := uuid.New().String()
184 f.sshKeys[uid] = &packngo.SSHKey{
185 ID: uid,
186 Label: req.Label,
187 Key: req.Key,
188 }
189
190 return f.sshKeys[uid], nil
191}
192
193func (f *fakequinix) UpdateSSHKey(_ context.Context, kid string, req *packngo.SSHKeyUpdateRequest) (*packngo.SSHKey, error) {
194 f.mu.Lock()
195 defer f.mu.Unlock()
196
197 key := f.sshKeys[kid]
198 if key == nil {
199 return nil, f.notFound()
200 }
201 key.Key = *req.Key
202
203 return key, nil
204}
205
Serge Bazanskiae004682023-04-18 13:28:48 +0200206func (f *fakequinix) RebootDevice(_ context.Context, did string) error {
207 f.mu.Lock()
208 defer f.mu.Unlock()
209
210 f.reboots[did]++
211
212 return nil
213}
214
Serge Bazanskicaa12082023-02-16 14:54:04 +0100215func (f *fakequinix) Close() {
216}