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