chore: adding code
This commit is contained in:
parent
1378861295
commit
0a2d1bd711
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jesús Pérez Lorenzo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
33
Makefile
Normal file
33
Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
.PHONY: all
|
||||
|
||||
# all: test build run
|
||||
all: build run
|
||||
|
||||
.PHONY: run
|
||||
|
||||
run:
|
||||
@go run ./...
|
||||
|
||||
.PHONY: build
|
||||
|
||||
build:
|
||||
@go build -o ./build/upclapi ./...
|
||||
@echo "[OK] upclapi was build in ./build/upclapi !"
|
||||
|
||||
.PHONY: install
|
||||
|
||||
install:
|
||||
@go install
|
||||
@echo "[OK] upclapi was installed in $$GOPATH/bin/upclapi"
|
||||
|
||||
# .PHONY: test
|
||||
|
||||
# test:
|
||||
# @go test -v -coverprofile=cover.out ./...
|
||||
# @echo "[OK] Test and coverage file was created!"
|
||||
|
||||
.PHONY: show_coverage
|
||||
|
||||
show_coverage:
|
||||
@go tool cover -html=cover.out
|
||||
@echo "[OK] Coverage file opened!"
|
4
bin/get_hosts_pub_ips.sh
Executable file
4
bin/get_hosts_pub_ips.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
[ -z "$1" ] && echo "source-cloud-home-name not found" && exit 1
|
||||
. ./.env
|
||||
../klouds/bin/hosts_list.sh $1 -src ../klouds/home -filter pub
|
23
bin/make_kenv.sh
Executable file
23
bin/make_kenv.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# tecoder --fencrypt _datacfg.yaml > kdata.yaml
|
||||
#
|
||||
ENCODER="/usr/local/bin/tecoder"
|
||||
ARGSENCODER="-e"
|
||||
|
||||
SOURCE_ENV=".env"
|
||||
TARGET_ENV=".envk"
|
||||
|
||||
[ ! -r "$SOURCE_ENV" ] && echo "File $SOURCE_ENV not found" && exit 1
|
||||
|
||||
USER=$(grep "USER" $SOURCE_ENV | cut -f2 -d"=")
|
||||
[ -z "$USER" ] && echo "User is empty" && exit 1
|
||||
|
||||
PASSWRD=$(grep "PASSWORD" $SOURCE_ENV | cut -f2 -d"=")
|
||||
[ -z "$PASSWRD" ] && echo "Password is empty" && exit 1
|
||||
|
||||
kuser=$($ENCODER $ARGSENCODER $USER)
|
||||
[ -z "$kuser" ] && echo "Unable to encode User" && exit 1
|
||||
kpasswdr=$($ENCODER $ARGSENCODER $PASSWRD)
|
||||
[ -z "$kpasswdr" ] && echo "Unable to encode Password" && exit 1
|
||||
|
||||
echo "export KUPCLAPI=\"$kuser $kpasswdr\"" > $TARGET_ENV
|
22
bin/on_cloud.sh
Executable file
22
bin/on_cloud.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
UPCLAPI_CMD="./build/upclapi"
|
||||
USAGE="on_cloud.sh home-cloud-dir-name tsksrvc [ args ]
|
||||
example: on_cloud.sh wuji/dvara info
|
||||
"
|
||||
[ -z "$1" ] || [ "$1" == "-h" ] && echo "$USAGE" && $UPCLAPI_CMD -h && exit
|
||||
. ./env
|
||||
CLOUD_CONFIG_PATH="$KLDS_HOME/$1/$KLDS_CONFIG"
|
||||
[ ! -r "$CLOUD_CONFIG_PATH" ] && echo "$CLOUD_CONFIG_PATH not found" && exit
|
||||
[ -z "$2" ] && echo "No tsksrvc defined" && echo "$USAGE" && exit 1
|
||||
case "$2" in
|
||||
c|create|createserver) TSKSRVC="createserver" ;;
|
||||
d|delete|deleteserver) TSKSRVC="deleteserver" ;;
|
||||
i|info) TSKSRVC="infoserver" ;;
|
||||
*) TSKSRVC="$2"
|
||||
esac
|
||||
|
||||
if $UPCLAPI_CMD -c "$TSKSRVC" -f "$CLOUD_CONFIG_PATH" ; then
|
||||
[ "$TSKSRVC" == "createserver" ] && "$ROOT_KLDS"/bin/hosts_list.sh "$1" -src "$KLDS_HOME" -filter pub
|
||||
fi
|
||||
|
||||
|
54
bin/update_storage.sh
Executable file
54
bin/update_storage.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
USAGE="update_storage.sh [-d] server-name new-size"
|
||||
[ "$1" == "-h" ] && echo "$USAGE" && exit
|
||||
[ "$1" == "-d" ] && DEBUG=$1 && shift
|
||||
[ -z "$1" ] && echo "No server found" && echo "$USAGE" && exit 1
|
||||
SERVER_ID=$1
|
||||
[ -z "$2" ] && echo "No new size found" && echo "$USAGE" && exit 1
|
||||
NEW_SIZE=$2
|
||||
STOPPED="stopped"
|
||||
STARTED="started"
|
||||
MAX_TRIES=5
|
||||
SLEEP_TIME=10
|
||||
|
||||
_server_state() {
|
||||
[ -z "$1" ] && return
|
||||
upctl server show "$1" | grep State | awk '{print $2}'
|
||||
}
|
||||
_is_server_started() {
|
||||
[ -z "$1" ] && return
|
||||
_server_state "$1" | grep started
|
||||
}
|
||||
_stop_server() {
|
||||
[ -z "$1" ] && return
|
||||
[[ "$(_server_state "$1")" =~ $STOPPED ]] && return
|
||||
#[[ ! "$(_server_state "$1")" =~ $STOPPED ]] &&
|
||||
upctl server stop "$1" 2>/dev/null
|
||||
local n=0
|
||||
echo -n "Stopping $1 "
|
||||
while [[ ! "$(_server_state "$1")" =~ $STOPPED ]]
|
||||
do
|
||||
n=$((n+1))
|
||||
echo -n ". "
|
||||
sleep $SLEEP_TIME
|
||||
[ "$n" -gt $MAX_TRIES ] && echo "Server $1 not $STOPPED" && exit 2
|
||||
done
|
||||
echo " $(_server_state "$1")"
|
||||
}
|
||||
|
||||
STORE_UUID=$(upctl server show "$SERVER_ID" -o json | jq -r '.storage[].uuid ' | sed 's/"//')
|
||||
[ -z "$STORE_UUID" ] && echo "No store found for $SERVER_ID" && exit 1
|
||||
STORE_SIZE=$(upctl server show "$SERVER_ID" -o json | jq '.storage[].size ')
|
||||
|
||||
echo "$SERVER_ID: store $STORE_UUID from $STORE_SIZE to $NEW_SIZE"
|
||||
[ "$STORE_SIZE" -gt "$NEW_SIZE" ] && echo "$NEW_SIZE is less then current $STORE_SIZE" && exit 1
|
||||
|
||||
_stop_server "$SERVER_ID"
|
||||
[ -n "$DEBUG" ] && _server_state "$SERVER_ID"
|
||||
|
||||
if upctl storage modify "$STORE_UUID" --size "$NEW_SIZE" ; then
|
||||
[ -n "$DEBUG" ] && _server_state "$SERVER_ID"
|
||||
[[ ! "$(_server_state "$1")" =~ $STARTED ]] && upctl server start "$SERVER_ID"
|
||||
else
|
||||
echo "errors in modify $SERVER_ID $STORE_UUID"
|
||||
fi
|
126
floatip.go
Normal file
126
floatip.go
Normal file
@ -0,0 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
// "encoding/json"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
)
|
||||
|
||||
func getFloatIP(s *service.Service, floatIP string, datacfg *DataConfig) (*upcloud.IPAddress,error) {
|
||||
ip := floatIP
|
||||
if ip == "" {
|
||||
ip = datacfg.FloatIP
|
||||
}
|
||||
ipinfo, err := s.GetIPAddressDetails(&request.GetIPAddressDetailsRequest{
|
||||
Address: ip,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error getting info %s: %#v\n", floatIP, err)
|
||||
return nil,err
|
||||
}
|
||||
return ipinfo,nil
|
||||
}
|
||||
func moveFloatIP(s *service.Service, data []string, datacfg *DataConfig) error {
|
||||
// err := s.ReleaseIPAddress(&request.ReleaseIPAddressRequest{
|
||||
// IPAddress: uuid,
|
||||
// })
|
||||
// fmt.Fprintf(os.Stderr, "details %#v: %#v\n", uuid, err)
|
||||
targetFloatIP := ""
|
||||
targetHost := ""
|
||||
if len(data) > 0 {
|
||||
targetFloatIP = data[0]
|
||||
targetHost = data[1]
|
||||
} else {
|
||||
targetFloatIP = datacfg.FloatIP
|
||||
}
|
||||
servers, err := s.GetServers()
|
||||
if err != nil || len(servers.Servers) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get servers: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
ipinfo, err := getFloatIP(s,targetFloatIP,datacfg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error getting info %s: %#v\n", targetFloatIP, err)
|
||||
return err
|
||||
}
|
||||
// fmt.Fprintf(os.Stderr, "ipinfo: %#v\n", ipinfo)
|
||||
// fmt.Printf("Retrieved %d servers\n", len(servers.Servers))
|
||||
// fmt.Println("Deleting all servers")
|
||||
currentFloatIP := ""
|
||||
for _, server := range servers.Servers {
|
||||
if datacfg.HostPrefix != "" && ! strings.Contains(server.Hostname,datacfg.HostPrefix) {
|
||||
continue
|
||||
}
|
||||
if ipinfo.ServerUUID == server.UUID {
|
||||
fmt.Fprintf(os.Stderr, "%s Located in %s %s:%s Server: %s) \n", targetFloatIP, ipinfo.PTRRecord, server.Hostname, ipinfo.MAC, ipinfo.ServerUUID)
|
||||
currentFloatIP = server.Hostname
|
||||
break
|
||||
}
|
||||
}
|
||||
if currentFloatIP == "" {
|
||||
fmt.Fprintf(os.Stderr, "%s Not in use in %s \n", targetFloatIP, ipinfo.PTRRecord)
|
||||
}
|
||||
for _, server := range servers.Servers {
|
||||
if (datacfg.HostPrefix != "" && ! strings.Contains(server.Hostname,datacfg.HostPrefix)) || ipinfo.ServerUUID == server.UUID {
|
||||
continue
|
||||
}
|
||||
var target_srv ServerConfig
|
||||
if targetHost == "" {
|
||||
for _,srv := range datacfg.Servers {
|
||||
if server.Hostname == srv.Hostname && srv.UseFloatIP {
|
||||
target_srv = srv
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if server.Hostname == targetHost {
|
||||
target_srv.Hostname = targetHost
|
||||
}
|
||||
}
|
||||
if target_srv.Hostname == "" {
|
||||
continue
|
||||
}
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
target_IP := ""
|
||||
target_MAC := ""
|
||||
for i := 0; i < len(info.Networking.Interfaces); i++ {
|
||||
if info.Networking.Interfaces[i].Type == upcloud.NetworkTypePublic {
|
||||
for _,ip := range info.Networking.Interfaces[i].IPAddresses {
|
||||
if ip.Address != targetFloatIP {
|
||||
target_IP = ip.Address
|
||||
break
|
||||
}
|
||||
}
|
||||
target_MAC=info.Networking.Interfaces[i].MAC
|
||||
break
|
||||
}
|
||||
}
|
||||
if target_IP != "" && target_MAC != "" {
|
||||
ptr := fmt.Sprintf("%s.%s.upcloud.host", target_IP, info.Zone)
|
||||
newIP,err := s.ModifyIPAddress(&request.ModifyIPAddressRequest{
|
||||
IPAddress: targetFloatIP,
|
||||
PTRRecord: ptr,
|
||||
MAC: target_MAC,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error %s: %#v\n", targetFloatIP, err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s Moved -> %s %s:%s Server: %s \n", newIP.Address, newIP.PTRRecord, target_srv.Hostname, newIP.MAC, server.UUID)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
131
inventory.go
Normal file
131
inventory.go
Normal file
@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
// "log"
|
||||
"os"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
)
|
||||
|
||||
func inventoryOneServer(s *service.Service, floatIP string, server upcloud.Server) (string, error) {
|
||||
ansible_data := "ansible_port=22 ansible_python_interpreter=/usr/bin/python3 ansible_user=root"
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details from server %#v: %#v\n", server.UUID, err)
|
||||
return "", err
|
||||
}
|
||||
public_ip :=""
|
||||
private_ip :=""
|
||||
vpn_ip :=""
|
||||
host :=""
|
||||
float := upcloud.False
|
||||
output := ""
|
||||
|
||||
for _, ip := range info.Networking.Interfaces {
|
||||
for _, addr := range ip.IPAddresses {
|
||||
if addr.Address == floatIP {
|
||||
continue
|
||||
}
|
||||
switch ip.Type {
|
||||
case upcloud.NetworkTypePublic:
|
||||
public_ip = addr.Address
|
||||
float = addr.Floating
|
||||
case upcloud.NetworkTypeUtility:
|
||||
private_ip = addr.Address
|
||||
case upcloud.NetworkTypePrivate:
|
||||
vpn_ip = addr.Address
|
||||
}
|
||||
}
|
||||
}
|
||||
if vpn_ip != "" {
|
||||
host = vpn_ip
|
||||
} else {
|
||||
host = public_ip
|
||||
}
|
||||
floating := "no"
|
||||
if float == upcloud.True {
|
||||
floating = "yes"
|
||||
}
|
||||
output += fmt.Sprintf("%s ansible_host=%s hostname=%s vpn_ip=%s pub_ip=%s private_ip=%s float=%s ",
|
||||
server.Hostname,
|
||||
host,
|
||||
server.Hostname,
|
||||
vpn_ip,
|
||||
public_ip,
|
||||
private_ip,
|
||||
floating)
|
||||
output += fmt.Sprintf(" uuid=%s %s\n",info.UUID,ansible_data)
|
||||
return output, nil
|
||||
}
|
||||
func hostsOneServer(s *service.Service, usetype string, floatIP string, server upcloud.Server, target ServerConfig) (string, error) {
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details from server %#v: %#v\n", server.UUID, err)
|
||||
return "", err
|
||||
}
|
||||
public_ip :=""
|
||||
private_ip :=""
|
||||
sdn_ip :=""
|
||||
vpn_ip :=""
|
||||
vpn_net :=""
|
||||
float := upcloud.False
|
||||
output := ""
|
||||
|
||||
for i := 0; i < len(info.Networking.Interfaces); i++ {
|
||||
for _,addr := range info.Networking.Interfaces[i].IPAddresses {
|
||||
if addr.Address == floatIP {
|
||||
continue
|
||||
}
|
||||
switch info.Networking.Interfaces[i].Type {
|
||||
case upcloud.NetworkTypePublic:
|
||||
public_ip = addr.Address
|
||||
float = addr.Floating
|
||||
case upcloud.NetworkTypeUtility:
|
||||
private_ip = addr.Address
|
||||
case upcloud.NetworkTypePrivate:
|
||||
sdn_ip = addr.Address
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(target.Networks); i++ {
|
||||
if target.Networks[i].Access == "vpn" {
|
||||
vpn_ip = target.Networks[i].IPAddress
|
||||
vpn_net = target.Networks[i].Network
|
||||
}
|
||||
}
|
||||
floating := "no"
|
||||
if float == upcloud.True {
|
||||
floating = "yes"
|
||||
}
|
||||
suffix := ""
|
||||
output += fmt.Sprintf("# %s \t %s float=%s | %s\n", server.Hostname, server.UUID, floating, server.Title)
|
||||
if public_ip != "" {
|
||||
if usetype == "prv" {
|
||||
suffix = ".pub"
|
||||
}
|
||||
output += fmt.Sprintf("%s \t %s%s \t# PUB\n", public_ip, server.Hostname, suffix)
|
||||
}
|
||||
if sdn_ip != "" {
|
||||
if usetype == "pub" {
|
||||
suffix = ".prv"
|
||||
} else {
|
||||
suffix = ""
|
||||
}
|
||||
output += fmt.Sprintf("%s \t %s%s \t# SDN\n", sdn_ip,server.Hostname, suffix)
|
||||
}
|
||||
if private_ip != "" {
|
||||
output += fmt.Sprintf("%s \t %s.pv \t# PV\n", private_ip, server.Hostname)
|
||||
}
|
||||
if vpn_ip != "" {
|
||||
output += fmt.Sprintf("%s \t %s.vpn \t# VPN /%s\n", vpn_ip, server.Hostname, vpn_net)
|
||||
}
|
||||
return output,nil
|
||||
}
|
||||
|
552
main.go
Normal file
552
main.go
Normal file
@ -0,0 +1,552 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
// https://abhinavg.net/posts/flexible-yaml/
|
||||
)
|
||||
|
||||
const SEPARATOR = "::"
|
||||
const DATA_CFG = "datacfg.yaml"
|
||||
const DFLT_COMMAND= "infoserver"
|
||||
const SSH_KEY_PATH = ".sshkeys"
|
||||
|
||||
const MONTH_HOURS = 672
|
||||
|
||||
var username string
|
||||
var password string
|
||||
|
||||
var TECODER = CoderConfig {
|
||||
cmd: "tecoder",
|
||||
abbrv: "tc",
|
||||
decoder: "-d",
|
||||
fdecoder: "--fdecrypt",
|
||||
encoder: "-e",
|
||||
fencoder: "--fencrypt",
|
||||
}
|
||||
|
||||
type RunFlags struct {
|
||||
command string
|
||||
dataCfgPath string
|
||||
id string
|
||||
runCmd string
|
||||
encdr string
|
||||
out string
|
||||
target string
|
||||
}
|
||||
type CoderConfig struct {
|
||||
cmd string
|
||||
abbrv string
|
||||
decoder string
|
||||
fdecoder string
|
||||
encoder string
|
||||
fencoder string
|
||||
}
|
||||
type StoreConfig struct {
|
||||
Title string `yaml:"title"`
|
||||
Uuid string `yaml:"uuid"`
|
||||
Size int `yaml:"size"`
|
||||
Servers []string `yaml:"servers"`
|
||||
}
|
||||
type DataStorageDevices struct {
|
||||
Action string `yaml:"action"`
|
||||
Title string `yaml:"title"`
|
||||
Storage string `yaml:"storage"`
|
||||
Size int `yaml:"size"`
|
||||
FinalSize int `yaml:"finalSize"`
|
||||
PartSizes string `yaml:"partSizes"`
|
||||
MakeFs string `yaml:"makefs"`
|
||||
Tier string `yaml:"tier"`
|
||||
Source string `yaml:"source"`
|
||||
// Type: string `yaml:"type"`
|
||||
// Address string `json:"address,omitempty"`
|
||||
}
|
||||
|
||||
type NetworksConfig struct {
|
||||
Access string `yaml:"access"`
|
||||
Family string `yaml:"family"`
|
||||
Network string `yaml:"network"`
|
||||
IPAddress string `yaml:"ipaddress"`
|
||||
SourceIPFiltering string `yaml:"source_ip_filtering"`
|
||||
// SourceIPFiltering upcloud.Boolean `yaml:"source_ip_filtering"`
|
||||
}
|
||||
|
||||
type ClusterRole struct {
|
||||
Role string `yaml:"role"`
|
||||
}
|
||||
|
||||
type TskSrvc struct {
|
||||
name string `yaml:"name"`
|
||||
path string `yaml:"path"`
|
||||
target string `yaml:"target"`
|
||||
req string `yaml:"req"`
|
||||
liveness string `yaml:"liveness"`
|
||||
}
|
||||
|
||||
type App struct {
|
||||
name string `yaml:"name"`
|
||||
path string `yaml:"path"`
|
||||
target string `yaml:"target"`
|
||||
req string `yaml:"req"`
|
||||
liveness string `yaml:"liveness"`
|
||||
}
|
||||
|
||||
type SSHAccess struct {
|
||||
Host string `yaml:"host"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
UType string `yaml:"utype"`
|
||||
KeyPath string `yaml:"keyPath"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
type LoginUserConfig struct {
|
||||
// CreatePassword string `yaml:"createPassword"`
|
||||
// Username string `yaml:"username"`
|
||||
SSHKeys []string `yaml:"sshKeys"`
|
||||
}
|
||||
|
||||
type Cntrllrs struct {
|
||||
host string `yaml:"host"`
|
||||
sshaccess SSHAccess `yaml:"sshaccess"`
|
||||
cldPath string `yaml:"cldPath"`
|
||||
masterPath string `yaml:"masterPath"`
|
||||
}
|
||||
|
||||
// https://abhinavg.net/posts/flexible-yaml/
|
||||
|
||||
type ServerConfig struct {
|
||||
Hostname string `yaml:"hostname"`
|
||||
Title string `yaml:"title"`
|
||||
UserData string `yaml:"userData"`
|
||||
Zone string `yaml:"zone"`
|
||||
UUID string `yaml:"uuid"`
|
||||
Host string `yaml:"host"`
|
||||
Tags []string `yaml:"tags"`
|
||||
Cluster ClusterRole `yaml:"cluster"`
|
||||
SSHAccess SSHAccess `yaml:"sshAccess"`
|
||||
LoginUser LoginUserConfig `yaml:"loginUser"`
|
||||
Plan string `yaml:"plan"`
|
||||
Metadata upcloud.Boolean `yaml:"metadata"`
|
||||
TimeZone string `yaml:"timeZone"`
|
||||
Networks []NetworksConfig `yaml:"networks"`
|
||||
StorageDevices []DataStorageDevices `yaml:"storages"`
|
||||
UseFloatIP bool `yaml:"useFloatIP"`
|
||||
TskSrvcs []TskSrvc `yaml:"tsksrvcs"`
|
||||
Apps []App `yaml:"apps"`
|
||||
Clients []string `yaml:"clients"`
|
||||
Rules []string `yaml:"rules"`
|
||||
Backup []string `yaml:"backup"`
|
||||
}
|
||||
|
||||
type DataConfig struct {
|
||||
Servers []ServerConfig `yaml:"servers"`
|
||||
FloatIP string `yaml:"floatIP"`
|
||||
Group string `yaml:"group"`
|
||||
GroupPath string `yaml:"group_path"`
|
||||
HostPrefix string `yaml:"hostPrefix"`
|
||||
MainName string `yaml:"main"`
|
||||
domainName string `yaml:"domainName"`
|
||||
cntrllrs []Cntrllrs `yaml:"cntrllrs"`
|
||||
}
|
||||
|
||||
type InfoServer struct {
|
||||
info upcloud.ServerDetails `json:"ServerDetails"`
|
||||
price Price `json:"Price"`
|
||||
// price upcloud.Price `json:"Price"`
|
||||
}
|
||||
/*
|
||||
type CloudGroup struct {
|
||||
name string `yaml:"name"`
|
||||
path string `yaml:"path"`
|
||||
info string `yaml:"info"`
|
||||
resources ConfigResources `yaml:"resources"`
|
||||
}
|
||||
|
||||
type KloudHome struct {
|
||||
name string `yaml:"name"`
|
||||
title string `yaml:"title"`
|
||||
dflts string `yaml:"dflts"`
|
||||
provider []ProviderName `yaml:"provider"`
|
||||
netips []IpDef `yaml:"netips"`
|
||||
cntrllrs []Cntrllrs `yaml:"cntrllrs"`
|
||||
groups []CloudGroup `yaml:"groups"`
|
||||
}
|
||||
*/
|
||||
// type DDataConfig struct {
|
||||
// // Servers []ServerConfig `yaml:"servers"`
|
||||
// floatIP string `yaml:"floatIP"`
|
||||
// hostPrefix string `yaml:"hostPrefix"`
|
||||
// mainName string `yaml:"main"`
|
||||
// }
|
||||
|
||||
// Price represents a price
|
||||
type Price struct {
|
||||
Amount int `yam:"amount"`
|
||||
Price float64 `yaml:"price"`
|
||||
Hour float64 `yaml:"price_hour"`
|
||||
Month float64 `yaml:"price_month"`
|
||||
}
|
||||
|
||||
type DataPrices struct {
|
||||
Prices PricesZones `yaml:"prices"`
|
||||
}
|
||||
type PricesZones struct {
|
||||
Zone []PricesZone `yaml:"zone"`
|
||||
}
|
||||
|
||||
type PricesZone struct {
|
||||
Name string `yaml:"name"`
|
||||
Firewall Price `yaml:"firewall"`
|
||||
IORequestBackup Price `yaml:"io_request_backup"`
|
||||
IORequestHDD Price `yaml:"io_request_hdd"`
|
||||
IORequestMaxIOPS Price `yaml:"io_request_maxiops"`
|
||||
IPv4Address Price `yaml:"ipv4_address"`
|
||||
IPv6Address Price `yaml:"ipv6_address"`
|
||||
ManagedDatabase1x1CPU2GB25GB Price `yaml:"managed_database_1x1xCPU-2GB-25GB"`
|
||||
ManagedDatabase1x2CPU4GB100GB Price `yaml:"managed_database_1x2xCPU-4GB-100GB"`
|
||||
ManagedDatabase1x2CPU4GB50GB Price `yaml:"managed_database_1x2xCPU-4GB-50GB"`
|
||||
ManagedDatabase2x2CPU4GB100GB Price `yaml:"managed_database_2x2xCPU-4GB-100GB"`
|
||||
ManagedDatabase2x2CPU4GB50GB Price `yaml:"managed_database_2x2xCPU-4GB-50GB"`
|
||||
ManagedDatabase2x4CPU8GB100GB Price `yaml:"managed_database_2x4xCPU-8GB-100GB"`
|
||||
ManagedDatabase2x4CPU8GB50GB Price `yaml:"managed_database_2x4xCPU-8GB-50GB"`
|
||||
ManagedDatabase2x6CPU16GB100GB Price `yaml:"managed_database_2x6xCPU-16GB-100GB"`
|
||||
ManagedDatabase2x6CPU16GB50GB Price `yaml:"managed_database_2x6xCPU-16GB-250GB"`
|
||||
ManagedDatabase2x8CPU32GB100GB Price `yaml:"managed_database_2x8xCPU-32GB-100GB"`
|
||||
ManagedDatabase2x8CPU22GB250GB Price `yaml:"managed_database_2x8xCPU-32GB-250GB"`
|
||||
ManagedDatabase3x2CPU4GB100GB Price `yaml:"managed_database_3x2xCPU-4GB-100GB"`
|
||||
ManagedDatabase3x2CPU4GB200GB Price `yaml:"managed_database_3x2xCPU-4GB-200GB"`
|
||||
ManagedDatabase3x4CPU8GB100GB Price `yaml:"managed_database_3x4xCPU-8GB-100GB"`
|
||||
ManagedDatabase3x4CPU8GB200GB Price `yaml:"managed_database_3x4xCPU-8GB-200GB"`
|
||||
ManagedDatabase3x6CPU16GB200GB Price `yaml:"managed_database_3x6xCPU-16GB-200GB"`
|
||||
ManagedDatabase3x6CPU16GB500GB Price `yaml:"managed_database_3x6xCPU-16GB-500GB"`
|
||||
ManagedDatabase3x8CPU32GB200GB Price `yaml:"managed_database_3x8xCPU-32GB-200GB"`
|
||||
ManagedDatabase3x8CPU32GB500GB Price `yaml:"managed_database_3x8xCPU-32GB-500GB"`
|
||||
NetworkPrivateVLAN Price `yaml:"network_private_vlan"`
|
||||
ObjectStorage1TB Price `yaml:"object_storage_1TB"`
|
||||
ObjectStorage250GB Price `yaml:"object_storage_250GB"`
|
||||
ObjectStorage500GB Price `yaml:"object_storage_500GB"`
|
||||
PublicIPv4BandwidthIn Price `yaml:"public_ipv4_bandwidth_in"`
|
||||
PublicIPv4BandwidthOut Price `yaml:"public_ipv4_bandwidth_out"`
|
||||
PublicIPv6BandwidthIn Price `yaml:"public_ipv6_bandwidth_in"`
|
||||
PublicIPv6BandwidthOut Price `yaml:"public_ipv6_bandwidth_out"`
|
||||
ServerCore Price `yaml:"server_core"`
|
||||
ServerMemory Price `yaml:"server_memory"`
|
||||
ServerPlan6xCPU8GB Price `yaml:"server_plan_6xCPU-8GB"`
|
||||
ServerPlan12xCPU48GB Price `yaml:"server_plan_12xCPU-48GB"`
|
||||
ServerPlan16xCPU64GB Price `yaml:"server_plan_16xCPU-64GB"`
|
||||
ServerPlan1xCPU1GB Price `yaml:"server_plan_1xCPU-1GB"`
|
||||
ServerPlan1xCPU2GB Price `yaml:"server_plan_1xCPU-2GB"`
|
||||
ServerPlan20xCPU128GB Price `yaml:"server_plan_20xCPU-128GB"`
|
||||
ServerPlan20xCPU96GB Price `yaml:"server_plan_20xCPU-96GB"`
|
||||
ServerPlan2xCPU4GB Price `yaml:"server_plan_2xCPU-4GB"`
|
||||
ServerPlan4xCPU8GB Price `yaml:"server_plan_4xCPU-8GB"`
|
||||
ServerPlan6xCPU16GB Price `yaml:"server_plan_6xCPU-16GB"`
|
||||
ServerPlan8xCPU32GB Price `yaml:"server_plan_8xCPU-32GB"`
|
||||
SimpleBackupDailies12xCPU48GB Price `yaml:"simple_backup_dailies_12xCPU-48GB"`
|
||||
SimpleBackupDailies16xCPU64GB Price `yaml:"simple_backup_dailies_16xCPU-64GB"`
|
||||
SimpleBackupDailiesx1CPU1GB Price `yaml:"simple_backup_dailies_1xCPU-1GB"`
|
||||
SimpleBackupDailies1xCPU2GB Price `yaml:"simple_backup_dailies_1xCPU-2GB"`
|
||||
SimpleBackupDailies20xCPU128GB Price `yaml:"simple_backup_dailies_20xCPU-128GB"`
|
||||
SimpleBackupDailies20xCPU96GB Price `yaml:"simple_backup_dailies_20xCPU-96GB"`
|
||||
SimpleBackupDailies2xCPU4GB Price `yaml:"simple_backup_dailies_2xCPU-4GB"`
|
||||
SimpleBackupDailies4xCPU8GB Price `yaml:"simple_backup_dailies_4xCPU-8GB"`
|
||||
SimpleBackupDailies6xCPU16GB Price `yaml:"simple_backup_dailies_6xCPU-16GB"`
|
||||
SimpleBackupDailies8xCPU32GB Price `yaml:"simple_backup_dailies_8xCPU-32GB"`
|
||||
SimpleBackupExtraDailies Price `yaml:"simple_backup_extra_dailies"`
|
||||
SimpleBackupExtraMontlies Price `yaml:"simple_backup_extra_monthlies"`
|
||||
SimpleBackupExtraWeeklies Price `yaml:"simple_backup_extra_weeklies"`
|
||||
SimpleBackupMonthlies12xCPU48GB Price `yaml:"simple_backup_monthlies_12xCPU-48GB"`
|
||||
SimpleBackupMonthlies16xCPU64GB Price `yaml:"simple_backup_monthlies_16xCPU-64GB"`
|
||||
SimpleBackupMonthlies1xCPU1GB Price `yaml:"simple_backup_monthlies_1xCPU-1GB"`
|
||||
SimpleBackupMonthlies1xCPU2GB Price `yaml:"simple_backup_monthlies_1xCPU-2GB"`
|
||||
SimpleBackupMonthlies20xCPU128GB Price `yaml:"simple_backup_monthlies_20xCPU-128GB"`
|
||||
SimpleBackupMonthlies20xCPU96GB Price `yaml:"simple_backup_monthlies_20xCPU-96GB"`
|
||||
SimpleBackupMonthlies2xCPU4GB Price `yaml:"simple_backup_monthlies_2xCPU-4GB"`
|
||||
SimpleBackupMonthlies4xCPU8GB Price `yaml:"simple_backup_monthlies_4xCPU-8GB"`
|
||||
SimpleBackupMonthlies6xCPU16GB Price `yaml:"simple_backup_monthlies_6xCPU-16GB"`
|
||||
SimpleBackupMonthlies8xCPU32GB Price `yaml:"simple_backup_monthlies_8xCPU-32GB"`
|
||||
SimpleBackupWeeklies12xCPU48GB Price `yaml:"simple_backup_weeklies_12xCPU-48GB"`
|
||||
SimpleBackupWeeklies16xCPU64GB Price `yaml:"simple_backup_weeklies_16xCPU-64GB"`
|
||||
SimpleBackupWeeklies1xCPU1GB Price `yaml:"simple_backup_weeklies_1xCPU-1GB"`
|
||||
SimpleBackupWeeklies1xCPU2GB Price `yaml:"simple_backup_weeklies_1xCPU-2GB"`
|
||||
SimpleBackupWeeklies20xCPU128GB Price `yaml:"simple_backup_weeklies_20xCPU-128GB"`
|
||||
SimpleBackupWeeklies20xCPU96GB Price `yaml:"simple_backup_weeklies_20xCPU-96GB"`
|
||||
SimpleBackupWeeklies2xCPU4GB Price `yaml:"simple_backup_weeklies_2xCPU-4GB"`
|
||||
SimpleBackupWeeklies4xCPU8GB Price `yaml:"simple_backup_weeklies_4xCPU-8GB"`
|
||||
SimpleBackupWeeklies6xCPU16GB Price `yaml:"simple_backup_weeklies_6xCPU-16GB"`
|
||||
SimpleBackupWeeklies8xCPU32GB Price `yaml:"simple_backup_weeklies_8xCPU-32GB"`
|
||||
StorageHDD Price `yaml:"storage_hdd"`
|
||||
StorageBackup Price `yaml:"storage_backup"`
|
||||
StorageMaxIOPS Price `yaml:"storage_maxiops"`
|
||||
StorageTemplate Price `yaml:"storage_template"`
|
||||
}
|
||||
|
||||
func (m *InfoServer) MarshalJSON() ([]byte, error) {
|
||||
// meta := `"Id":` + strconv.Itoa(m.Meta.Id)
|
||||
info, err_info := json.Marshal(m.info)
|
||||
if err_info != nil {
|
||||
return nil, err_info
|
||||
}
|
||||
price, err_price := json.Marshal(m.price)
|
||||
if err_price != nil {
|
||||
return nil, err_price
|
||||
}
|
||||
// fmt.Printf("price %s \n", price)
|
||||
// Stitching it all together
|
||||
// return []byte(`{` + meta + `,"Contents":` + string(cont) + `}`), nil
|
||||
return []byte(`{"info":` + string(info) + `,"price":` + string(price) + `}`), nil
|
||||
}
|
||||
//func (s *InfoServer) UnmarshalJSON(b []byte) error {
|
||||
// type serverWrapper struct {
|
||||
// PriceZones []PriceZone `json:"zone"`
|
||||
// }
|
||||
|
||||
// v := struct {
|
||||
// PriceZones serverWrapper `json:"prices"`
|
||||
// }{}
|
||||
// err := json.Unmarshal(b, &v)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// s.PriceZones = v.PriceZones.PriceZones
|
||||
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func getDataPrices() (*DataPrices, error) {
|
||||
dataPrices := &DataPrices{}
|
||||
if len(os.Getenv("UPCLOUD_PRICES")) == 0 {
|
||||
return dataPrices,nil
|
||||
}
|
||||
file, err := os.Open(os.Getenv("UPCLOUD_PRICES"))
|
||||
if err != nil {
|
||||
return dataPrices,err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Init new YAML decode
|
||||
d := yaml.NewDecoder(file)
|
||||
// Start YAML decoding from file
|
||||
if err := d.Decode(&dataPrices); err != nil {
|
||||
return dataPrices,err
|
||||
}
|
||||
// fmt.Printf("Loaded prices: %#v\n", dataPrices)
|
||||
return dataPrices,nil
|
||||
}
|
||||
// NewDataConfig returns a new decoded DataConfig struct
|
||||
func NewDataConfig(runFlags RunFlags) (*DataConfig, error) {
|
||||
// Load config structure from YAML
|
||||
dataConfig := &DataConfig{}
|
||||
// fmt.Printf("Loaded config: %#v\n", runFlags.dataCfgPath)
|
||||
/*
|
||||
if runFlags.encdr == TECODER.cmd || runFlags.encdr == TECODER.abbrv {
|
||||
// content, err := ioutil.ReadFile(runFlags.dataCfgPath)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// return nil,err
|
||||
// }
|
||||
//out, err := exec.Command(CODER,ARGS_DECODER,string(content)).Output()
|
||||
out, err := exec.Command(TECODER.cmd,TECODER.fdecoder,runFlags.dataCfgPath).Output()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to decode %s error: %#v\n ",runFlags.dataCfgPath,err)
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(out,&dataConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
ddataConfig := &DDataConfig{}
|
||||
bytes, err := ioutil.ReadFile(runFlags.dataCfgPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = dhall.Unmarshal(bytes, &ddataConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Loaded config: %#v\n", ddataConfig)
|
||||
*/
|
||||
// Open config file
|
||||
file, err := os.Open(runFlags.dataCfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Init new YAML decode
|
||||
d := yaml.NewDecoder(file)
|
||||
// Start YAML decoding from file
|
||||
if err := d.Decode(&dataConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// fmt.Printf("Loaded config: %#v\n", dataConfig)
|
||||
// }
|
||||
return dataConfig, nil
|
||||
}
|
||||
func getAuthKeysData(path string) string {
|
||||
pathAuth := fmt.Sprintf("%s/%s", path,SSH_KEY_PATH)
|
||||
// fmt.Fprintf(os.Stdout, "%#v\n",pathAuth)
|
||||
if _, err := os.Stat(pathAuth); err == nil {
|
||||
file, err := os.Open(pathAuth)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer file.Close()
|
||||
}
|
||||
return pathAuth
|
||||
}
|
||||
func loadLoginUserKeys(runFlags RunFlags) request.SSHKeySlice {
|
||||
dirAuth := filepath.Dir(runFlags.dataCfgPath)
|
||||
keysPath := getAuthKeysData(dirAuth)
|
||||
for i := 0; i < 3; i++ {
|
||||
if keysPath == "" {
|
||||
break
|
||||
}
|
||||
dirAuth = filepath.Dir(dirAuth)
|
||||
keysPath = getAuthKeysData(dirAuth)
|
||||
}
|
||||
if keysPath == "" {
|
||||
return nil
|
||||
}
|
||||
file, err := os.Open(keysPath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer file.Close()
|
||||
// fmt.Fprintf(os.Stdout, "%#v\n",keysPath)
|
||||
var sshKeys request.SSHKeySlice
|
||||
d := yaml.NewDecoder(file)
|
||||
if err := d.Decode(&sshKeys); err != nil {
|
||||
fmt.Fprintf(os.Stdout, "%#v\n",err)
|
||||
return nil
|
||||
}
|
||||
// fmt.Fprintf(os.Stdout, "%#v\n",sshKeys)
|
||||
return sshKeys
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 || len(os.Getenv("UPCLAPI_COMMAND")) > 0 {
|
||||
os.Exit(run())
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "Use --help to see options")
|
||||
}
|
||||
}
|
||||
|
||||
func hasID(id string) bool {
|
||||
if len(id) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "D must be specified")
|
||||
os.Exit(2)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func loadDataConfig(runFlags RunFlags) (*DataConfig, error) {
|
||||
// datacfg := &DataConfig{}
|
||||
datacfg, err := NewDataConfig(runFlags)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return datacfg, err
|
||||
}
|
||||
return datacfg, nil
|
||||
}
|
||||
|
||||
// ValidateDataPath just makes sure, that the path provided is a file,
|
||||
// that can be read
|
||||
func ValidateDataPath(path string) error {
|
||||
s, err := os.Stat(path); os.IsNotExist(err)
|
||||
if err != nil {
|
||||
return fmt.Errorf("'%s' config file not found", path)
|
||||
}
|
||||
if s.IsDir() {
|
||||
return fmt.Errorf("'%s' is a directory, not a normal file", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseFlags will create and parse the CLI flags
|
||||
// and return the path to be used elsewhere
|
||||
func ParseFlags() (RunFlags,error) {
|
||||
// target := flag.Arg(1)
|
||||
// fmt.Printf("%+v ...\n",target) // Print with Variable Name
|
||||
// String that contains the configured configuration path
|
||||
runFlags := RunFlags {
|
||||
command: os.Getenv("UPCLAPI_COMMAND"),
|
||||
dataCfgPath: os.Getenv("UPCLAPI_DATACFG"),
|
||||
id: os.Getenv("UPCLAPI_ID"),
|
||||
runCmd: os.Getenv("UPCLAPI_RUNCMD"),
|
||||
encdr: os.Getenv("UPCLAPI_ENCODER"),
|
||||
out: os.Getenv("UPCLAPI_OUT"),
|
||||
target: os.Getenv("UPCLAPI_TARGET"),
|
||||
}
|
||||
if runFlags.command == "" {
|
||||
runFlags.command = DFLT_COMMAND
|
||||
}
|
||||
if runFlags.dataCfgPath == "" {
|
||||
runFlags.dataCfgPath = DATA_CFG
|
||||
}
|
||||
// var command string
|
||||
// var dataCfgPath string
|
||||
// var id string
|
||||
// var cmd string
|
||||
// var encdr string
|
||||
|
||||
// Set up a CLI flag called "-config" to allow users
|
||||
// to supply the configuration file
|
||||
commandInfo := fmt.Sprintf("command to run [\n%s\n%s\n%s\n%s\n%s\n%s\n]",
|
||||
"createserver, infoserver, restartserver, startserver, stopserver, modifyserver, deleteserver,",
|
||||
"infofloatip, movefloatip, modifyip,",
|
||||
"infotags, addtags, deletetags (use -t keep to keep storages)",
|
||||
"liststorages, fixstorage (-t size | part0 | part1 | final), deletestorage, modifystorage, createstorageimage (-t title),",
|
||||
"inventory, pubhosts, prvhosts",
|
||||
"runssh, runcmd")
|
||||
flag.StringVar(&runFlags.command, "c", runFlags.command, commandInfo)
|
||||
flag.StringVar(&runFlags.dataCfgPath, "f", runFlags.dataCfgPath, "path to data file")
|
||||
flag.StringVar(&runFlags.id, "id", runFlags.id, "resource name or uuid")
|
||||
flag.StringVar(&runFlags.runCmd, "cmd", runFlags.runCmd, "run [ssh] command")
|
||||
flag.StringVar(&runFlags.encdr, "kdr", runFlags.encdr, "use coder ")
|
||||
flag.StringVar(&runFlags.out, "o", runFlags.out, "output format ")
|
||||
flag.StringVar(&runFlags.target, "t", runFlags.out, "target item for command ")
|
||||
|
||||
// Actually parse the flags
|
||||
flag.Parse()
|
||||
|
||||
if len(runFlags.id) == 0 {
|
||||
if _, err := os.Stat(runFlags.dataCfgPath); os.IsNotExist(err) {
|
||||
msg := fmt.Errorf("'%s' config file not found", DATA_CFG)
|
||||
if len(os.Getenv("UPCLAPI_DATACFG")) == 0 {
|
||||
err = fmt.Errorf("%s\nUPCLAPI_DATACFG environment value not set\n",msg)
|
||||
return runFlags,err
|
||||
}
|
||||
}
|
||||
// fmt.Printf("dataCfgPath: %+v\n",dataCfgPath) // Print with Variable Name
|
||||
// Validate the path first
|
||||
// if err := ValidateDataPath(runFlags.dataCfgPath); err != nil {
|
||||
// return runFlags,err
|
||||
// }
|
||||
} else {
|
||||
if runFlags.command != os.Getenv("UPCLAPI_COMMAND") && runFlags.id == os.Getenv("UPCLAPI_ID") {
|
||||
fmt.Fprintf(os.Stdout, "Warning: Resource ID is set in UPCLAPI_ID enviroment to: %s\n",runFlags.id)
|
||||
}
|
||||
}
|
||||
// Return the configuration path
|
||||
return runFlags,nil
|
||||
}
|
158
networks.go
Normal file
158
networks.go
Normal file
@ -0,0 +1,158 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
)
|
||||
|
||||
func getNetworkInterfaces(srv ServerConfig) []request.CreateServerInterface {
|
||||
var networkInterfaces []request.CreateServerInterface
|
||||
for _,net := range srv.Networks {
|
||||
if net.Access == "private" {
|
||||
var sourceIPFiltering upcloud.Boolean = upcloud.True
|
||||
if net.SourceIPFiltering == "no" {
|
||||
sourceIPFiltering = upcloud.False
|
||||
}
|
||||
networkInterfaces = append(networkInterfaces, request.CreateServerInterface{
|
||||
IPAddresses: []request.CreateServerIPAddress{
|
||||
{
|
||||
Family: net.Family,
|
||||
Address: net.IPAddress,
|
||||
},
|
||||
},
|
||||
Type: net.Access,
|
||||
Network: net.Network,
|
||||
SourceIPFiltering: sourceIPFiltering,
|
||||
})
|
||||
} else {
|
||||
networkInterfaces = append(networkInterfaces, request.CreateServerInterface{
|
||||
IPAddresses: []request.CreateServerIPAddress{
|
||||
{
|
||||
Family: net.Family,
|
||||
},
|
||||
},
|
||||
Type: net.Access,
|
||||
// SourceIPFiltering: net.SourceIPFiltering,
|
||||
})
|
||||
}
|
||||
}
|
||||
return networkInterfaces
|
||||
}
|
||||
|
||||
func modifyIPOneServer(s *service.Service, server upcloud.Server,nettype string, target ServerConfig) error {
|
||||
var target_NetCfg NetworksConfig
|
||||
for _,it := range target.Networks {
|
||||
if it.Access == nettype { // upcloud.NetworkTypePrivate {
|
||||
target_NetCfg = it
|
||||
break
|
||||
}
|
||||
}
|
||||
if target_NetCfg.IPAddress == "" {
|
||||
return nil
|
||||
}
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// target_MAC := ""
|
||||
target_Index := -1
|
||||
target_pos := -1
|
||||
org_IPAddress := ""
|
||||
for i := 0; i < len(info.Networking.Interfaces); i++ {
|
||||
if info.Networking.Interfaces[i].Type == target_NetCfg.Access {
|
||||
// fmt.Fprintf(os.Stderr, "Info: %#v\n",info.Networking.Interfaces[i])
|
||||
target_pos=i
|
||||
target_Index=info.Networking.Interfaces[i].Index
|
||||
for _,ip := range info.Networking.Interfaces[i].IPAddresses {
|
||||
if ip.Address == target_NetCfg.IPAddress {
|
||||
fmt.Fprintf(os.Stderr, "Already interface in server: %s to config %#v\n", server.Hostname,target_NetCfg)
|
||||
return nil
|
||||
}
|
||||
org_IPAddress = ip.Address
|
||||
}
|
||||
break
|
||||
}
|
||||
target_Index=info.Networking.Interfaces[i].Index
|
||||
}
|
||||
if target_pos == -1 {
|
||||
target_Index +=1
|
||||
}
|
||||
if target_Index == -1 { // } && target_MAC != "" {
|
||||
fmt.Fprintf(os.Stderr, "Unable to find interface in server: %s to config %#v\n", server.Hostname,target_NetCfg)
|
||||
return nil
|
||||
}
|
||||
err = stopOneServer(s,server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
if target_pos > -1 {
|
||||
err = s.DeleteNetworkInterface(&request.DeleteNetworkInterfaceRequest{
|
||||
Index: target_Index,
|
||||
ServerUUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: Unable to delete interface %d server %s: %#v\n",org_IPAddress, target_Index,server.Hostname,err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
var ipAddress []request.CreateNetworkInterfaceIPAddress
|
||||
var r *request.CreateNetworkInterfaceRequest
|
||||
switch(target_NetCfg.Access) {
|
||||
case upcloud.NetworkTypeUtility:
|
||||
ip_addrr := request.CreateNetworkInterfaceIPAddress{
|
||||
Family: target_NetCfg.Family,
|
||||
}
|
||||
ipAddress = append(ipAddress, ip_addrr)
|
||||
r = &request.CreateNetworkInterfaceRequest{
|
||||
ServerUUID: server.UUID,
|
||||
Type: upcloud.NetworkTypeUtility,
|
||||
IPAddresses: ipAddress,
|
||||
}
|
||||
case upcloud.NetworkTypePublic:
|
||||
ip_addrr := request.CreateNetworkInterfaceIPAddress{
|
||||
Family: target_NetCfg.Family,
|
||||
}
|
||||
ipAddress = append(ipAddress, ip_addrr)
|
||||
r = &request.CreateNetworkInterfaceRequest{
|
||||
ServerUUID: server.UUID,
|
||||
Type: upcloud.NetworkTypePublic,
|
||||
IPAddresses: ipAddress,
|
||||
}
|
||||
case upcloud.NetworkTypePrivate:
|
||||
ip_addrr := request.CreateNetworkInterfaceIPAddress{
|
||||
Family: target_NetCfg.Family,
|
||||
Address: target_NetCfg.IPAddress,
|
||||
}
|
||||
var sourceIPFiltering upcloud.Boolean = upcloud.True
|
||||
if target_NetCfg.SourceIPFiltering == "no" {
|
||||
sourceIPFiltering = upcloud.False
|
||||
}
|
||||
ipAddress = append(ipAddress, ip_addrr)
|
||||
r = &request.CreateNetworkInterfaceRequest{
|
||||
ServerUUID: server.UUID,
|
||||
Type: upcloud.NetworkTypePrivate,
|
||||
NetworkUUID: target_NetCfg.Network,
|
||||
IPAddresses: ipAddress,
|
||||
SourceIPFiltering: sourceIPFiltering,
|
||||
}
|
||||
}
|
||||
newIP,err := s.CreateNetworkInterface(r)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error %s: %#v\n", target_NetCfg.IPAddress, err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "IP %s installed for Private Network: %s in %s\n", target_NetCfg.IPAddress, newIP.Network, server.Hostname)
|
||||
}
|
||||
err = startOneServer(s,server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to start server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
279
prices.go
Normal file
279
prices.go
Normal file
@ -0,0 +1,279 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
// "log"
|
||||
|
||||
// "strings"
|
||||
// "encoding/json"
|
||||
|
||||
// "github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
// "github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
// "gocloud.dev/server"
|
||||
// "gocloud.dev/server"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
func dataPriceResource(s *service.Service, dataprices DataPrices, zone string, target string) (*Price,error) {
|
||||
resource_price := &Price{}
|
||||
resource_zone := PricesZone{}
|
||||
for _,price_zone := range dataprices.Prices.Zone {
|
||||
if price_zone.Name == zone {
|
||||
resource_zone = price_zone
|
||||
break
|
||||
}
|
||||
}
|
||||
if resource_zone.Name == zone {
|
||||
switch target {
|
||||
case "firewall":
|
||||
resource_price = &resource_zone.Firewall
|
||||
case "io_request_backup":
|
||||
resource_price = &resource_zone.IORequestBackup
|
||||
case "io_request_maxiops":
|
||||
resource_price = &resource_zone.IORequestMaxIOPS
|
||||
case "ipv4_address":
|
||||
resource_price = &resource_zone.IPv4Address
|
||||
case "ipv6_address":
|
||||
resource_price = &resource_zone.IPv6Address
|
||||
case "managed_database_1x1xCPU-2GB-25GB":
|
||||
resource_price = &resource_zone.ManagedDatabase1x1CPU2GB25GB
|
||||
case "managed_database_1x2xCPU-4GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase1x2CPU4GB100GB
|
||||
case "managed_database_1x2xCPU-4GB-50GB":
|
||||
resource_price = &resource_zone.ManagedDatabase1x2CPU4GB50GB
|
||||
case "managed_database_2x2xCPU-4GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x2CPU4GB100GB
|
||||
case "managed_database_2x2xCPU-4GB-50GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x2CPU4GB50GB
|
||||
case "managed_database_2x4xCPU-8GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x4CPU8GB100GB
|
||||
case "managed_database_2x4xCPU-8GB-50GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x4CPU8GB50GB
|
||||
case "managed_database_2x6xCPU-16GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x6CPU16GB100GB
|
||||
case "managed_database_2x6xCPU-16GB-250GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x6CPU16GB50GB
|
||||
case "managed_database_2x8xCPU-32GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x8CPU32GB100GB
|
||||
case "managed_database_2x8xCPU-32GB-250GB":
|
||||
resource_price = &resource_zone.ManagedDatabase2x8CPU22GB250GB
|
||||
case "managed_database_3x2xCPU-4GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x2CPU4GB100GB
|
||||
case "managed_database_3x2xCPU-4GB-200GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x2CPU4GB200GB
|
||||
case "managed_database_3x4xCPU-8GB-100GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x4CPU8GB100GB
|
||||
case "managed_database_3x4xCPU-8GB-200GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x4CPU8GB200GB
|
||||
case "managed_database_3x6xCPU-16GB-200GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x6CPU16GB200GB
|
||||
case "managed_database_3x6xCPU-16GB-500GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x6CPU16GB500GB
|
||||
case "managed_database_3x8xCPU-32GB-200GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x8CPU32GB200GB
|
||||
case "managed_database_3x8xCPU-32GB-500GB":
|
||||
resource_price = &resource_zone.ManagedDatabase3x8CPU32GB500GB
|
||||
case "network_private_vlan":
|
||||
resource_price = &resource_zone.NetworkPrivateVLAN
|
||||
case "object_storage_1TB":
|
||||
resource_price = &resource_zone.ObjectStorage1TB
|
||||
case "object_storage_250GB":
|
||||
resource_price = &resource_zone.ObjectStorage250GB
|
||||
case "object_storage_500GB":
|
||||
resource_price = &resource_zone.ObjectStorage500GB
|
||||
case "public_ipv4_bandwidth_in":
|
||||
resource_price = &resource_zone.PublicIPv4BandwidthIn
|
||||
case "public_ipv4_bandwidth_out":
|
||||
resource_price = &resource_zone.PublicIPv4BandwidthOut
|
||||
case "public_ipv6_bandwidth_in":
|
||||
resource_price = &resource_zone.PublicIPv6BandwidthIn
|
||||
case "public_ipv6_bandwidth_out":
|
||||
resource_price = &resource_zone.PublicIPv6BandwidthOut
|
||||
case "server_core":
|
||||
resource_price = &resource_zone.ServerCore
|
||||
case "server_memory":
|
||||
resource_price = &resource_zone.ServerMemory
|
||||
case "server_plan_6xCPU-8GB":
|
||||
resource_price = &resource_zone.ServerPlan6xCPU8GB
|
||||
case "server_plan_12xCPU-48GB":
|
||||
resource_price = &resource_zone.ServerPlan12xCPU48GB
|
||||
case "server_plan_16xCPU-64GB":
|
||||
resource_price = &resource_zone.ServerPlan16xCPU64GB
|
||||
case "server_plan_1xCPU-1GB":
|
||||
resource_price = &resource_zone.ServerPlan1xCPU1GB
|
||||
case "server_plan_1xCPU-2GB":
|
||||
resource_price = &resource_zone.ServerPlan1xCPU2GB
|
||||
case "server_plan_20xCPU-128GB":
|
||||
resource_price = &resource_zone.ServerPlan20xCPU128GB
|
||||
case "server_plan_20xCPU-96GB":
|
||||
resource_price = &resource_zone.ServerPlan20xCPU96GB
|
||||
case "server_plan_2xCPU-4GB":
|
||||
resource_price = &resource_zone.ServerPlan2xCPU4GB
|
||||
case "server_plan_4xCPU-8GB":
|
||||
resource_price = &resource_zone.ServerPlan4xCPU8GB
|
||||
case "server_plan_6xCPU-16GB":
|
||||
resource_price = &resource_zone.ServerPlan6xCPU16GB
|
||||
case "server_plan_8xCPU-32GB":
|
||||
resource_price = &resource_zone.ServerPlan8xCPU32GB
|
||||
case "simple_backup_dailies_12xCPU-48GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies12xCPU48GB
|
||||
case "simple_backup_dailies_16xCPU-64GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies16xCPU64GB
|
||||
case "simple_backup_dailies_1xCPU-1GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailiesx1CPU1GB
|
||||
case "simple_backup_dailies_1xCPU-2GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies1xCPU2GB
|
||||
case "simple_backup_dailies_20xCPU-128GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies20xCPU128GB
|
||||
case "simple_backup_dailies_20xCPU-96GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies20xCPU96GB
|
||||
case "simple_backup_dailies_2xCPU-4GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies2xCPU4GB
|
||||
case "simple_backup_dailies_4xCPU-8GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies4xCPU8GB
|
||||
case "simple_backup_dailies_6xCPU-16GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies6xCPU16GB
|
||||
case "simple_backup_dailies_8xCPU-32GB":
|
||||
resource_price = &resource_zone.SimpleBackupDailies8xCPU32GB
|
||||
case "simple_backup_extra_dailies":
|
||||
resource_price = &resource_zone.SimpleBackupExtraDailies
|
||||
case "simple_backup_extra_monthlies":
|
||||
resource_price = &resource_zone.SimpleBackupExtraMontlies
|
||||
case "simple_backup_extra_weeklies":
|
||||
resource_price = &resource_zone.SimpleBackupExtraWeeklies
|
||||
case "simple_backup_monthlies_12xCPU-48GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies12xCPU48GB
|
||||
case "simple_backup_monthlies_16xCPU-64GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies16xCPU64GB
|
||||
case "simple_backup_monthlies_1xCPU-1GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies1xCPU1GB
|
||||
case "simple_backup_monthlies_1xCPU-2GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies1xCPU2GB
|
||||
case "simple_backup_monthlies_20xCPU-128GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies20xCPU128GB
|
||||
case "simple_backup_monthlies_20xCPU-96GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies20xCPU96GB
|
||||
case "simple_backup_monthlies_2xCPU-4GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies2xCPU4GB
|
||||
case "simple_backup_monthlies_4xCPU-8GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies4xCPU8GB
|
||||
case "simple_backup_monthlies_6xCPU-16GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies6xCPU16GB
|
||||
case "simple_backup_monthlies_8xCPU-32GB":
|
||||
resource_price = &resource_zone.SimpleBackupMonthlies8xCPU32GB
|
||||
case "simple_backup_weeklies_12xCPU-48GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies12xCPU48GB
|
||||
case "simple_backup_weeklies_16xCPU-64GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies16xCPU64GB
|
||||
case "simple_backup_weeklies_1xCPU-1GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies1xCPU1GB
|
||||
case "simple_backup_weeklies_1xCPU-2GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies1xCPU2GB
|
||||
case "simple_backup_weeklies_20xCPU-128GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies20xCPU128GB
|
||||
case "simple_backup_weeklies_20xCPU-96GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies20xCPU96GB
|
||||
case "simple_backup_weeklies_2xCPU-4GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies2xCPU4GB
|
||||
case "simple_backup_weeklies_4xCPU-8GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies4xCPU8GB
|
||||
case "simple_backup_weeklies_6xCPU-16GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies6xCPU16GB
|
||||
case "simple_backup_weeklies_8xCPU-32GB":
|
||||
resource_price = &resource_zone.SimpleBackupWeeklies8xCPU32GB
|
||||
case "storage_hdd":
|
||||
resource_price = &resource_zone.StorageHDD
|
||||
case "storage_backup":
|
||||
resource_price = &resource_zone.StorageBackup
|
||||
case "storage_maxiops":
|
||||
resource_price = &resource_zone.StorageMaxIOPS
|
||||
case "storage_template":
|
||||
resource_price = &resource_zone.StorageTemplate
|
||||
default:
|
||||
//fmt.Fprintf(os.Stderr, "Resource price %s in %s NOT FOUND",target,zone)
|
||||
return resource_price, fmt.Errorf("Resource price %s in %s NOT FOUND",target,zone)
|
||||
}
|
||||
resource_price.Hour = (resource_price.Price / 100)
|
||||
// resource_price.Month = (resource_price.Hour * MONTH_HOURS)
|
||||
resource_price.Month = math.Round(resource_price.Hour * MONTH_HOURS)
|
||||
// fmt.Printf("Resource %s price in %s: %#v\n", target, zone, resource_price)
|
||||
// fmt.Printf("Resource %s price in %s: %d %.4f\n", target, zone, resource_price.Amount, resource_price.Price)
|
||||
}
|
||||
// enc := json.NewEncoder(os.Stdout)
|
||||
// enc.Encode(resource_price)
|
||||
|
||||
return resource_price, nil
|
||||
}
|
||||
/*
|
||||
// UpCloud API is incomplete to make this work
|
||||
// priceZones := upcloud.PriceZones{}
|
||||
func upcloud_priceResource(s *service.Service, zone string, target string) (upcloud.Price,error) {
|
||||
pricesZones,err:= s.GetPriceZones()
|
||||
resource_price := new(upcloud.Price)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get prices zones: %#v\n", err)
|
||||
return *resource_price,err
|
||||
}
|
||||
resource_zone := upcloud.PriceZone{}
|
||||
for _,price_zone := range pricesZones.PriceZones {
|
||||
if price_zone.Name == zone {
|
||||
resource_zone = price_zone
|
||||
break
|
||||
}
|
||||
}
|
||||
if resource_zone.Name == zone {
|
||||
switch target {
|
||||
case "firewall":
|
||||
resource_price = resource_zone.Firewall
|
||||
case "io_request_backup":
|
||||
resource_price = resource_zone.IORequestBackup
|
||||
case "io_request_maxiops":
|
||||
resource_price = resource_zone.IORequestMaxIOPS
|
||||
case "ipv4_address":
|
||||
resource_price = resource_zone.IPv4Address
|
||||
case "ipv6_address":
|
||||
resource_price = resource_zone.IPv6Address
|
||||
case "public_ipv4_bandwidth_in":
|
||||
resource_price = resource_zone.PublicIPv4BandwidthIn
|
||||
case "public_ipv4_bandwidth_out":
|
||||
resource_price = resource_zone.PublicIPv4BandwidthOut
|
||||
case "public_ipv6_bandwidth_in":
|
||||
resource_price = resource_zone.PublicIPv6BandwidthIn
|
||||
case "public_ipv6_bandwidth_out":
|
||||
resource_price = resource_zone.PublicIPv6BandwidthOut
|
||||
case "server_core":
|
||||
resource_price = resource_zone.ServerCore
|
||||
case "server_memory":
|
||||
resource_price = resource_zone.ServerMemory
|
||||
case "server_plan_1xCPU-1GB":
|
||||
resource_price = resource_zone.ServerPlan1xCPU1GB
|
||||
case "server_plan_2xCPU-2GB":
|
||||
resource_price = resource_zone.ServerPlan2xCPU2GB
|
||||
case "server_plan_2xCPU-4GB":
|
||||
resource_price.Price = 2.9761
|
||||
case "server_plan_4xCPU-4GB":
|
||||
resource_price = resource_zone.ServerPlan4xCPU4GB
|
||||
case "server_plan_6xCPU-8GB":
|
||||
resource_price = resource_zone.ServerPlan6xCPU8GB
|
||||
case "storage_backup":
|
||||
resource_price = resource_zone.StorageBackup
|
||||
case "storage_maxiops":
|
||||
resource_price = resource_zone.StorageMaxIOPS
|
||||
case "storage_template":
|
||||
resource_price = resource_zone.StorageTemplate
|
||||
default:
|
||||
//fmt.Fprintf(os.Stderr, "Resource price %s in %s NOT FOUND",target,zone)
|
||||
return *resource_price, fmt.Errorf("Resource price %s in %s NOT FOUND",target,zone)
|
||||
}
|
||||
// fmt.Printf("Resource %s price in %s: %#v\n", target, zone, resource_price)
|
||||
// fmt.Printf("Resource %s price in %s: %d %.4f\n", target, zone, resource_price.Amount, resource_price.Price)
|
||||
}
|
||||
// enc := json.NewEncoder(os.Stdout)
|
||||
// enc.Encode(resource_price)
|
||||
|
||||
return *resource_price, nil
|
||||
}
|
||||
*/
|
447
run.go
Normal file
447
run.go
Normal file
@ -0,0 +1,447 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/client"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
)
|
||||
|
||||
func cmdexec(command string, args []string) (string, error) {
|
||||
cmd := &exec.Cmd {
|
||||
Path: command,
|
||||
Args: args,
|
||||
// Stdout: os.Stdout,
|
||||
// Stderr: os.Stdout,
|
||||
}
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s error: %#v\n",command,err)
|
||||
return "",err
|
||||
} else {
|
||||
return string(out), nil
|
||||
}
|
||||
// cmd.Start();
|
||||
// cmd.Wait()
|
||||
}
|
||||
func run() int {
|
||||
runFlags, err := ParseFlags()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
username := ""
|
||||
password := ""
|
||||
if runFlags.encdr == TECODER.cmd || runFlags.encdr == TECODER.abbrv {
|
||||
k := os.Getenv("KUPCLAPI")
|
||||
if len(k) > 0 {
|
||||
kdata := strings.Split(k," ")
|
||||
out, err := exec.Command(TECODER.cmd,TECODER.decoder,kdata[0]).Output()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Auth info: Username not found in ecoded: %#v\n ",err)
|
||||
return 1
|
||||
}
|
||||
username = strings.TrimSuffix(string(out),"\n")
|
||||
out, err = exec.Command(TECODER.cmd,TECODER.decoder,kdata[1]).Output()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Auth info: Password not found in ecoded: %#v\n",err)
|
||||
return 1
|
||||
}
|
||||
password = strings.TrimSuffix(string(out),"\n")
|
||||
}
|
||||
} else {
|
||||
username = os.Getenv("UPCLOUD_USERNAME")
|
||||
password = os.Getenv("UPCLOUD_PASSWORD")
|
||||
}
|
||||
|
||||
if len(username) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "Auth info: Username must be specified")
|
||||
return 1
|
||||
}
|
||||
|
||||
if len(password) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "Auth info: Password must be specified")
|
||||
return 2
|
||||
}
|
||||
|
||||
c := client.New(username, password)
|
||||
s := service.New(c)
|
||||
|
||||
switch runFlags.command {
|
||||
case "infoserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"info",runFlags,datacfg)
|
||||
case "inventory":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"inventory",runFlags,datacfg)
|
||||
case "pubhosts":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"pubhosts",runFlags,datacfg)
|
||||
case "prvhosts":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"prvhosts",runFlags,datacfg)
|
||||
case "deleteserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"delete",runFlags,datacfg)
|
||||
case "startserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"start",runFlags,datacfg)
|
||||
case "restartserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"restart",runFlags,datacfg)
|
||||
case "stopserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"stop",runFlags,datacfg)
|
||||
case "createserver":
|
||||
datacfg,err := loadDataConfig(runFlags)
|
||||
if err != nil {
|
||||
return 99
|
||||
}
|
||||
sshkeys := loadLoginUserKeys(runFlags)
|
||||
if err := createServer(s,datacfg,sshkeys); err != nil {
|
||||
return 3
|
||||
}
|
||||
case "modifyserver":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
if runFlags.target == "" {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run modifyserver command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
onServers(s,"modifyserver",runFlags,datacfg)
|
||||
case "fixstorage":
|
||||
datacfg,err := loadDataConfig(runFlags)
|
||||
if err != nil {
|
||||
return 99
|
||||
}
|
||||
if runFlags.target == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"fixstorage",runFlags,datacfg)
|
||||
case "modifystorage":
|
||||
storecfg,err := loadStoreConfig(runFlags.dataCfgPath)
|
||||
if err != nil {
|
||||
return 99
|
||||
}
|
||||
if err := modifyStorage(s,storecfg); err != nil {
|
||||
return 3
|
||||
}
|
||||
case "deletestorage":
|
||||
hasID(runFlags.id)
|
||||
if err := deleteStorage(s, runFlags.id); err != nil {
|
||||
return 2
|
||||
}
|
||||
case "liststorages":
|
||||
datacfg,_ := loadDataConfig(runFlags)
|
||||
if err := listStorages(s, datacfg, runFlags.target); err != nil {
|
||||
return 2
|
||||
}
|
||||
case "createstorageimage":
|
||||
hasID(runFlags.id)
|
||||
if runFlags.target == "" {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run createStorageImage no title: ", runFlags.target)
|
||||
return 99
|
||||
}
|
||||
if err := createStorageImage(s, runFlags.id,runFlags.target); err != nil {
|
||||
return 2
|
||||
}
|
||||
case "runssh":
|
||||
if len(runFlags.runCmd) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run ssh command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
datacfg,err := loadDataConfig(runFlags)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run ssh command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
onServers(s,"runssh",runFlags,datacfg)
|
||||
case "runcmd":
|
||||
if len(runFlags.runCmd) == 0 {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
datacfg,err := loadDataConfig(runFlags)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Unable to run command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
onServers(s,"runcmd",runFlags,datacfg)
|
||||
case "infofloatip":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
ipinfo, err := getFloatIP(s,runFlags.id,datacfg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error getting info %s: %#v\n", datacfg.FloatIP, err)
|
||||
return 99
|
||||
}
|
||||
if runFlags.out == "attached" {
|
||||
ipData := strings.Split(ipinfo.PTRRecord,".")
|
||||
ip := strings.Join(ipData[0:4],".")
|
||||
fmt.Fprintf(os.Stdout, "%s\n",ip)
|
||||
} else {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.Encode(ipinfo)
|
||||
}
|
||||
// fmt.Fprintf(os.Stderr, "%s Located in %s %s Server: %s) \n", datacfg.FloatIP, ipinfo.PTRRecord, ipinfo.MAC, ipinfo.ServerUUID)
|
||||
case "movefloatip":
|
||||
datacfg := &DataConfig{}
|
||||
id := runFlags.id
|
||||
var data []string
|
||||
if id == "" {
|
||||
id = os.Getenv("UPCLOUD_MOVEFLOATIP")
|
||||
}
|
||||
if id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
if datacfg.FloatIP == "" {
|
||||
fmt.Fprintln(os.Stderr, "Float IP not found in: ", runFlags.dataCfgPath)
|
||||
return 99
|
||||
}
|
||||
} else {
|
||||
data = strings.Split(id, SEPARATOR)
|
||||
}
|
||||
moveFloatIP(s,data,datacfg)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Unable to move Float IP: ", datacfg.FloatIP)
|
||||
return 99
|
||||
}
|
||||
case "modifyip":
|
||||
datacfg,err := loadDataConfig(runFlags)
|
||||
if err != nil {
|
||||
return 99
|
||||
}
|
||||
onServers(s,"modifyip",runFlags,datacfg)
|
||||
case "infotags":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"infotags",runFlags,datacfg)
|
||||
case "addtags":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"addtags",runFlags,datacfg)
|
||||
case "deletetags":
|
||||
datacfg := &DataConfig{}
|
||||
if runFlags.id == "" {
|
||||
datacfg,err = loadDataConfig(runFlags)
|
||||
}
|
||||
onServers(s,"deletetags",runFlags,datacfg)
|
||||
default:
|
||||
fmt.Fprintln(os.Stderr, "Unknown command: ", runFlags.command)
|
||||
return 99
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func onServers(s *service.Service, tsksrvc string, runFlags RunFlags, datacfg *DataConfig) error {
|
||||
uuid := runFlags.id
|
||||
runComand := runFlags.runCmd
|
||||
servers, err := s.GetServers()
|
||||
if err != nil || len(servers.Servers) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get servers: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
inventory := map[string][]string{}
|
||||
sshAccess := SSHAccess{}
|
||||
var target ServerConfig
|
||||
for _, server := range servers.Servers {
|
||||
target_srvr := ""
|
||||
role_srvr := ""
|
||||
if uuid != "" {
|
||||
if server.UUID == uuid || server.Hostname == uuid {
|
||||
target_srvr = uuid
|
||||
for _,srv := range datacfg.Servers {
|
||||
if srv.Hostname == server.Hostname {
|
||||
target = srv
|
||||
role_srvr = srv.Cluster.Role
|
||||
sshAccess = srv.SSHAccess
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if datacfg.HostPrefix != "" && !strings.Contains(server.Hostname,datacfg.HostPrefix) {
|
||||
continue
|
||||
}
|
||||
for _,srv := range datacfg.Servers {
|
||||
if srv.Hostname == server.Hostname || srv.UUID == server.UUID {
|
||||
target_srvr = server.UUID
|
||||
target = srv
|
||||
role_srvr = srv.Cluster.Role
|
||||
sshAccess = srv.SSHAccess
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if target_srvr == "" {
|
||||
continue
|
||||
}
|
||||
switch tsksrvc {
|
||||
case "delete":
|
||||
err := deleteOneServer(s, server, runFlags.target)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to delete server %#v: %#v\n", server.UUID, err)
|
||||
return err
|
||||
}
|
||||
case "stop":
|
||||
err := stopOneServer(s, server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
case "start":
|
||||
err := startOneServer(s, server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to start server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
case "restart":
|
||||
err := restarOneServer(s, server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to restart server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
case "info":
|
||||
dataPrices,err_prices := getDataPrices()
|
||||
if err_prices != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to load prices for server %#v: %#v\n", server.UUID, err_prices)
|
||||
}
|
||||
err := detailsOneServer(s, server, *dataPrices)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details for server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
case "inventory":
|
||||
info, err := inventoryOneServer(s, datacfg.FloatIP, server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to make inventory from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
inventory[role_srvr] = append(inventory[role_srvr],info)
|
||||
}
|
||||
case "pubhosts":
|
||||
info, err := hostsOneServer(s,"pub", datacfg.FloatIP, server, target)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to make hosts list from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
fmt.Printf("%s",info)
|
||||
}
|
||||
case "prvhosts":
|
||||
info, err := hostsOneServer(s,"prv", datacfg.FloatIP, server, target)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to make hosts list from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
fmt.Printf("%s",info)
|
||||
}
|
||||
case "modifyip":
|
||||
nettype := upcloud.NetworkTypePrivate
|
||||
err := modifyIPOneServer(s, server, nettype, target)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to modify IP server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
case "infotags":
|
||||
tags, err := infoTagsFromId(s, server.UUID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get tags from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.Encode(tags)
|
||||
}
|
||||
case "addtags":
|
||||
if uuid != "" {
|
||||
fmt.Fprintf(os.Stderr, "No tags found, for server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
err := addTagsToId(s, server.UUID, target.Tags)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to add tags to server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
}
|
||||
case "deletetags":
|
||||
if uuid != "" {
|
||||
fmt.Fprintf(os.Stderr, "No tags found, for server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
err := deleteTagsFromId(s, server.UUID, target.Tags)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to delete tags from server %#v: %#v\n", server.UUID, err)
|
||||
}
|
||||
}
|
||||
case "fixstorage":
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
fixStorageDevices(s, target, info, runFlags.target)
|
||||
}
|
||||
case "modifyserver":
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details from server %#v: %#v\n", server.UUID, err)
|
||||
} else {
|
||||
modifyServer(s, target, info, runFlags.target)
|
||||
}
|
||||
case "runssh":
|
||||
if sshAccess.Host != "" {
|
||||
output, err := runSSH(sshAccess, runComand)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "No Host to run ssh on %s \n", server.UUID)
|
||||
}
|
||||
case "runcmd":
|
||||
args := strings.Split(runComand, " ")
|
||||
output, err := cmdexec(args[0],args[1:])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
fmt.Fprintf(os.Stderr, "No Host to run on %s \n", server.UUID)
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
}
|
||||
}
|
||||
if tsksrvc == "inventory" {
|
||||
for key,items := range inventory {
|
||||
fmt.Printf("[%s]\n",key)
|
||||
for _,item := range items {
|
||||
fmt.Printf("%s\n",item)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
306
servers.go
Normal file
306
servers.go
Normal file
@ -0,0 +1,306 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
// "log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
// "strings"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
// "gocloud.dev/server"
|
||||
// "gocloud.dev/server"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
func createServer(s *service.Service, datacfg *DataConfig,sshkeys request.SSHKeySlice) error {
|
||||
fmt.Println("Creating servers ...")
|
||||
//fmt.Fprintf(os.Stdout, "%#v\n",sshkeys)
|
||||
//fmt.Printf("%+v\n",datacfg) // Print with Variable Name
|
||||
// fmt.Printf("Created server: %#v\n", details)
|
||||
servers, _ := s.GetServers()
|
||||
for _,srv := range datacfg.Servers {
|
||||
alreadyExists := false
|
||||
for _, server := range servers.Servers {
|
||||
if server.Hostname == srv.Hostname {
|
||||
alreadyExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// Networking: setNetworkInterfaces(datacfg),
|
||||
title := fmt.Sprintf("%s %s", srv.Hostname, srv.Title)
|
||||
if alreadyExists {
|
||||
fmt.Fprintf(os.Stderr, "Already exists server: %s\n", title)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("server: %s\n", title)
|
||||
var srv_sshkeys request.SSHKeySlice
|
||||
if len(srv_sshkeys) == 0 && len(sshkeys) > 0 {
|
||||
srv_sshkeys = sshkeys
|
||||
} else {
|
||||
srv_sshkeys = srv.LoginUser.SSHKeys
|
||||
}
|
||||
details, err := s.CreateServer(&request.CreateServerRequest{
|
||||
Hostname: srv.Hostname,
|
||||
Title: title, // fmt.Sprintf("example-cli-server-%04d", rand.Int31n(1000)),
|
||||
Zone: srv.Zone,
|
||||
Plan: srv.Plan,
|
||||
Metadata: srv.Metadata,
|
||||
TimeZone: srv.TimeZone,
|
||||
StorageDevices: getStorageDevices(srv),
|
||||
Networking: &request.CreateServerNetworking{
|
||||
Interfaces: getNetworkInterfaces(srv),
|
||||
},
|
||||
LoginUser: &request.LoginUser{
|
||||
SSHKeys: srv_sshkeys,
|
||||
},
|
||||
UserData: srv.UserData,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to create server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
// spew.Println(details)
|
||||
if len(details.UUID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "UUID missing")
|
||||
return errors.New("UUID too short")
|
||||
}
|
||||
details, err = s.WaitForServerState(&request.WaitForServerStateRequest{
|
||||
UUID: details.UUID,
|
||||
DesiredState: upcloud.ServerStateStarted,
|
||||
Timeout: 1 * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to wait for server: %#v", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Created server: %#v\n", details)
|
||||
fixStorageDevices(s,srv,details,"size")
|
||||
addTagsToId(s,details.UUID,srv.Tags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func modifyServer(s *service.Service,srvrCfg ServerConfig, serverDetails *upcloud.ServerDetails, targetPlan string) error {
|
||||
title := fmt.Sprintf("%s %s", serverDetails.Hostname, serverDetails.Title)
|
||||
fmt.Printf("Modify server %s ...\n",title)
|
||||
if serverDetails.Plan == targetPlan {
|
||||
fmt.Printf("%s == %s\n",serverDetails.Plan, targetPlan)
|
||||
return nil
|
||||
}
|
||||
if serverDetails.State != upcloud.ServerStateStopped {
|
||||
err := stopOneServer(s, serverDetails.Server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server %#v: %#v\n", serverDetails.UUID, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
details,err := s.WaitForServerState(&request.WaitForServerStateRequest{
|
||||
UUID: serverDetails.UUID,
|
||||
DesiredState: upcloud.ServerStateStopped,
|
||||
Timeout: 1 * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to wait for server: %#v", err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Modify server after to: %s\n", targetPlan)
|
||||
details, err = s.ModifyServer(&request.ModifyServerRequest{
|
||||
UUID: serverDetails.UUID,
|
||||
Plan: targetPlan,
|
||||
})
|
||||
fmt.Printf("Modify server done: %#v %#v\n", details, err)
|
||||
// if err != nil {
|
||||
// } else {
|
||||
// fmt.Fprintf(os.Stderr, "Failed to modify server: %#v", err)
|
||||
// // return err
|
||||
// }
|
||||
fmt.Fprintf(os.Stderr, "Start server after modify: %s\n", title)
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: serverDetails.UUID,
|
||||
})
|
||||
if info.State != upcloud.ServerStateStarted {
|
||||
err = startOneServer(s, info.Server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to start server %#v: %#v\n", serverDetails.UUID, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForState(s *service.Service, server upcloud.Server, desiredState string) error {
|
||||
_, err := s.WaitForServerState(&request.WaitForServerStateRequest{
|
||||
UUID: server.UUID,
|
||||
DesiredState: desiredState,
|
||||
Timeout: 1 * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to wait for server to reach desired state: %#v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func startOneServer(s *service.Service, server upcloud.Server) error {
|
||||
fmt.Printf("Starting %s (%s) ... \n", server.Hostname, server.UUID)
|
||||
if server.State == upcloud.ServerStateStopped {
|
||||
fmt.Printf("Server %s (%s) is stopped. Starting\n", server.Title, server.UUID)
|
||||
}
|
||||
_, err := s.StartServer(&request.StartServerRequest{
|
||||
UUID: server.UUID,
|
||||
// StopType: request.ServerStopTypeHard,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to start server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
err = waitForState(s,server,upcloud.ServerStateStarted)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to start state server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully started %s (%s)\n", server.Title, server.UUID)
|
||||
return nil
|
||||
}
|
||||
func restarOneServer(s *service.Service, server upcloud.Server) error {
|
||||
fmt.Printf("Restarting %s (%s) ... \n", server.Hostname, server.UUID)
|
||||
_, err := s.RestartServer(&request.RestartServerRequest{
|
||||
UUID: server.UUID,
|
||||
StopType: request.ServerStopTypeHard,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to restart server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
err = waitForState(s,server,upcloud.ServerStateStarted)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to restart state server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully restarted %s (%s)\n", server.Title, server.UUID)
|
||||
return nil
|
||||
}
|
||||
func stopOneServer(s *service.Service, server upcloud.Server) error {
|
||||
fmt.Printf("Stopping %s (%s) ... \n", server.Hostname, server.UUID)
|
||||
if server.State != upcloud.ServerStateStopped {
|
||||
// fmt.Printf("Server %s (%s) is not stopped. Stopping\n", server.Title, server.UUID)
|
||||
_, err := s.StopServer(&request.StopServerRequest{
|
||||
UUID: server.UUID,
|
||||
StopType: request.ServerStopTypeHard,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
err = waitForState(s,server,upcloud.ServerStateStopped)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop state server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully stopped %s (%s)\n", server.Title, server.UUID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func deleteOneServer(s *service.Service, server upcloud.Server, keepStorage string) error {
|
||||
err := stopOneServer(s,server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
if keepStorage != "keep" {
|
||||
fmt.Printf("Deleting %s (%s) with storage\n", server.Title, server.UUID)
|
||||
err = s.DeleteServerAndStorages(&request.DeleteServerAndStoragesRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
} else {
|
||||
fmt.Printf("Deleting %s (%s) keep storage\n", server.Title, server.UUID)
|
||||
err = s.DeleteServer(&request.DeleteServerRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to delete server: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully deleted %s (%s)\n", server.Title, server.UUID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func detailsOneServer(s *service.Service, server upcloud.Server, dataprices DataPrices) error {
|
||||
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get details from server %#v: %#v\n", server.UUID, err)
|
||||
return err
|
||||
}
|
||||
// price,err_price:= priceResource(s,server.Zone,fmt.Sprintf("server_plan_%s",server.Plan))
|
||||
price,err_price:= dataPriceResource(s,dataprices,server.Zone,fmt.Sprintf("server_plan_%s",server.Plan))
|
||||
if err_price != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get price info from server %#v: %#v\n", server.UUID, err_price)
|
||||
return err
|
||||
}
|
||||
info_server := &InfoServer{info: *info, price: *price}
|
||||
// c, err := json.Marshal(info_server)
|
||||
// if err != nil {
|
||||
// fmt.Println("error:", err)
|
||||
// }
|
||||
// os.Stdout.Write(c)
|
||||
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.Encode(info_server)
|
||||
// enc.Encode(price)
|
||||
|
||||
/*
|
||||
i,_ := json.Marshal(info)
|
||||
p,_ := json.Marshal(price)
|
||||
fmt.Printf("info %s \n", i)
|
||||
fmt.Printf("price %s \n", p)
|
||||
jsonData := []byte(`{"pric": "Value"}`)
|
||||
// info_server := &v{info: fmt.Sprintf("%s",i) , price: fmt.Sprintf("%s",p)}
|
||||
info_server := InfoServerPrice{info: "HOLA", price: "$$$" }
|
||||
// v := struct {
|
||||
// info upcloud.ServerDetails `json:"upcloud.ServerDetails"`
|
||||
// price upcloud.Price `json:"upcloud.Price"`
|
||||
// }{}
|
||||
fmt.Printf("InfoServer %#v\n", info_server)
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.Encode(info_server)
|
||||
// b,err_un := json.Marshal(info_server) // json.Marshal(info_server)
|
||||
// if err_un != nil {
|
||||
// fmt.Fprintf(os.Stderr, "Unable to marshall: %#v\n", err_un)
|
||||
// return err_un
|
||||
// }
|
||||
// os.Stdout.Write(b)
|
||||
type ColorGroup struct {
|
||||
ID int
|
||||
Name string
|
||||
Colors []string
|
||||
}
|
||||
group := ColorGroup{
|
||||
ID: 1,
|
||||
Name: "Reds",
|
||||
Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
|
||||
}
|
||||
c, err := json.Marshal(group)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
}
|
||||
os.Stdout.Write(c)
|
||||
// err_en := enc.Encode(info_server)
|
||||
// if err_en != nil {
|
||||
// fmt.Fprintf(os.Stderr, "Unable to encode info_server: %#v\n", err_en)
|
||||
// return err_en
|
||||
// }
|
||||
// fmt.Printf("InfoServer %#v\n", info)
|
||||
|
||||
*/
|
||||
return nil
|
||||
}
|
110
ssh.go
Normal file
110
ssh.go
Normal file
@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
// "github.com/mitchellh/go-homedir"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
func publicKeyAuthFunc(kPath string) ssh.AuthMethod {
|
||||
// keyPath, err := homedir.Expand(kPath)
|
||||
// if err != nil {
|
||||
// log.Fatal("find key's home dir failed", err)
|
||||
// }
|
||||
// key, err := ioutil.ReadFile(keyPath )
|
||||
key, err := ioutil.ReadFile(kPath )
|
||||
if err != nil {
|
||||
log.Fatal("ssh key file read failed", err)
|
||||
}
|
||||
// Create the Signer for this private key.
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
if err != nil {
|
||||
log.Fatal("ssh key signer failed", err)
|
||||
}
|
||||
return ssh.PublicKeys(signer)
|
||||
}
|
||||
func runSSH(cfg SSHAccess, cmds ...string ) ([]byte, error) {
|
||||
// fmt.Fprintf(os.Stderr, "SSH: %#v\n", cfg)
|
||||
fmt.Fprintf(os.Stderr, "%s - running : %s\n\n", cfg.Host, cmds)
|
||||
|
||||
// Create SSHP login configuration
|
||||
config := &ssh.ClientConfig{
|
||||
Timeout: time.Second, //ssh connection time out time is one second, if SSH validation error returns in one second
|
||||
User: cfg.User,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // This is OK, but not safe enough.
|
||||
// HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
||||
}
|
||||
if cfg.UType == "password" {
|
||||
config.Auth = []ssh.AuthMethod{ssh.Password(cfg.Password)}
|
||||
} else {
|
||||
config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(cfg.KeyPath)}
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
|
||||
conn, err := ssh.Dial("tcp", addr,config)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to dial SSH client", err)
|
||||
return []byte{}, err
|
||||
}
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer session.Close()
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // disable echoing
|
||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||
}
|
||||
err = session.RequestPty("xterm", 80, 40, modes)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
in, err := session.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
out, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var output []byte
|
||||
go func(in io.WriteCloser, out io.Reader, output *[]byte) {
|
||||
var (
|
||||
line string
|
||||
r = bufio.NewReader(out)
|
||||
)
|
||||
for {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
*output = append(*output, b)
|
||||
if b == byte('\n') {
|
||||
line = ""
|
||||
continue
|
||||
}
|
||||
line += string(b)
|
||||
if strings.HasPrefix(line, "[sudo] password for ") && strings.HasSuffix(line, ": ") {
|
||||
_, err = in.Write([]byte(cfg.Password+ "\n"))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}(in, out, &output)
|
||||
cmd := strings.Join(cmds, "; ")
|
||||
_, err = session.Output(cmd)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return output, nil
|
||||
}
|
281
storage.go
Normal file
281
storage.go
Normal file
@ -0,0 +1,281 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func NewStoreConfig(dataPath string) (*StoreConfig, error) {
|
||||
// Create config structure
|
||||
storeConfig := &StoreConfig{}
|
||||
|
||||
// Open config file
|
||||
file, err := os.Open(dataPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Init new YAML decode
|
||||
d := yaml.NewDecoder(file)
|
||||
|
||||
// Start YAML decoding from file
|
||||
if err := d.Decode(&storeConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return storeConfig, nil
|
||||
}
|
||||
|
||||
func loadStoreConfig(dataCfgPath string) (*StoreConfig, error) {
|
||||
// datacfg := &DataConfig{}
|
||||
storecfg, err := NewStoreConfig(dataCfgPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return storecfg, err
|
||||
}
|
||||
return storecfg, nil
|
||||
}
|
||||
|
||||
func getStorageDevices(srv ServerConfig) []request.CreateServerStorageDevice {
|
||||
var storageDevices []request.CreateServerStorageDevice
|
||||
for _,storage := range srv.StorageDevices {
|
||||
storageDevices = append(storageDevices,request.CreateServerStorageDevice{
|
||||
Action : storage.Action,
|
||||
Title : storage.Title,
|
||||
Storage : storage.Storage,
|
||||
Size : storage.Size,
|
||||
Tier : storage.Tier,
|
||||
})
|
||||
}
|
||||
return storageDevices
|
||||
}
|
||||
func deleteStorage(s *service.Service, uuid string) error {
|
||||
fmt.Println("Getting storage")
|
||||
storages, err := s.GetStorages(&request.GetStoragesRequest{
|
||||
Access: upcloud.StorageAccessPrivate,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get storages: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Retrieved %d storages\n", len(storages.Storages))
|
||||
if len(storages.Storages) > 0 {
|
||||
for _, storage := range storages.Storages {
|
||||
if storage.UUID == uuid {
|
||||
fmt.Printf("Deleting storage %s", storage.UUID)
|
||||
err := errors.New("Dummy")
|
||||
for i := 0; err != nil && i < 5; i++ {
|
||||
fmt.Printf("%d: Deleting %s (%s)\n", i, storage.Title, storage.UUID)
|
||||
err = s.DeleteStorage(&request.DeleteStorageRequest{
|
||||
UUID: storage.UUID,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to delete storage: %#v (%s)\n", err, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully deleted %s (%s)\n", storage.Title, storage.UUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func modifyStorage(s *service.Service, storecfg *StoreConfig) error {
|
||||
if len(storecfg.Uuid) == 0 {
|
||||
fmt.Printf("Unable to get storages uuid from data file \n")
|
||||
return nil
|
||||
}
|
||||
for _, item := range storecfg.Servers {
|
||||
s.StopServer(&request.StopServerRequest{
|
||||
UUID: item,
|
||||
StopType: request.ServerStopTypeHard,
|
||||
})
|
||||
}
|
||||
fmt.Println("Getting storage")
|
||||
storages, err := s.GetStorages(&request.GetStoragesRequest{
|
||||
Access: upcloud.StorageAccessPrivate,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get storages: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Retrieved %d storages\n", len(storages.Storages))
|
||||
|
||||
if len(storages.Storages) > 0 {
|
||||
for _, storage := range storages.Storages {
|
||||
if storage.UUID == storecfg.Uuid {
|
||||
fmt.Printf("Modify storage %s (%s)\n",storage.Title, storage.UUID)
|
||||
err := errors.New("Dummy")
|
||||
for i := 0; err != nil && i < 5; i++ {
|
||||
fmt.Printf("%d: Modify %s (%s)\n", i, storage.Title, storage.UUID)
|
||||
_, err = s.ModifyStorage(&request.ModifyStorageRequest{
|
||||
UUID: storecfg.Uuid,
|
||||
// Title: datacfg.Title,
|
||||
Size: storecfg.Size,
|
||||
// BackupRule *upcloud.BackupRule `json:"backup_rule,omitempty"`
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to modify storage: %#v (%s)\n", err, err.Error())
|
||||
// return err
|
||||
}
|
||||
fmt.Printf("Successfully modified %s (%s)\n", storage.Title, storage.UUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, item := range storecfg.Servers {
|
||||
s.StartServer(&request.StartServerRequest{
|
||||
UUID: item,
|
||||
// StopType: request.ServerStopTypeHard,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fixStorageDevices(s *service.Service,srvrCfg ServerConfig, serverDetails *upcloud.ServerDetails, targetSize string) {
|
||||
if len(serverDetails.StorageDevices) == 0 {
|
||||
return
|
||||
}
|
||||
err := errors.New("Dummy")
|
||||
// fmt.Fprintf(os.Stderr, "%#v: %#v\n", serverDetails.StorageDevices, srvrCfg)
|
||||
for i, storage := range serverDetails.StorageDevices {
|
||||
store_size := 0
|
||||
switch targetSize {
|
||||
case "size":
|
||||
store_size = srvrCfg.StorageDevices[i].Size
|
||||
case "part0":
|
||||
s := strings.Split(srvrCfg.StorageDevices[i].PartSizes, ",")
|
||||
store_size, err = strconv.Atoi(s[0])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get partsize 0 to create image storage for %s: %#v (%s)\n", storage.Title, err, err.Error())
|
||||
return
|
||||
}
|
||||
case "part1":
|
||||
s := strings.Split(srvrCfg.StorageDevices[i].PartSizes, ",")
|
||||
store_size, err = strconv.Atoi(s[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get partsize 1 to create image storage for %s: %#v (%s)\n", storage.Title, err, err.Error())
|
||||
return
|
||||
}
|
||||
case "final":
|
||||
store_size = srvrCfg.StorageDevices[i].FinalSize
|
||||
}
|
||||
if store_size == 0 {
|
||||
fmt.Printf("No targetSize found [size|final] for %s (%s) %dGB == %dGB\n",storage.Title, storage.UUID, storage.Size, store_size)
|
||||
continue
|
||||
}
|
||||
if store_size== storage.Size {
|
||||
fmt.Printf("%s (%s) %dGB == %dGB\n",storage.Title, storage.UUID, storage.Size, store_size)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("FixStorage %s (%s) %dGB to %dGB\n",storage.Title, storage.UUID, storage.Size, store_size)
|
||||
if serverDetails.Server.State != upcloud.ServerStateStopped {
|
||||
err = stopOneServer(s, serverDetails.Server)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to stop server %#v: %#v\n", serverDetails.Server.UUID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
_, err = s.ModifyStorage(&request.ModifyStorageRequest{
|
||||
UUID: storage.UUID,
|
||||
// Title: srvrCfg.StorageDevices[i].Title,
|
||||
Size: store_size,
|
||||
// BackupRule *upcloud.BackupRule `json:"backup_rule,omitempty"`
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to modify storage: %#v (%s)\n", err, err.Error())
|
||||
} else {
|
||||
fmt.Printf("Successfully modified %s (%s) to %dGB\n", storage.Title, storage.UUID, store_size)
|
||||
}
|
||||
}
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: serverDetails.UUID,
|
||||
})
|
||||
if info.Server.State != upcloud.ServerStateStarted {
|
||||
startOneServer(s, serverDetails.Server)
|
||||
}
|
||||
}
|
||||
|
||||
func createStorageImage(s *service.Service, target_uuid string, title string) error {
|
||||
info,err := s.TemplatizeStorage(&request.TemplatizeStorageRequest{
|
||||
UUID: target_uuid,
|
||||
Title: strings.Trim(title, "\""),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to create image storage: %#v (%s)\n", err, err.Error())
|
||||
} else {
|
||||
fmt.Printf("Successfully created %s (%s)\n", title, target_uuid)
|
||||
}
|
||||
s.WaitForStorageState(&request.WaitForStorageStateRequest{
|
||||
UUID: target_uuid,
|
||||
DesiredState: "online",
|
||||
Timeout: 1 * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to wait for storage to reach desired online state: %#v", err)
|
||||
return err
|
||||
}
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.Encode(info)
|
||||
return nil
|
||||
}
|
||||
func listStorages(s *service.Service, dataCfg *DataConfig, target string) error {
|
||||
storages, err := s.GetStorages(&request.GetStoragesRequest{
|
||||
Access: upcloud.StorageAccessPrivate,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to get storages: %#v\n", err)
|
||||
return err
|
||||
}
|
||||
servers, _ := s.GetServers()
|
||||
fmt.Printf("Scanning over %d storages and %d servers \n", len(storages.Storages), len(servers.Servers))
|
||||
if len(storages.Storages) > 0 {
|
||||
for _, storage := range storages.Storages {
|
||||
storage_out := fmt.Sprintf("title: \"%s\", id: %s, size: %d, plan: %s, state: %s, zone: %s, type: %s",
|
||||
storage.Title, storage.UUID, storage.Size, storage.PartOfPlan, storage.State, storage.Zone, storage.Type)
|
||||
is_attached := false
|
||||
for _, server := range servers.Servers {
|
||||
isInGroup := false
|
||||
for _, srv := range dataCfg.Servers {
|
||||
if server.Hostname == srv.Hostname {
|
||||
isInGroup = true
|
||||
break
|
||||
}
|
||||
}
|
||||
info,err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: server.UUID,
|
||||
})
|
||||
if err == nil {
|
||||
for _, srv_storage := range info.StorageDevices {
|
||||
if srv_storage.UUID == storage.UUID {
|
||||
is_attached=true
|
||||
if isInGroup {
|
||||
fmt.Printf("%s, attached: \"%s\", id: %s\n", storage_out, server.Title, server.UUID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! is_attached {
|
||||
fmt.Printf("%s, attached: none\n", storage_out)
|
||||
}
|
||||
if target != "" && storage.UUID == target {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
56
tags.go
Normal file
56
tags.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/request"
|
||||
"github.com/UpCloudLtd/upcloud-go-api/upcloud/service"
|
||||
)
|
||||
|
||||
func infoTagsFromId(s *service.Service, id string) (upcloud.TagServerSlice,error) {
|
||||
var upTags upcloud.TagServerSlice
|
||||
if id == "" {
|
||||
fmt.Fprintf(os.Stderr, "Resouce not found to get tags\n")
|
||||
return upTags,nil
|
||||
}
|
||||
info, err := s.GetServerDetails(&request.GetServerDetailsRequest{
|
||||
UUID: id,
|
||||
})
|
||||
for _, tag := range info.Tags {
|
||||
upTags = append(upTags, tag)
|
||||
}
|
||||
return upTags, err
|
||||
}
|
||||
func addTagsToId(s *service.Service, id string, tags []string) error {
|
||||
if id == "" || len(tags) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Resouce not found to add tags to (%s)\n",id)
|
||||
return nil
|
||||
}
|
||||
var upTags upcloud.TagServerSlice
|
||||
for i := 0; i < len(tags); i++ {
|
||||
upTags = append(upTags,tags[i])
|
||||
}
|
||||
_, err := s.TagServer(&request.TagServerRequest{
|
||||
UUID: id,
|
||||
Tags: upTags,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to tag server %s: %#v", id, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func deleteTagsFromId(s *service.Service, id string, tags []string) error {
|
||||
if id == "" || len(tags) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Resouce not found to get tags (%s)\n",id)
|
||||
return nil
|
||||
}
|
||||
_, err := s.UntagServer(&request.UntagServerRequest{
|
||||
UUID: id,
|
||||
Tags: tags,
|
||||
})
|
||||
// fmt.Printf("Delete Tag form server: %#v\n", msg)
|
||||
return err
|
||||
}
|
Loading…
Reference in New Issue
Block a user