Skip to content

Commit

Permalink
Merge pull request #200 from civo/volume-boot-attach
Browse files Browse the repository at this point in the history
Support attaching/detaching volumes on create/update instance and det…
  • Loading branch information
vishalanarase authored Aug 29, 2024
2 parents 22e0a73 + 2b6369e commit 4fee779
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 70 deletions.
6 changes: 3 additions & 3 deletions fake_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ type Clienter interface {
FindVolume(search string) (*Volume, error)
NewVolume(v *VolumeConfig) (*VolumeResult, error)
ResizeVolume(id string, size int) (*SimpleResponse, error)
AttachVolume(id string, instance string) (*SimpleResponse, error)
AttachVolume(id string, cfg VolumeAttachConfig) (*SimpleResponse, error)
DetachVolume(id string) (*SimpleResponse, error)
DeleteVolume(id string) (*SimpleResponse, error)

Expand Down Expand Up @@ -1283,10 +1283,10 @@ func (c *FakeClient) ResizeVolume(id string, size int) (*SimpleResponse, error)
}

// AttachVolume implemented in a fake way for automated tests
func (c *FakeClient) AttachVolume(id string, instance string) (*SimpleResponse, error) {
func (c *FakeClient) AttachVolume(id string, cfg VolumeAttachConfig) (*SimpleResponse, error) {
for i, volume := range c.Volumes {
if volume.ID == id {
c.Volumes[i].InstanceID = instance
c.Volumes[i].InstanceID = cfg.InstanceID
c.Volumes[i].Status = "attached"
return &SimpleResponse{Result: "success"}, nil
}
Expand Down
130 changes: 69 additions & 61 deletions instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,48 @@ import (

// Instance represents a virtual server within Civo's infrastructure
type Instance struct {
ID string `json:"id,omitempty"`
OpenstackServerID string `json:"openstack_server_id,omitempty"`
Hostname string `json:"hostname,omitempty"`
ReverseDNS string `json:"reverse_dns,omitempty"`
Size string `json:"size,omitempty"`
Region string `json:"region,omitempty"`
NetworkID string `json:"network_id,omitempty"`
PrivateIP string `json:"private_ip,omitempty"`
PublicIP string `json:"public_ip,omitempty"`
IPv6 string `json:"ipv6,omitempty"`
PseudoIP string `json:"pseudo_ip,omitempty"`
TemplateID string `json:"template_id,omitempty"`
SourceType string `json:"source_type,omitempty"`
SourceID string `json:"source_id,omitempty"`
SnapshotID string `json:"snapshot_id,omitempty"`
InitialUser string `json:"initial_user,omitempty"`
InitialPassword string `json:"initial_password,omitempty"`
SSHKey string `json:"ssh_key,omitempty"`
SSHKeyID string `json:"ssh_key_id,omitempty"`
Status string `json:"status,omitempty"`
Notes string `json:"notes,omitempty"`
FirewallID string `json:"firewall_id,omitempty"`
Tags []string `json:"tags,omitempty"`
CivostatsdToken string `json:"civostatsd_token,omitempty"`
CivostatsdStats string `json:"civostatsd_stats,omitempty"`
CivostatsdStatsPerMinute []string `json:"civostatsd_stats_per_minute,omitempty"`
CivostatsdStatsPerHour []string `json:"civostatsd_stats_per_hour,omitempty"`
OpenstackImageID string `json:"openstack_image_id,omitempty"`
RescuePassword string `json:"rescue_password,omitempty"`
VolumeBacked bool `json:"volume_backed,omitempty"`
CPUCores int `json:"cpu_cores,omitempty"`
RAMMegabytes int `json:"ram_mb,omitempty"`
DiskGigabytes int `json:"disk_gb,omitempty"`
GPUCount int `json:"gpu_count,omitempty"`
GPUType string `json:"gpu_type,omitempty"`
Script string `json:"script,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
ReservedIPID string `json:"reserved_ip_id,omitempty"`
ReservedIPName string `json:"reserved_ip_name,omitempty"`
ReservedIP string `json:"reserved_ip,omitempty"`
Subnets []Subnet `json:"subnets,omitempty"`
ID string `json:"id,omitempty"`
OpenstackServerID string `json:"openstack_server_id,omitempty"`
Hostname string `json:"hostname,omitempty"`
ReverseDNS string `json:"reverse_dns,omitempty"`
Size string `json:"size,omitempty"`
Region string `json:"region,omitempty"`
NetworkID string `json:"network_id,omitempty"`
PrivateIP string `json:"private_ip,omitempty"`
PublicIP string `json:"public_ip,omitempty"`
IPv6 string `json:"ipv6,omitempty"`
PseudoIP string `json:"pseudo_ip,omitempty"`
TemplateID string `json:"template_id,omitempty"`
SourceType string `json:"source_type,omitempty"`
SourceID string `json:"source_id,omitempty"`
SnapshotID string `json:"snapshot_id,omitempty"`
InitialUser string `json:"initial_user,omitempty"`
InitialPassword string `json:"initial_password,omitempty"`
SSHKey string `json:"ssh_key,omitempty"`
SSHKeyID string `json:"ssh_key_id,omitempty"`
Status string `json:"status,omitempty"`
Notes string `json:"notes,omitempty"`
FirewallID string `json:"firewall_id,omitempty"`
Tags []string `json:"tags,omitempty"`
CivostatsdToken string `json:"civostatsd_token,omitempty"`
CivostatsdStats string `json:"civostatsd_stats,omitempty"`
CivostatsdStatsPerMinute []string `json:"civostatsd_stats_per_minute,omitempty"`
CivostatsdStatsPerHour []string `json:"civostatsd_stats_per_hour,omitempty"`
OpenstackImageID string `json:"openstack_image_id,omitempty"`
RescuePassword string `json:"rescue_password,omitempty"`
VolumeBacked bool `json:"volume_backed,omitempty"`
CPUCores int `json:"cpu_cores,omitempty"`
RAMMegabytes int `json:"ram_mb,omitempty"`
DiskGigabytes int `json:"disk_gb,omitempty"`
GPUCount int `json:"gpu_count,omitempty"`
GPUType string `json:"gpu_type,omitempty"`
Script string `json:"script,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
ReservedIPID string `json:"reserved_ip_id,omitempty"`
ReservedIPName string `json:"reserved_ip_name,omitempty"`
ReservedIP string `json:"reserved_ip,omitempty"`
Subnets []Subnet `json:"subnets,omitempty"`
AttachedVolume []AttachedVolume `json:"attached_volume,omitempty"`
}

//"cpu_cores":1,"ram_mb":2048,"disk_gb":25
Expand All @@ -70,30 +71,37 @@ type PaginatedInstanceList struct {
Items []Instance `json:"items"`
}

// AttachedVolume disk information
type AttachedVolume struct {
// ID of the volume to attach
ID string `json:"id"`
}

// InstanceConfig describes the parameters for a new instance
// none of the fields are mandatory and will be automatically
// set with default values
type InstanceConfig struct {
Count int `json:"count"`
Hostname string `json:"hostname"`
ReverseDNS string `json:"reverse_dns"`
Size string `json:"size"`
Region string `json:"region"`
PublicIPRequired string `json:"public_ip"`
ReservedIPv4 string `json:"reserved_ipv4"`
PrivateIPv4 string `json:"private_ipv4"`
NetworkID string `json:"network_id"`
TemplateID string `json:"template_id"`
SourceType string `json:"source_type"`
SourceID string `json:"source_id"`
SnapshotID string `json:"snapshot_id"`
Subnets []string `json:"subnets,omitempty"`
InitialUser string `json:"initial_user"`
SSHKeyID string `json:"ssh_key_id"`
Script string `json:"script"`
Tags []string `json:"-"`
TagsList string `json:"tags"`
FirewallID string `json:"firewall_id"`
Count int `json:"count"`
Hostname string `json:"hostname"`
ReverseDNS string `json:"reverse_dns"`
Size string `json:"size"`
Region string `json:"region"`
PublicIPRequired string `json:"public_ip"`
ReservedIPv4 string `json:"reserved_ipv4"`
PrivateIPv4 string `json:"private_ipv4"`
NetworkID string `json:"network_id"`
TemplateID string `json:"template_id"`
SourceType string `json:"source_type"`
SourceID string `json:"source_id"`
SnapshotID string `json:"snapshot_id"`
Subnets []string `json:"subnets,omitempty"`
InitialUser string `json:"initial_user"`
SSHKeyID string `json:"ssh_key_id"`
Script string `json:"script"`
Tags []string `json:"-"`
TagsList string `json:"tags"`
FirewallID string `json:"firewall_id"`
AttachedVolume []AttachedVolume `json:"attached_volume"`
}

// ListInstances returns a page of Instances owned by the calling API account
Expand Down
14 changes: 9 additions & 5 deletions volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ type VolumeConfig struct {
Bootable bool `json:"bootable"`
}

// VolumeAttachConfig is the configuration used to attach volume
type VolumeAttachConfig struct {
InstanceID string `json:"instance_id"`
AttachAtBoot bool `json:"attach_at_boot"`
Region string `json:"region"`
}

// ListVolumes returns all volumes owned by the calling API account
// https://www.civo.com/api/volumes#list-volumes
func (c *Client) ListVolumes() ([]Volume, error) {
Expand Down Expand Up @@ -199,11 +206,8 @@ func (c *Client) ResizeVolume(id string, size int) (*SimpleResponse, error) {

// AttachVolume attaches a volume to an instance
// https://www.civo.com/api/volumes#attach-a-volume-to-an-instance
func (c *Client) AttachVolume(id string, instance string) (*SimpleResponse, error) {
resp, err := c.SendPutRequest(fmt.Sprintf("/v2/volumes/%s/attach", id), map[string]string{
"instance_id": instance,
"region": c.Region,
})
func (c *Client) AttachVolume(id string, v VolumeAttachConfig) (*SimpleResponse, error) {
resp, err := c.SendPutRequest(fmt.Sprintf("/v2/volumes/%s/attach", id), v)
if err != nil {
return nil, decodeError(err)
}
Expand Down
5 changes: 4 additions & 1 deletion volume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ func TestAttachVolumes(t *testing.T) {
"/v2/volumes/12346/attach": `{"result": "success"}`,
})
defer server.Close()
got, err := client.AttachVolume("12346", "123456")
cfg := VolumeAttachConfig{
InstanceID: "123456",
}
got, err := client.AttachVolume("12346", cfg)
if err != nil {
t.Errorf("Request returned an error: %s", err)
return
Expand Down

0 comments on commit 4fee779

Please sign in to comment.