krates-plugin-digitalocean 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.gitmodules +0 -0
- data/.rspec +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +214 -0
- data/README.md +18 -0
- data/krates-plugin-digitalocean.gemspec +29 -0
- data/lib/kontena/machine/digital_ocean/cloudinit.yml +86 -0
- data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +126 -0
- data/lib/kontena/machine/digital_ocean/master_destroyer.rb +30 -0
- data/lib/kontena/machine/digital_ocean/master_provisioner.rb +99 -0
- data/lib/kontena/machine/digital_ocean/node_destroyer.rb +39 -0
- data/lib/kontena/machine/digital_ocean/node_provisioner.rb +90 -0
- data/lib/kontena/machine/digital_ocean/ssh_key_manager.rb +31 -0
- data/lib/kontena/machine/digital_ocean.rb +8 -0
- data/lib/kontena/plugin/digital_ocean/master/create_command.rb +53 -0
- data/lib/kontena/plugin/digital_ocean/master/terminate_command.rb +29 -0
- data/lib/kontena/plugin/digital_ocean/master_command.rb +4 -0
- data/lib/kontena/plugin/digital_ocean/node_command.rb +5 -0
- data/lib/kontena/plugin/digital_ocean/nodes/create_command.rb +68 -0
- data/lib/kontena/plugin/digital_ocean/nodes/restart_command.rb +34 -0
- data/lib/kontena/plugin/digital_ocean/nodes/terminate_command.rb +36 -0
- data/lib/kontena/plugin/digital_ocean/prompts.rb +112 -0
- data/lib/kontena/plugin/digital_ocean.rb +7 -0
- data/lib/kontena/plugin/digital_ocean_command.rb +4 -0
- data/lib/kontena_cli_plugin.rb +5 -0
- metadata +153 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module Kontena
|
6
|
+
module Machine
|
7
|
+
module DigitalOcean
|
8
|
+
class NodeProvisioner
|
9
|
+
include RandomName
|
10
|
+
include Kontena::Cli::ShellSpinner
|
11
|
+
|
12
|
+
attr_reader :client, :api_client
|
13
|
+
|
14
|
+
# @param [Kontena::Client] api_client Kontena api client
|
15
|
+
# @param [String] token Digital Ocean token
|
16
|
+
def initialize(api_client, token)
|
17
|
+
@api_client = api_client
|
18
|
+
@client = DropletKit::Client.new(access_token: token)
|
19
|
+
end
|
20
|
+
|
21
|
+
def run!(opts)
|
22
|
+
userdata_vars = {
|
23
|
+
version: opts[:version],
|
24
|
+
master_uri: opts[:master_uri],
|
25
|
+
grid_token: opts[:grid_token],
|
26
|
+
}
|
27
|
+
image = "coreos-#{opts[:channel]}"
|
28
|
+
droplets = []
|
29
|
+
opts[:count].to_i.times do
|
30
|
+
droplet = DropletKit::Droplet.new(
|
31
|
+
name: opts[:name] || generate_name,
|
32
|
+
region: opts[:region],
|
33
|
+
image: image,
|
34
|
+
size: opts[:size],
|
35
|
+
private_networking: true,
|
36
|
+
user_data: user_data(userdata_vars),
|
37
|
+
ssh_keys: [opts[:ssh_key_id]],
|
38
|
+
tags: [opts[:grid]]
|
39
|
+
)
|
40
|
+
created = client.droplets.create(droplet)
|
41
|
+
spinner "Creating DigitalOcean droplet #{droplet.name.colorize(:cyan)} " do
|
42
|
+
sleep 1 until client.droplets.find(id: created.id).status == 'active'
|
43
|
+
end
|
44
|
+
droplets << droplet
|
45
|
+
end
|
46
|
+
droplets.each do |droplet|
|
47
|
+
node = nil
|
48
|
+
spinner "Waiting for node #{droplet.name.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do
|
49
|
+
sleep 1 until node = droplet_exists_in_grid?(opts[:grid], droplet)
|
50
|
+
end
|
51
|
+
set_labels(
|
52
|
+
node,
|
53
|
+
[
|
54
|
+
"region=#{opts[:region]}",
|
55
|
+
"az=#{opts[:region]}",
|
56
|
+
"provider=digitalocean"
|
57
|
+
]
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def user_data(vars)
|
63
|
+
cloudinit_template = File.join(__dir__ , '/cloudinit.yml')
|
64
|
+
erb(File.read(cloudinit_template), vars)
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_name
|
68
|
+
"#{super}-#{rand(1..99)}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def ssh_key(public_key)
|
72
|
+
ssh_key = client.ssh_keys.all.find{|key| key.public_key == public_key}
|
73
|
+
end
|
74
|
+
|
75
|
+
def droplet_exists_in_grid?(grid, droplet)
|
76
|
+
api_client.get("grids/#{grid}/nodes")['nodes'].find{|n| n['name'] == droplet.name}
|
77
|
+
end
|
78
|
+
|
79
|
+
def erb(template, vars)
|
80
|
+
ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_labels(node, labels)
|
84
|
+
data = {labels: labels}
|
85
|
+
api_client.put("nodes/#{node['id']}", data, {}, {'Kontena-Grid-Token' => node['grid']['token']})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Kontena
|
2
|
+
module Machine
|
3
|
+
module DigitalOcean
|
4
|
+
class SshKeyManager
|
5
|
+
|
6
|
+
attr_reader :client
|
7
|
+
|
8
|
+
# @param [String] token Digital Ocean API token
|
9
|
+
def initialize(token)
|
10
|
+
@client = DropletKit::Client.new(access_token: token)
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_by_public_key(public_key)
|
14
|
+
list.find { |key| key.public_key == public_key }
|
15
|
+
end
|
16
|
+
|
17
|
+
def list
|
18
|
+
client.ssh_keys.all.to_a
|
19
|
+
end
|
20
|
+
|
21
|
+
def create(public_key)
|
22
|
+
client.ssh_keys.create(DropletKit::SSHKey.new(public_key: public_key, name: public_key.split(/\s+/).last))
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_or_create_by_public_key(public_key)
|
26
|
+
find_by_public_key(public_key) || create(public_key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'droplet_kit'
|
2
|
+
require 'kontena/machine/random_name'
|
3
|
+
require 'kontena/machine/cert_helper'
|
4
|
+
require_relative 'digital_ocean/node_provisioner'
|
5
|
+
require_relative 'digital_ocean/node_destroyer'
|
6
|
+
require_relative 'digital_ocean/master_provisioner'
|
7
|
+
require_relative 'digital_ocean/master_destroyer'
|
8
|
+
require_relative 'digital_ocean/ssh_key_manager'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'kontena/plugin/digital_ocean/prompts'
|
2
|
+
|
3
|
+
module Kontena::Plugin::DigitalOcean::Master
|
4
|
+
class CreateCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Plugin::DigitalOcean::Prompts
|
7
|
+
|
8
|
+
option "--name", "[NAME]", "Set master name"
|
9
|
+
option "--token", "TOKEN", "DigitalOcean API token", environment_variable: "DO_TOKEN"
|
10
|
+
option "--region", "REGION", "Region"
|
11
|
+
option "--size", "SIZE", "Droplet size"
|
12
|
+
option "--ssh-key", "SSH_KEY", "Path to ssh public key"
|
13
|
+
option "--ssl-cert", "SSL CERT", "SSL certificate file"
|
14
|
+
option "--vault-secret", "VAULT_SECRET", "Secret key for Vault (optional)"
|
15
|
+
option "--vault-iv", "VAULT_IV", "Initialization vector for Vault (optional)"
|
16
|
+
option "--mongodb-uri", "URI", "External MongoDB uri (optional)"
|
17
|
+
option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
|
18
|
+
|
19
|
+
def execute
|
20
|
+
suppress_warnings # until DO merges resource_kit pr #32
|
21
|
+
do_token = ask_do_token
|
22
|
+
|
23
|
+
require 'securerandom'
|
24
|
+
require 'kontena/machine/digital_ocean'
|
25
|
+
|
26
|
+
do_token = ask_do_token
|
27
|
+
do_region = ask_droplet_region(do_token)
|
28
|
+
do_size = ask_droplet_size(do_token, do_region)
|
29
|
+
do_ssh_key_id = ask_ssh_key(do_token)
|
30
|
+
|
31
|
+
provisioner = provisioner(do_token)
|
32
|
+
provisioner.run!(
|
33
|
+
name: name,
|
34
|
+
ssh_key_id: do_ssh_key_id,
|
35
|
+
ssl_cert: ssl_cert,
|
36
|
+
size: do_size,
|
37
|
+
region: do_region,
|
38
|
+
version: version,
|
39
|
+
vault_secret: vault_secret || SecureRandom.hex(24),
|
40
|
+
vault_iv: vault_iv || SecureRandom.hex(24),
|
41
|
+
initial_admin_code: SecureRandom.hex(16),
|
42
|
+
mongodb_uri: mongodb_uri
|
43
|
+
)
|
44
|
+
ensure
|
45
|
+
resume_warnings
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param [String] token
|
49
|
+
def provisioner(token)
|
50
|
+
Kontena::Machine::DigitalOcean::MasterProvisioner.new(token)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'kontena/plugin/digital_ocean/prompts'
|
2
|
+
|
3
|
+
module Kontena::Plugin::DigitalOcean::Master
|
4
|
+
class TerminateCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Plugin::DigitalOcean::Prompts
|
8
|
+
|
9
|
+
parameter "NAME", "Master name"
|
10
|
+
option "--token", "TOKEN", "DigitalOcean API token", environment_variable: "DO_TOKEN"
|
11
|
+
option "--force", :flag, "Force remove", default: false, attribute_name: :forced
|
12
|
+
|
13
|
+
def execute
|
14
|
+
suppress_warnings # until DO merges resource_kit pr #32
|
15
|
+
require 'kontena/machine/digital_ocean'
|
16
|
+
do_token = ask_do_token
|
17
|
+
confirm_command(name) unless forced?
|
18
|
+
destroyer = destroyer(do_token)
|
19
|
+
destroyer.run!(name)
|
20
|
+
ensure
|
21
|
+
resume_warnings
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [String] token
|
25
|
+
def destroyer(token)
|
26
|
+
Kontena::Machine::DigitalOcean::MasterDestroyer.new(token)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
class Kontena::Plugin::DigitalOcean::MasterCommand < Kontena::Command
|
2
|
+
subcommand "create", "Create a new master to DigitalOcean", load_subcommand('kontena/plugin/digital_ocean/master/create_command')
|
3
|
+
subcommand "terminate", "Terminate DigitalOcean master", load_subcommand('kontena/plugin/digital_ocean/master/terminate_command')
|
4
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
class Kontena::Plugin::DigitalOcean::NodeCommand < Kontena::Command
|
2
|
+
subcommand "create", "Create a new node to DigitalOcean", load_subcommand('kontena/plugin/digital_ocean/nodes/create_command')
|
3
|
+
subcommand "restart", "Restart DigitalOcean node", load_subcommand('kontena/plugin/digital_ocean/nodes/restart_command')
|
4
|
+
subcommand "terminate", "Terminate DigitalOcean node", load_subcommand('kontena/plugin/digital_ocean/nodes/terminate_command')
|
5
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'kontena/plugin/digital_ocean/prompts'
|
2
|
+
|
3
|
+
module Kontena::Plugin::DigitalOcean::Nodes
|
4
|
+
class CreateCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Plugin::DigitalOcean::Prompts
|
8
|
+
|
9
|
+
parameter "[NAME]", "Node name"
|
10
|
+
option "--token", "TOKEN", "DigitalOcean API token", environment_variable: 'DO_TOKEN'
|
11
|
+
option "--region", "REGION", "Region"
|
12
|
+
option "--ssh-key", "SSH_KEY", "Path to ssh public key"
|
13
|
+
option "--size", "SIZE", "Droplet size"
|
14
|
+
option "--count", "COUNT", "How many droplets to create"
|
15
|
+
option "--version", "VERSION", "Define installed Kontena version", default: 'latest'
|
16
|
+
option "--channel", "CHANNEL", "Define CoreOS image channel"
|
17
|
+
|
18
|
+
def execute
|
19
|
+
suppress_warnings # until DO merges resource_kit pr #32
|
20
|
+
require 'kontena/machine/digital_ocean'
|
21
|
+
require_api_url
|
22
|
+
require_current_grid
|
23
|
+
|
24
|
+
do_token = ask_do_token
|
25
|
+
do_region = ask_droplet_region(do_token)
|
26
|
+
coreos_channel = self.channel || ask_channel
|
27
|
+
do_size = ask_droplet_size(do_token, do_region)
|
28
|
+
do_count = ask_droplet_count
|
29
|
+
do_ssh_key_id = ask_ssh_key(do_token)
|
30
|
+
|
31
|
+
grid = fetch_grid
|
32
|
+
provisioner = provisioner(client(require_token), do_token)
|
33
|
+
provisioner.run!(
|
34
|
+
master_uri: api_url,
|
35
|
+
grid_token: grid['token'],
|
36
|
+
grid: current_grid,
|
37
|
+
ssh_key_id: do_ssh_key_id,
|
38
|
+
name: name,
|
39
|
+
size: do_size,
|
40
|
+
count: do_count,
|
41
|
+
region: do_region,
|
42
|
+
version: version,
|
43
|
+
channel: coreos_channel
|
44
|
+
)
|
45
|
+
ensure
|
46
|
+
resume_warnings
|
47
|
+
end
|
48
|
+
|
49
|
+
def ask_droplet_count
|
50
|
+
if self.count.nil?
|
51
|
+
prompt.ask('How many droplets?:', default: 1)
|
52
|
+
else
|
53
|
+
self.count
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [Kontena::Client] client
|
58
|
+
# @param [String] token
|
59
|
+
def provisioner(client, token)
|
60
|
+
Kontena::Machine::DigitalOcean::NodeProvisioner.new(client, token)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Hash]
|
64
|
+
def fetch_grid
|
65
|
+
client(require_token).get("grids/#{current_grid}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'kontena/plugin/digital_ocean/prompts'
|
2
|
+
|
3
|
+
module Kontena::Plugin::DigitalOcean::Nodes
|
4
|
+
class RestartCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Plugin::DigitalOcean::Prompts
|
8
|
+
|
9
|
+
parameter "[NAME]", "Node name"
|
10
|
+
option "--token", "TOKEN", "DigitalOcean API token", environment_variable: "DO_TOKEN"
|
11
|
+
|
12
|
+
def execute
|
13
|
+
suppress_warnings # until DO merges resource_kit pr #32
|
14
|
+
require 'kontena/machine/digital_ocean'
|
15
|
+
require_api_url
|
16
|
+
require_current_grid
|
17
|
+
do_token = ask_do_token
|
18
|
+
|
19
|
+
node_name = ask_node(require_token)
|
20
|
+
client = DropletKit::Client.new(access_token: do_token)
|
21
|
+
droplet = client.droplets.all.find{|d| d.name == node_name}
|
22
|
+
if droplet
|
23
|
+
spinner "Restarting DigitalOcean droplet #{pastel.cyan(name)} " do
|
24
|
+
client.droplet_actions.reboot(droplet_id: droplet.id)
|
25
|
+
sleep 1 until client.droplets.find(id: droplet.id).status == 'active'
|
26
|
+
end
|
27
|
+
else
|
28
|
+
exit_with_error "Cannot find droplet #{pastel.cyan(name)} in DigitalOcean"
|
29
|
+
end
|
30
|
+
ensure
|
31
|
+
resume_warnings
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'kontena/plugin/digital_ocean/prompts'
|
2
|
+
|
3
|
+
module Kontena::Plugin::DigitalOcean::Nodes
|
4
|
+
class TerminateCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Plugin::DigitalOcean::Prompts
|
8
|
+
|
9
|
+
parameter "[NAME]", "Node name"
|
10
|
+
option "--token", "TOKEN", "DigitalOcean API token", environment_variable: "DO_TOKEN"
|
11
|
+
option "--force", :flag, "Force remove", default: false, attribute_name: :forced
|
12
|
+
|
13
|
+
def execute
|
14
|
+
suppress_warnings # until DO merges resource_kit pr #32
|
15
|
+
require 'kontena/machine/digital_ocean'
|
16
|
+
require_api_url
|
17
|
+
require_current_grid
|
18
|
+
token = require_token
|
19
|
+
node_name = ask_node(token)
|
20
|
+
do_token = ask_do_token
|
21
|
+
confirm_command(node_name) unless forced?
|
22
|
+
|
23
|
+
grid = client(require_token).get("grids/#{current_grid}")
|
24
|
+
destroyer = destroyer(client(token), do_token)
|
25
|
+
destroyer.run!(grid, node_name)
|
26
|
+
ensure
|
27
|
+
resume_warnings
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [Kontena::Client] client
|
31
|
+
# @param [String] token
|
32
|
+
def destroyer(client, token)
|
33
|
+
Kontena::Machine::DigitalOcean::NodeDestroyer.new(client, token)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Kontena::Plugin::DigitalOcean::Prompts
|
2
|
+
|
3
|
+
# Until DO merges https://github.com/digitalocean/resource_kit/pull/32
|
4
|
+
def suppress_warnings
|
5
|
+
@original_verbosity = $VERBOSE
|
6
|
+
$VERBOSE = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def resume_warnings
|
10
|
+
$VERBOSE = @original_verbosity
|
11
|
+
end
|
12
|
+
|
13
|
+
def ask_ssh_key(do_token)
|
14
|
+
manager = Kontena::Machine::DigitalOcean::SshKeyManager.new(do_token)
|
15
|
+
|
16
|
+
if self.ssh_key
|
17
|
+
public_key = File.read(self.ssh_key).strip
|
18
|
+
else
|
19
|
+
keys = manager.list
|
20
|
+
key = :new
|
21
|
+
|
22
|
+
default_path = File.join(Dir.home, '.ssh', 'id_rsa.pub')
|
23
|
+
default = File.exist?(default_path) ? File.read(default_path).strip : nil
|
24
|
+
|
25
|
+
unless keys.empty?
|
26
|
+
key = prompt.select("Choose SSH key:") do |menu|
|
27
|
+
i = 1
|
28
|
+
keys.each do |item|
|
29
|
+
menu.choice "#{item.name} (#{item.fingerprint})" , item
|
30
|
+
menu.default i if item.public_key == default
|
31
|
+
i += 1
|
32
|
+
end
|
33
|
+
menu.choice "Create new SSH key", :new
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if key == :new
|
38
|
+
|
39
|
+
public_key = prompt.ask('SSH public key: (enter an ssh key in OpenSSH format "ssh-xxx xxxxx key_name")', default: default) do |q|
|
40
|
+
q.validate /^ssh-rsa \S+ \S+$/
|
41
|
+
end
|
42
|
+
else
|
43
|
+
return key.id
|
44
|
+
end
|
45
|
+
end
|
46
|
+
manager.find_or_create_by_public_key(public_key).id
|
47
|
+
end
|
48
|
+
|
49
|
+
def ask_do_token
|
50
|
+
if self.token.nil?
|
51
|
+
prompt.mask('DigitalOcean API token:')
|
52
|
+
else
|
53
|
+
self.token
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def ask_droplet_region(do_token)
|
58
|
+
if self.region.nil?
|
59
|
+
prompt.select("Choose a datacenter region:") do |menu|
|
60
|
+
do_client = DropletKit::Client.new(access_token: do_token)
|
61
|
+
do_client.regions.all.sort_by{|r| r.slug }.each{ |region|
|
62
|
+
menu.choice region.name, region.slug
|
63
|
+
}
|
64
|
+
end
|
65
|
+
else
|
66
|
+
self.region
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def ask_droplet_size(do_token, do_region)
|
71
|
+
if self.size.nil?
|
72
|
+
prompt.select("Choose droplet size:") do |menu|
|
73
|
+
do_client = DropletKit::Client.new(access_token: do_token)
|
74
|
+
do_client.sizes.all.to_a.select{ |s| s.memory > 1000 }.sort_by{|s| s.memory }.each{ |size|
|
75
|
+
#p size
|
76
|
+
if size.regions.include?(do_region)
|
77
|
+
memory = size.memory.to_i / 1024
|
78
|
+
menu.choice "#{size.slug}: #{memory}GB/#{size.vcpus}CPU/#{size.disk}GB ($#{size.price_monthly.to_i}/mo)", size.slug
|
79
|
+
end
|
80
|
+
}
|
81
|
+
end
|
82
|
+
else
|
83
|
+
self.size
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def ask_node(token)
|
88
|
+
if self.name.nil?
|
89
|
+
nodes = client(token).get("grids/#{current_grid}/nodes")
|
90
|
+
nodes = nodes['nodes'].select{ |n|
|
91
|
+
n['labels'] && n['labels'].include?('provider=digitalocean'.freeze)
|
92
|
+
}
|
93
|
+
raise "Did not find any nodes with label provider=digitalocean" if nodes.size == 0
|
94
|
+
prompt.select("Select node:") do |menu|
|
95
|
+
nodes.sort_by{|n| n['node_number'] }.reverse.each do |node|
|
96
|
+
initial = node['initial_member'] ? '(initial) ' : ''
|
97
|
+
menu.choice "#{node['name']} #{initial}", node['name']
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else
|
101
|
+
self.name
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def ask_channel
|
106
|
+
prompt.select('Select Container Linux channel:') do |menu|
|
107
|
+
menu.choice 'Stable', 'stable'
|
108
|
+
menu.choice 'Beta', 'beta'
|
109
|
+
menu.choice 'Alpha', 'alpha'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
class Kontena::Plugin::DigitalOceanCommand < Kontena::Command
|
2
|
+
subcommand 'master', 'DigitalOcean master related commands', load_subcommand('kontena/plugin/digital_ocean/master_command')
|
3
|
+
subcommand 'node', 'DigitalOcean node related commands', load_subcommand('kontena/plugin/digital_ocean/node_command')
|
4
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: krates-plugin-digitalocean
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pavel Tsurbeleu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kontena-cli
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: droplet_kit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pastel
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.2
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.7.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.11'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
description: Krates DigitalOcean plugin
|
98
|
+
email:
|
99
|
+
- staticpagesio@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".gitmodules"
|
106
|
+
- ".rspec"
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- krates-plugin-digitalocean.gemspec
|
111
|
+
- lib/kontena/machine/digital_ocean.rb
|
112
|
+
- lib/kontena/machine/digital_ocean/cloudinit.yml
|
113
|
+
- lib/kontena/machine/digital_ocean/cloudinit_master.yml
|
114
|
+
- lib/kontena/machine/digital_ocean/master_destroyer.rb
|
115
|
+
- lib/kontena/machine/digital_ocean/master_provisioner.rb
|
116
|
+
- lib/kontena/machine/digital_ocean/node_destroyer.rb
|
117
|
+
- lib/kontena/machine/digital_ocean/node_provisioner.rb
|
118
|
+
- lib/kontena/machine/digital_ocean/ssh_key_manager.rb
|
119
|
+
- lib/kontena/plugin/digital_ocean.rb
|
120
|
+
- lib/kontena/plugin/digital_ocean/master/create_command.rb
|
121
|
+
- lib/kontena/plugin/digital_ocean/master/terminate_command.rb
|
122
|
+
- lib/kontena/plugin/digital_ocean/master_command.rb
|
123
|
+
- lib/kontena/plugin/digital_ocean/node_command.rb
|
124
|
+
- lib/kontena/plugin/digital_ocean/nodes/create_command.rb
|
125
|
+
- lib/kontena/plugin/digital_ocean/nodes/restart_command.rb
|
126
|
+
- lib/kontena/plugin/digital_ocean/nodes/terminate_command.rb
|
127
|
+
- lib/kontena/plugin/digital_ocean/prompts.rb
|
128
|
+
- lib/kontena/plugin/digital_ocean_command.rb
|
129
|
+
- lib/kontena_cli_plugin.rb
|
130
|
+
homepage: https://krates.appsters.io
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubygems_version: 3.0.4
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Krates DigitalOcean plugin
|
153
|
+
test_files: []
|