kontena-plugin-upcloud 0.3.0 → 0.3.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2c4c7355ad5cb678eae3164eab3d4e7a431737b0
4
- data.tar.gz: f2cacd22c569d7f9c71ea3dbfa10d54d385dc36a
3
+ metadata.gz: aa71abdd5e6d879f8868bfb1e14f669a5879d197
4
+ data.tar.gz: 35cd56ca6f880a201813cfc4ed2724c01a84cbd8
5
5
  SHA512:
6
- metadata.gz: 6ab242dc67aa75f27f53bae70f0c2cd1ccebc5d139e286ffdb725950a074982b6c45fef817d33f7cd6e21abb030595971f45461d2c57785732ffe2777f73ef84
7
- data.tar.gz: 7ea9fb517948d7225fe869a542fcc0e7b742f1695f1147cb3846784c780384d6bf1318e17e8bb25bbf1c6cf0e0c15ee5938bac92a10279e22ede1a70d7b83138
6
+ metadata.gz: 5c82aabaaa2c8b6f97d0ad708590e67178aede22b22955d8e1aa7c4320951b7c3b1ea730dafc7a019bb7176aed4f46905439685a4837be72bc8551d2d60fa8a3
7
+ data.tar.gz: 0791e9666f8b9fad40fb3b6558046b1c4cbd0004cc0fc5e9772f841db61aa33c5b22356a1d6e7e13d6c770a4ab897459ba2834c10d190fe202c93e06feea3082
@@ -0,0 +1,92 @@
1
+ require 'excon'
2
+ require 'json'
3
+
4
+ module Kontena
5
+ module Machine
6
+ module Upcloud
7
+ class Client
8
+
9
+ API_URL = 'https://api.upcloud.com'.freeze
10
+ ACCEPT = 'Accept'.freeze
11
+ CTYPE = 'Content-Type'.freeze
12
+ APP_JSON = 'application/json'.freeze
13
+ CTYPE_HEAD = { CTYPE => APP_JSON }
14
+
15
+ attr_reader :http_client
16
+
17
+ def initialize(username, password)
18
+ @http_client = Excon.new(
19
+ API_URL,
20
+ omit_default_port: true,
21
+ user: username,
22
+ password: password,
23
+ )
24
+ end
25
+
26
+ def get(path)
27
+ request(method: :get, path: path)
28
+ end
29
+
30
+ def post(path, body)
31
+ request(method: :post, path: path, body: body, headers: CTYPE_HEAD)
32
+ end
33
+
34
+ def delete(path)
35
+ request(method: :delete, path: path)
36
+ end
37
+
38
+ def find_template(name)
39
+ get('storage/template')[:storages][:storage].find{|s| s[:title].downcase.start_with?(name.downcase)}
40
+ end
41
+
42
+ def find_plan(name)
43
+ list_plans.find{|s| s[:name].downcase.eql?(name.downcase)}
44
+ end
45
+
46
+ def list_plans
47
+ get('plan')[:plans][:plan]
48
+ end
49
+
50
+ def list_zones
51
+ get('zone')[:zones][:zone]
52
+ end
53
+
54
+ def zone_exist?(name)
55
+ list_zones.any? { |zone| zone[:id] == name }
56
+ end
57
+
58
+ def get_server(id)
59
+ get("server/#{id}").fetch(:server, nil)
60
+ end
61
+
62
+ def api_access?
63
+ response = get('account')
64
+ response.kind_of?(Hash) && response.has_key?(:account)
65
+ rescue
66
+ false
67
+ end
68
+
69
+ private
70
+
71
+ def request(opts)
72
+ response = http_client.request(
73
+ opts.merge(
74
+ path: "/1.2/#{opts[:path]}",
75
+ headers: (opts[:headers] || {}).merge(ACCEPT => APP_JSON),
76
+ )
77
+ )
78
+
79
+ if (200..299).cover?(response.status)
80
+ if response.body && response.body.start_with?('{'.freeze)
81
+ JSON.parse(response.body, symbolize_names: true)
82
+ else
83
+ { success: true }
84
+ end
85
+ else
86
+ raise "Request to Upcloud failed: #{response.status} #{response.body}"
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -9,23 +9,17 @@ module Kontena
9
9
  class MasterProvisioner
