1package vps 2 3import ( 4 "fmt" 5 "github.com/transip/gotransip/v6" 6 "github.com/transip/gotransip/v6/ipaddress" 7 "github.com/transip/gotransip/v6/product" 8 "github.com/transip/gotransip/v6/repository" 9 "github.com/transip/gotransip/v6/rest" 10 "net" 11 "net/url" 12 "strings" 13 "time" 14) 15 16// Repository is the vps repository 17// this repository allows you to manage all VPS services for your TransIP account 18type Repository repository.RestRepository 19 20// GetAll returns a list of all your VPSs 21func (r *Repository) GetAll() ([]Vps, error) { 22 var response vpssWrapper 23 restRequest := rest.Request{Endpoint: "/vps"} 24 err := r.Client.Get(restRequest, &response) 25 26 return response.Vpss, err 27} 28 29// GetAllByTags returns a list of all VPSs that match the tags provided 30func (r *Repository) GetAllByTags(tags []string) ([]Vps, error) { 31 var response vpssWrapper 32 restRequest := rest.Request{Endpoint: "/vps", Parameters: url.Values{"tags": tags}} 33 err := r.Client.Get(restRequest, &response) 34 35 return response.Vpss, err 36} 37 38// GetSelection returns a limited list of VPSs, 39// specify how many and which page/chunk of VPSs you want to retrieve 40func (r *Repository) GetSelection(page int, itemsPerPage int) ([]Vps, error) { 41 var response vpssWrapper 42 params := url.Values{ 43 "pageSize": []string{fmt.Sprintf("%d", itemsPerPage)}, 44 "page": []string{fmt.Sprintf("%d", page)}, 45 } 46 47 restRequest := rest.Request{Endpoint: "/vps", Parameters: params} 48 err := r.Client.Get(restRequest, &response) 49 50 return response.Vpss, err 51} 52 53// GetByName returns information on a specific VPS by name 54func (r *Repository) GetByName(vpsName string) (Vps, error) { 55 var response vpsWrapper 56 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName)} 57 err := r.Client.Get(restRequest, &response) 58 59 return response.Vps, err 60} 61 62// Order allows you to order a new VPS 63func (r *Repository) Order(vpsOrder Order) error { 64 restRequest := rest.Request{Endpoint: "/vps", Body: &vpsOrder} 65 66 return r.Client.Post(restRequest) 67} 68 69// OrderMultiple allows you to order multiple vpses at the same time 70func (r *Repository) OrderMultiple(orders []Order) error { 71 requestBody := vpssOrderWrapper{Orders: orders} 72 restRequest := rest.Request{Endpoint: "/vps", Body: &requestBody} 73 74 return r.Client.Post(restRequest) 75} 76 77// Clone allows you to clone an existing VPS 78// There are a few things to take into account when you want to clone an existing VPS to a new VPS: 79// 80// - If the original VPS (which you’re going to clone) is currently locked, the clone will fail; 81// 82// - Cloned control panels can be used on the VPS, but as the IP address changes, this does require you to synchronise 83// the new license on the new VPS (licenses are often IP-based); 84// 85// - Possibly, your VPS has its network interface(s) configured using (a) static IP(‘s) rather than a dynamic allocation 86// using DHCP. If this is the case, you have to configure the new IP(‘s) on the new VPS. 87// Do note that this is not the case with our pre-installed control panel images; 88// 89// - VPS add-ons such as Big Storage aren’t affected by cloning - these will stay attached to the original VPS and can’t 90// be swapped automatically 91func (r *Repository) Clone(vpsName string) error { 92 requestBody := cloneRequest{VpsName: vpsName} 93 restRequest := rest.Request{Endpoint: "/vps", Body: &requestBody} 94 95 return r.Client.Post(restRequest) 96} 97 98// CloneToAvailabilityZone allows you to clone a vps to a specific availability zone, identified by name 99func (r *Repository) CloneToAvailabilityZone(vpsName string, availabilityZone string) error { 100 requestBody := cloneRequest{VpsName: vpsName, AvailabilityZone: availabilityZone} 101 restRequest := rest.Request{Endpoint: "/vps", Body: &requestBody} 102 103 return r.Client.Post(restRequest) 104} 105 106// Update allows you to lock/unlock a VPS, update a VPS description, and add/remove tags. 107// 108// For locking the VPS, set isCustomerLocked to true. Set the value to false for unlocking the VPS 109// You can change your VPS description by simply changing the description attribute 110// To add/remove tags, you must update the tags attribute 111func (r *Repository) Update(vps Vps) error { 112 requestBody := vpsWrapper{Vps: vps} 113 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vps.Name), Body: &requestBody} 114 115 return r.Client.Put(restRequest) 116} 117 118// Start allows you to start a VPS, given that it’s currently in a stopped state 119func (r *Repository) Start(vpsName string) error { 120 requestBody := actionWrapper{Action: "start"} 121 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName), Body: &requestBody} 122 123 return r.Client.Patch(restRequest) 124} 125 126// Stop allows you to stop a VPS 127func (r *Repository) Stop(vpsName string) error { 128 requestBody := actionWrapper{Action: "stop"} 129 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName), Body: &requestBody} 130 131 return r.Client.Patch(restRequest) 132} 133 134// Reset allows you to reset a VPS, a reset is essentially the stop and start command combined into one 135func (r *Repository) Reset(vpsName string) error { 136 requestBody := actionWrapper{Action: "reset"} 137 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName), Body: &requestBody} 138 139 return r.Client.Patch(restRequest) 140} 141 142// Handover will handover a VPS to another TransIP Account. This call will initiate the handover process. 143// The actual handover will be done when the target customer accepts the handover 144func (r *Repository) Handover(vpsName string, targetCustomerName string) error { 145 requestBody := handoverRequest{Action: "handover", TargetCustomerName: targetCustomerName} 146 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName), Body: &requestBody} 147 148 return r.Client.Patch(restRequest) 149} 150 151// Cancel will cancel the VPS, thus deleting it 152func (r *Repository) Cancel(vpsName string, endTime gotransip.CancellationTime) error { 153 requestBody := gotransip.CancellationRequest{EndTime: endTime} 154 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s", vpsName), Body: &requestBody} 155 156 return r.Client.Delete(restRequest) 157} 158 159// GetUsage will allow you to request your vps usage for a specified period and usage type, 160// for convenience you can also use the GetUsages or GetUsagesLast24Hours 161func (r *Repository) GetUsage(vpsName string, usageTypes []UsageType, period UsagePeriod) (Usage, error) { 162 var response usageWrapper 163 var types []string 164 for _, usageType := range usageTypes { 165 types = append(types, string(usageType)) 166 } 167 168 parameters := url.Values{ 169 "dateTimeStart": []string{fmt.Sprintf("%d", period.TimeStart)}, 170 "dateTimeEnd": []string{fmt.Sprintf("%d", period.TimeEnd)}, 171 "types": []string{strings.Join(types, ",")}, 172 } 173 174 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/usage", vpsName), Parameters: parameters} 175 err := r.Client.Get(restRequest, &response) 176 177 return response.Usage, err 178} 179 180// GetAllUsage returns a Usage struct filled with all usage data for the given UsagePeriod. 181// UsagePeriod is struct containing a start and end unix timestamp 182func (r *Repository) GetAllUsage(vpsName string, period UsagePeriod) (Usage, error) { 183 return r.GetUsage( 184 vpsName, 185 []UsageType{UsageTypeCPU, UsageTypeDisk, UsageTypeNetwork}, 186 period, 187 ) 188} 189 190// GetAllUsage24Hours returns all usage data for a given Vps within the last 24 hours 191func (r *Repository) GetAllUsage24Hours(vpsName string) (Usage, error) { 192 // always define a period body, this way we don't have to depend on the empty body logic on the api server 193 period := UsagePeriod{TimeStart: time.Now().Add(-24 * time.Hour).Unix(), TimeEnd: time.Now().Unix()} 194 195 return r.GetAllUsage(vpsName, period) 196} 197 198// GetVNCData will return VncData about your vps. 199// It allows you to get the location, token and password in order to connect directly to the VNC console of your VPS. 200func (r *Repository) GetVNCData(vpsName string) (VncData, error) { 201 var response vncDataWrapper 202 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/vnc-data", vpsName)} 203 err := r.Client.Get(restRequest, &response) 204 205 return response.VncData, err 206} 207 208// RegenerateVNCToken allows you to regenerate the VNC credentials for a VPS 209func (r *Repository) RegenerateVNCToken(vpsName string) error { 210 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/vnc-data", vpsName)} 211 212 return r.Client.Patch(restRequest) 213} 214 215// GetAddons returns a struct with 'cancellable', 'available' and 'active' addons in it for the given VPS 216func (r *Repository) GetAddons(vpsName string) (Addons, error) { 217 var response addonsWrapper 218 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/addons", vpsName)} 219 err := r.Client.Get(restRequest, &response) 220 221 return response.Addons, err 222} 223 224// OrderAddons allows you to expand VPS specs with a given list of addons to order 225func (r *Repository) OrderAddons(vpsName string, addons []string) error { 226 response := addonOrderRequest{Addons: addons} 227 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/addons", vpsName), Body: &response} 228 229 return r.Client.Post(restRequest) 230} 231 232// CancelAddon allows you to cancel an add-on by name, specifying the VPS name as well. 233// Due to technical restrictions (possible dataloss) storage add-ons cannot be cancelled. 234func (r *Repository) CancelAddon(vpsName string, addon string) error { 235 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/addons/%s", vpsName, addon)} 236 237 return r.Client.Delete(restRequest) 238} 239 240// GetUpgrades returns all available product upgrades for a VPS 241func (r *Repository) GetUpgrades(vpsName string) ([]product.Product, error) { 242 var response upgradesWrapper 243 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/upgrades", vpsName)} 244 err := r.Client.Get(restRequest, &response) 245 246 return response.Upgrades, err 247} 248 249// Upgrade allows you to upgrade a VPS by name and productName 250func (r *Repository) Upgrade(vpsName string, productName string) error { 251 requestBody := upgradeRequest{ProductName: productName} 252 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/upgrades", vpsName), Body: &requestBody} 253 254 return r.Client.Post(restRequest) 255} 256 257// GetOperatingSystems returns a list of operating systems that you can install on a vps 258func (r *Repository) GetOperatingSystems(vpsName string) ([]OperatingSystem, error) { 259 var response operatingSystemsWrapper 260 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/operating-systems", vpsName)} 261 err := r.Client.Get(restRequest, &response) 262 263 return response.OperatingSystems, err 264} 265 266// InstallOperatingSystem allows you to install an operating system to a Vps, 267// optionally you can specify a hostname and a base64InstallText, 268// which would be the automatic installation configuration of your Vps 269// for more information, see: https://api.transip.nl/rest/docs.html#vps-operatingsystems-post 270func (r *Repository) InstallOperatingSystem(vpsName string, operatingSystemName string, hostname string, base64InstallText string) error { 271 requestBody := installRequest{OperatingSystemName: operatingSystemName, Hostname: hostname, Base64InstallText: base64InstallText} 272 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/operating-systems", vpsName), Body: &requestBody} 273 274 return r.Client.Post(restRequest) 275} 276 277// InstallOperatingSystemWithOptions allows you to install an operating system to a Vps, 278// in the options you can specify hostname, username, ssh keys, and base64InstallText, 279// which would be the automatic installation configuration of your Vps 280// for more information, see: https://api.transip.nl/rest/docs.html#vps-operatingsystems-post 281func (r *Repository) InstallOperatingSystemWithOptions(vpsName string, options InstallOptions) error { 282 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/operating-systems", vpsName), Body: &options} 283 284 return r.Client.Post(restRequest) 285} 286 287// GetIPAddresses returns all IPv4 and IPv6 addresses attached to the VPS 288func (r *Repository) GetIPAddresses(vpsName string) ([]ipaddress.IPAddress, error) { 289 var response ipaddress.IPAddressesWrapper 290 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/ip-addresses", vpsName)} 291 err := r.Client.Get(restRequest, &response) 292 293 return response.IPAddresses, err 294} 295 296// GetIPAddressByAddress returns network information for the specified IP address 297func (r *Repository) GetIPAddressByAddress(vpsName string, address net.IP) (ipaddress.IPAddress, error) { 298 var response ipAddressWrapper 299 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/ip-addresses/%s", vpsName, address.String())} 300 err := r.Client.Get(restRequest, &response) 301 302 return response.IPAddress, err 303} 304 305// AddIPv6Address allows you to add an IPv6 address to your VPS. 306// After adding an IPv6 address, you can set the reverse DNS for this address using the UpdateReverseDNS function. 307func (r *Repository) AddIPv6Address(vpsName string, address net.IP) error { 308 requestBody := addIPRequest{IPAddress: address} 309 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/ip-addresses", vpsName), Body: &requestBody} 310 311 return r.Client.Post(restRequest) 312} 313 314// UpdateReverseDNS allows you to update the reverse dns for IPv4 addresses as wal as IPv6 addresses 315func (r *Repository) UpdateReverseDNS(vpsName string, ip ipaddress.IPAddress) error { 316 requestBody := ipAddressWrapper{IPAddress: ip} 317 restRequest := rest.Request{ 318 Endpoint: fmt.Sprintf("/vps/%s/ip-addresses/%s", vpsName, ip.Address.String()), 319 Body: &requestBody, 320 } 321 322 return r.Client.Put(restRequest) 323} 324 325// RemoveIPv6Address allows you to remove an IPv6 address from the registered list of IPv6 address within your VPS's `/64` range. 326func (r *Repository) RemoveIPv6Address(vpsName string, address net.IP) error { 327 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/ip-addresses/%s", vpsName, address.String())} 328 329 return r.Client.Delete(restRequest) 330} 331 332// GetSnapshots returns a list of Snapshots for a given VPS 333func (r *Repository) GetSnapshots(vpsName string) ([]Snapshot, error) { 334 var response snapshotsWrapper 335 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots", vpsName)} 336 err := r.Client.Get(restRequest, &response) 337 338 return response.Snapshots, err 339} 340 341// GetSnapshotByName returns a Snapshot for a VPS given its snapshotName and vpsName 342func (r *Repository) GetSnapshotByName(vpsName string, snapshotName string) (Snapshot, error) { 343 var response snapshotWrapper 344 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots/%s", vpsName, snapshotName)} 345 err := r.Client.Get(restRequest, &response) 346 347 return response.Snapshot, err 348} 349 350// CreateSnapshot allows you to create a snapshot for restoring it at a later time or restoring it to another VPS. 351// See the function RevertSnapshot for this. 352func (r *Repository) CreateSnapshot(vpsName string, description string, shouldStartVps bool) error { 353 requestBody := createSnapshotRequest{Description: description, ShouldStartVps: shouldStartVps} 354 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots", vpsName), Body: &requestBody} 355 356 return r.Client.Post(restRequest) 357} 358 359// RevertSnapshot allows you to revert a snapshot of a vps, 360// if you want to revert a snapshot to a different vps you can use the RevertSnapshotToOtherVps method 361func (r *Repository) RevertSnapshot(vpsName string, snapshotName string) error { 362 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots/%s", vpsName, snapshotName)} 363 364 return r.Client.Patch(restRequest) 365} 366 367// RevertSnapshotToOtherVps allows you to revert a snapshot to a different vps 368func (r *Repository) RevertSnapshotToOtherVps(vpsName string, snapshotName string, destinationVps string) error { 369 requestBody := revertSnapshotRequest{DestinationVpsName: destinationVps} 370 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots/%s", vpsName, snapshotName), Body: &requestBody} 371 372 return r.Client.Patch(restRequest) 373} 374 375// RemoveSnapshot allows you to remove a snapshot from a given VPS 376func (r *Repository) RemoveSnapshot(vpsName string, snapshotName string) error { 377 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/snapshots/%s", vpsName, snapshotName)} 378 379 return r.Client.Delete(restRequest) 380} 381 382// GetBackups allows you to get a list of backups for a given VPS which you can use to revert or convert to snapshot 383func (r *Repository) GetBackups(vpsName string) ([]Backup, error) { 384 var response backupsWrapper 385 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/backups", vpsName)} 386 err := r.Client.Get(restRequest, &response) 387 388 return response.Backups, err 389} 390 391// RevertBackup allows you to revert a backup 392func (r *Repository) RevertBackup(vpsName string, backupID int64) error { 393 requestBody := actionWrapper{Action: "revert"} 394 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/backups/%d", vpsName, backupID), Body: &requestBody} 395 396 return r.Client.Patch(restRequest) 397} 398 399// ConvertBackupToSnapshot allows you to convert a backup to a snapshot 400func (r *Repository) ConvertBackupToSnapshot(vpsName string, backupID int64, snapshotDescription string) error { 401 requestBody := convertBackupRequest{SnapshotDescription: snapshotDescription, Action: "convert"} 402 restRequest := rest.Request{Endpoint: fmt.Sprintf("/vps/%s/backups/%d", vpsName, backupID), Body: &requestBody} 403 404 return r.Client.Patch(restRequest) 405} 406