kontena-cli 0.13.4 → 0.14.0

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/kontena-cli.gemspec +2 -0
  4. data/lib/kontena/cli/app_command.rb +2 -0
  5. data/lib/kontena/cli/apps/common.rb +80 -74
  6. data/lib/kontena/cli/apps/config_command.rb +29 -0
  7. data/lib/kontena/cli/apps/deploy_command.rb +12 -81
  8. data/lib/kontena/cli/apps/docker_helper.rb +3 -3
  9. data/lib/kontena/cli/apps/init_command.rb +0 -3
  10. data/lib/kontena/cli/apps/list_command.rb +2 -3
  11. data/lib/kontena/cli/apps/logs_command.rb +2 -3
  12. data/lib/kontena/cli/apps/monitor_command.rb +3 -4
  13. data/lib/kontena/cli/apps/remove_command.rb +4 -4
  14. data/lib/kontena/cli/apps/restart_command.rb +2 -3
  15. data/lib/kontena/cli/apps/scale_command.rb +3 -5
  16. data/lib/kontena/cli/apps/service_generator.rb +123 -0
  17. data/lib/kontena/cli/apps/service_generator_v2.rb +26 -0
  18. data/lib/kontena/cli/apps/show_command.rb +1 -2
  19. data/lib/kontena/cli/apps/start_command.rb +2 -3
  20. data/lib/kontena/cli/apps/stop_command.rb +2 -3
  21. data/lib/kontena/cli/apps/yaml/reader.rb +150 -0
  22. data/lib/kontena/cli/apps/yaml/service_extender.rb +60 -0
  23. data/lib/kontena/cli/apps/yaml/validations.rb +79 -0
  24. data/lib/kontena/cli/apps/yaml/validator.rb +55 -0
  25. data/lib/kontena/cli/apps/yaml/validator_v2.rb +74 -0
  26. data/lib/kontena/cli/common.rb +23 -0
  27. data/lib/kontena/cli/etcd/remove_command.rb +2 -0
  28. data/lib/kontena/cli/grids/remove_command.rb +2 -0
  29. data/lib/kontena/cli/grids/users/remove_command.rb +3 -0
  30. data/lib/kontena/cli/master/azure/create_command.rb +0 -2
  31. data/lib/kontena/cli/master/packet/create_command.rb +42 -0
  32. data/lib/kontena/cli/master/packet_command.rb +14 -0
  33. data/lib/kontena/cli/master/upcloud/create_command.rb +39 -0
  34. data/lib/kontena/cli/master/upcloud_command.rb +13 -0
  35. data/lib/kontena/cli/master/users/remove_command.rb +3 -0
  36. data/lib/kontena/cli/master/users/roles/remove_command.rb +2 -0
  37. data/lib/kontena/cli/master_command.rb +4 -0
  38. data/lib/kontena/cli/node_command.rb +4 -0
  39. data/lib/kontena/cli/nodes/azure/create_command.rb +0 -2
  40. data/lib/kontena/cli/nodes/list_command.rb +4 -8
  41. data/lib/kontena/cli/nodes/packet/create_command.rb +35 -0
  42. data/lib/kontena/cli/nodes/packet/restart_command.rb +17 -0
  43. data/lib/kontena/cli/nodes/packet/terminate_command.rb +20 -0
  44. data/lib/kontena/cli/nodes/packet_command.rb +15 -0
  45. data/lib/kontena/cli/nodes/remove_command.rb +2 -0
  46. data/lib/kontena/cli/nodes/show_command.rb +3 -1
  47. data/lib/kontena/cli/nodes/upcloud/create_command.rb +33 -0
  48. data/lib/kontena/cli/nodes/upcloud/restart_command.rb +20 -0
  49. data/lib/kontena/cli/nodes/upcloud/terminate_command.rb +20 -0
  50. data/lib/kontena/cli/nodes/upcloud_command.rb +15 -0
  51. data/lib/kontena/cli/registry/remove_command.rb +3 -0
  52. data/lib/kontena/cli/services/remove_command.rb +2 -0
  53. data/lib/kontena/cli/services/services_helper.rb +1 -0
  54. data/lib/kontena/cli/vault/list_command.rb +2 -0
  55. data/lib/kontena/cli/vault/read_command.rb +2 -0
  56. data/lib/kontena/cli/vault/remove_command.rb +4 -0
  57. data/lib/kontena/cli/vault/update_command.rb +8 -1
  58. data/lib/kontena/cli/vault/write_command.rb +2 -0
  59. data/lib/kontena/cli/vpn/remove_command.rb +3 -0
  60. data/lib/kontena/machine/azure/master_provisioner.rb +2 -2
  61. data/lib/kontena/machine/azure/node_provisioner.rb +7 -4
  62. data/lib/kontena/machine/digital_ocean/node_provisioner.rb +1 -1
  63. data/lib/kontena/machine/packet.rb +17 -0
  64. data/lib/kontena/machine/packet/cloudinit.yml +66 -0
  65. data/lib/kontena/machine/packet/cloudinit_master.yml +118 -0
  66. data/lib/kontena/machine/packet/master_provisioner.rb +93 -0
  67. data/lib/kontena/machine/packet/node_destroyer.rb +42 -0
  68. data/lib/kontena/machine/packet/node_provisioner.rb +77 -0
  69. data/lib/kontena/machine/packet/node_restarter.rb +41 -0
  70. data/lib/kontena/machine/packet/packet_common.rb +89 -0
  71. data/lib/kontena/machine/upcloud.rb +9 -0
  72. data/lib/kontena/machine/upcloud/cloudinit.yml +64 -0
  73. data/lib/kontena/machine/upcloud/cloudinit_master.yml +118 -0
  74. data/lib/kontena/machine/upcloud/master_provisioner.rb +136 -0
  75. data/lib/kontena/machine/upcloud/node_destroyer.rb +82 -0
  76. data/lib/kontena/machine/upcloud/node_provisioner.rb +119 -0
  77. data/lib/kontena/machine/upcloud/node_restarter.rb +47 -0
  78. data/lib/kontena/machine/upcloud/upcloud_common.rb +70 -0
  79. data/lib/kontena/scripts/completer +8 -3
  80. data/spec/fixtures/docker-compose_v2.yml +10 -0
  81. data/spec/fixtures/kontena-invalid.yml +4 -0
  82. data/spec/fixtures/kontena-with-variables.yml +19 -0
  83. data/spec/fixtures/kontena.yml +2 -2
  84. data/spec/fixtures/kontena_v2.yml +35 -0
  85. data/spec/kontena/cli/app/common_spec.rb +39 -101
  86. data/spec/kontena/cli/app/deploy_command_spec.rb +37 -388
  87. data/spec/kontena/cli/app/docker_helper_spec.rb +4 -4
  88. data/spec/kontena/cli/app/service_generator_spec.rb +374 -0
  89. data/spec/kontena/cli/app/service_generator_v2_spec.rb +74 -0
  90. data/spec/kontena/cli/app/yaml/reader_spec.rb +249 -0
  91. data/spec/kontena/cli/app/yaml/service_extender_spec.rb +104 -0
  92. data/spec/kontena/cli/app/yaml/validator_spec.rb +263 -0
  93. data/spec/kontena/cli/app/yaml/validator_v2_spec.rb +309 -0
  94. data/spec/kontena/cli/common_spec.rb +39 -1
  95. data/spec/kontena/cli/master/users/remove_command_spec.rb +9 -0
  96. data/spec/kontena/cli/master/users/roles/remove_command_spec.rb +2 -0
  97. metadata +86 -2