10
10
  include RandomName
11
11
  include Machine::CertHelper
12
- include UpcloudCommon
13
12
  include Kontena::Cli::Common
14
13
 
15
- attr_reader :http_client, :username, :password
14
+ attr_reader :http_client, :uc_client
16
15
 
17
16
  # @param [String] token Upcloud token
18
17
  def initialize(upcloud_username, upcloud_password)
19
- @username = upcloud_username
20
- @password = upcloud_password
18
+ @uc_client = Kontena::Machine::Upcloud::Client.new(upcloud_username, upcloud_password)
21
19
  end
22
20
 
23
21
  def run!(opts)
24
- if File.readable?(File.expand_path(opts[:ssh_key]))
25
- ssh_key = File.read(File.expand_path(opts[:ssh_key])).strip
26
- end
27
-
28
- abort('Invalid ssh key') unless ssh_key && ssh_key.start_with?('ssh-')
22
+ abort('Invalid ssh key') unless opts[:ssh_key].to_s.start_with?('ssh-')
29
23
 
30
24
  if opts[:ssl_cert]
31
25
  abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
@@ -36,11 +30,9 @@ module Kontena
36
30
  end
37
31
  end
38
32
 
39
- abort_unless_api_access
40
-
41
- abort('CoreOS template not found on Upcloud') unless coreos_template = find_template('CoreOS Stable')
42
- abort('Server plan not found on Upcloud') unless plan = find_plan(opts[:plan])
43
- abort('Zone not found on Upcloud') unless zone_exist?(opts[:zone])
33
+ abort('CoreOS template not found on Upcloud') unless coreos_template = uc_client.find_template('CoreOS Stable')
34
+ abort('Server plan not found on Upcloud') unless plan = uc_client.find_plan(opts[:plan])
35
+ abort('Zone not found on Upcloud') unless uc_client.zone_exist?(opts[:zone])
44
36
 
45
37
  if opts[:name]
46
38
  server_name = opts[:name]
@@ -61,7 +53,7 @@ module Kontena
61
53
  device_data = {
62
54
  server: {
63
55
  zone: opts[:zone],
64
- title: server_name,
56
+ title: hostname,
65
57
  hostname: hostname,
66
58
  plan: plan[:name],
67
59
  vnc: 'off',
@@ -83,21 +75,21 @@ module Kontena
83
75
  create_password: 'no',
84
76
  username: 'root',
85
77
  ssh_keys: {
86
- ssh_key: [ssh_key]
78
+ ssh_key: [opts[:ssh_key]]
87
79
  }
88
80
  }
89
81
  }
90
82
  }.to_json
91
83
 
92
84
  spinner "Creating an Upcloud server #{hostname.colorize(:cyan)} " do
93
- response = post('server', body: device_data)
85
+ response = uc_client.post('server', device_data)
94
86
  if response.has_key?(:error)
95
87
  abort("\nUpcloud server creation failed (#{response[:error].fetch(:error_message, '')})")
96
88
  end
97
89
  device_data = response[:server]
98
90
 
99
91
  until device_data && device_data.fetch(:state, nil).to_s == 'maintenance'
100
- device_data = get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
92
+ device_data = uc_client.get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
101
93
  sleep 5
102
94
  end
103
95
  end
@@ -128,7 +120,8 @@ module Kontena
128
120
  public_ip: device_public_ip[:address],
129
121
  provider: 'upcloud',
130
122
  version: master_version,
131
- code: opts[:initial_admin_code]
123
+ code: opts[:initial_admin_code],
124
+ ssl_certificate: (respond_to?(:certificate_public_key) && !opts[:ssl_cert]) ? certificate_public_key(ssl_cert) : nil
132
125
  }
133
126
  end
134
127
 
@@ -3,24 +3,20 @@ module Kontena
3
3
  module Upcloud
4
4
  class NodeDestroyer
5
5
  include RandomName
6
- include UpcloudCommon
7
6
  include Kontena::Cli::ShellSpinner
8
7
 
