Skip to content

Commit

Permalink
add support for applications
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesClonk committed Mar 18, 2017
1 parent 422d48e commit abaa6c0
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 4 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $ export VULTR_API_KEY=87dFbC91rJjkL/18zJEQxS
* Run it
```sh
$ vultr version
Client version: 1.12.0
Client version: 1.13.0
Vultr API endpoint: https://api.vultr.com/
Vultr API version: v1
OS/Arch (client): linux/amd64
Expand All @@ -46,7 +46,7 @@ $ export VULTR_API_KEY=89dFbb91rGjkL/12zJEQxS
* Run it
```sh
$ vultr version
Client version: 1.12.0
Client version: 1.13.0
Vultr API endpoint: https://api.vultr.com/
Vultr API version: v1
OS/Arch (client): linux/amd64
Expand Down
7 changes: 7 additions & 0 deletions cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func (c *CLI) RegisterCommands() {
// os
c.Command("os", "list all available operating systems", osList)

// applications
c.Command("apps", "list all available applications", appList)

// plans
c.Command("plans", "list all active plans", planList)

Expand Down Expand Up @@ -64,6 +67,10 @@ func (c *CLI) RegisterCommands() {
cmd.Command("change", "change operating system of virtual machine (all data will be lost)", serversChangeOS)
cmd.Command("list", "show a list of operating systems to which can be changed to", serversListOS)
})
cmd.Command("app", "show and change application on a virtual machine", func(cmd *cli.Cmd) {
cmd.Command("change", "change application of virtual machine (all data will be lost)", serversChangeApplication)
cmd.Command("list", "show a list of available applications to which can be changed to", serversListApplications)
})
cmd.Command("iso", "attach/detach ISO of a virtual machine", func(cmd *cli.Cmd) {
cmd.Command("attach", "attach ISO to a virtual machine (server will hard reboot)", serversAttachISO)
cmd.Command("detach", "detach ISO from a virtual machine (server will hard reboot)", serversDetachISO)
Expand Down
29 changes: 29 additions & 0 deletions cmd/commands_applications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cmd

import (
"fmt"
"log"

"github.com/jawher/mow.cli"
)

func appList(cmd *cli.Cmd) {
cmd.Action = func() {
apps, err := GetClient().GetApplications()
if err != nil {
log.Fatal(err)
}

if len(apps) == 0 {
fmt.Println()
return
}

lengths := []int{8, 32, 24, 32, 12}
tabsPrint(columns{"APPID", "NAME", "SHORT_NAME", "DEPLOY_NAME", "SURCHARGE"}, lengths)
for _, app := range apps {
tabsPrint(columns{app.ID, app.Name, app.ShortName, app.DeployName, app.Surcharge}, lengths)
}
tabsFlush()
}
}
36 changes: 36 additions & 0 deletions cmd/commands_servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func serversCreate(cmd *cli.Cmd) {
sshkey := cmd.StringOpt("k sshkey", "", "SSHKEYID (see <sshkeys>) of SSH key to apply to this server on install")
hostname := cmd.StringOpt("hostname", "", "Hostname to assign to this server")
tag := cmd.StringOpt("tag", "", "Tag to assign to this server")
appID := cmd.StringOpt("a app", "", "If launching an application (OSID 186), this is the APPID to launch")
ipv6 := cmd.BoolOpt("ipv6", false, "Assign an IPv6 subnet to this virtual machine (where available)")
privateNetworking := cmd.BoolOpt("private-networking", false, "Add private networking support for this virtual machine")
autoBackups := cmd.BoolOpt("autobackups", false, "Enable automatic backups for this virtual machine")
Expand All @@ -44,6 +45,7 @@ func serversCreate(cmd *cli.Cmd) {
AutoBackups: *autoBackups,
Hostname: *hostname,
Tag: *tag,
AppID: *appID,
DontNotifyOnActivate: !*notifyActivate,
}
if *userDataFile != "" {
Expand Down Expand Up @@ -474,3 +476,37 @@ func reverseIpv4Set(cmd *cli.Cmd) {
fmt.Printf("IPv4 reverse DNS set to: %v\n", *entry)
}
}

func serversChangeApplication(cmd *cli.Cmd) {
cmd.Spec = "SUBID APPID"
id := cmd.StringArg("SUBID", "", "SUBID of virtual machine (see <servers>)")
appID := cmd.StringArg("APPID", "", "Application to use (see <apps>)")
cmd.Action = func() {
if err := GetClient().ChangeApplicationofServer(*id, *appID); err != nil {
log.Fatal(err)
}
fmt.Printf("Virtual machine application changed to: %v\n", *appID)
}
}

func serversListApplications(cmd *cli.Cmd) {
id := cmd.StringArg("SUBID", "", "SUBID of virtual machine (see <servers>)")
cmd.Action = func() {
apps, err := GetClient().ListApplicationsforServer(*id)
if err != nil {
log.Fatal(err)
}

if len(apps) == 0 {
fmt.Println()
return
}

lengths := []int{8, 32, 24, 32, 12}
tabsPrint(columns{"APPID", "NAME", "SHORT_NAME", "DEPLOY_NAME", "SURCHARGE"}, lengths)
for _, app := range apps {
tabsPrint(columns{app.ID, app.Name, app.ShortName, app.DeployName, app.Surcharge}, lengths)
}
tabsFlush()
}
}
38 changes: 38 additions & 0 deletions lib/applications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lib

import (
"sort"
"strings"
)

// Application on Vultr
type Application struct {
ID string `json:"APPID"`
Name string `json:"name"`
ShortName string `json:"short_name"`
DeployName string `json:"deploy_name"`
Surcharge float64 `json:"surcharge"`
}

type applications []Application

func (s applications) Len() int { return len(s) }
func (s applications) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s applications) Less(i, j int) bool {
return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name)
}

// GetApplications returns a list of all available applications on Vultr
func (c *Client) GetApplications() ([]Application, error) {
var appMap map[string]Application
if err := c.get(`app/list`, &appMap); err != nil {
return nil, err
}

var appList []Application
for _, app := range appMap {
appList = append(appList, app)
}
sort.Sort(applications(appList))
return appList, nil
}
57 changes: 57 additions & 0 deletions lib/applications_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package lib

import (
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

func Test_Applications_GetApplications_Error(t *testing.T) {
server, client := getTestServerAndClient(http.StatusNotAcceptable, `{error}`)
defer server.Close()

apps, err := client.GetApplications()
assert.Nil(t, apps)
if assert.NotNil(t, err) {
assert.Equal(t, `{error}`, err.Error())
}
}

func Test_Applications_GetApplications_NoApplication(t *testing.T) {
server, client := getTestServerAndClient(http.StatusOK, `[]`)
defer server.Close()

apps, err := client.GetApplications()
if err != nil {
t.Error(err)
}
assert.Nil(t, apps)
}

func Test_Applications_GetApplications_OK(t *testing.T) {
server, client := getTestServerAndClient(http.StatusOK, `{
"2": {"APPID": "2","name": "WordPress","short_name": "wordpress","deploy_name": "WordPress on CentOS 6 x64","surcharge": 0},
"1": {"APPID": "1","name": "LEMP","short_name": "lemp","deploy_name": "LEMP on CentOS 6 x64","surcharge": 5}
}`)
defer server.Close()

apps, err := client.GetApplications()
if err != nil {
t.Error(err)
}
if assert.NotNil(t, apps) {
assert.Equal(t, 2, len(apps))

assert.Equal(t, "1", apps[0].ID)
assert.Equal(t, "LEMP", apps[0].Name)
assert.Equal(t, "lemp", apps[0].ShortName)
assert.Equal(t, "LEMP on CentOS 6 x64", apps[0].DeployName)
assert.Equal(t, float64(5), apps[0].Surcharge)

assert.Equal(t, "2", apps[1].ID)
assert.Equal(t, "WordPress", apps[1].Name)
assert.Equal(t, "wordpress", apps[1].ShortName)
assert.Equal(t, "WordPress on CentOS 6 x64", apps[1].DeployName)
}
}
2 changes: 1 addition & 1 deletion lib/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

const (
// Version of this libary
Version = "1.12.0"
Version = "1.13.0"

// APIVersion of Vultr
APIVersion = "v1"
Expand Down
46 changes: 46 additions & 0 deletions lib/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type Server struct {
KVMUrl string `json:"kvm_url"`
AutoBackups string `json:"auto_backups"`
Tag string `json:"tag"`
OSID string `json:"OSID"`
AppID string `json:"APPID"`
}

// ServerOptions are optional parameters to be used during server creation
Expand All @@ -54,6 +56,7 @@ type ServerOptions struct {
DontNotifyOnActivate bool
Hostname string
Tag string
AppID string
}

type servers []Server
Expand Down Expand Up @@ -156,6 +159,18 @@ func (s *Server) UnmarshalJSON(data []byte) (err error) {
}
s.AllowedBandwidth = ab

value = fmt.Sprintf("%v", fields["OSID"])
if value == "<nil>" {
value = ""
}
s.OSID = value

value = fmt.Sprintf("%v", fields["APPID"])
if value == "<nil>" {
value = ""
}
s.AppID = value

s.ID = fmt.Sprintf("%v", fields["SUBID"])
s.Name = fmt.Sprintf("%v", fields["label"])
s.OS = fmt.Sprintf("%v", fields["os"])
Expand Down Expand Up @@ -292,6 +307,10 @@ func (c *Client) CreateServer(name string, regionID, planID, osID int, options *
if options.Tag != "" {
values.Add("tag", options.Tag)
}

if options.AppID != "" {
values.Add("APPID", options.AppID)
}
}

var server Server
Expand Down Expand Up @@ -465,3 +484,30 @@ func (c *Client) BandwidthOfServer(id string) (bandwidth []map[string]string, er

return bandwidth, nil
}

// ChangeApplicationofServer changes the virtual machine to a different application
func (c *Client) ChangeApplicationofServer(id string, appID string) error {
values := url.Values{
"SUBID": {id},
"APPID": {appID},
}

if err := c.post(`server/app_change`, values, nil); err != nil {
return err
}
return nil
}

// ListApplicationsforServer lists all available operating systems to which an existing virtual machine can be changed
func (c *Client) ListApplicationsforServer(id string) (apps []Application, err error) {
var appMap map[string]Application
if err := c.get(`server/app_change_list?SUBID=`+id, &appMap); err != nil {
return nil, err
}

for _, app := range appMap {
apps = append(apps, app)
}
sort.Sort(applications(apps))
return apps, nil
}
Loading

0 comments on commit abaa6c0

Please sign in to comment.