@@ -0,0 +1,41 @@
1
+ require 'shell-spinner'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module Packet
6
+ class NodeRestarter
7
+ include RandomName
8
+ include PacketCommon
9
+
10
+ attr_reader :client
11
+
12
+ # @param [String] token Packet api token
13
+ def initialize(token)
14
+ @client = login(token)
15
+ end
16
+
17
+ # @param [String] project_id Packet project id
18
+ # @param [String] token Node hostname
19
+ def run!(project_id, name)
20
+ device = client.list_devices(project_id).find{|d| d.hostname == name}
21
+ abort("Device #{name.colorize(:cyan)} not found in Packet") unless device
22
+ abort("Your version of 'packethost' gem does not support rebooting servers") unless client.respond_to?(:reboot_device)
23
+
24
+ ShellSpinner "Restarting Packet device #{device.hostname.colorize(:cyan)} " do
25
+ begin
26
+ response = client.reboot_device(device)
27
+ raise unless response.success?
28
+ rescue
29
+ abort "Cannot delete device #{name.colorize(:cyan)} in Packet"
30
+ end
31
+ sleep 5
32
+ until device && device.state == :active
33
+ device = find_device(project.id, device.hostname) rescue nil
34
+ sleep 5
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,89 @@
1
+ require 'erb'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module Packet
6
+ module PacketCommon
7
+ # @param [String] token Packet token
8
+ def login(token)
9
+ ::Packet::Client.new(token)
10
+ end
11
+
12
+ def create_ssh_key(ssh_key)
13
+ client.create_ssh_key(ssh_key_label(ssh_key))
14
+ end
15
+
16
+ def ssh_key_exist?(ssh_key)
17
+ client.list_ssh_keys.any?{|key| key.key == ssh_key}
18
+ end
19
+
20
+ def ssh_key_label(ssh_key)
21
+ label = ssh_key[/^ssh.+?\s+\S+\s+(.*)$/, 1].to_s.strip
22
+ label.empty? ? "kontena-ssh-key-#{rand(1..9)}" : label
23
+ end
24
+
25
+ # @param [String] keyfile_path Path to ssh keyfile
26
+ def check_or_create_ssh_key(keyfile_path)
27
+ abort('Ssh key file not found') unless File.exist?(keyfile_path)
28
+ abort('Ssh key file not readable') unless File.readable?(keyfile_path)
29
+ ssh_key = File.read(keyfile_path).strip
30
+ create_ssh_key(ssh_key) unless ssh_key_exist?(ssh_key)
31
+ end
32
+
33
+ def find_project(project_id)
34
+ client.list_projects.find{|project| project.id == project_id}
35
+ end
36
+
37
+ def find_device(project_id, device_hostname)
38
+ client.list_devices(project_id).find{|device| device.hostname == device_hostname}
39
+ end
40
+
41
+ def find_facility(facility_code)
42
+ client.list_facilities.find{|f| f.code == facility_code}
43
+ end
44
+
45
+ def find_os(os_code)
46
+ client.list_operating_systems.find{|os| os.slug == os_code}
47
+ end
48
+
49
+ def find_plan(plan_code)
50
+ client.list_plans.find{|plan| plan.slug == plan_code}
51
+ end
52
+
53
+ def device_public_ip(device)
54
+ api_retry "Packet API did not find a public ip address for the device" do
55
+ device.ip_addresses.find{|ip| ip['public'] && ip['address_family'] == 4}
56
+ end
57
+ end
58
+
59
+ # Retry API requests to recover from random tls errors
60
+ # @param [String] message Message to output when giving up
61
+ # @param [Fixnum] times Default: 5
62
+ def api_retry(message, times=5, &block)
63
+ attempt = 1
64
+ begin
65
+ yield
66
+ rescue => error
67
+ ENV['DEBUG'] && puts("Packet API error: #{error}: #{error.message} - attempt #{attempt}")
68
+ attempt += 1
69
+ if attempt < times
70
+ sleep 5 and retry
71
+ else
72
+ abort(message)
73
+ end
74
+ end
75
+ end
76
+
77
+ def user_data(vars, template_filename)
78
+ cloudinit_template = File.join(__dir__ , template_filename)
79
+ erb(File.read(cloudinit_template), vars)
80
+ end
81
+
82
+ def erb(template, vars)
83
+ ERB.new(template, nil, '%<>-').result(OpenStruct.new(vars).instance_eval { binding })
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
@@ -0,0 +1,9 @@
1
+ require 'excon'
2
+
3
+ require_relative 'random_name'
4
+ require_relative 'cert_helper'
5
+ require_relative 'upcloud/upcloud_common'
6
+ require_relative 'upcloud/node_provisioner'
7
+ require_relative 'upcloud/node_destroyer'
8
+ require_relative 'upcloud/node_restarter'
9
+ require_relative 'upcloud/master_provisioner'
@@ -0,0 +1,64 @@
1
+ #cloud-config
2
+ write_files:
3
+ - path: /etc/kontena-agent.env
4
+ permissions: 0600
5
+ owner: root
6
+ content: |
7
+ KONTENA_URI="<%= master_uri %>"
8
+ KONTENA_TOKEN="<%= grid_token %>"
9
+ KONTENA_PEER_INTERFACE=eth1
10
+ KONTENA_VERSION=<%= version %>
11
+ - path: /etc/systemd/system/docker.service.d/50-kontena.conf
12
+ content: |
13
+ [Service]
14
+ Environment='DOCKER_OPTS=--insecure-registry="10.81.0.0/19" --bip="172.17.43.1/16"'
15
+ - path: /etc/sysctl.d/99-inotify.conf
16
+ owner: root
17
+ permissions: 0644
18
+ content: |
19
+ fs.inotify.max_user_instances = 8192
20
+ - path: /etc/resolv.conf
21
+ permissions: 0644
22
+ owner: root
23
+ content: |
24
+ nameserver 172.17.43.1
25
+ nameserver 8.8.8.8
26
+ nameserver 8.8.4.4
27
+ coreos:
28
+ units:
29
+ - name: 10-weave.network
30
+ runtime: false
31
+ content: |
32
+ [Match]
33
+ Type=bridge
34
+ Name=weave*
35
+
36
+ [Network]
37
+ - name: kontena-agent.service
38
+ command: start
39
+ enable: true
40
+ content: |
41
+ [Unit]
42
+ Description=kontena-agent
43
+ After=network-online.target
44
+ After=docker.service
45
+ Description=Kontena Agent
46
+ Documentation=http://www.kontena.io/
47
+ Requires=network-online.target
48
+ Requires=docker.service
49
+
50
+ [Service]
51
+ Restart=always
52
+ RestartSec=5
53
+ EnvironmentFile=/etc/kontena-agent.env
54
+ ExecStartPre=-/usr/bin/docker stop kontena-agent
55
+ ExecStartPre=-/usr/bin/docker rm kontena-agent
56
+ ExecStartPre=/usr/bin/docker pull kontena/agent:${KONTENA_VERSION}
57
+ ExecStart=/usr/bin/docker run --name kontena-agent \
58
+ -e KONTENA_URI=${KONTENA_URI} \
59
+ -e KONTENA_TOKEN=${KONTENA_TOKEN} \
60
+ -e KONTENA_PEER_INTERFACE=${KONTENA_PEER_INTERFACE} \
61
+ -v=/var/run/docker.sock:/var/run/docker.sock \
62
+ -v=/etc/kontena-agent.env:/etc/kontena.env \
63
+ --net=host \
64
+ kontena/agent:${KONTENA_VERSION}
@@ -0,0 +1,118 @@
1
+ #cloud-config
2
+ write_files:
3
+ - path: /etc/kontena-server.env
4
+ permissions: 0600
5
+ owner: root
6
+ content: |
7
+ KONTENA_VERSION=<%= version %>
8
+ KONTENA_VAULT_KEY=<%= vault_secret %>
9
+ KONTENA_VAULT_IV=<%= vault_iv %>
10
+ <% if ssl_cert %>SSL_CERT="/etc/kontena-server.pem"
11
+
12
+ - path: /etc/kontena-server.pem
13
+ permissions: 0600
14
+ owner: root
15
+ content: | <% ssl_cert.split(/\n/).each do |row| %>
16
+ <%= row %><% end %><% end %>
17
+ - path: /opt/bin/kontena-haproxy.sh
18
+ permissions: 0755
19
+ owner: root
20
+ content: |
21
+ #!/bin/sh
22
+ if [ -n "$SSL_CERT" ]; then
23
+ SSL_CERT=$(awk 1 ORS='\\n' $SSL_CERT)
24
+ else
25
+ SSL_CERT="**None**"
26
+ fi
27
+ /usr/bin/docker run --name=kontena-server-haproxy \
28
+ --link kontena-server-api:kontena-server-api \
29
+ -e SSL_CERT="$SSL_CERT" \
30
+ -p 80:80 -p 443:443 kontena/haproxy:latest
31
+ coreos:
32
+ units:
33
+ <% unless mongodb_uri -%>
34
+ - name: kontena-server-mongo.service
35
+ command: start
36
+ enable: true
37
+ content: |
38
+ [Unit]
39
+ Description=kontena-server-mongo
40
+ After=network-online.target
41
+ After=docker.service
42
+ Description=Kontena Server MongoDB
43
+ Documentation=http://www.mongodb.org/
44
+ Requires=network-online.target
45
+ Requires=docker.service
46
+
47
+ [Service]
48
+ Restart=always
49
+ RestartSec=5
50
+ ExecStartPre=/usr/bin/docker pull mongo:3.0
51
+ ExecStartPre=-/usr/bin/docker create --name=kontena-server-mongo-data mongo:3.0
52
+ ExecStartPre=-/usr/bin/docker stop kontena-server-mongo
53
+ ExecStartPre=-/usr/bin/docker rm kontena-server-mongo
54
+ ExecStart=/usr/bin/docker run --name=kontena-server-mongo \
55
+ --volumes-from=kontena-server-mongo-data \
56
+ mongo:3.0 mongod --smallfiles
57
+ <% end -%>
58
+ - name: kontena-server-api.service
59
+ command: start
60
+ enable: true
61
+ content: |
62
+ [Unit]
63
+ Description=kontena-server-api
64
+ After=network-online.target
65
+ After=docker.service
66
+ After=kontena-server-mongo.service
67
+ Description=Kontena Master
68
+ Documentation=http://www.kontena.io/
69
+ Before=kontena-server-haproxy.service
70
+ Wants=kontena-server-haproxy.service
71
+ Requires=network-online.target
72
+ Requires=docker.service
73
+ <% unless mongodb_uri -%>
74
+ Requires=kontena-server-mongo.service
75
+ <% end %>
76
+
77
+ [Service]
78
+ Restart=always
79
+ RestartSec=5
80
+ EnvironmentFile=/etc/kontena-server.env
81
+ ExecStartPre=-/usr/bin/docker stop kontena-server-api
82
+ ExecStartPre=-/usr/bin/docker rm kontena-server-api
83
+ ExecStartPre=/usr/bin/docker pull kontena/server:${KONTENA_VERSION}
84
+ ExecStart=/usr/bin/docker run --name kontena-server-api \
85
+ <% if mongodb_uri -%>
86
+ -e MONGODB_URI=<%= mongodb_uri %> \
87
+ <% else -%>
88
+ --link kontena-server-mongo:mongodb \
89
+ -e MONGODB_URI=mongodb://mongodb:27017/kontena_server \
90
+ <% end -%>
91
+ <% if auth_server %>
92
+ -e AUTH_API_URL=<%= auth_server %> \
93
+ <% end -%>
94
+ -e VAULT_KEY=${KONTENA_VAULT_KEY} -e VAULT_IV=${KONTENA_VAULT_IV} \
95
+ kontena/server:${KONTENA_VERSION}
96
+
97
+ - name: kontena-server-haproxy.service
98
+ command: start
99
+ enable: true
100
+ content: |
101
+ [Unit]
102
+ Description=kontena-server-haproxy
103
+ After=network-online.target
104
+ After=docker.service
105
+ Description=Kontena Server HAProxy
106
+ Documentation=http://www.kontena.io/
107
+ Requires=network-online.target
108
+ Requires=docker.service
109
+ Requires=kontena-server-api.service
110
+
111
+ [Service]
112
+ Restart=always
113
+ RestartSec=5
114
+ EnvironmentFile=/etc/kontena-server.env
115
+ ExecStartPre=-/usr/bin/docker stop kontena-server-haproxy
116
+ ExecStartPre=-/usr/bin/docker rm kontena-server-haproxy
117
+ ExecStartPre=/usr/bin/docker pull kontena/haproxy:latest
118
+ ExecStart=/opt/bin/kontena-haproxy.sh
@@ -0,0 +1,136 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+ require 'open3'
4
+ require 'shell-spinner'
5
+
6
+ module Kontena
7
+ module Machine
8
+ module Upcloud
9
+ class MasterProvisioner
10
+ include RandomName
11
+ include Machine::CertHelper
12
+ include UpcloudCommon
13
+
14
+ attr_reader :http_client, :username, :password
15
+
16
+ # @param [String] token Upcloud token
17
+ def initialize(upcloud_username, upcloud_password)
18
+ @username = upcloud_username
19
+ @password = upcloud_password
20
+ end
21
+
22
+ def run!(opts)
23
+ if File.readable?(File.expand_path(opts[:ssh_key]))
24
+ ssh_key = File.read(File.expand_path(opts[:ssh_key])).strip
25
+ end
26
+
27
+ abort('Invalid ssh key') unless ssh_key && ssh_key.start_with?('ssh-')
28
+
29
+ if opts[:ssl_cert]
30
+ abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
31
+ ssl_cert = File.read(File.expand_path(opts[:ssl_cert]))
32
+ else
33
+ ShellSpinner "Generating self-signed SSL certificate" do
34
+ ssl_cert = generate_self_signed_cert
35
+ end
36
+ end
37
+
38
+ abort('CoreOS template not found on Upcloud') unless coreos_template = find_template('CoreOS Stable')
39
+ abort('Server plan not found on Upcloud') unless plan = find_plan(opts[:plan])
40
+ abort('Zone not found on Upcloud') unless zone_exist?(opts[:zone])
41
+
42
+ hostname = generate_name
43
+
44
+ userdata_vars = {
45
+ ssl_cert: ssl_cert,
46
+ auth_server: opts[:auth_server],
47
+ version: opts[:version],
48
+ vault_secret: opts[:vault_secret],
49
+ vault_iv: opts[:vault_iv],
50
+ mongodb_uri: opts[:mongodb_uri]
51
+ }
52
+
53
+ device_data = {
54
+ server: {
55
+ zone: opts[:zone],
56
+ title: "Kontena Master #{hostname}",
57
+ hostname: hostname,
58
+ plan: plan[:name],
59
+ vnc: 'off',
60
+ timezone: 'UTC',
61
+ user_data: user_data(userdata_vars),
62
+ firewall: 'off',
63
+ storage_devices: {
64
+ storage_device: [
65
+ {
66
+ action: 'clone',
67
+ storage: coreos_template[:uuid],
68
+ title: "From template #{coreos_template[:title]}",
69
+ size: plan[:storage_size],
70
+ tier: 'maxiops'
71
+ }
72
+ ]
73
+ },
74
+ login_user: {
75
+ create_password: 'no',
76
+ username: 'root',
77
+ ssh_keys: {
78
+ ssh_key: [ssh_key]
79
+ }
80
+ }
81
+ }
82
+ }.to_json
83
+
84
+ ShellSpinner "Creating Upcloud master #{hostname.colorize(:cyan)} " do
85
+ response = post('server', body: device_data)
86
+ if response.has_key?(:error)
87
+ abort("\nUpcloud server creation failed (#{response[:error].fetch(:error_message, '')})")
88
+ end
89
+ device_data = response[:server]
90
+
91
+ until device_data && device_data.fetch(:state, nil).to_s == 'maintenance'
92
+ device_data = get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
93
+ sleep 5
94
+ end
95
+ end
96
+
97
+ device_public_ip = device_data[:ip_addresses][:ip_address].find do |ip|
98
+ ip[:access].eql?('public') && ip[:family].eql?('IPv4')
99
+ end
100
+
101
+ abort('Server public ip not found, destroy manually.') unless device_public_ip
102
+
103
+ master_url = "https://#{device_public_ip[:address]}"
104
+ Excon.defaults[:ssl_verify_peer] = false
105
+ @http_client = Excon.new("#{master_url}", :connect_timeout => 10)
106
+
107
+ ShellSpinner "Waiting for #{hostname.colorize(:cyan)} to start" do
108
+ sleep 5 until master_running?
109
+ end
110
+
111
+ puts "Kontena Master is now running at #{master_url}"
112
+ puts "Use #{"kontena login --name=#{hostname.sub('kontena-master-', '')} #{master_url}".colorize(:light_black)} to complete Kontena Master setup"
113
+ end
114
+
115
+ def user_data(vars)
116
+ cloudinit_template = File.join(__dir__ , '/cloudinit_master.yml')
117
+ erb(File.read(cloudinit_template), vars)
118
+ end
119
+
120
+ def generate_name
121
+ "kontena-master-#{super}-#{rand(1..9)}"
122
+ end
123
+
124
+ def master_running?
125
+ http_client.get(path: '/').status == 200
126
+ rescue
127
+ false
128
+ end
129
+
130
+ def erb(template, vars)
131
+ ERB.new(template, nil, '%<>-').result(OpenStruct.new(vars).instance_eval { binding })
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end