9
- attr_reader :api_client, :username, :password
8
+ attr_reader :api_client, :uc_client
10
9
 
11
10
  # @param [Kontena::Client] api_client Kontena api client
12
11
  # @param [String] token Upcloud token
13
12
  def initialize(api_client, upcloud_username, upcloud_password)
14
13
  @api_client = api_client
15
- @username = upcloud_username
16
- @password = upcloud_password
14
+ @uc_client = Kontena::Machine::Upcloud::Client.new(upcloud_username, upcloud_password)
17
15
  end
18
16
 
19
17
  def run!(grid, name)
20
18
 
21
- abort_unless_api_access
22
-
23
- servers = get('server')
19
+ servers = uc_client.get('server')
24
20
  unless servers && servers.has_key?(:servers)
25
21
  abort('Upcloud API error')
26
22
  end
@@ -29,7 +25,7 @@ module Kontena
29
25
 
30
26
  abort "Cannot find node #{name.colorize(:cyan)} in UpCloud" unless server
31
27
 
32
- server_data = get("server/#{server[:uuid]}")
28
+ server_data = uc_client.get("server/#{server[:uuid]}")
33
29
 
34
30
  storage_devices = server_data.fetch(:server, {}).fetch(:storage_devices, {}).fetch(:storage_device, [])
35
31
  storage_uuids = storage_devices.map{|s| s[:storage]}
@@ -39,8 +35,8 @@ module Kontena
39
35
  if server
40
36
  unless server[:state].eql?('stopped')
41
37
  spinner "Shutting down UpCloud node #{name.colorize(:cyan)} " do
