blob: bd0df4a58559d78aca4040f5eba40cc8767d4052 [file] [log] [blame] [edit]
package main
import (
"context"
"fmt"
"net/http"
"sync"
"github.com/google/uuid"
"github.com/packethost/packngo"
)
// fakequinix implements a wrapngo.Client for testing. It starts out with a
// number of made up hardware reservations, and allows for creating devices and
// SSH keys.
type fakequinix struct {
mu sync.Mutex
pid string
devices map[string]*packngo.Device
reservations map[string]*packngo.HardwareReservation
sshKeys map[string]*packngo.SSHKey
reboots map[string]int
}
// newFakequinix makes a fakequinix with a given fake project ID and number of
// hardware reservations to create.
func newFakequinix(pid string, numReservations int) *fakequinix {
f := fakequinix{
pid: pid,
devices: make(map[string]*packngo.Device),
reservations: make(map[string]*packngo.HardwareReservation),
sshKeys: make(map[string]*packngo.SSHKey),
reboots: make(map[string]int),
}
for i := 0; i < numReservations; i++ {
uid := uuid.New()
f.reservations[uid.String()] = &packngo.HardwareReservation{
ID: uid.String(),
ShortID: uid.String(),
Provisionable: true,
}
}
return &f
}
func (f *fakequinix) notFound() error {
return &packngo.ErrorResponse{
Response: &http.Response{
StatusCode: http.StatusNotFound,
},
}
}
func (f *fakequinix) GetDevice(_ context.Context, pid, did string, _ *packngo.ListOptions) (*packngo.Device, error) {
f.mu.Lock()
defer f.mu.Unlock()
val := f.devices[did]
if val == nil {
return nil, f.notFound()
}
return val, nil
}
func (f *fakequinix) ListDevices(_ context.Context, pid string) ([]packngo.Device, error) {
f.mu.Lock()
defer f.mu.Unlock()
if pid != f.pid {
return nil, nil
}
var res []packngo.Device
for _, dev := range f.devices {
res = append(res, *dev)
}
return res, nil
}
func (f *fakequinix) UpdateDevice(ctx context.Context, id string, r *packngo.DeviceUpdateRequest) (*packngo.Device, error) {
return nil, fmt.Errorf("not implemented")
}
// MoveReservation is not implemented in fakequinix
func (f *fakequinix) MoveReservation(_ context.Context, hardwareReservationDID, projectID string) (*packngo.HardwareReservation, error) {
return nil, &packngo.ErrorResponse{
Response: &http.Response{
StatusCode: http.StatusNotImplemented,
},
}
}
func (f *fakequinix) DeleteDevice(_ context.Context, id string) error {
f.mu.Lock()
defer f.mu.Unlock()
if _, ok := f.devices[id]; !ok {
return f.notFound()
}
delete(f.devices, id)
return nil
}
func (f *fakequinix) CreateDevice(_ context.Context, request *packngo.DeviceCreateRequest) (*packngo.Device, error) {
f.mu.Lock()
defer f.mu.Unlock()
rid := request.HardwareReservationID
res := f.reservations[rid]
if res == nil {
return nil, f.notFound()
}
if res.Device != nil {
return nil, f.notFound()
}
dev := &packngo.Device{
ID: uuid.New().String(),
State: "active",
HardwareReservation: &packngo.HardwareReservation{
ID: rid,
},
Network: []*packngo.IPAddressAssignment{
{
IpAddressCommon: packngo.IpAddressCommon{
Public: true,
Address: "1.2.3.4",
},
},
},
Facility: &packngo.Facility{
Code: "wad",
},
Hostname: request.Hostname,
OS: &packngo.OS{
Name: request.OS,
Slug: request.OS,
},
}
res.Device = dev
res.Provisionable = false
f.devices[dev.ID] = dev
return dev, nil
}
func (f *fakequinix) ListReservations(_ context.Context, pid string) ([]packngo.HardwareReservation, error) {
f.mu.Lock()
defer f.mu.Unlock()
var res []packngo.HardwareReservation
for _, r := range f.reservations {
res = append(res, *r)
}
return res, nil
}
func (f *fakequinix) ListSSHKeys(_ context.Context) ([]packngo.SSHKey, error) {
f.mu.Lock()
defer f.mu.Unlock()
var res []packngo.SSHKey
for _, key := range f.sshKeys {
res = append(res, *key)
}
return res, nil
}
func (f *fakequinix) CreateSSHKey(_ context.Context, req *packngo.SSHKeyCreateRequest) (*packngo.SSHKey, error) {
f.mu.Lock()
defer f.mu.Unlock()
for _, k := range f.sshKeys {
if k.Key == req.Key {
return nil, f.notFound()
}
if k.Label == req.Label {
return nil, f.notFound()
}
}
uid := uuid.New().String()
f.sshKeys[uid] = &packngo.SSHKey{
ID: uid,
Label: req.Label,
Key: req.Key,
}
return f.sshKeys[uid], nil
}
func (f *fakequinix) UpdateSSHKey(_ context.Context, kid string, req *packngo.SSHKeyUpdateRequest) (*packngo.SSHKey, error) {
f.mu.Lock()
defer f.mu.Unlock()
key := f.sshKeys[kid]
if key == nil {
return nil, f.notFound()
}
key.Key = *req.Key
return key, nil
}
func (f *fakequinix) RebootDevice(_ context.Context, did string) error {
f.mu.Lock()
defer f.mu.Unlock()
f.reboots[did]++
return nil
}
func (f *fakequinix) Close() {
}