forked from TrueCloudLab/lego
319 lines
6.8 KiB
Go
319 lines
6.8 KiB
Go
package govultr
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
)
|
|
|
|
// BlockStorageService is the interface to interact with Block-Storage endpoint on the Vultr API
|
|
// Link: https://www.vultr.com/api/#block
|
|
type BlockStorageService interface {
|
|
Attach(ctx context.Context, blockID, InstanceID string) error
|
|
Create(ctx context.Context, regionID, size int, label string) (*BlockStorage, error)
|
|
Delete(ctx context.Context, blockID string) error
|
|
Detach(ctx context.Context, blockID string) error
|
|
SetLabel(ctx context.Context, blockID, label string) error
|
|
List(ctx context.Context) ([]BlockStorage, error)
|
|
Get(ctx context.Context, blockID string) (*BlockStorage, error)
|
|
Resize(ctx context.Context, blockID string, size int) error
|
|
}
|
|
|
|
// BlockStorageServiceHandler handles interaction with the block-storage methods for the Vultr API
|
|
type BlockStorageServiceHandler struct {
|
|
client *Client
|
|
}
|
|
|
|
// BlockStorage represents Vultr Block-Storage
|
|
type BlockStorage struct {
|
|
BlockStorageID string `json:"SUBID"`
|
|
DateCreated string `json:"date_created"`
|
|
CostPerMonth string `json:"cost_per_month"`
|
|
Status string `json:"status"`
|
|
SizeGB int `json:"size_gb"`
|
|
RegionID int `json:"DCID"`
|
|
InstanceID string `json:"attached_to_SUBID"`
|
|
Label string `json:"label"`
|
|
}
|
|
|
|
// UnmarshalJSON implements json.Unmarshaller on BlockStorage to handle the inconsistent types returned from the Vultr v1 API.
|
|
func (b *BlockStorage) UnmarshalJSON(data []byte) (err error) {
|
|
if b == nil {
|
|
*b = BlockStorage{}
|
|
}
|
|
|
|
var v map[string]interface{}
|
|
if err := json.Unmarshal(data, &v); err != nil {
|
|
return err
|
|
}
|
|
|
|
b.BlockStorageID, err = b.unmarshalStr(fmt.Sprintf("%v", v["SUBID"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b.RegionID, err = b.unmarshalInt(fmt.Sprintf("%v", v["DCID"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b.SizeGB, err = b.unmarshalInt(fmt.Sprintf("%v", v["size_gb"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b.InstanceID, err = b.unmarshalStr(fmt.Sprintf("%v", v["attached_to_SUBID"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b.CostPerMonth, err = b.unmarshalStr(fmt.Sprintf("%v", v["cost_per_month"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
date := fmt.Sprintf("%v", v["date_created"])
|
|
if date == "<nil>" {
|
|
date = ""
|
|
}
|
|
b.DateCreated = date
|
|
|
|
status := fmt.Sprintf("%v", v["status"])
|
|
if status == "<nil>" {
|
|
status = ""
|
|
}
|
|
b.Status = status
|
|
|
|
b.Label = fmt.Sprintf("%v", v["label"])
|
|
|
|
return nil
|
|
}
|
|
|
|
func (b *BlockStorage) unmarshalInt(value string) (int, error) {
|
|
if len(value) == 0 || value == "<nil>" {
|
|
value = "0"
|
|
}
|
|
|
|
i, err := strconv.ParseInt(value, 10, 64)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return int(i), nil
|
|
}
|
|
|
|
func (b *BlockStorage) unmarshalStr(value string) (string, error) {
|
|
if len(value) == 0 || value == "<nil>" || value == "0" || value == "false" {
|
|
return "", nil
|
|
}
|
|
|
|
f, err := strconv.ParseFloat(value, 64)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return strconv.FormatFloat(f, 'f', -1, 64), nil
|
|
}
|
|
|
|
// Attach will link a given block storage to a given Vultr vps
|
|
func (b *BlockStorageServiceHandler) Attach(ctx context.Context, blockID, InstanceID string) error {
|
|
|
|
uri := "/v1/block/attach"
|
|
|
|
values := url.Values{
|
|
"SUBID": {blockID},
|
|
"attach_to_SUBID": {InstanceID},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = b.client.DoWithContext(ctx, req, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Create builds out a block storage
|
|
func (b *BlockStorageServiceHandler) Create(ctx context.Context, regionID, sizeGB int, label string) (*BlockStorage, error) {
|
|
|
|
uri := "/v1/block/create"
|
|
|
|
values := url.Values{
|
|
"DCID": {strconv.Itoa(regionID)},
|
|
"size_gb": {strconv.Itoa(sizeGB)},
|
|
"label": {label},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
blockStorage := new(BlockStorage)
|
|
|
|
err = b.client.DoWithContext(ctx, req, blockStorage)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
blockStorage.RegionID = regionID
|
|
blockStorage.Label = label
|
|
blockStorage.SizeGB = sizeGB
|
|
|
|
return blockStorage, nil
|
|
}
|
|
|
|
// Delete will remove block storage instance from your Vultr account
|
|
func (b *BlockStorageServiceHandler) Delete(ctx context.Context, blockID string) error {
|
|
|
|
uri := "/v1/block/delete"
|
|
|
|
values := url.Values{
|
|
"SUBID": {blockID},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = b.client.DoWithContext(ctx, req, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Detach will de-link a given block storage to the Vultr vps it is attached to
|
|
func (b *BlockStorageServiceHandler) Detach(ctx context.Context, blockID string) error {
|
|
|
|
uri := "/v1/block/detach"
|
|
|
|
values := url.Values{
|
|
"SUBID": {blockID},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = b.client.DoWithContext(ctx, req, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetLabel allows you to set/update the label on your Vultr Block storage
|
|
func (b *BlockStorageServiceHandler) SetLabel(ctx context.Context, blockID, label string) error {
|
|
uri := "/v1/block/label_set"
|
|
|
|
values := url.Values{
|
|
"SUBID": {blockID},
|
|
"label": {label},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = b.client.DoWithContext(ctx, req, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// List returns a list of all block storage instances on your Vultr Account
|
|
func (b *BlockStorageServiceHandler) List(ctx context.Context) ([]BlockStorage, error) {
|
|
|
|
uri := "/v1/block/list"
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var blockStorage []BlockStorage
|
|
err = b.client.DoWithContext(ctx, req, &blockStorage)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return blockStorage, nil
|
|
}
|
|
|
|
// Get returns a single block storage instance based ony our blockID you provide from your Vultr Account
|
|
func (b *BlockStorageServiceHandler) Get(ctx context.Context, blockID string) (*BlockStorage, error) {
|
|
|
|
uri := "/v1/block/list"
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
q := req.URL.Query()
|
|
q.Add("SUBID", blockID)
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
blockStorage := new(BlockStorage)
|
|
err = b.client.DoWithContext(ctx, req, blockStorage)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return blockStorage, nil
|
|
}
|
|
|
|
// Resize allows you to resize your Vultr block storage instance
|
|
func (b *BlockStorageServiceHandler) Resize(ctx context.Context, blockID string, sizeGB int) error {
|
|
|
|
uri := "/v1/block/resize"
|
|
|
|
values := url.Values{
|
|
"SUBID": {blockID},
|
|
"size_gb": {strconv.Itoa(sizeGB)},
|
|
}
|
|
|
|
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = b.client.DoWithContext(ctx, req, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|