42
- device_data = post(
43
- "server/#{server[:uuid]}/stop", body: {
38
+ device_data = uc_client.post(
39
+ "server/#{server[:uuid]}/stop", {
44
40
  stop_server: {
45
41
  stop_type: 'soft',
46
42
  timeout: 120
@@ -49,20 +45,20 @@ module Kontena
49
45
  )
50
46
 
51
47
  until device_data && device_data.fetch(:state, nil).to_s.eql?('stopped')
52
- device_data = get("server/#{server[:uuid]}").fetch(:server, {}) rescue nil
48
+ device_data = uc_client.get("server/#{server[:uuid]}").fetch(:server, {}) rescue nil
53
49
  sleep 5
54
50
  end
55
51
  end
56
52
  end
57
53
 
58
54
  spinner "Terminating UpCloud node #{name.colorize(:cyan)} " do
59
- response = delete("server/#{server[:uuid]}")
55
+ response = uc_client.delete("server/#{server[:uuid]}")
60
56
  abort "Cannot delete node #{name.colorize(:cyan)} in Upcloud" unless response[:success]
61
57
  end
62
58
 
63
59
  storage_uuids.each do |uuid|
64
60
  spinner "Deleting UpCloud storage device '#{uuid.colorize(:cyan)}' " do
65
- response = delete("storage/#{uuid}")
61
+ response = uc_client.delete("storage/#{uuid}")
66
62
  unless response[:success]
67
63
  puts "#{"WARNING".colorize(:red)}: Couldn't delete UpCloud storage '#{uuid.colorize(:cyan)}', check manually."
68
64
  end
@@ -7,26 +7,20 @@ module Kontena
7
7
  module Upcloud
8
8
  class NodeProvisioner
9
9
  include RandomName
10
- include UpcloudCommon
11
10
  include Kontena::Cli::ShellSpinner
12
11
 
13
- attr_reader :api_client, :username, :password
12
+ attr_reader :api_client, :uc_client
14
13
 
15
14
  # @param [Kontena::Client] api_client Kontena api client
16
15
  # @param [String] upcloud_username Upcloud username
17
16
  # @param [String] upcloud_password Upcloud password
18
17
  def initialize(api_client, upcloud_username, upcloud_password)
19
18
  @api_client = api_client
20
- @username = upcloud_username
21
- @password = upcloud_password
19
+ @uc_client = Kontena::Machine::Upcloud::Client.new(upcloud_username, upcloud_password)
22
20
  end
23
21
 
24
22
  def run!(opts)
25
- if File.readable?(File.expand_path(opts[:ssh_key]))
26
- ssh_key = File.read(File.expand_path(opts[:ssh_key])).strip
27
- end
28
-
29
- abort('Invalid ssh key') unless ssh_key && ssh_key.start_with?('ssh-')
23
+ abort('Invalid ssh key') unless opts[:ssh_key].to_s.start_with?('ssh-')
30
24
 
31
25
  count = opts[:count].to_i
32
26
  userdata_vars = {
@@ -35,11 +29,9 @@ module Kontena
35
29
  grid_token: opts[:grid_token],
36
30
  }
37
31
 
38
- abort_unless_api_access
39
-
40
- abort('CoreOS template not found on Upcloud') unless coreos_template = find_template('CoreOS Stable')
41
- abort('Server plan not found on Upcloud') unless plan = find_plan(opts[:plan])
42
- abort('Zone not found on Upcloud') unless zone_exist?(opts[:zone])
32
+ abort('CoreOS template not found on Upcloud') unless coreos_template = uc_client.find_template('CoreOS Stable')
33
+ abort('Server plan not found on Upcloud') unless plan = uc_client.find_plan(opts[:plan])
34
+ abort('Zone not found on Upcloud') unless uc_client.zone_exist?(opts[:zone])
43
35
 
44
36
  count.times do |i|
45
37
  if opts[:name]
@@ -72,14 +64,14 @@ module Kontena
72
64
  create_password: 'no',
73
65
  username: 'root',
74
66
  ssh_keys: {
75
- ssh_key: [ssh_key]
67
+ ssh_key: [opts[:ssh_key]]
76
68
  }
77
69
  }
78
70
  }
79
71
  }.to_json
80
72
 
81
73
  spinner "Creating UpCloud node #{hostname.colorize(:cyan)} " do
82
- response = post('server', body: device_data)
74
+ response = uc_client.post('server', device_data)
83
75
 
84
76
  if response.has_key?(:error)
85
77
  abort("\nUpCloud server creation failed (#{response[:error].fetch(:error_message, '')})")
@@ -87,7 +79,7 @@ module Kontena
87
79
  device_data = response[:server]
88
80
 
89
81
  until device_data && device_data.fetch(:state, nil).to_s == 'maintenance'
90
- device_data = get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
82
+ device_data = uc_client.get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
91
83
  sleep 5
92
84
  end
93
85
  end
@@ -3,22 +3,19 @@ module Kontena
3
3
  module Upcloud
4
4
  class NodeRestarter
5
5
  include RandomName
6
- include UpcloudCommon
7
6
  include Kontena::Cli::ShellSpinner
8
7
 
9
- attr_reader :username, :password
8
+ attr_reader :uc_client
10
9
 
11
10
  # @param [String] upcloud_username Upcloud username
12
11
  # @param [String] upcloud_password Upcloud password
13
12
  def initialize(upcloud_username, upcloud_password)
14
- @username = upcloud_username
15
- @password = upcloud_password
13
+ @uc_client = Kontena::Machine::Upcloud::Client.new(upcloud_username, upcloud_password)
16
14
  end
17
15
 
18
16
  def run!(name)
19
- abort_unless_api_access
20
17
 
21
- servers = get('server')
18
+ servers = uc_client.get('server')
22
19
  unless servers && servers.has_key?(:servers)
23
20
  abort('Upcloud API error')
24
21
  end
@@ -27,8 +24,8 @@ module Kontena
27
24
 
28
25
  if server
29
26
  spinner "Restarting UpCloud node #{name.colorize(:cyan)} " do
30
- result = post(
31
- "server/#{server[:uuid]}/restart", body: {
27
+ result = uc_client.post(
28
+ "server/#{server[:uuid]}/restart", {
32
29
  restart_server: {
33
30
  stop_type: 'soft',
34
31
  timeout: 600,
@@ -1,6 +1,6 @@
1
1
  require 'kontena/machine/random_name'
2
2
  require 'kontena/machine/cert_helper'
3
- require_relative 'upcloud/upcloud_common'
3
+ require_relative 'upcloud/client'
4
4
  require_relative 'upcloud/node_provisioner'
5
5
  require_relative 'upcloud/node_destroyer'
6
6
  require_relative 'upcloud/node_restarter'
@@ -1,24 +1,24 @@
1
1
  require 'securerandom'
2
+ require 'kontena/plugin/upcloud/prompts'
2
3
 
3
4
  module Kontena::Plugin::Upcloud::Master
4
5
  class CreateCommand < Kontena::Command
5
6
  include Kontena::Cli::Common
6
7
 
7
8
  option "--name", "[NAME]", "Set Kontena Master name"
8
- option "--username", "USER", "Upcloud username", required: true, environment_variable: 'UPCLOUD_USERNAME'
9
- option "--password", "PASS", "Upcloud password", required: true, environment_variable: 'UPCLOUD_PASSWORD'
10
- option "--ssh-key", "SSH_KEY", "Path to ssh public key", default: '~/.ssh/id_rsa.pub'
9
+
10
+ include Kontena::Plugin::Upcloud::Prompts::Create
11
+
11
12
  option "--ssl-cert", "SSL CERT", "SSL certificate file (optional)"
12
- option "--plan", "PLAN", "Server plan", required: true
13
- option "--zone", "ZONE", "Zone", required: true
14
13
  option "--vault-secret", "VAULT_SECRET", "Secret key for Vault (optional)"
15
14
  option "--vault-iv", "VAULT_IV", "Initialization vector for Vault (optional)"
16
15
  option "--mongodb-uri", "URI", "External MongoDB uri (optional)"
17
- option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
18
16
 
19
17
  def execute
20
18
  require_relative '../../../machine/upcloud'
21
19
 
20
+ abort_unless_api_access
21
+
22
22
  provisioner.run!(
23
23
  name: self.name,
24
24
  ssh_key: ssh_key,
@@ -36,29 +36,5 @@ module Kontena::Plugin::Upcloud::Master
36
36
  def provisioner
37
37
  Kontena::Machine::Upcloud::MasterProvisioner.new(username, password)
38
38
  end
39
-
40
- def default_username
41
- prompt.ask('UpCloud username:', echo: true)
42
- end
43
-
44
- def default_password
45
- prompt.ask('UpCloud password:', echo: false)
46
- end
47
-
48
- def default_plan
49
- prompt.select("Choose plan:") do |menu|
50
- Kontena::Plugin::Upcloud::PLANS.each do |plan, name|
51
- menu.choice name, plan
52
- end
53
- end
54
- end
55
-
56
- def default_zone
57
- prompt.select("Choose availability zone:") do |menu|
58
- Kontena::Plugin::Upcloud::ZONES.each do |zone, name|
59
- menu.choice name, zone
60
- end
61
- end
62
- end
63
39
  end
64
40
  end
@@ -1,21 +1,23 @@
1
+ require 'kontena/plugin/upcloud/prompts'
2
+
1
3
  module Kontena::Plugin::Upcloud::Nodes
2
4
  class CreateCommand < Kontena::Command
3
5
  include Kontena::Cli::Common
4
6
  include Kontena::Cli::GridOptions
5
7
 
6
8
  parameter "[NAME]", "Node name"
7
- option "--username", "USER", "Upcloud username", required: true, environment_variable: 'UPCLOUD_USERNAME'
8
- option "--password", "PASS", "Upcloud password", required: true, environment_variable: 'UPCLOUD_PASSWORD'
9
- option "--ssh-key", "SSH_KEY", "Path to ssh public key", default: '~/.ssh/id_rsa.pub'
9
+
10
+ include Kontena::Plugin::Upcloud::Prompts::Create
11
+
10
12
  option "--count", "COUNT", "How many nodes should be created"
11
- option "--zone", "ZONE", "Zone", required: true
12
- option "--plan", "PLAN", "Server size", required: true
13
- option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
14
13
 
15
14
  requires_current_master_token
16
15
 
17
16
  def execute
18
17
  require_relative '../../../machine/upcloud'
18
+
19
+ abort_unless_api_access
20
+
19
21
  grid = fetch_grid
20
22
  provisioner = Kontena::Machine::Upcloud::NodeProvisioner.new(client, username, password)
21
23
  provisioner.run!(
@@ -37,33 +39,8 @@ module Kontena::Plugin::Upcloud::Nodes
37
39
  client.get("grids/#{current_grid}")
38
40
  end
39
41
 
40
-
41
- def default_username
42
- prompt.ask('UpCloud username:', echo: true)
43
- end
44
-
45
- def default_password
46
- prompt.ask('UpCloud password:', echo: false)
47
- end
48
-
49
42
  def default_count
50
43
  prompt.ask('How many servers:', default: 1)
51
44
  end
52
-
53
- def default_plan
54
- prompt.select("Choose plan:") do |menu|
55
- Kontena::Plugin::Upcloud::PLANS.each do |plan, name|
56
- menu.choice name, plan
57
- end
58
- end
59
- end
60
-
61
- def default_zone
62
- prompt.select("Choose availability zone:") do |menu|
63
- Kontena::Plugin::Upcloud::ZONES.each do |zone, name|
64
- menu.choice name, zone
65
- end
66
- end
67
- end
68
45
  end
69
46
  end
@@ -1,16 +1,19 @@
1
+ require 'kontena/plugin/upcloud/prompts'
2
+
1
3
  module Kontena::Plugin::Upcloud::Nodes
2
4
  class RestartCommand < Kontena::Command
3
5
  include Kontena::Cli::Common
4
6
  include Kontena::Cli::GridOptions
5
7
 
6
- parameter "NAME", "Node name"
7
- option "--username", "USER", "Upcloud username", required: true, environment_variable: 'UPCLOUD_USERNAME'
8
- option "--password", "PASS", "Upcloud password", required: true, environment_variable: 'UPCLOUD_PASSWORD'
8
+ include Kontena::Plugin::Upcloud::Prompts::NodeName
9
+ include Kontena::Plugin::Upcloud::Prompts::Common
9
10
 
10
11
  def execute
11
12
  require_api_url
12
13
  require_current_grid
13
14
 
15
+ abort_unless_api_access
16
+
14
17
  require 'kontena/machine/upcloud'
15
18
 
16
19
  restarter = Kontena::Machine::Upcloud::NodeRestarter.new(username, password)
@@ -1,17 +1,18 @@
1
+ require 'kontena/plugin/upcloud/prompts'
1
2
  module Kontena::Plugin::Upcloud::Nodes
2
3
  class TerminateCommand < Kontena::Command
3
4
  include Kontena::Cli::Common
4
5
  include Kontena::Cli::GridOptions
5
6
 
6
- parameter "[NAME]", "Node name"
7
- option "--username", "USER", "Upcloud username", required: true, environment_variable: 'UPCLOUD_USERNAME'
8
- option "--password", "PASS", "Upcloud password", required: true, environment_variable: 'UPCLOUD_PASSWORD'
7
+ include Kontena::Plugin::Upcloud::Prompts::NodeName
8
+ include Kontena::Plugin::Upcloud::Prompts::Common
9
9
 
10
10
  option '--force', :flag, "Force terminate", attribute_name: :forced
11
11
 
12
12
  requires_current_master_token
13
13
 
14
14
  def execute
15
+ abort_unless_api_access
15
16
  require_relative '../../../machine/upcloud'
16
17
  confirm_command(name) unless forced?
17
18
  grid = client.get("grids/#{current_grid}")
@@ -0,0 +1,99 @@
1
+ require 'kontena/machine/upcloud/client'
2
+
3
+ module Kontena
4
+ module Plugin
5
+ module Upcloud
6
+ module Prompts
7
+ module Common
8
+ def self.included(base)
9
+ base.prepend Defaults
10
+ base.option "--username", "USER", "Upcloud username", required: true, environment_variable: 'UPCLOUD_USERNAME'
11
+ base.option "--password", "PASS", "Upcloud password", required: true, environment_variable: 'UPCLOUD_PASSWORD'
12
+ end
13
+
14
+ def upcloud_client
15
+ @upcloud_client ||= Kontena::Machine::Upcloud::Client.new(username, password)
16
+ end
17
+
18
+ def abort_unless_api_access
19
+ unless upcloud_client.api_access?
20
+ exit_with_error('Upcloud API authentication failed. Check that API access is enabled for the user.')
21
+ end
22
+ end
23
+
24
+ module Defaults
25
+ def default_username
26
+ prompt.ask('UpCloud username:', echo: true)
27
+ end
28
+
29
+ def default_password
30
+ pass = prompt.ask('UpCloud password:', echo: false)
31
+ end
32
+ end
33
+ end
34
+
35
+ module NodeName
36
+ def self.included(base)
37
+ base.prepend Defaults
38
+ base.parameter "[NAME]", "Node name"
39
+ end
40
+
41
+ module Defaults
42
+ def default_name
43
+ nodes = client.get("grids/#{current_grid}/nodes")
44
+ nodes = nodes['nodes'].select{ |n|
45
+ n['labels'] && n['labels'].include?('provider=upcloud'.freeze)
46
+ }
47
+ raise "Did not find any nodes with label provider=upcloud" if nodes.empty?
48
+ prompt.select("Select node:") do |menu|
49
+ nodes.sort_by{|n| n['node_number'] }.reverse.each do |node|
50
+ initial = node['initial_member'] ? '(initial) ' : ''
51
+ menu.choice "#{node['name']} #{initial}", node['name']
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ module Create
59
+ def self.included(base)
60
+ base.include Common
61
+ base.prepend Defaults
62
+ base.option "--ssh-key", "SSH_KEY", "Path to ssh public key", attribute_name: :ssh_key_path
63
+ base.option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
64
+ base.option "--zone", "ZONE", "Zone", required: true
65
+ base.option "--plan", "PLAN", "Server size", required: true
66
+ end
67
+
68
+ def ssh_key
69
+ return File.read(ssh_key_path) unless ssh_key_path.nil?
70
+ default = File.read(Defaults::DEFAULT_SSH_KEY_PATH).strip rescue nil
71
+ prompt.ask('SSH public key: (enter an ssh key in OpenSSH format "ssh-xxx xxxxx key_name")', default: default) do |q|
72
+ q.validate /^ssh-rsa \S+ \S+$/
73
+ end
74
+ end
75
+
76
+ module Defaults
77
+ DEFAULT_SSH_KEY_PATH = File.join(Dir.home, '.ssh', 'id_rsa.pub')
78
+
79
+ def default_plan
80
+ prompt.select("Choose plan:") do |menu|
81
+ upcloud_client.list_plans.each do |plan|
82
+ menu.choice "#{plan[:name]} (#{plan[:memory_amount]}MB #{plan[:storage_size]}GB #{plan[:storage_tier]})", plan[:name]
83
+ end
84
+ end
85
+ end
86
+
87
+ def default_zone
88
+ prompt.select("Choose availability zone:") do |menu|
89
+ upcloud_client.list_zones.each do |zone|
90
+ menu.choice zone[:description], zone[:id]
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,23 +1,7 @@
1
1
  module Kontena
2
2
  module Plugin
3
3
  module Upcloud
4
- VERSION = "0.3.0"
5
-
6
- ZONES = {
7
- 'nl-ams1' => 'Amsterdam #1',
8
- 'us-chi1' => 'Chicago #1',
9
- 'de-fra1' => 'Frankfurt #1',
10
- 'fi-hel1' => 'Helsinki #1',
11
- 'uk-lon1' => 'London #1',
12
- 'sg-sin1' => 'Singapore #1'
13
- }.freeze
14
-
15
- PLANS = {
16
- '1xCPU-1GB' => '1024MB / 1 CPU, 30GB MaxIOPS disk, 2048GB transfer',
17
- '2xCPU-2GB' => '2048MB / 2 CPU, 50GB MaxIOPS disk, 3072GB transfer',
18
- '4xCPU-4GB' => '4096MB / 4 CPU, 100GB MaxIOPS disk, 4096GB transfer',
19
- '6xCPU-8GB' => '8192MB / 6 CPU, 200GB MaxIOPS disk, 8192GB transfer'
20
- }.freeze
4
+ VERSION = "0.3.1.rc1"
21
5
  end
22
6
  end
23
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kontena-plugin-upcloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kontena, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-20 00:00:00.000000000 Z
11
+ date: 2017-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kontena-cli
@@ -67,13 +67,13 @@ files:
67
67
  - README.md
68
68
  - kontena-plugin-upcloud.gemspec
69
69
  - lib/kontena/machine/upcloud.rb
70
+ - lib/kontena/machine/upcloud/client.rb
70
71
  - lib/kontena/machine/upcloud/cloudinit.yml
71
72
  - lib/kontena/machine/upcloud/cloudinit_master.yml
72
73
  - lib/kontena/machine/upcloud/master_provisioner.rb
73
74
  - lib/kontena/machine/upcloud/node_destroyer.rb
74
75
  - lib/kontena/machine/upcloud/node_provisioner.rb
75
76
  - lib/kontena/machine/upcloud/node_restarter.rb
76
- - lib/kontena/machine/upcloud/upcloud_common.rb
77
77
  - lib/kontena/plugin/upcloud.rb
78
78
  - lib/kontena/plugin/upcloud/master/create_command.rb
79
79
  - lib/kontena/plugin/upcloud/master_command.rb
@@ -81,6 +81,7 @@ files:
81
81
  - lib/kontena/plugin/upcloud/nodes/create_command.rb
82
82
  - lib/kontena/plugin/upcloud/nodes/restart_command.rb
83
83
  - lib/kontena/plugin/upcloud/nodes/terminate_command.rb
84
+ - lib/kontena/plugin/upcloud/prompts.rb
84
85
  - lib/kontena/plugin/upcloud_command.rb
85
86
  - lib/kontena_cli_plugin.rb
86
87
  homepage: https://github.com/kontena/kontena-plugin-upcloud
@@ -98,9 +99,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
99
  version: '0'
99
100
  required_rubygems_version: !ruby/object:Gem::Requirement
100
101
  requirements:
101
- - - ">="
102
+ - - ">"
102
103
  - !ruby/object:Gem::Version
103
- version: '0'
104
+ version: 1.3.1
104
105
  requirements: []
105
106
  rubyforge_project:
106
107
  rubygems_version: 2.4.5
@@ -1,72 +0,0 @@
1
- require 'excon'
2
- require 'json'
3
-
4
- module Kontena
5
- module Machine
6
- module Upcloud
7
- module UpcloudCommon
8
-
9
- attr_reader :username
10
- attr_reader :password
11
-
12
- def upcloud_client
13
- @upcloud_client ||= Excon.new(
14
- 'https://api.upcloud.com',
15
- omit_default_port: true,
16
- user: username,
17
- password: password,
18
- headers: { "Accept-Encoding" => 'application/json' }
19
- )
20
- end
21
-
22
- def find_template(name)
23
- get('storage/template')[:storages][:storage].find{|s| s[:title].downcase.start_with?(name.downcase)}
24
- end
25
-
26
- def find_plan(name)
27
- get('plan')[:plans][:plan].find{|s| s[:name].downcase.eql?(name.downcase)}
28
- end
29
-
30
- def zone_exist?(name)
31
- get('zone')[:zones][:zone].map{|p| p[:id]}.include?(name)
32
- end
33
-
34
- def get_server(id)
35
- get("server/#{id}").fetch(:server, nil)
36
- end
37
-
38
- def api_access?
39
- response = get('account')
40
- response.kind_of?(Hash) && response.has_key?(:account)
41
- rescue
42
- false
43
- end
44
-
45
- def abort_unless_api_access
46
- unless api_access?
47
- abort('Upcloud API authentication failed. Check that API access is enabled for the user.')
48
- end
49
- end
50
-
51
- [:get, :post, :delete].each do |http_method|
52
- define_method http_method do |path, options={}|
53
- response = upcloud_client.send(
54
- http_method,
55
- {
56
- path: File.join('/1.2', path),
57
- headers: { 'Content-Type' => 'application/json' }
58
- }.merge(options)
59
- )
60
- if response.body && response.body.start_with?('{')
61
- JSON.parse(response.body, symbolize_names: true)
62
- elsif response.status.to_s.start_with?('2')
63
- {success: true}
64
- else
65
- {error: response.status}
66
- end
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end