├── .gitignore ├── README.md ├── account.go ├── account_test.go ├── background.go ├── background_test.go ├── backup.go ├── backup_test.go ├── billing.go ├── billing_test.go ├── client.go ├── configuration.go ├── configuration_test.go ├── domain.go ├── domain_record.go ├── domain_record_test.go ├── domain_tags.go ├── domain_tags_test.go ├── domain_test.go ├── notification.go ├── notification_test.go ├── ptr_records.go ├── ptr_records_test.go ├── scalet.go ├── scalet_test.go ├── server_tags.go ├── server_tags_test.go ├── sshkey.go ├── sshkey_test.go └── utils.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-vscale 2 | 3 | go-vscale is a Go client library for accessing the [Vscale API](https://developers.vscale.io/documentation/api/v1/). 4 | 5 | ## Usage 6 | 7 | ```go 8 | import "github.com/vscale/go-vscale" 9 | ``` 10 | 11 | First step is constructing Vscale client which allows to use API services. 12 | You can generate token in [Vscale Panel](https://vscale.io/panel/settings/tokens/). 13 | 14 | ```go 15 | client := NewClient("token should be here") 16 | account, _, err := client.Account.Get() 17 | ``` 18 | 19 | Some operations with scalets can be started both sync and async. 20 | 21 | ```go 22 | // Second argument is "wait" which expects boolean value 23 | // true - if you want to wait until the end of operation 24 | // false - if you want this operation to be handled in background 25 | client := NewClient("token should be here") 26 | scalet, _, err := client.Scalet.Rebuild(11111, true) 27 | ``` 28 | 29 | ## Tests 30 | 31 | You can run tests which make requests straightly to Vscale API. 32 | For now they can't be run together. Run specific test if you want to test some method. 33 | 34 | ```bash 35 | $ go test -v github.com/vscale/go-vscale -run TestAccountService_Get 36 | ``` 37 | 38 | For convenience you can use "VSCALE_API_TOKEN" env for not passing token to every test. 39 | -------------------------------------------------------------------------------- /account.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type AccountService struct { 8 | client Client 9 | } 10 | 11 | type Account struct { 12 | Info struct { 13 | Actdate string `json:"actdate,omitempty"` 14 | Country string `json:"country,omitempty"` 15 | Email string `json:"email,omitempty"` 16 | FaceID string `json:"face_id,omitempty"` 17 | ID string `json:"id,omitempty"` 18 | Locale string `json:"locale,omitempty"` 19 | Middlename string `json:"middlename,omitempty"` 20 | Mobile string `json:"mobile,omitempty"` 21 | Name string `json:"name,omitempty"` 22 | State string `json:"state,omitempty"` 23 | Surname string `json:"surname,omitempty"` 24 | } `json:"info,omitempty"` 25 | } 26 | 27 | func (a *AccountService) Get() (*Account, *http.Response, error) { 28 | 29 | account := new(Account) 30 | 31 | res, err := a.client.ExecuteRequest("GET", "account", []byte{}, account) 32 | 33 | return account, res, err 34 | } 35 | -------------------------------------------------------------------------------- /account_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAccountService_Get(t *testing.T) { 8 | 9 | token, err := GetToken() 10 | if err != nil { 11 | t.Error(err) 12 | return 13 | } 14 | 15 | client := NewClient(token) 16 | account, _, err := client.Account.Get() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | if account.Info.Name == "" { 23 | t.Error("Account name is empty") 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | -------------------------------------------------------------------------------- /background.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type BackgroundService struct { 8 | client Client 9 | } 10 | 11 | type Location struct { 12 | Active bool `json:"active,omitempty"` 13 | PrivateNetworking bool `json:"private_networking,omitempty"` 14 | Image []string `json:"image,omitempty"` 15 | ID string `json:"id,omitempty"` 16 | Description string `json:"description,omitempty"` 17 | Rplans []string `json:"rplans,omitempty"` 18 | } 19 | 20 | type Image struct { 21 | Rplans []string `json:"rplans,omitempty"` 22 | Active bool `json:"active,omitempty"` 23 | Size int64 `json:"size,omitempty"` 24 | Locations []string `json:"locations,omitempty"` 25 | ID string `json:"id,omitempty"` 26 | Description string `json:"description,omitempty"` 27 | } 28 | 29 | func (b *BackgroundService) ListLocations() (*[]Location, *http.Response, error) { 30 | 31 | dcs := new([]Location) 32 | 33 | res, err := b.client.ExecuteRequest("GET", "locations", []byte{}, dcs) 34 | 35 | return dcs, res, err 36 | } 37 | 38 | func (b *BackgroundService) ListImages() (*[]Image, *http.Response, error) { 39 | 40 | images := new([]Image) 41 | 42 | res, err := b.client.ExecuteRequest("GET", "images", []byte{}, images) 43 | 44 | return images, res, err 45 | } 46 | -------------------------------------------------------------------------------- /background_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBackgroundService_ListDataCenters(t *testing.T) { 8 | 9 | token, err := GetToken() 10 | if err != nil { 11 | t.Error(err) 12 | return 13 | } 14 | 15 | client := NewClient(token) 16 | dcs, _, err := client.Background.ListLocations() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | if len(*dcs) == 0 { 23 | t.Error("No datacenters received") 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestBackgroundService_ListImages(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | images, _, err := client.Background.ListImages() 41 | if err != nil { 42 | t.Error(err) 43 | return 44 | } 45 | 46 | if len(*images) == 0 { 47 | t.Error("No images received") 48 | return 49 | } 50 | 51 | return 52 | 53 | } 54 | -------------------------------------------------------------------------------- /backup.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | type BackupService struct { 9 | client Client 10 | } 11 | 12 | func (s *BackupService) List() (*[]Backup, *http.Response, error) { 13 | 14 | backups := new([]Backup) 15 | 16 | res, err := s.client.ExecuteRequest("GET", "backups", []byte{}, backups) 17 | 18 | return backups, res, err 19 | } 20 | 21 | func (s *BackupService) Get(BackupID string) (*Backup, *http.Response, error) { 22 | 23 | backup := new(Backup) 24 | 25 | res, err := s.client.ExecuteRequest("GET", fmt.Sprintf("backups/%s", BackupID), []byte{}, backup) 26 | 27 | return backup, res, err 28 | } 29 | 30 | func (s *BackupService) Remove(BackupID string) (*Backup, *http.Response, error) { 31 | 32 | backup := new(Backup) 33 | 34 | res, err := s.client.ExecuteRequest("DELETE", fmt.Sprintf("backups/%s", BackupID), []byte{}, backup) 35 | 36 | return backup, res, err 37 | } 38 | -------------------------------------------------------------------------------- /backup_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBackupService_List(t *testing.T) { 8 | 9 | token, err := GetToken() 10 | if err != nil { 11 | t.Error(err) 12 | return 13 | } 14 | 15 | client := NewClient(token) 16 | _, _, err = client.Backup.List() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | return 23 | 24 | } 25 | 26 | func TestBackupService_Get(t *testing.T) { 27 | 28 | token, err := GetToken() 29 | if err != nil { 30 | t.Error(err) 31 | return 32 | } 33 | 34 | client := NewClient(token) 35 | _, _, err = client.Backup.Get(BackupID) 36 | if err != nil { 37 | t.Error(err) 38 | return 39 | } 40 | 41 | return 42 | 43 | } 44 | 45 | func TestBackupService_Remove(t *testing.T) { 46 | 47 | token, err := GetToken() 48 | if err != nil { 49 | t.Error(err) 50 | return 51 | } 52 | 53 | client := NewClient(token) 54 | _, _, err = client.Backup.Remove(BackupID) 55 | if err != nil { 56 | t.Error(err) 57 | return 58 | } 59 | 60 | return 61 | 62 | } 63 | -------------------------------------------------------------------------------- /billing.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | type BillingService struct { 9 | client Client 10 | } 11 | 12 | type Billing struct { 13 | Balance int64 `json:"balance,omitempty"` 14 | Bonus int64 `json:"bonus,omitempty"` 15 | Status string `json:"status,omitempty"` 16 | Summ int64 `json:"summ,omitempty"` 17 | Unpaid int64 `json:"unpaid,omitempty"` 18 | UserID int64 `json:"user_id,omitempty"` 19 | } 20 | 21 | type Payments struct { 22 | Items []struct { 23 | Created int64 `json:"created,omitempty"` 24 | Desc string `json:"desc,omitempty"` 25 | Dir int64 `json:"dir,omitempty"` 26 | ID int64 `json:"id,omitempty"` 27 | IsBonus int64 `json:"is_bonus,omitempty"` 28 | Price int64 `json:"price,omitempty"` 29 | State int64 `json:"state,omitempty"` 30 | Type int64 `json:"type,omitempty"` 31 | } `json:"items,omitempty"` 32 | Status string `json:"status,omitempty"` 33 | } 34 | 35 | type Consumption struct { 36 | Huge struct { 37 | Count int64 `json:"count,omitempty"` 38 | Summ int64 `json:"summ,omitempty"` 39 | } `json:"huge,omitempty"` 40 | Large struct { 41 | Count int64 `json:"count,omitempty"` 42 | Summ int64 `json:"summ,omitempty"` 43 | } `json:"large,omitempty"` 44 | Medium struct { 45 | Count int64 `json:"count,omitempty"` 46 | Summ int64 `json:"summ,omitempty"` 47 | } `json:"medium,omitempty"` 48 | Monster struct { 49 | Count int64 `json:"count,omitempty"` 50 | Summ int64 `json:"summ,omitempty"` 51 | } `json:"moster,omitempty"` 52 | Small struct { 53 | Count int64 `json:"count,omitempty"` 54 | Summ int64 `json:"summ,omitempty"` 55 | } `json:"small,omitempty"` 56 | Summ int64 `json:"summ,omitempty"` 57 | } 58 | 59 | func (c *BillingService) Billing() (*Billing, *http.Response, error) { 60 | 61 | billing := new(Billing) 62 | 63 | res, err := c.client.ExecuteRequest("GET", "billing/balance", []byte{}, billing) 64 | 65 | return billing, res, err 66 | } 67 | 68 | func (c *BillingService) Payments() (*Payments, *http.Response, error) { 69 | 70 | payments := new(Payments) 71 | 72 | res, err := c.client.ExecuteRequest("GET", "billing/payments/", []byte{}, payments) 73 | 74 | return payments, res, err 75 | } 76 | 77 | func (c *BillingService) Consumption(start, end string) (*map[string]Consumption, *http.Response, error) { 78 | 79 | consumption := make(map[string]Consumption) 80 | 81 | res, err := c.client.ExecuteRequest("GET", fmt.Sprintf("billing/consumption?start=%s&end=%s", start, end), []byte{}, &consumption) 82 | 83 | return &consumption, res, err 84 | } 85 | -------------------------------------------------------------------------------- /billing_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBillingService_Billing(t *testing.T) { 8 | 9 | token, err := GetToken() 10 | if err != nil { 11 | t.Error(err) 12 | return 13 | } 14 | 15 | client := NewClient(token) 16 | billing, _, err := client.Billing.Billing() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | if billing.UserID == 0 { 23 | t.Error("Empty user id") 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestBillingService_Payments(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | _, _, err = client.Billing.Payments() 41 | if err != nil { 42 | t.Error(err) 43 | return 44 | } 45 | 46 | return 47 | 48 | } 49 | 50 | func TestBillingService_Consumption(t *testing.T) { 51 | 52 | token, err := GetToken() 53 | if err != nil { 54 | t.Error(err) 55 | return 56 | } 57 | 58 | client := NewClient(token) 59 | _, _, err = client.Billing.Consumption("2016-06-01", "2016-06-30") 60 | if err != nil { 61 | t.Error(err) 62 | return 63 | } 64 | 65 | return 66 | 67 | } 68 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "github.com/gorilla/websocket" 9 | "io" 10 | "io/ioutil" 11 | "log" 12 | "net/http" 13 | "net/url" 14 | ) 15 | 16 | // Interface of Client for mocking data receiving in tests 17 | type Client interface { 18 | ExecuteRequest(method, url string, body []byte, object interface{}) (*http.Response, error) 19 | WSSConn() (*websocket.Conn, error) 20 | WaitTask(c *websocket.Conn, taskID string) (bool, error) 21 | } 22 | 23 | type WebClient struct { 24 | Token string 25 | HTTPClient *http.Client 26 | 27 | // TODO Change to type url 28 | // In fact it is host url and API version, example: https://api.vscale.io/v1/ 29 | BaseURL string 30 | 31 | // Services which is used for accessing API 32 | Account *AccountService 33 | Scalet *ScaletService 34 | Background *BackgroundService 35 | Configuration *ConfigurationService 36 | SSHKey *SSHKeyService 37 | Notification *NotificationService 38 | Billing *BillingService 39 | Domain *DomainService 40 | DomainRecord *DomainRecordService 41 | DomainTag *DomainTagService 42 | PTRRecord *PTRRecordService 43 | Backup *BackupService 44 | ServerTag *ServerTagService 45 | } 46 | 47 | type Error struct { 48 | Error string `json:"error,omitempty"` 49 | Field string `json:"field,omitempty"` 50 | } 51 | 52 | // Web client creating 53 | func NewClient(token string) *WebClient { 54 | 55 | // TODO Maybe it will be better to check if token is empty 56 | 57 | client := &WebClient{ 58 | Token: token, 59 | HTTPClient: new(http.Client), 60 | BaseURL: "https://api.vscale.io/v1/", 61 | } 62 | 63 | // TODO Maybe it will be better to add account checking here via token, to be sure that token is valid and user exists 64 | 65 | // Passing client to all services for easy client mocking in future and not passing it to every function 66 | client.Account = &AccountService{client} 67 | client.Scalet = &ScaletService{client} 68 | client.Background = &BackgroundService{client} 69 | client.Configuration = &ConfigurationService{client} 70 | client.SSHKey = &SSHKeyService{client} 71 | client.Notification = &NotificationService{client} 72 | client.Billing = &BillingService{client} 73 | client.Domain = &DomainService{client} 74 | client.DomainRecord = &DomainRecordService{client} 75 | client.DomainTag = &DomainTagService{client} 76 | client.PTRRecord = &PTRRecordService{client} 77 | client.Backup = &BackupService{client} 78 | client.ServerTag = &ServerTagService{client} 79 | 80 | return client 81 | 82 | } 83 | 84 | // Executing HTTP Request (receiving info from API) 85 | func (client *WebClient) ExecuteRequest(method, url string, body []byte, object interface{}) (*http.Response, error) { 86 | 87 | req, err := http.NewRequest(method, fmt.Sprint(client.BaseURL, url), bytes.NewBuffer(body)) 88 | if err != nil { 89 | return new(http.Response), err 90 | } 91 | 92 | req.Header.Set("X-Token", client.Token) 93 | req.Header.Set("Content-Type", "application/json;charset=utf-8") 94 | 95 | res, err := client.HTTPClient.Do(req) 96 | if err != nil { 97 | return res, err 98 | } 99 | defer res.Body.Close() 100 | 101 | // Cloning response body for future using 102 | buf, _ := ioutil.ReadAll(res.Body) 103 | reader := ioutil.NopCloser(bytes.NewBuffer(buf)) 104 | 105 | res.Body = ioutil.NopCloser(bytes.NewBuffer(buf)) 106 | 107 | if res.Header.Get("Vscale-Error-Message") != "None" && res.Header.Get("Vscale-Error-Message") != "" { 108 | return res, errors.New(res.Header.Get("Vscale-Error-Message")) 109 | } 110 | 111 | if !IsSuccess(res.StatusCode) { 112 | return res, errors.New("Not successful status code") 113 | } 114 | 115 | if object != nil && (res.StatusCode == 200 || res.StatusCode == 201) { 116 | err := json.NewDecoder(reader).Decode(object) 117 | 118 | // EOF means empty response body, this error is not needed 119 | if err != nil && err != io.EOF { 120 | log.Println(err) 121 | return res, err 122 | } 123 | } 124 | 125 | return res, nil 126 | } 127 | 128 | func (client *WebClient) WSSConn() (*websocket.Conn, error) { 129 | u := url.URL{Scheme: "wss", Host: "ws.api.vscale.io", Path: "/v1/ws"} 130 | header := http.Header{} 131 | header["X-Token"] = []string{client.Token} 132 | c, _, err := websocket.DefaultDialer.Dial(u.String(), header) 133 | if err != nil { 134 | return c, err 135 | } 136 | return c, nil 137 | } 138 | 139 | // Waiting until operation will be complete 140 | func (client *WebClient) WaitTask(c *websocket.Conn, taskID string) (bool, error) { 141 | 142 | defer c.Close() 143 | 144 | msg := struct { 145 | ID int64 `json:"id,omitempty"` 146 | Result struct { 147 | Type string `json:"type,omitempty"` 148 | Error string `json:"error,omitempty"` 149 | Name string `json:"name,omitempty"` 150 | Status string `json:"status,omitempty"` 151 | Message string `json:"message,omitempty"` 152 | Done bool `json:"done,omitempty"` 153 | ID string `json:"id,omitempty"` 154 | } `json:"result,omitempty"` 155 | Time string `json:"time,omitempty"` 156 | }{} 157 | 158 | for { 159 | code, message, err := c.ReadMessage() 160 | if err != nil { 161 | return false, err 162 | } 163 | 164 | if code == 1 { 165 | json.Unmarshal(message, &msg) 166 | 167 | if msg.Result.ID == taskID && msg.Result.Done == true { 168 | if msg.Result.Error != "" { 169 | return false, errors.New(msg.Result.Error) 170 | } 171 | return true, nil 172 | } 173 | 174 | } 175 | 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /configuration.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | type ConfigurationService struct { 8 | client Client 9 | } 10 | 11 | type Rplan struct { 12 | Addresses int64 `json:"addresses,omitempty"` 13 | CPUs int64 `json:"cpus,omitempty"` 14 | Locations []string `json:"locations,omitempty"` 15 | ID string `json:"id,omitempty"` 16 | Memory int64 `json:"memory,omitempty"` 17 | Templates []string `json:"templates,omitempty"` 18 | Network int64 `json:"network,omitempty"` 19 | Disk int64 `json:"disk,omitempty"` 20 | } 21 | 22 | type Prices struct { 23 | Default struct { 24 | Huge struct { 25 | Hour int64 `json:"hour,omitempty"` 26 | Month int64 `json:"month,omitempty"` 27 | } `json:"huge,omitempty"` 28 | Large struct { 29 | Hour int64 `json:"hour,omitempty"` 30 | Month int64 `json:"month,omitempty"` 31 | } `json:"large,omitempty"` 32 | Medium struct { 33 | Hour int64 `json:"hour,omitempty"` 34 | Month int64 `json:"month,omitempty"` 35 | } `json:"medium,omitempty"` 36 | Monster struct { 37 | Hour int64 `json:"hour,omitempty"` 38 | Month int64 `json:"month,omitempty"` 39 | } `json:"monster,omitempty"` 40 | Network int64 `json:"network,omitempty"` 41 | Small struct { 42 | Hour int64 `json:"hour,omitempty"` 43 | Month int64 `json:"month,omitempty"` 44 | } `json:"small,omitempty"` 45 | Backup20 struct { 46 | Hour int64 `json:"hour,omitempty"` 47 | Month int64 `json:"month,omitempty"` 48 | } `json:"backup_20,omitempty"` 49 | Backup30 struct { 50 | Hour int64 `json:"hour,omitempty"` 51 | Month int64 `json:"month,omitempty"` 52 | } `json:"backup_30,omitempty"` 53 | Backup40 struct { 54 | Hour int64 `json:"hour,omitempty"` 55 | Month int64 `json:"month,omitempty"` 56 | } `json:"backup_40,omitempty"` 57 | Backup60 struct { 58 | Hour int64 `json:"hour,omitempty"` 59 | Month int64 `json:"month,omitempty"` 60 | } `json:"backup_60,omitempty"` 61 | Backup80 struct { 62 | Hour int64 `json:"hour,omitempty"` 63 | Month int64 `json:"month,omitempty"` 64 | } `json:"backup_80,omitempty"` 65 | } `json:"default,omitempty"` 66 | Period string `json:"period,omitempty"` 67 | } 68 | 69 | func (c *ConfigurationService) ListRplans() (*[]Rplan, *http.Response, error) { 70 | 71 | rplans := new([]Rplan) 72 | 73 | res, err := c.client.ExecuteRequest("GET", "rplans", []byte{}, rplans) 74 | 75 | return rplans, res, err 76 | } 77 | 78 | func (c *ConfigurationService) ListPrices() (*Prices, *http.Response, error) { 79 | 80 | prices := new(Prices) 81 | 82 | res, err := c.client.ExecuteRequest("GET", "billing/prices", []byte{}, prices) 83 | 84 | return prices, res, err 85 | } 86 | -------------------------------------------------------------------------------- /configuration_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestConfigurationService_ListRplans(t *testing.T) { 8 | 9 | token, err := GetToken() 10 | if err != nil { 11 | t.Error(err) 12 | return 13 | } 14 | 15 | client := NewClient(token) 16 | rplans, _, err := client.Configuration.ListRplans() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | if len(*rplans) == 0 { 23 | t.Error("No plans received") 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestConfigurationService_ListPrices(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | _, _, err = client.Configuration.ListPrices() 41 | if err != nil { 42 | t.Error(err) 43 | return 44 | } 45 | 46 | return 47 | 48 | } 49 | -------------------------------------------------------------------------------- /domain.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type DomainService struct { 11 | client Client 12 | } 13 | 14 | type Domain struct { 15 | ID int64 `json:"id,omitempty"` 16 | ChangeDate int64 `json:"change_date,omitempty"` 17 | CreateDate int64 `json:"create_date,omitempty"` 18 | Name string `json:"name,omitempty"` 19 | Tags []DomainTag `json:"tags,omitempty"` 20 | UserID int64 `json:"user_id,omitempty"` 21 | } 22 | 23 | func (d *DomainService) List() (*[]Domain, *http.Response, error) { 24 | 25 | domains := new([]Domain) 26 | 27 | res, err := d.client.ExecuteRequest("GET", "domains/", []byte{}, domains) 28 | 29 | return domains, res, err 30 | } 31 | 32 | func (d *DomainService) Create(name string) (*Domain, *http.Response, error) { 33 | 34 | // TODO Add bind zone 35 | 36 | domain := new(Domain) 37 | 38 | body := struct { 39 | Name string `json:"name,omitempty"` 40 | }{name} 41 | 42 | b, _ := json.Marshal(body) 43 | 44 | res, err := d.client.ExecuteRequest("POST", "domains/", b, domain) 45 | 46 | return domain, res, err 47 | } 48 | 49 | func (d *DomainService) Get(domainID int64) (*Domain, *http.Response, error) { 50 | 51 | domain := new(Domain) 52 | 53 | res, err := d.client.ExecuteRequest("GET", fmt.Sprint("domains/", strconv.FormatInt(domainID, 10)), []byte{}, domain) 54 | 55 | return domain, res, err 56 | } 57 | 58 | func (d *DomainService) Update(domainID int64, tags []int64) (*Domain, *http.Response, error) { 59 | 60 | domain := new(Domain) 61 | 62 | body := struct { 63 | Tags []int64 `json:"tags,omitempty"` 64 | }{tags} 65 | 66 | b, _ := json.Marshal(body) 67 | 68 | res, err := d.client.ExecuteRequest("PATCH", fmt.Sprint("domains/", strconv.FormatInt(domainID, 10)), b, domain) 69 | 70 | return domain, res, err 71 | } 72 | 73 | func (d *DomainService) Remove(domainID int64) (bool, *http.Response, error) { 74 | 75 | res, err := d.client.ExecuteRequest("DELETE", fmt.Sprint("domains/", strconv.FormatInt(domainID, 10)), []byte{}, struct{}{}) 76 | 77 | if err != nil { 78 | return false, res, err 79 | } 80 | 81 | return true, res, err 82 | } 83 | -------------------------------------------------------------------------------- /domain_record.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type DomainRecordService struct { 11 | client Client 12 | } 13 | 14 | type DomainRecord struct { 15 | TTL int64 `json:"ttl,omitempty"` 16 | Name string `json:"name,omitempty"` 17 | Type string `json:"type,omitempty"` 18 | ID int64 `json:"id,omitempty"` 19 | Content string `json:"content,omitempty"` 20 | } 21 | 22 | func (d *DomainRecordService) List(domainID int64) (*[]DomainRecord, *http.Response, error) { 23 | 24 | domainRecords := new([]DomainRecord) 25 | 26 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/") 27 | 28 | res, err := d.client.ExecuteRequest("GET", url, []byte{}, domainRecords) 29 | 30 | return domainRecords, res, err 31 | } 32 | 33 | func (d *DomainRecordService) Create(domainID int64, name, recordType string, ttl int64, content string) (*DomainRecord, *http.Response, error) { 34 | 35 | domainRecord := new(DomainRecord) 36 | 37 | body := struct { 38 | Name string `json:"name,omitempty"` 39 | Type string `json:"type,omitempty"` 40 | TTL int64 `json:"ttl,omitempty"` 41 | Content string `json:"content,omitempty"` 42 | }{name, recordType, ttl, content} 43 | 44 | b, _ := json.Marshal(body) 45 | 46 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/") 47 | 48 | res, err := d.client.ExecuteRequest("POST", url, b, domainRecord) 49 | 50 | return domainRecord, res, err 51 | } 52 | 53 | func (d *DomainRecordService) CreateSOA(domainID int64, name string, ttl int64, content, email string) (*DomainRecord, *http.Response, error) { 54 | 55 | domainRecord := new(DomainRecord) 56 | 57 | body := struct { 58 | Name string `json:"name,omitempty"` 59 | Type string `json:"type,omitempty"` 60 | TTL int64 `json:"ttl,omitempty"` 61 | Content string `json:"content,omitempty"` 62 | Email string `json:"email,omitempty"` 63 | }{name, "SOA", ttl, content, email} 64 | 65 | b, _ := json.Marshal(body) 66 | 67 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/") 68 | 69 | res, err := d.client.ExecuteRequest("POST", url, b, domainRecord) 70 | 71 | return domainRecord, res, err 72 | } 73 | 74 | func (d *DomainRecordService) CreateSRV(domainID int64, name string, ttl, weight, port int64, 75 | target string, priority int64) (*DomainRecord, *http.Response, error) { 76 | 77 | domainRecord := new(DomainRecord) 78 | 79 | body := struct { 80 | Name string `json:"name,omitempty"` 81 | Type string `json:"type,omitempty"` 82 | TTL int64 `json:"ttl,omitempty"` 83 | Weight int64 `json:"weight,omitempty"` 84 | Port int64 `json:"port,omitempty"` 85 | Target string `json:"target,omitempty"` 86 | Priority int64 `json:"priority,omitempty"` 87 | }{name, "SRV", ttl, weight, port, target, priority} 88 | 89 | b, _ := json.Marshal(body) 90 | 91 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/") 92 | 93 | res, err := d.client.ExecuteRequest("POST", url, b, domainRecord) 94 | 95 | return domainRecord, res, err 96 | } 97 | 98 | func (d *DomainRecordService) CreateMX(domainID int64, name string, ttl int64, content string, priority int64) (*DomainRecord, *http.Response, error) { 99 | 100 | domainRecord := new(DomainRecord) 101 | 102 | body := struct { 103 | Name string `json:"name,omitempty"` 104 | Type string `json:"type,omitempty"` 105 | TTL int64 `json:"ttl,omitempty"` 106 | Content string `json:"content,omitempty"` 107 | Priority int64 `json:"priority,omitempty"` 108 | }{name, "MX", ttl, content, priority} 109 | 110 | b, _ := json.Marshal(body) 111 | 112 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/") 113 | 114 | res, err := d.client.ExecuteRequest("POST", url, b, domainRecord) 115 | 116 | return domainRecord, res, err 117 | } 118 | 119 | func (d *DomainRecordService) Update(domainID, recordID int64, name, recordType string, ttl int64, content string) (*DomainRecord, *http.Response, error) { 120 | 121 | domainRecord := new(DomainRecord) 122 | 123 | body := struct { 124 | Name string `json:"name,omitempty"` 125 | Type string `json:"type,omitempty"` 126 | TTL int64 `json:"ttl,omitempty"` 127 | Content string `json:"content,omitempty"` 128 | }{name, recordType, ttl, content} 129 | 130 | b, _ := json.Marshal(body) 131 | 132 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 133 | 134 | res, err := d.client.ExecuteRequest("PUT", url, b, domainRecord) 135 | 136 | return domainRecord, res, err 137 | } 138 | 139 | func (d *DomainRecordService) UpdateSOA(domainID, recordID int64, name string, ttl int64, content, email string) (*DomainRecord, *http.Response, error) { 140 | 141 | domainRecord := new(DomainRecord) 142 | 143 | body := struct { 144 | Name string `json:"name,omitempty"` 145 | Type string `json:"type,omitempty"` 146 | TTL int64 `json:"ttl,omitempty"` 147 | Content string `json:"content,omitempty"` 148 | Email string `json:"email,omitempty"` 149 | }{name, "SOA", ttl, content, email} 150 | 151 | b, _ := json.Marshal(body) 152 | 153 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 154 | 155 | res, err := d.client.ExecuteRequest("PUT", url, b, domainRecord) 156 | 157 | return domainRecord, res, err 158 | } 159 | 160 | func (d *DomainRecordService) UpdateSRV(domainID, recordID int64, name string, ttl, weight, port int64, 161 | target string, priority int64) (*DomainRecord, *http.Response, error) { 162 | 163 | domainRecord := new(DomainRecord) 164 | 165 | body := struct { 166 | Name string `json:"name,omitempty"` 167 | Type string `json:"type,omitempty"` 168 | TTL int64 `json:"ttl,omitempty"` 169 | Weight int64 `json:"weight,omitempty"` 170 | Port int64 `json:"port,omitempty"` 171 | Target string `json:"target,omitempty"` 172 | Priority int64 `json:"priority,omitempty"` 173 | }{name, "SRV", ttl, weight, port, target, priority} 174 | 175 | b, _ := json.Marshal(body) 176 | 177 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 178 | 179 | res, err := d.client.ExecuteRequest("PUT", url, b, domainRecord) 180 | 181 | return domainRecord, res, err 182 | } 183 | 184 | func (d *DomainRecordService) UpdateMX(domainID, recordID int64, name string, ttl int64, content string, 185 | priority int64) (*DomainRecord, *http.Response, error) { 186 | 187 | domainRecord := new(DomainRecord) 188 | 189 | body := struct { 190 | Name string `json:"name,omitempty"` 191 | Type string `json:"type,omitempty"` 192 | TTL int64 `json:"ttl,omitempty"` 193 | Content string `json:"content,omitempty"` 194 | Priority int64 `json:"priority,omitempty"` 195 | }{name, "MX", ttl, content, priority} 196 | 197 | b, _ := json.Marshal(body) 198 | 199 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 200 | 201 | res, err := d.client.ExecuteRequest("PUT", url, b, domainRecord) 202 | 203 | return domainRecord, res, err 204 | } 205 | 206 | func (d *DomainRecordService) Get(domainID, recordID int64) (*DomainRecord, *http.Response, error) { 207 | 208 | domainRecord := new(DomainRecord) 209 | 210 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 211 | 212 | res, err := d.client.ExecuteRequest("GET", url, []byte{}, domainRecord) 213 | 214 | return domainRecord, res, err 215 | } 216 | 217 | func (d *DomainRecordService) Remove(domainID, recordID int64) (*DomainRecord, *http.Response, error) { 218 | 219 | domainRecord := new(DomainRecord) 220 | 221 | url := fmt.Sprint("domains/", strconv.FormatInt(domainID, 10), "/records/", strconv.FormatInt(recordID, 10)) 222 | 223 | res, err := d.client.ExecuteRequest("DELETE", url, []byte{}, domainRecord) 224 | 225 | return domainRecord, res, err 226 | } 227 | -------------------------------------------------------------------------------- /domain_record_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var DomainRecordName string = "example.com" 8 | var DomainRecordID int64 = 13644 9 | var DomainRecordContent string = "3.1.3.37" 10 | var SOAEmail string = "gofort@example.com" 11 | 12 | func TestDomainRecordService_List(t *testing.T) { 13 | 14 | token, err := GetToken() 15 | if err != nil { 16 | t.Error(err) 17 | return 18 | } 19 | 20 | client := NewClient(token) 21 | _, _, err = client.DomainRecord.List(TestDomainID) 22 | if err != nil { 23 | t.Error(err) 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestDomainRecordService_Create(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | record, _, err := client.DomainRecord.Create(TestDomainID, DomainRecordName, "A", 300, "3.1.3.37") 41 | if err != nil { 42 | t.Error(err) 43 | return 44 | } 45 | 46 | if record.Name == "" { 47 | t.Error("Record name can't be empty") 48 | return 49 | } 50 | 51 | return 52 | 53 | } 54 | 55 | func TestDomainRecordService_CreateSOA(t *testing.T) { 56 | 57 | // TODO Doesn't work, reason: unknown, response: {"error": "cant_add_soa"} 58 | 59 | token, err := GetToken() 60 | if err != nil { 61 | t.Error(err) 62 | return 63 | } 64 | 65 | client := NewClient(token) 66 | record, _, err := client.DomainRecord.CreateSOA(TestDomainID, DomainRecordName, 300, DomainRecordContent, SOAEmail) 67 | if err != nil { 68 | t.Error(err) 69 | return 70 | } 71 | 72 | if record.Name == "" { 73 | t.Error("Record name can't be empty") 74 | return 75 | } 76 | 77 | return 78 | 79 | } 80 | 81 | func TestDomainRecordService_CreateSRV(t *testing.T) { 82 | 83 | token, err := GetToken() 84 | if err != nil { 85 | t.Error(err) 86 | return 87 | } 88 | 89 | client := NewClient(token) 90 | record, _, err := client.DomainRecord.CreateSRV(TestDomainID, DomainRecordName, 300, 3000, 3000, "example.com", 1) 91 | if err != nil { 92 | t.Error(err) 93 | return 94 | } 95 | 96 | if record.Name == "" { 97 | t.Error("Record name can't be empty") 98 | return 99 | } 100 | 101 | return 102 | 103 | } 104 | 105 | func TestDomainRecordService_CreateMX(t *testing.T) { 106 | 107 | token, err := GetToken() 108 | if err != nil { 109 | t.Error(err) 110 | return 111 | } 112 | 113 | client := NewClient(token) 114 | record, _, err := client.DomainRecord.CreateMX(TestDomainID, DomainRecordName, 300, "example.com", 1) 115 | if err != nil { 116 | t.Error(err) 117 | return 118 | } 119 | 120 | if record.Name == "" { 121 | t.Error("Record name can't be empty") 122 | return 123 | } 124 | 125 | return 126 | 127 | } 128 | 129 | func TestDomainRecordService_Update(t *testing.T) { 130 | 131 | token, err := GetToken() 132 | if err != nil { 133 | t.Error(err) 134 | return 135 | } 136 | 137 | client := NewClient(token) 138 | record, _, err := client.DomainRecord.Update(TestDomainID, DomainRecordID, DomainRecordName, "A", 300, "3.1.3.38") 139 | if err != nil { 140 | t.Error(err) 141 | return 142 | } 143 | 144 | if record.Name == "" { 145 | t.Error("Record name can't be empty") 146 | return 147 | } 148 | 149 | return 150 | 151 | } 152 | 153 | func TestDomainRecordService_UpdateSOA(t *testing.T) { 154 | 155 | token, err := GetToken() 156 | if err != nil { 157 | t.Error(err) 158 | return 159 | } 160 | 161 | client := NewClient(token) 162 | record, _, err := client.DomainRecord.UpdateSOA(TestDomainID, DomainRecordID, DomainRecordName, 300, DomainRecordContent, SOAEmail) 163 | if err != nil { 164 | t.Error(err) 165 | return 166 | } 167 | 168 | if record.Name == "" { 169 | t.Error("Record name can't be empty") 170 | return 171 | } 172 | 173 | return 174 | 175 | } 176 | 177 | func TestDomainRecordService_UpdateSRV(t *testing.T) { 178 | 179 | token, err := GetToken() 180 | if err != nil { 181 | t.Error(err) 182 | return 183 | } 184 | 185 | client := NewClient(token) 186 | record, _, err := client.DomainRecord.UpdateSRV(TestDomainID, DomainRecordID, DomainRecordName, 300, 3000, 3000, "example.com", 1) 187 | if err != nil { 188 | t.Error(err) 189 | return 190 | } 191 | 192 | if record.Name == "" { 193 | t.Error("Record name can't be empty") 194 | return 195 | } 196 | 197 | return 198 | 199 | } 200 | 201 | func TestDomainRecordService_UpdateMX(t *testing.T) { 202 | 203 | token, err := GetToken() 204 | if err != nil { 205 | t.Error(err) 206 | return 207 | } 208 | 209 | client := NewClient(token) 210 | record, _, err := client.DomainRecord.UpdateMX(TestDomainID, DomainRecordID, DomainRecordName, 300, "example.com", 1) 211 | if err != nil { 212 | t.Error(err) 213 | return 214 | } 215 | 216 | if record.Name == "" { 217 | t.Error("Record name can't be empty") 218 | return 219 | } 220 | 221 | return 222 | 223 | } 224 | 225 | func TestDomainRecordService_Get(t *testing.T) { 226 | 227 | token, err := GetToken() 228 | if err != nil { 229 | t.Error(err) 230 | return 231 | } 232 | 233 | client := NewClient(token) 234 | record, _, err := client.DomainRecord.Get(TestDomainID, DomainRecordID) 235 | if err != nil { 236 | t.Error(err) 237 | return 238 | } 239 | 240 | if record.Name == "" { 241 | t.Error("Record name can't be empty") 242 | return 243 | } 244 | 245 | return 246 | 247 | } 248 | 249 | func TestDomainRecordService_Remove(t *testing.T) { 250 | 251 | token, err := GetToken() 252 | if err != nil { 253 | t.Error(err) 254 | return 255 | } 256 | 257 | client := NewClient(token) 258 | _, _, err = client.DomainRecord.Remove(TestDomainID, DomainRecordID) 259 | if err != nil { 260 | t.Error(err) 261 | return 262 | } 263 | 264 | return 265 | 266 | } 267 | -------------------------------------------------------------------------------- /domain_tags.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type DomainTagService struct { 11 | client Client 12 | } 13 | 14 | type DomainTag struct { 15 | Name string `json:"name,omitempty"` 16 | Domains []int64 `json:"domains,omitempty"` 17 | ID int64 `json:"id,omitempty"` 18 | } 19 | 20 | type DomainTagInfo struct { 21 | Name string `json:"name,omitempty"` 22 | Domains []Domain `json:"domains,omitempty"` 23 | ID int64 `json:"id,omitempty"` 24 | } 25 | 26 | func (d *DomainTagService) Create(name string, domains []int64) (*DomainTag, *http.Response, error) { 27 | 28 | domainTag := new(DomainTag) 29 | 30 | body := struct { 31 | Name string `json:"name,omitempty"` 32 | Domains []int64 `json:"domains,omitempty"` 33 | }{name, domains} 34 | 35 | b, _ := json.Marshal(body) 36 | 37 | res, err := d.client.ExecuteRequest("POST", "domains/tags/", b, domainTag) 38 | 39 | return domainTag, res, err 40 | } 41 | 42 | func (d *DomainTagService) List() (*[]DomainTag, *http.Response, error) { 43 | 44 | domainTags := new([]DomainTag) 45 | 46 | res, err := d.client.ExecuteRequest("GET", "domains/tags/", []byte{}, domainTags) 47 | 48 | return domainTags, res, err 49 | } 50 | 51 | func (d *DomainTagService) Get(tagID int64) (*DomainTagInfo, *http.Response, error) { 52 | 53 | domainTag := new(DomainTagInfo) 54 | 55 | url := fmt.Sprint("domains/tags/", strconv.FormatInt(tagID, 10)) 56 | 57 | res, err := d.client.ExecuteRequest("GET", url, []byte{}, domainTag) 58 | 59 | return domainTag, res, err 60 | } 61 | 62 | func (d *DomainTagService) Update(tagID int64, name string, domains []int64) (*DomainTag, *http.Response, error) { 63 | 64 | domainTag := new(DomainTag) 65 | 66 | body := struct { 67 | Name string `json:"name,omitempty"` 68 | Domains []int64 `json:"domains,omitempty"` 69 | }{name, domains} 70 | 71 | b, _ := json.Marshal(body) 72 | 73 | url := fmt.Sprint("domains/tags/", strconv.FormatInt(tagID, 10)) 74 | 75 | res, err := d.client.ExecuteRequest("PUT", url, b, domainTag) 76 | 77 | return domainTag, res, err 78 | } 79 | 80 | func (d *DomainTagService) Remove(tagID int64) (bool, *http.Response, error) { 81 | 82 | url := fmt.Sprint("domains/tags/", strconv.FormatInt(tagID, 10)) 83 | 84 | res, err := d.client.ExecuteRequest("DELETE", url, []byte{}, struct{}{}) 85 | 86 | if err != nil { 87 | return false, res, err 88 | } 89 | 90 | return true, res, err 91 | } 92 | -------------------------------------------------------------------------------- /domain_tags_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var DomainsTagName string = "group_2" 8 | var DomainsTagID int64 = 3 9 | 10 | func TestDomainTagService_Create(t *testing.T) { 11 | 12 | token, err := GetToken() 13 | if err != nil { 14 | t.Error(err) 15 | return 16 | } 17 | 18 | client := NewClient(token) 19 | tag, _, err := client.DomainTag.Create(DomainsTagName, []int64{TestDomainID}) 20 | if err != nil { 21 | t.Error(err) 22 | return 23 | } 24 | 25 | if tag.Name == "" { 26 | t.Error("Tag name can't be empty") 27 | return 28 | } 29 | 30 | return 31 | 32 | } 33 | 34 | func TestDomainTagService_List(t *testing.T) { 35 | 36 | token, err := GetToken() 37 | if err != nil { 38 | t.Error(err) 39 | return 40 | } 41 | 42 | client := NewClient(token) 43 | _, _, err = client.DomainTag.List() 44 | if err != nil { 45 | t.Error(err) 46 | return 47 | } 48 | 49 | return 50 | 51 | } 52 | 53 | func TestDomainTagService_Get(t *testing.T) { 54 | 55 | token, err := GetToken() 56 | if err != nil { 57 | t.Error(err) 58 | return 59 | } 60 | 61 | client := NewClient(token) 62 | tag, _, err := client.DomainTag.Get(DomainsTagID) 63 | if err != nil { 64 | t.Error(err) 65 | return 66 | } 67 | 68 | if tag.Name == "" { 69 | t.Error("Tag name can't be empty") 70 | return 71 | } 72 | 73 | return 74 | 75 | } 76 | 77 | func TestDomainTagService_Update(t *testing.T) { 78 | 79 | token, err := GetToken() 80 | if err != nil { 81 | t.Error(err) 82 | return 83 | } 84 | 85 | client := NewClient(token) 86 | tag, _, err := client.DomainTag.Update(DomainsTagID, "new_name", []int64{2541}) 87 | if err != nil { 88 | t.Error(err) 89 | return 90 | } 91 | 92 | if tag.Name == "" { 93 | t.Error("Tag name can't be empty") 94 | return 95 | } 96 | 97 | return 98 | 99 | } 100 | 101 | func TestDomainTagService_Remove(t *testing.T) { 102 | 103 | token, err := GetToken() 104 | if err != nil { 105 | t.Error(err) 106 | return 107 | } 108 | 109 | client := NewClient(token) 110 | _, _, err = client.DomainTag.Remove(DomainsTagID) 111 | if err != nil { 112 | t.Error(err) 113 | return 114 | } 115 | 116 | return 117 | 118 | } 119 | -------------------------------------------------------------------------------- /domain_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var TestDomain string = "example.com" 8 | var TestDomainID int64 = 2540 9 | var DomainTags []int64 = []int64{543} 10 | 11 | func TestDomainService_List(t *testing.T) { 12 | 13 | token, err := GetToken() 14 | if err != nil { 15 | t.Error(err) 16 | return 17 | } 18 | 19 | client := NewClient(token) 20 | _, _, err = client.Domain.List() 21 | if err != nil { 22 | t.Error(err) 23 | return 24 | } 25 | 26 | return 27 | 28 | } 29 | 30 | func TestDomainService_Create(t *testing.T) { 31 | 32 | token, err := GetToken() 33 | if err != nil { 34 | t.Error(err) 35 | return 36 | } 37 | 38 | client := NewClient(token) 39 | domain, _, err := client.Domain.Create(TestDomain) 40 | if err != nil { 41 | t.Error(err) 42 | return 43 | } 44 | 45 | if domain.ID == 0 { 46 | t.Error("Domain ID can not be empty") 47 | return 48 | } 49 | 50 | return 51 | 52 | } 53 | 54 | func TestDomainService_Get(t *testing.T) { 55 | 56 | token, err := GetToken() 57 | if err != nil { 58 | t.Error(err) 59 | return 60 | } 61 | 62 | client := NewClient(token) 63 | domain, _, err := client.Domain.Get(TestDomainID) 64 | if err != nil { 65 | t.Error(err) 66 | return 67 | } 68 | 69 | if domain.ID == 0 { 70 | t.Error("Domain ID can not be empty") 71 | return 72 | } 73 | 74 | return 75 | 76 | } 77 | 78 | func TestDomainService_Update(t *testing.T) { 79 | 80 | token, err := GetToken() 81 | if err != nil { 82 | t.Error(err) 83 | return 84 | } 85 | 86 | client := NewClient(token) 87 | domain, _, err := client.Domain.Update(TestDomainID, DomainTags) 88 | if err != nil { 89 | t.Error(err) 90 | return 91 | } 92 | 93 | if domain.ID == 0 { 94 | t.Error("Domain ID can not be empty") 95 | return 96 | } 97 | 98 | return 99 | 100 | } 101 | 102 | func TestDomainService_Remove(t *testing.T) { 103 | 104 | token, err := GetToken() 105 | if err != nil { 106 | t.Error(err) 107 | return 108 | } 109 | 110 | client := NewClient(token) 111 | status, _, err := client.Domain.Remove(TestDomainID) 112 | if err != nil { 113 | t.Error(err) 114 | return 115 | } 116 | 117 | if !status { 118 | t.Fail() 119 | return 120 | } 121 | 122 | return 123 | 124 | } 125 | -------------------------------------------------------------------------------- /notification.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | type NotificationService struct { 9 | client Client 10 | } 11 | 12 | type Notification struct { 13 | NotifyBalance int64 `json:"notify_balance,omitempty"` 14 | Status string `json:"status,omitempty"` 15 | } 16 | 17 | func (n *NotificationService) BillingSettings() (*Notification, *http.Response, error) { 18 | 19 | notification := new(Notification) 20 | 21 | res, err := n.client.ExecuteRequest("GET", "billing/notify", []byte{}, notification) 22 | 23 | return notification, res, err 24 | } 25 | 26 | func (n *NotificationService) BillingSettingsUpdate(notifyBalance int64) (*Notification, *http.Response, error) { 27 | 28 | // TODO Doesn't work because API don't use JSON in this case 29 | 30 | notification := new(Notification) 31 | 32 | body := struct { 33 | NotifyBalance int64 `json:"notify_balance,omitempty"` 34 | }{notifyBalance} 35 | 36 | b, _ := json.Marshal(body) 37 | 38 | res, err := n.client.ExecuteRequest("PUT", "billing/notify", b, notification) 39 | 40 | return notification, res, err 41 | } 42 | -------------------------------------------------------------------------------- /notification_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | "testing" 7 | ) 8 | 9 | // Test data 10 | var BillingLimit int64 = 10000 11 | 12 | func TestNotificationService_BillingSettings(t *testing.T) { 13 | 14 | token, err := GetToken() 15 | if err != nil { 16 | t.Error(err) 17 | return 18 | } 19 | 20 | client := NewClient(token) 21 | _, _, err = client.Notification.BillingSettings() 22 | if err != nil { 23 | t.Error(err) 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestNotificationService_BillingSettingsUpdate(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | _, res, err := client.Notification.BillingSettingsUpdate(BillingLimit) 41 | data, _ := ioutil.ReadAll(res.Body) 42 | log.Println(string(data)) 43 | if err != nil { 44 | t.Error(err) 45 | return 46 | } 47 | 48 | return 49 | 50 | } 51 | -------------------------------------------------------------------------------- /ptr_records.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type PTRRecordService struct { 11 | client Client 12 | } 13 | 14 | type PTRRecord struct { 15 | Content string `json:"content,omitempty"` 16 | UserID int64 `json:"user_id,omitempty"` 17 | IP string `json:"ip,omitempty"` 18 | ID int64 `json:"id,omitempty"` 19 | } 20 | 21 | func (p *PTRRecordService) Create(content, ip string) (*PTRRecord, *http.Response, error) { 22 | 23 | ptrRecord := new(PTRRecord) 24 | 25 | body := struct { 26 | Content string `json:"content,omitempty"` 27 | IP string `json:"ip,omitempty"` 28 | }{content, ip} 29 | 30 | b, _ := json.Marshal(body) 31 | 32 | res, err := p.client.ExecuteRequest("POST", "domains/ptr/", b, ptrRecord) 33 | 34 | return ptrRecord, res, err 35 | } 36 | 37 | func (p *PTRRecordService) List() (*[]PTRRecord, *http.Response, error) { 38 | 39 | ptrRecords := new([]PTRRecord) 40 | 41 | res, err := p.client.ExecuteRequest("GET", "domains/ptr/", []byte{}, ptrRecords) 42 | 43 | return ptrRecords, res, err 44 | } 45 | 46 | func (p *PTRRecordService) Get(recordID int64) (*PTRRecord, *http.Response, error) { 47 | 48 | ptrRecord := new(PTRRecord) 49 | 50 | url := fmt.Sprint("domains/ptr/", strconv.FormatInt(recordID, 10)) 51 | 52 | res, err := p.client.ExecuteRequest("GET", url, []byte{}, ptrRecord) 53 | 54 | return ptrRecord, res, err 55 | } 56 | 57 | func (p *PTRRecordService) Update(recordID int64, content, ip string) (*PTRRecord, *http.Response, error) { 58 | 59 | ptrRecord := new(PTRRecord) 60 | 61 | body := struct { 62 | Content string `json:"content,omitempty"` 63 | IP string `json:"ip,omitempty"` 64 | }{content, ip} 65 | 66 | b, _ := json.Marshal(body) 67 | 68 | url := fmt.Sprint("domains/ptr/", strconv.FormatInt(recordID, 10)) 69 | 70 | res, err := p.client.ExecuteRequest("PUT", url, b, ptrRecord) 71 | 72 | return ptrRecord, res, err 73 | } 74 | 75 | func (p *PTRRecordService) Remove(recordID int64) (bool, *http.Response, error) { 76 | 77 | url := fmt.Sprint("domains/ptr/", strconv.FormatInt(recordID, 10)) 78 | 79 | res, err := p.client.ExecuteRequest("DELETE", url, []byte{}, struct{}{}) 80 | 81 | if err != nil { 82 | return false, res, err 83 | } 84 | 85 | return true, res, err 86 | } 87 | -------------------------------------------------------------------------------- /ptr_records_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var PTRRecordContent string = "example.com" 8 | var PTRRecordIP string = "95.213.195.160" 9 | var PTRRecordID int64 = 2293 10 | 11 | func TestPTRRecordService_Create(t *testing.T) { 12 | 13 | token, err := GetToken() 14 | if err != nil { 15 | t.Error(err) 16 | return 17 | } 18 | 19 | client := NewClient(token) 20 | ptrRecord, _, err := client.PTRRecord.Create("123123", "1232") 21 | if err != nil { 22 | t.Error(err) 23 | return 24 | } 25 | 26 | if ptrRecord.ID == 0 { 27 | t.Error("PTR record id can't be empty") 28 | } 29 | 30 | return 31 | } 32 | 33 | func TestPTRRecordService_List(t *testing.T) { 34 | 35 | token, err := GetToken() 36 | if err != nil { 37 | t.Error(err) 38 | return 39 | } 40 | 41 | client := NewClient(token) 42 | _, _, err = client.PTRRecord.List() 43 | 44 | if err != nil { 45 | t.Error(err) 46 | return 47 | } 48 | 49 | return 50 | } 51 | 52 | func TestPTRRecordService_Get(t *testing.T) { 53 | 54 | token, err := GetToken() 55 | if err != nil { 56 | t.Error(err) 57 | return 58 | } 59 | 60 | client := NewClient(token) 61 | record, _, err := client.PTRRecord.Get(PTRRecordID) 62 | 63 | if err != nil { 64 | t.Error(err) 65 | return 66 | } 67 | 68 | if record.ID == 0 { 69 | t.Error("Record ID can't be empty") 70 | return 71 | } 72 | 73 | return 74 | } 75 | 76 | func TestPTRRecordService_Update(t *testing.T) { 77 | 78 | token, err := GetToken() 79 | if err != nil { 80 | t.Error(err) 81 | return 82 | } 83 | 84 | client := NewClient(token) 85 | ptrRecord, _, err := client.PTRRecord.Update(PTRRecordID, "example2.com", PTRRecordIP) 86 | 87 | if err != nil { 88 | t.Error(err) 89 | return 90 | } 91 | 92 | if ptrRecord.ID == 0 { 93 | t.Error("PTR record id can't be empty") 94 | } 95 | 96 | return 97 | } 98 | 99 | func TestPTRRecordService_Remove(t *testing.T) { 100 | 101 | token, err := GetToken() 102 | if err != nil { 103 | t.Error(err) 104 | return 105 | } 106 | 107 | client := NewClient(token) 108 | _, _, err = client.PTRRecord.Remove(PTRRecordID) 109 | 110 | if err != nil { 111 | t.Error(err) 112 | return 113 | } 114 | 115 | return 116 | } 117 | -------------------------------------------------------------------------------- /scalet.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/gorilla/websocket" 7 | "net/http" 8 | "strconv" 9 | ) 10 | 11 | type ScaletService struct { 12 | client Client 13 | } 14 | 15 | type Scalet struct { 16 | Hostname string `json:"hostname,omitempty"` 17 | Locked bool `json:"locked,omitempty"` 18 | Location string `json:"location,omitempty"` 19 | Rplan string `json:"rplan,omitempty"` 20 | Name string `json:"name,omitempty"` 21 | Active bool `json:"active,omitempty"` 22 | Keys []Keys `json:"keys,omitempty"` 23 | PublicAddresses PublicAddress `json:"public_address,omitempty"` 24 | Status string `json:"status,omitempty"` 25 | MadeFrom string `json:"made_from,omitempty"` 26 | CTID int64 `json:"ctid,omitempty"` 27 | } 28 | 29 | type Backup struct { 30 | ID string `json:"id,omitempty"` 31 | Template string `json:"template,omitempty"` 32 | Active bool `json:"active"` 33 | Name string `json:"name"` 34 | Scalet int64 `json:"scalet"` 35 | Status string `json:"status"` 36 | Size float64 `json:"size"` 37 | Locked bool `json:"locked"` 38 | Location string `json:"location"` 39 | Created string `json:"created"` 40 | } 41 | 42 | type Keys struct { 43 | Name string `json:"name,omitempty"` 44 | ID int64 `json:"id,omitempty"` 45 | } 46 | 47 | type PublicAddress struct { 48 | Netmask string `json:"netmask,omitempty"` 49 | Gateway string `json:"gateway,omitempty"` 50 | Address string `json:"address,omitempty"` 51 | } 52 | 53 | type Task struct { 54 | Location string `json:"location,omitempty"` 55 | DInsert string `json:"d_insert,omitempty"` 56 | ID string `json:"id,omitempty"` 57 | Done bool `json:"done,omitempty"` 58 | Scalet int64 `json:"scalet,omitempty"` 59 | Error bool `json:"error,omitempty"` 60 | DStart string `json:"d_start,omitempty"` 61 | Method string `json:"method,omitempty"` 62 | DEnd string `json:"d_end,omitempty"` 63 | } 64 | 65 | func (s *ScaletService) List() (*[]Scalet, *http.Response, error) { 66 | 67 | scalets := new([]Scalet) 68 | 69 | res, err := s.client.ExecuteRequest("GET", "scalets", []byte{}, scalets) 70 | 71 | return scalets, res, err 72 | } 73 | 74 | func (s *ScaletService) Create(makeFrom, rplan, name, password, location string, doStart bool, 75 | keys []int64, wait bool) (*Scalet, *http.Response, error) { 76 | 77 | scalet := new(Scalet) 78 | 79 | conn := new(websocket.Conn) 80 | var wsserr error 81 | 82 | if wait { 83 | conn, wsserr = s.client.WSSConn() 84 | defer conn.Close() 85 | } 86 | 87 | body := struct { 88 | MakeFrom string `json:"make_from,omitempty"` 89 | Rplan string `json:"rplan,omitempty"` 90 | DoStart bool `json:"do_start,omitempty"` 91 | Name string `json:"name,omitempty"` 92 | Keys []int64 `json:"keys,omitempty"` 93 | Password string `json:"password,omitempty"` 94 | Location string `json:"location,omitempty"` 95 | }{makeFrom, rplan, doStart, name, keys, password, location} 96 | 97 | b, _ := json.Marshal(body) 98 | 99 | res, err := s.client.ExecuteRequest("POST", "scalets", b, scalet) 100 | 101 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 102 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 103 | return scalet, res, err 104 | } 105 | 106 | return scalet, res, err 107 | } 108 | 109 | func (s *ScaletService) CreateWithoutPassword(makeFrom, rplan, name, location string, doStart bool, 110 | keys []int64, wait bool) (*Scalet, *http.Response, error) { 111 | 112 | scalet := new(Scalet) 113 | 114 | conn := new(websocket.Conn) 115 | var wsserr error 116 | 117 | if wait { 118 | conn, wsserr = s.client.WSSConn() 119 | defer conn.Close() 120 | } 121 | 122 | body := struct { 123 | MakeFrom string `json:"make_from,omitempty"` 124 | Rplan string `json:"rplan,omitempty"` 125 | DoStart bool `json:"do_start,omitempty"` 126 | Name string `json:"name,omitempty"` 127 | Keys []int64 `json:"keys,omitempty"` 128 | Location string `json:"location,omitempty"` 129 | }{makeFrom, rplan, doStart, name, keys, location} 130 | 131 | b, _ := json.Marshal(body) 132 | 133 | res, err := s.client.ExecuteRequest("POST", "scalets", b, scalet) 134 | 135 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 136 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 137 | return scalet, res, err 138 | } 139 | 140 | return scalet, res, err 141 | } 142 | 143 | func (s *ScaletService) Remove(CTID int64, wait bool) (*Scalet, *http.Response, error) { 144 | 145 | scalet := new(Scalet) 146 | 147 | conn := new(websocket.Conn) 148 | var wsserr error 149 | 150 | if wait { 151 | conn, wsserr = s.client.WSSConn() 152 | defer conn.Close() 153 | } 154 | 155 | res, err := s.client.ExecuteRequest("DELETE", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10)), []byte{}, scalet) 156 | 157 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 158 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 159 | return scalet, res, err 160 | } 161 | 162 | return scalet, res, err 163 | } 164 | 165 | func (s *ScaletService) Get(CTID int64) (*Scalet, *http.Response, error) { 166 | 167 | scalet := new(Scalet) 168 | 169 | res, err := s.client.ExecuteRequest("GET", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10)), []byte{}, scalet) 170 | 171 | return scalet, res, err 172 | } 173 | 174 | func (s *ScaletService) Restart(CTID int64, wait bool) (*Scalet, *http.Response, error) { 175 | 176 | scalet := new(Scalet) 177 | 178 | conn := new(websocket.Conn) 179 | var wsserr error 180 | 181 | if wait { 182 | conn, wsserr = s.client.WSSConn() 183 | defer conn.Close() 184 | } 185 | 186 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10), "/restart"), []byte{}, scalet) 187 | 188 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 189 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 190 | return scalet, res, err 191 | } 192 | 193 | return scalet, res, err 194 | } 195 | 196 | func (s *ScaletService) Rebuild(CTID int64, wait bool) (*Scalet, *http.Response, error) { 197 | 198 | scalet := new(Scalet) 199 | 200 | conn := new(websocket.Conn) 201 | var wsserr error 202 | 203 | if wait { 204 | conn, wsserr = s.client.WSSConn() 205 | defer conn.Close() 206 | } 207 | 208 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10), "/rebuild"), []byte{}, scalet) 209 | 210 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 211 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 212 | return scalet, res, err 213 | } 214 | 215 | return scalet, res, err 216 | } 217 | 218 | func (s *ScaletService) Stop(CTID int64, wait bool) (*Scalet, *http.Response, error) { 219 | 220 | scalet := new(Scalet) 221 | 222 | conn := new(websocket.Conn) 223 | var wsserr error 224 | 225 | if wait { 226 | conn, wsserr = s.client.WSSConn() 227 | defer conn.Close() 228 | } 229 | 230 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10), "/stop"), []byte{}, scalet) 231 | 232 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 233 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 234 | return scalet, res, err 235 | } 236 | 237 | return scalet, res, err 238 | } 239 | 240 | func (s *ScaletService) Start(CTID int64, wait bool) (*Scalet, *http.Response, error) { 241 | 242 | scalet := new(Scalet) 243 | 244 | conn := new(websocket.Conn) 245 | var wsserr error 246 | 247 | if wait { 248 | conn, wsserr = s.client.WSSConn() 249 | defer conn.Close() 250 | } 251 | 252 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10), "/start"), []byte{}, scalet) 253 | 254 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 255 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 256 | return scalet, res, err 257 | } 258 | 259 | return scalet, res, err 260 | } 261 | 262 | func (s *ScaletService) Upgrade(CTID int64, rplan string, wait bool) (*Scalet, *http.Response, error) { 263 | 264 | scalet := new(Scalet) 265 | 266 | body := struct { 267 | Rplan string `json:"rplan,omitempty"` 268 | }{rplan} 269 | 270 | b, _ := json.Marshal(body) 271 | 272 | conn := new(websocket.Conn) 273 | var wsserr error 274 | 275 | if wait { 276 | conn, wsserr = s.client.WSSConn() 277 | defer conn.Close() 278 | } 279 | 280 | res, err := s.client.ExecuteRequest("POST", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10), "/upgrade"), b, scalet) 281 | 282 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 283 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 284 | return scalet, res, err 285 | } 286 | 287 | return scalet, res, err 288 | } 289 | 290 | func (s *ScaletService) Tasks() (*[]Task, *http.Response, error) { 291 | 292 | tasks := new([]Task) 293 | 294 | res, err := s.client.ExecuteRequest("GET", "tasks", []byte{}, tasks) 295 | 296 | return tasks, res, err 297 | } 298 | 299 | func (s *ScaletService) AddSSHKeys(CTID int64, keys []int64) (*Scalet, *http.Response, error) { 300 | 301 | scalet := new(Scalet) 302 | 303 | body := struct { 304 | Keys []int64 `json:"keys,omitempty"` 305 | }{keys} 306 | 307 | b, _ := json.Marshal(body) 308 | 309 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprint("scalets/", strconv.FormatInt(CTID, 10)), b, scalet) 310 | 311 | return scalet, res, err 312 | } 313 | 314 | func (s *ScaletService) Backup(CTID int64, name string) (*Backup, *http.Response, error) { 315 | 316 | backup := new(Backup) 317 | 318 | body := struct { 319 | Name string `json:"name,omitempty"` 320 | }{name} 321 | 322 | b, _ := json.Marshal(body) 323 | 324 | res, err := s.client.ExecuteRequest("POST", fmt.Sprintf("scalets/%d/backup", CTID), b, backup) 325 | 326 | return backup, res, err 327 | } 328 | 329 | func (s *ScaletService) Restore(CTID int64, makeFrom string, wait bool) (*Scalet, *http.Response, error) { 330 | 331 | scalet := new(Scalet) 332 | 333 | conn := new(websocket.Conn) 334 | var wsserr error 335 | 336 | if wait { 337 | conn, wsserr = s.client.WSSConn() 338 | defer conn.Close() 339 | } 340 | 341 | body := struct { 342 | MakeFrom string `json:"make_from,omitempty"` 343 | }{makeFrom} 344 | 345 | b, _ := json.Marshal(body) 346 | 347 | res, err := s.client.ExecuteRequest("PATCH", fmt.Sprintf("scalets/%d/rebuild", CTID), b, scalet) 348 | 349 | if wait && wsserr == nil && res.Header.Get("VSCALE-TASK-ID") != "" { 350 | _, err := s.client.WaitTask(conn, res.Header.Get("VSCALE-TASK-ID")) 351 | return scalet, res, err 352 | } 353 | 354 | return scalet, res, err 355 | } 356 | -------------------------------------------------------------------------------- /scalet_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // Test data 8 | var CTID int64 = 48149 9 | var KeyID int64 = 4639 10 | var AdditionalKeyID int64 = 4674 11 | var UpgradePlan string = "medium" 12 | var BackupID string = "2cb27ca9-9fab-4d77-9c05-4bebe3a02980" 13 | 14 | func TestScaletService_List(t *testing.T) { 15 | 16 | token, err := GetToken() 17 | if err != nil { 18 | t.Error(err) 19 | return 20 | } 21 | 22 | client := NewClient(token) 23 | _, _, err = client.Scalet.List() 24 | if err != nil { 25 | t.Error(err) 26 | return 27 | } 28 | 29 | return 30 | 31 | } 32 | 33 | func TestScaletService_Create(t *testing.T) { 34 | 35 | token, err := GetToken() 36 | if err != nil { 37 | t.Error(err) 38 | return 39 | } 40 | 41 | client := NewClient(token) 42 | scalet, _, err := client.Scalet.Create("ubuntu_16.04_64_001_master", "small", "test-1", 43 | "", "spb0", true, []int64{KeyID}, true) 44 | 45 | if err != nil { 46 | t.Error(err) 47 | return 48 | } 49 | 50 | if scalet.Name == "" { 51 | t.Error("Scalet name can\t be empty") 52 | return 53 | } 54 | 55 | return 56 | } 57 | 58 | func TestScaletService_CreateWithoutPassword(t *testing.T) { 59 | 60 | token, err := GetToken() 61 | if err != nil { 62 | t.Error(err) 63 | return 64 | } 65 | 66 | client := NewClient(token) 67 | scalet, _, err := client.Scalet.CreateWithoutPassword("ubuntu_16.04_64_001_master", "small", "test-1", "spb0", true, []int64{KeyID}, true) 68 | 69 | if err != nil { 70 | t.Error(err) 71 | return 72 | } 73 | 74 | if scalet.Name == "" { 75 | t.Error("Scalet name can\t be empty") 76 | return 77 | } 78 | 79 | return 80 | } 81 | 82 | func TestScaletService_Remove(t *testing.T) { 83 | 84 | token, err := GetToken() 85 | if err != nil { 86 | t.Error(err) 87 | return 88 | } 89 | 90 | client := NewClient(token) 91 | _, _, err = client.Scalet.Remove(35758, true) 92 | if err != nil { 93 | t.Error(err) 94 | return 95 | } 96 | 97 | return 98 | 99 | } 100 | 101 | func TestScaletService_Get(t *testing.T) { 102 | 103 | token, err := GetToken() 104 | if err != nil { 105 | t.Error(err) 106 | return 107 | } 108 | 109 | client := NewClient(token) 110 | scalet, _, err := client.Scalet.Get(CTID) 111 | 112 | if err != nil { 113 | t.Error(err) 114 | return 115 | } 116 | 117 | if scalet.Name == "" { 118 | t.Error("Scalet name is empty") 119 | return 120 | } 121 | 122 | return 123 | } 124 | 125 | func TestScaletService_Restart(t *testing.T) { 126 | 127 | token, err := GetToken() 128 | if err != nil { 129 | t.Error(err) 130 | return 131 | } 132 | 133 | client := NewClient(token) 134 | scalet, _, err := client.Scalet.Restart(35758, true) 135 | 136 | if err != nil { 137 | t.Error(err) 138 | return 139 | } 140 | 141 | if scalet.Name == "" { 142 | t.Error("Scalet name is empty") 143 | return 144 | } 145 | 146 | return 147 | } 148 | 149 | func TestScaletService_Rebuild(t *testing.T) { 150 | 151 | token, err := GetToken() 152 | if err != nil { 153 | t.Error(err) 154 | return 155 | } 156 | 157 | client := NewClient(token) 158 | scalet, _, err := client.Scalet.Rebuild(35758, true) 159 | 160 | if err != nil { 161 | t.Error(err) 162 | return 163 | } 164 | 165 | if scalet.Name == "" { 166 | t.Error("Scalet name is empty") 167 | return 168 | } 169 | 170 | return 171 | } 172 | 173 | func TestScaletService_Stop(t *testing.T) { 174 | 175 | token, err := GetToken() 176 | if err != nil { 177 | t.Error(err) 178 | return 179 | } 180 | 181 | client := NewClient(token) 182 | scalet, _, err := client.Scalet.Stop(35758, true) 183 | 184 | if err != nil { 185 | t.Error(err) 186 | return 187 | } 188 | 189 | if scalet.Name == "" { 190 | t.Error("Scalet name is empty") 191 | return 192 | } 193 | 194 | return 195 | } 196 | 197 | func TestScaletService_Start(t *testing.T) { 198 | 199 | token, err := GetToken() 200 | if err != nil { 201 | t.Error(err) 202 | return 203 | } 204 | 205 | client := NewClient(token) 206 | scalet, _, err := client.Scalet.Start(35758, true) 207 | 208 | if err != nil { 209 | t.Error(err) 210 | return 211 | } 212 | 213 | if scalet.Name == "" { 214 | t.Error("Scalet name is empty") 215 | return 216 | } 217 | 218 | return 219 | } 220 | 221 | func TestScaletService_Uprade(t *testing.T) { 222 | 223 | token, err := GetToken() 224 | if err != nil { 225 | t.Error(err) 226 | return 227 | } 228 | 229 | client := NewClient(token) 230 | scalet, _, err := client.Scalet.Upgrade(35758, UpgradePlan, true) 231 | 232 | if err != nil { 233 | t.Error(err) 234 | return 235 | } 236 | 237 | if scalet.Name == "" { 238 | t.Error("Scalet name is empty") 239 | return 240 | } 241 | 242 | return 243 | } 244 | 245 | func TestScaletService_Tasks(t *testing.T) { 246 | 247 | token, err := GetToken() 248 | if err != nil { 249 | t.Error(err) 250 | return 251 | } 252 | 253 | client := NewClient(token) 254 | _, _, err = client.Scalet.Tasks() 255 | 256 | if err != nil { 257 | t.Error(err) 258 | return 259 | } 260 | 261 | return 262 | } 263 | 264 | func TestScaletService_AddSSHKeys(t *testing.T) { 265 | 266 | token, err := GetToken() 267 | if err != nil { 268 | t.Error(err) 269 | return 270 | } 271 | 272 | client := NewClient(token) 273 | _, _, err = client.Scalet.AddSSHKeys(CTID, []int64{AdditionalKeyID}) 274 | 275 | if err != nil { 276 | t.Error(err) 277 | return 278 | } 279 | 280 | return 281 | } 282 | 283 | func TestScaletService_Backup(t *testing.T) { 284 | 285 | token, err := GetToken() 286 | if err != nil { 287 | t.Error(err) 288 | return 289 | } 290 | 291 | client := NewClient(token) 292 | _, _, err = client.Scalet.Backup(CTID, "my_new_backup") 293 | 294 | if err != nil { 295 | t.Error(err) 296 | return 297 | } 298 | 299 | return 300 | } 301 | 302 | func TestScaletService_Restore(t *testing.T) { 303 | 304 | token, err := GetToken() 305 | if err != nil { 306 | t.Error(err) 307 | return 308 | } 309 | 310 | client := NewClient(token) 311 | _, _, err = client.Scalet.Restore(CTID, BackupID, false) 312 | 313 | if err != nil { 314 | t.Error(err) 315 | return 316 | } 317 | 318 | return 319 | } 320 | -------------------------------------------------------------------------------- /server_tags.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type ServerTagService struct { 11 | client Client 12 | } 13 | 14 | type ServerTag struct { 15 | Name string `json:"name,omitempty"` 16 | Scalets []int64 `json:"scalets,omitempty"` 17 | ID int64 `json:"id,omitempty"` 18 | } 19 | 20 | func (d *ServerTagService) Create(name string, scalets []int64) (*ServerTag, *http.Response, error) { 21 | 22 | serverTag := new(ServerTag) 23 | 24 | body := struct { 25 | Name string `json:"name,omitempty"` 26 | Scalets []int64 `json:"scalets,omitempty"` 27 | }{name, scalets} 28 | 29 | b, _ := json.Marshal(body) 30 | 31 | res, err := d.client.ExecuteRequest("POST", "scalets/tags", b, serverTag) 32 | 33 | return serverTag, res, err 34 | } 35 | 36 | func (d *ServerTagService) List() (*[]ServerTag, *http.Response, error) { 37 | 38 | serverTags := new([]ServerTag) 39 | 40 | res, err := d.client.ExecuteRequest("GET", "scalets/tags", []byte{}, serverTags) 41 | 42 | return serverTags, res, err 43 | } 44 | 45 | func (d *ServerTagService) Get(tagID int64) (*ServerTag, *http.Response, error) { 46 | 47 | serverTag := new(ServerTag) 48 | 49 | url := fmt.Sprint("scalets/tags/", strconv.FormatInt(tagID, 10)) 50 | 51 | res, err := d.client.ExecuteRequest("GET", url, []byte{}, serverTag) 52 | 53 | return serverTag, res, err 54 | } 55 | 56 | func (d *ServerTagService) Update(tagID int64, name string, scalets []int64) (*ServerTag, *http.Response, error) { 57 | 58 | serverTag := new(ServerTag) 59 | 60 | body := struct { 61 | Name string `json:"name,omitempty"` 62 | Scalets []int64 `json:"scalets,omitempty"` 63 | }{name, scalets} 64 | 65 | b, _ := json.Marshal(body) 66 | 67 | url := fmt.Sprint("scalets/tags/", strconv.FormatInt(tagID, 10)) 68 | 69 | res, err := d.client.ExecuteRequest("PUT", url, b, serverTag) 70 | 71 | return serverTag, res, err 72 | } 73 | 74 | func (d *ServerTagService) Remove(tagID int64) (bool, *http.Response, error) { 75 | 76 | url := fmt.Sprint("scalets/tags/", strconv.FormatInt(tagID, 10)) 77 | 78 | res, err := d.client.ExecuteRequest("DELETE", url, []byte{}, struct{}{}) 79 | 80 | if err != nil { 81 | return false, res, err 82 | } 83 | 84 | return true, res, err 85 | } 86 | -------------------------------------------------------------------------------- /server_tags_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var ServersTagName string = "vpn_scalets" 8 | var ServersTagID int64 = 3 9 | 10 | func TestServerTagService_Create(t *testing.T) { 11 | 12 | token, err := GetToken() 13 | if err != nil { 14 | t.Error(err) 15 | return 16 | } 17 | 18 | client := NewClient(token) 19 | tag, _, err := client.ServerTag.Create(ServersTagName, []int64{CTID}) 20 | if err != nil { 21 | t.Error(err) 22 | return 23 | } 24 | 25 | if tag.Name == "" { 26 | t.Error("Tag name can't be empty") 27 | return 28 | } 29 | 30 | return 31 | } 32 | 33 | func TestServerTagService_List(t *testing.T) { 34 | 35 | token, err := GetToken() 36 | if err != nil { 37 | t.Error(err) 38 | return 39 | } 40 | 41 | client := NewClient(token) 42 | _, _, err = client.ServerTag.List() 43 | if err != nil { 44 | t.Error(err) 45 | return 46 | } 47 | 48 | return 49 | } 50 | 51 | func TestServerTagService_Get(t *testing.T) { 52 | 53 | token, err := GetToken() 54 | if err != nil { 55 | t.Error(err) 56 | return 57 | } 58 | 59 | client := NewClient(token) 60 | tag, _, err := client.ServerTag.Get(ServersTagID) 61 | if err != nil { 62 | t.Error(err) 63 | return 64 | } 65 | 66 | if tag.Name == "" { 67 | t.Error("Tag name can't be empty") 68 | return 69 | } 70 | 71 | return 72 | 73 | } 74 | 75 | func TestServerTagService_Update(t *testing.T) { 76 | 77 | token, err := GetToken() 78 | if err != nil { 79 | t.Error(err) 80 | return 81 | } 82 | 83 | client := NewClient(token) 84 | tag, _, err := client.ServerTag.Update(ServersTagID, "new_name", []int64{49174}) 85 | if err != nil { 86 | t.Error(err) 87 | return 88 | } 89 | 90 | if tag.Name == "" { 91 | t.Error("Tag name can't be empty") 92 | return 93 | } 94 | 95 | return 96 | 97 | } 98 | 99 | func TestServerTagService_Remove(t *testing.T) { 100 | 101 | token, err := GetToken() 102 | if err != nil { 103 | t.Error(err) 104 | return 105 | } 106 | 107 | client := NewClient(token) 108 | _, _, err = client.ServerTag.Remove(ServersTagID) 109 | if err != nil { 110 | t.Error(err) 111 | return 112 | } 113 | 114 | return 115 | 116 | } 117 | -------------------------------------------------------------------------------- /sshkey.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type SSHKeyService struct { 11 | client Client 12 | } 13 | 14 | type SSHKey struct { 15 | ID int64 `json:"id,omitempty"` 16 | Key string `json:"key,omitempty"` 17 | Name string `json:"name,omitempty"` 18 | } 19 | 20 | func (a *SSHKeyService) List() (*[]SSHKey, *http.Response, error) { 21 | 22 | sshkeys := new([]SSHKey) 23 | 24 | res, err := a.client.ExecuteRequest("GET", "sshkeys", []byte{}, sshkeys) 25 | 26 | return sshkeys, res, err 27 | } 28 | 29 | func (s *SSHKeyService) Create(key, name string) (*SSHKey, *http.Response, error) { 30 | 31 | sshkey := new(SSHKey) 32 | 33 | body := struct { 34 | Key string `json:"key,omitempty"` 35 | Name string `json:"name,omitempty"` 36 | }{key, name} 37 | 38 | b, _ := json.Marshal(body) 39 | 40 | res, err := s.client.ExecuteRequest("POST", "sshkeys", b, sshkey) 41 | 42 | return sshkey, res, err 43 | } 44 | 45 | func (s *SSHKeyService) Remove(keyID int64) (bool, *http.Response, error) { 46 | 47 | res, err := s.client.ExecuteRequest("DELETE", fmt.Sprint("sshkeys/", strconv.FormatInt(keyID, 10)), []byte{}, struct{}{}) 48 | 49 | if err != nil { 50 | return false, res, nil 51 | } 52 | 53 | return true, res, nil 54 | } 55 | -------------------------------------------------------------------------------- /sshkey_test.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // Test data 8 | var Key string = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4jpT+KSXtUCWerNHTnqQd9qmyDEow84lKdp12/R/gfM28BQ+KbMMVJQmrWSNf1zEMmMTsiNR2h/20iw2V/guxRzF4jJm5NRwodKCwsZrAhjbGe0yMKG7GpHe50DhF8enxAOudcEMCBekrFlUrT+nd4bJVZ6ChrBN4BDaDlpKbJ9JN7lENB4Bs357K7hCahT3PPa+w/GnQ30vip5bi7BZEoOW2sgnF3BJS8IYPTNs253581PmvpepPpTM8TnE+tjvHHt6lwIbHw2nj7Diihik0r/TrBGJMFACkEh+MupIw0jzSh0GAhnZHJ8QuCCnVfScC04Fz1031QRzNPwK0rh4t bogdankurnosov@MacBook-Pro-Bogdan.local` 9 | var KeyName string = "test_key" 10 | var TestKeyID int64 = 4679 11 | 12 | func TestSSHKeyService_List(t *testing.T) { 13 | 14 | token, err := GetToken() 15 | if err != nil { 16 | t.Error(err) 17 | return 18 | } 19 | 20 | client := NewClient(token) 21 | _, _, err = client.SSHKey.List() 22 | if err != nil { 23 | t.Error(err) 24 | return 25 | } 26 | 27 | return 28 | 29 | } 30 | 31 | func TestSSHKeyService_Create(t *testing.T) { 32 | 33 | token, err := GetToken() 34 | if err != nil { 35 | t.Error(err) 36 | return 37 | } 38 | 39 | client := NewClient(token) 40 | sshkey, _, err := client.SSHKey.Create(Key, KeyName) 41 | if err != nil { 42 | t.Error(err) 43 | return 44 | } 45 | 46 | if sshkey.Name == "" { 47 | t.Error("SSH key's name is empty") 48 | } 49 | 50 | return 51 | 52 | } 53 | 54 | func TestSSHKeyService_Remove(t *testing.T) { 55 | 56 | token, err := GetToken() 57 | if err != nil { 58 | t.Error(err) 59 | return 60 | } 61 | 62 | client := NewClient(token) 63 | _, _, err = client.SSHKey.Remove(TestKeyID) 64 | if err != nil { 65 | t.Error(err) 66 | return 67 | } 68 | 69 | return 70 | 71 | } 72 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package vscale_api_go 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | ) 7 | 8 | func GetToken() (string, error) { 9 | 10 | token := os.Getenv("VSCALE_API_TOKEN") 11 | if token == "" { 12 | return token, errors.New("Token is empty") 13 | } 14 | 15 | return token, nil 16 | } 17 | 18 | func IsSuccess(code int) bool { 19 | 20 | successCodes := []int{200, 201, 202, 203, 204, 205, 206, 207} 21 | 22 | for _, i := range successCodes { 23 | if i == code { 24 | return true 25 | } 26 | } 27 | 28 | return false 29 | } 30 | --------------------------------------------------------------------------------