kontena-cli 0.8.4 → 0.9.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/kontena +4 -0
  4. data/lib/kontena/cli/app_command.rb +2 -0
  5. data/lib/kontena/cli/apps/build_command.rb +26 -0
  6. data/lib/kontena/cli/apps/common.rb +41 -12
  7. data/lib/kontena/cli/apps/deploy_command.rb +31 -13
  8. data/lib/kontena/cli/apps/docker_helper.rb +34 -0
  9. data/lib/kontena/cli/apps/init_command.rb +130 -10
  10. data/lib/kontena/cli/apps/list_command.rb +4 -2
  11. data/lib/kontena/cli/apps/logs_command.rb +4 -2
  12. data/lib/kontena/cli/apps/remove_command.rb +4 -2
  13. data/lib/kontena/cli/apps/start_command.rb +4 -2
  14. data/lib/kontena/cli/apps/stop_command.rb +4 -2
  15. data/lib/kontena/cli/common.rb +3 -3
  16. data/lib/kontena/cli/container_command.rb +3 -0
  17. data/lib/kontena/cli/containers/inspect_command.rb +16 -0
  18. data/lib/kontena/cli/deploy_command.rb +3 -0
  19. data/lib/kontena/cli/etcd/get_command.rb +21 -0
  20. data/lib/kontena/cli/etcd/list_command.rb +26 -0
  21. data/lib/kontena/cli/etcd/mkdir_command.rb +17 -0
  22. data/lib/kontena/cli/etcd/remove_command.rb +21 -0
  23. data/lib/kontena/cli/etcd/set_command.rb +18 -0
  24. data/lib/kontena/cli/etcd_command.rb +17 -0
  25. data/lib/kontena/cli/grid_command.rb +2 -0
  26. data/lib/kontena/cli/grids/logs_command.rb +71 -0
  27. data/lib/kontena/cli/master/aws/create_command.rb +33 -0
  28. data/lib/kontena/cli/master/aws_command.rb +8 -0
  29. data/lib/kontena/cli/master/azure/create_command.rb +33 -0
  30. data/lib/kontena/cli/master/azure_command.rb +13 -0
  31. data/lib/kontena/cli/master/digital_ocean/create_command.rb +30 -0
  32. data/lib/kontena/cli/master/digital_ocean_command.rb +13 -0
  33. data/lib/kontena/cli/master/vagrant/create_command.rb +19 -0
  34. data/lib/kontena/cli/master/vagrant/restart_command.rb +20 -0
  35. data/lib/kontena/cli/master/vagrant/ssh_command.rb +15 -0
  36. data/lib/kontena/cli/master/vagrant/start_command.rb +20 -0
  37. data/lib/kontena/cli/master/vagrant/stop_command.rb +20 -0
  38. data/lib/kontena/cli/master/vagrant/terminate_command.rb +13 -0
  39. data/lib/kontena/cli/master/vagrant_command.rb +23 -0
  40. data/lib/kontena/cli/master_command.rb +15 -0
  41. data/lib/kontena/cli/node_command.rb +4 -0
  42. data/lib/kontena/cli/nodes/aws/create_command.rb +39 -0
  43. data/lib/kontena/cli/nodes/aws/restart_command.rb +28 -0
  44. data/lib/kontena/cli/nodes/aws/terminate_command.rb +20 -0
  45. data/lib/kontena/cli/nodes/aws_command.rb +15 -0
  46. data/lib/kontena/cli/nodes/azure/create_command.rb +39 -0
  47. data/lib/kontena/cli/nodes/azure/restart_command.rb +31 -0
  48. data/lib/kontena/cli/nodes/azure/terminate_command.rb +20 -0
  49. data/lib/kontena/cli/nodes/azure_command.rb +15 -0
  50. data/lib/kontena/cli/nodes/digital_ocean/create_command.rb +1 -1
  51. data/lib/kontena/cli/nodes/vagrant/create_command.rb +1 -1
  52. data/lib/kontena/cli/service_command.rb +4 -0
  53. data/lib/kontena/cli/services/add_env_command.rb +18 -0
  54. data/lib/kontena/cli/services/create_command.rb +8 -0
  55. data/lib/kontena/cli/services/remove_env_command.rb +17 -0
  56. data/lib/kontena/cli/services/services_helper.rb +20 -1
  57. data/lib/kontena/cli/services/update_command.rb +10 -0
  58. data/lib/kontena/client.rb +22 -1
  59. data/lib/kontena/machine/aws.rb +13 -0
  60. data/lib/kontena/machine/aws/cloudinit.yml +66 -0
  61. data/lib/kontena/machine/aws/cloudinit_master.yml +105 -0
  62. data/lib/kontena/machine/aws/master_provisioner.rb +161 -0
  63. data/lib/kontena/machine/aws/node_destroyer.rb +39 -0
  64. data/lib/kontena/machine/aws/node_provisioner.rb +168 -0
  65. data/lib/kontena/machine/azure.rb +13 -0
  66. data/lib/kontena/machine/azure/cloudinit.yml +59 -0
  67. data/lib/kontena/machine/azure/cloudinit_master.yml +105 -0
  68. data/lib/kontena/machine/azure/logger.rb +27 -0
  69. data/lib/kontena/machine/azure/master_provisioner.rb +126 -0
  70. data/lib/kontena/machine/azure/node_destroyer.rb +53 -0
  71. data/lib/kontena/machine/azure/node_provisioner.rb +128 -0
  72. data/lib/kontena/machine/digital_ocean.rb +1 -0
  73. data/lib/kontena/machine/digital_ocean/cloudinit.yml +1 -0
  74. data/lib/kontena/machine/digital_ocean/cloudinit_master.yml +105 -0
  75. data/lib/kontena/machine/digital_ocean/master_provisioner.rb +94 -0
  76. data/lib/kontena/machine/digital_ocean/node_provisioner.rb +8 -1
  77. data/lib/kontena/machine/vagrant.rb +2 -0
  78. data/lib/kontena/machine/vagrant/Vagrantfile.master.rb.erb +101 -0
  79. data/lib/kontena/machine/vagrant/{Vagrantfile.coreos.rb.erb → Vagrantfile.node.rb.erb} +0 -0
  80. data/lib/kontena/machine/vagrant/cloudinit.yml +2 -1
  81. data/lib/kontena/machine/vagrant/master_destroyer.rb +37 -0
  82. data/lib/kontena/machine/vagrant/master_provisioner.rb +75 -0
  83. data/lib/kontena/machine/vagrant/node_destroyer.rb +4 -0
  84. data/lib/kontena/machine/vagrant/node_provisioner.rb +1 -1
  85. data/lib/kontena/scripts/completer +29 -3
  86. data/spec/kontena/cli/app/common_spec.rb +61 -0
  87. data/spec/kontena/cli/app/deploy_command_spec.rb +25 -6
  88. data/spec/kontena/cli/app/docker_helper_spec.rb +32 -0
  89. data/spec/kontena/cli/common_spec.rb +53 -0
  90. metadata +61 -3
@@ -0,0 +1,39 @@
1
+ require 'shell-spinner'
2
+
3
+ module Kontena
4
+ module Machine
5
+ module Aws
6
+ class NodeDestroyer
7
+
8
+ attr_reader :client, :api_client
9
+
10
+ # @param [Kontena::Client] api_client Kontena api client
11
+ # @param [String] access_key_id aws_access_key_id
12
+ # @param [String] secret_key aws_secret_access_key
13
+ # @param [String] region
14
+ def initialize(api_client, access_key_id, secret_key, region = 'eu-west-1')
15
+ @api_client = api_client
16
+ @client = Fog::Compute.new(:provider => 'AWS', :aws_access_key_id => access_key_id, :aws_secret_access_key => secret_key, :region => region)
17
+ end
18
+
19
+ def run!(grid, name)
20
+ instance = client.servers.all({'tag:kontena_name' => name}).first
21
+ if instance
22
+ ShellSpinner "Terminating AWS instance #{name.colorize(:cyan)} " do
23
+ instance.destroy
24
+ sleep 2 until client.servers.get(instance.id).state == 'terminated'
25
+ end
26
+ else
27
+ abort "Cannot find instance #{name.colorize(:cyan)} in AWS"
28
+ end
29
+ node = api_client.get("grids/#{grid['id']}/nodes")['nodes'].find{|n| n['name'] == name}
30
+ if node
31
+ ShellSpinner "Removing node #{name.colorize(:cyan)} from grid #{grid['name'].colorize(:cyan)} " do
32
+ api_client.delete("grids/#{grid['id']}/nodes/#{name}")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,168 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+ require 'open3'
4
+ require 'shell-spinner'
5
+
6
+ module Kontena
7
+ module Machine
8
+ module Aws
9
+ class NodeProvisioner
10
+ include RandomName
11
+
12
+ attr_reader :client, :api_client, :region
13
+
14
+ # @param [Kontena::Client] api_client Kontena api client
15
+ # @param [String] access_key_id aws_access_key_id
16
+ # @param [String] secret_key aws_secret_access_key
17
+ # @param [String] region
18
+ def initialize(api_client, access_key_id, secret_key, region)
19
+ @api_client = api_client
20
+ @client = Fog::Compute.new(:provider => 'AWS', :aws_access_key_id => access_key_id, :aws_secret_access_key => secret_key, :region => region)
21
+
22
+ end
23
+
24
+ # @param [Hash] opts
25
+ def run!(opts)
26
+ ami = resolve_ami(client.region)
27
+ abort('No valid AMI found for region') unless ami
28
+
29
+ security_group = ensure_security_group(opts[:grid], opts[:vpc])
30
+ name = opts[:name ] || generate_name
31
+
32
+ opts[:vpc] = default_vpc.id unless opts[:vpc]
33
+ if opts[:subnet].nil?
34
+ subnet = default_subnet(opts[:vpc], client.region+opts[:zone])
35
+ opts[:subnet] = subnet.subnet_id
36
+ else
37
+ subnet = client.subnets.get(opts[:subnet])
38
+ end
39
+ dns_server = aws_dns_supported?(opts[:vpc]) ? '169.254.169.253' : '8.8.8.8'
40
+ userdata_vars = {
41
+ name: name,
42
+ version: opts[:version],
43
+ master_uri: opts[:master_uri],
44
+ grid_token: opts[:grid_token],
45
+ dns_server: dns_server
46
+ }
47
+
48
+ response = client.run_instances(
49
+ ami,
50
+ 1,
51
+ 1,
52
+ 'InstanceType' => opts[:type],
53
+ 'SecurityGroupId' => security_group.group_id,
54
+ 'KeyName' => opts[:key_pair],
55
+ 'SubnetId' => opts[:subnet],
56
+ 'UserData' => user_data(userdata_vars),
57
+ 'BlockDeviceMapping' => [
58
+ {
59
+ 'DeviceName' => '/dev/xvda',
60
+ 'VirtualName' => 'Root',
61
+ 'Ebs.VolumeSize' => opts[:storage],
62
+ 'Ebs.VolumeType' => 'gp2'
63
+ }
64
+ ]
65
+
66
+ )
67
+ instance_id = response.body['instancesSet'].first['instanceId']
68
+
69
+ instance = client.servers.get(instance_id)
70
+ ShellSpinner "Creating AWS instance #{name.colorize(:cyan)} " do
71
+ instance.wait_for { ready? }
72
+ end
73
+ client.create_tags(instance.id, {'kontena_name' => name, 'kontena_grid' => opts[:grid]})
74
+ node = nil
75
+ ShellSpinner "Waiting for node #{name.colorize(:cyan)} join to grid #{opts[:grid].colorize(:cyan)} " do
76
+ sleep 2 until node = instance_exists_in_grid?(opts[:grid], name)
77
+ end
78
+ labels = ["region=#{client.region}", "az=#{opts[:zone]}"]
79
+ set_labels(node, labels)
80
+ end
81
+
82
+ ##
83
+ # @param [String] grid
84
+ # @return Fog::Compute::AWS::SecurityGroup
85
+ def ensure_security_group(grid, vpc_id)
86
+ group_name = "kontena_grid_#{grid}"
87
+ if vpc_id
88
+ client.security_groups.all({'group-name' => group_name, 'vpc-id' => vpc_id}).first || create_security_group(group_name, vpc_id)
89
+ else
90
+ client.security_groups.get(group_name) || create_security_group(group_name)
91
+ end
92
+ end
93
+
94
+ ##
95
+ # creates security_group and authorizes default port ranges
96
+ #
97
+ # @param [String] name
98
+ # @return Fog::Compute::AWS::SecurityGroup
99
+ def create_security_group(name, vpc_id = nil)
100
+ security_group = client.security_groups.new(:name => name, :description => "Kontena Node", :vpc_id => vpc_id)
101
+ security_group.save
102
+
103
+ security_group.authorize_port_range(80..80)
104
+ security_group.authorize_port_range(443..443)
105
+ security_group.authorize_port_range(22..22)
106
+ security_group.authorize_port_range(6783..6783, group: {security_group.owner_id => security_group.group_id}, ip_protocol: 'tcp')
107
+ security_group.authorize_port_range(6783..6783, group: {security_group.owner_id => security_group.group_id}, ip_protocol: 'udp')
108
+ security_group
109
+ end
110
+
111
+
112
+ # @param [String] region
113
+ # @return String
114
+ def resolve_ami(region)
115
+ images = {
116
+ 'eu-central-1' => 'ami-74bbba69',
117
+ 'ap-northeast-1' => 'ami-1e77ff1e',
118
+ 'us-gov-west-1' => 'ami-f1d1b2d2',
119
+ 'sa-east-1' => 'ami-632ba17e',
120
+ 'ap-southeast-2' => 'ami-83f8b4b9',
121
+ 'ap-southeast-1' => 'ami-12060c40',
122
+ 'us-east-1' => 'ami-f396fa96',
123
+ 'us-west-2' => 'ami-99bfada9',
124
+ 'us-west-1' => 'ami-dbe71d9f',
125
+ 'eu-west-1' => 'ami-83e9c8f4'
126
+ }
127
+ images[region]
128
+ end
129
+
130
+ def default_subnet(vpc, zone)
131
+ client.subnets.all('vpc-id' => vpc, 'availabilityZone' => zone).first
132
+ end
133
+
134
+ def default_vpc
135
+ client.vpcs.all('isDefault' => true).first
136
+ end
137
+
138
+ def user_data(vars)
139
+ cloudinit_template = File.join(__dir__ , '/cloudinit.yml')
140
+ erb(File.read(cloudinit_template), vars)
141
+ end
142
+
143
+ def generate_name
144
+ "#{super}-#{rand(1..99)}"
145
+ end
146
+
147
+ def instance_exists_in_grid?(grid, name)
148
+ api_client.get("grids/#{grid}/nodes")['nodes'].find{|n| n['name'] == name}
149
+ end
150
+
151
+ def erb(template, vars)
152
+ ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
153
+ end
154
+
155
+ def set_labels(node, labels)
156
+ data = {}
157
+ data[:labels] = labels
158
+ api_client.put("nodes/#{node['id']}", data, {}, {'Kontena-Grid-Token' => node['grid']['token']})
159
+ end
160
+
161
+ def aws_dns_supported?(vpc_id)
162
+ response = client.describe_vpc_attribute(vpc_id,'enableDnsSupport')
163
+ response.data[:body]['enableDnsSupport']
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,13 @@
1
+ begin
2
+ require "azure"
3
+ rescue LoadError
4
+ puts "It seems that you don't have Azure SDK installed."
5
+ puts "Install it using: gem install azure:0.7.0"
6
+ exit 1
7
+ end
8
+
9
+ require_relative 'random_name'
10
+ require_relative 'azure/logger'
11
+ require_relative 'azure/node_provisioner'
12
+ require_relative 'azure/node_destroyer'
13
+ require_relative 'azure/master_provisioner'
@@ -0,0 +1,59 @@
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.42.1/16"'
15
+ - path: /etc/resolv.conf
16
+ permissions: 0644
17
+ owner: root
18
+ content: |
19
+ nameserver 172.17.42.1
20
+ nameserver 8.8.8.8
21
+ nameserver 8.8.4.4
22
+ coreos:
23
+ units:
24
+ - name: 10-weave.network
25
+ runtime: false
26
+ content: |
27
+ [Match]
28
+ Type=bridge
29
+ Name=weave*
30
+
31
+ [Network]
32
+ - name: kontena-agent.service
33
+ command: start
34
+ enable: true
35
+ content: |
36
+ [Unit]
37
+ Description=kontena-agent
38
+ After=network-online.target
39
+ After=docker.service
40
+ Description=Kontena Agent
41
+ Documentation=http://www.kontena.io/
42
+ Requires=network-online.target
43
+ Requires=docker.service
44
+
45
+ [Service]
46
+ Restart=always
47
+ RestartSec=5
48
+ EnvironmentFile=/etc/kontena-agent.env
49
+ ExecStartPre=-/usr/bin/docker stop kontena-agent
50
+ ExecStartPre=-/usr/bin/docker rm kontena-agent
51
+ ExecStartPre=/usr/bin/docker pull kontena/agent:${KONTENA_VERSION}
52
+ ExecStart=/usr/bin/docker run --name kontena-agent \
53
+ -e KONTENA_URI=${KONTENA_URI} \
54
+ -e KONTENA_TOKEN=${KONTENA_TOKEN} \
55
+ -e KONTENA_PEER_INTERFACE=${KONTENA_PEER_INTERFACE} \
56
+ -v=/var/run/docker.sock:/var/run/docker.sock \
57
+ -v=/etc/kontena-agent.env:/etc/kontena.env \
58
+ --net=host \
59
+ kontena/agent:${KONTENA_VERSION}
@@ -0,0 +1,105 @@
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
+ <% if ssl_cert %>SSL_CERT="/etc/kontena-server.pem"
9
+
10
+ - path: /etc/kontena-server.pem
11
+ permissions: 0600
12
+ owner: root
13
+ content: | <% ssl_cert.split(/\n/).each do |row| %>
14
+ <%= row %><% end %><% end %>
15
+ - path: /opt/bin/kontena-haproxy.sh
16
+ permissions: 0755
17
+ owner: root
18
+ content: |
19
+ #!/bin/sh
20
+ if [ -n "$SSL_CERT" ]; then
21
+ SSL_CERT=$(awk 1 ORS='\\n' $SSL_CERT)
22
+ else
23
+ SSL_CERT="**None**"
24
+ fi
25
+ /usr/bin/docker run --name=kontena-server-haproxy \
26
+ --link kontena-server-api:kontena-server-api \
27
+ -e SSL_CERT="$SSL_CERT" -e BACKEND_PORT=9292 \
28
+ -p 80:80 -p 443:443 kontena/haproxy:latest
29
+ coreos:
30
+ update:
31
+ reboot-strategy: off
32
+ units:
33
+ - name: kontena-server-mongo.service
34
+ command: start
35
+ enable: true
36
+ content: |
37
+ [Unit]
38
+ Description=kontena-server-mongo
39
+ After=network-online.target
40
+ After=docker.service
41
+ Description=Kontena Server MongoDB
42
+ Documentation=http://www.mongodb.org/
43
+ Requires=network-online.target
44
+ Requires=docker.service
45
+
46
+ [Service]
47
+ Restart=always
48
+ RestartSec=5
49
+ ExecStartPre=/usr/bin/docker pull mongo:3.0
50
+ ExecStartPre=-/usr/bin/docker create --name=kontena-server-mongo-data mongo:3.0
51
+ ExecStartPre=-/usr/bin/docker stop kontena-server-mongo
52
+ ExecStartPre=-/usr/bin/docker rm kontena-server-mongo
53
+ ExecStart=/usr/bin/docker run --name=kontena-server-mongo \
54
+ --volumes-from=kontena-server-mongo-data \
55
+ mongo:3.0 mongod --smallfiles
56
+
57
+ - name: kontena-server-api.service
58
+ command: start
59
+ enable: true
60
+ content: |
61
+ [Unit]
62
+ Description=kontena-server-api
63
+ After=network-online.target
64
+ After=docker.service
65
+ After=kontena-server-mongo.service
66
+ Description=Kontena Master
67
+ Documentation=http://www.kontena.io/
68
+ Requires=network-online.target
69
+ Requires=docker.service
70
+ Requires=kontena-server-mongo.service
71
+
72
+ [Service]
73
+ Restart=always
74
+ RestartSec=5
75
+ EnvironmentFile=/etc/kontena-server.env
76
+ ExecStartPre=-/usr/bin/docker stop kontena-server-api
77
+ ExecStartPre=-/usr/bin/docker rm kontena-server-api
78
+ ExecStartPre=/usr/bin/docker pull kontena/server:${KONTENA_VERSION}
79
+ ExecStart=/usr/bin/docker run --name kontena-server-api \
80
+ --link kontena-server-mongo:mongodb \
81
+ -e MONGODB_URI=mongodb://mongodb:27017/kontena_server \
82
+ <% if auth_server %>-e AUTH_API_URL=<%= auth_server %><% end %> \
83
+ kontena/server:${KONTENA_VERSION}
84
+
85
+ - name: kontena-server-haproxy.service
86
+ command: start
87
+ enable: true
88
+ content: |
89
+ [Unit]
90
+ Description=kontena-server-haproxy
91
+ After=network-online.target
92
+ After=docker.service
93
+ Description=Kontena Server HAProxy
94
+ Documentation=http://www.kontena.io/
95
+ Requires=network-online.target
96
+ Requires=docker.service
97
+
98
+ [Service]
99
+ Restart=always
100
+ RestartSec=5
101
+ EnvironmentFile=/etc/kontena-server.env
102
+ ExecStartPre=-/usr/bin/docker stop kontena-server-haproxy
103
+ ExecStartPre=-/usr/bin/docker rm kontena-server-haproxy
104
+ ExecStartPre=/usr/bin/docker pull kontena/haproxy:latest
105
+ ExecStart=/opt/bin/kontena-haproxy.sh
@@ -0,0 +1,27 @@
1
+ module Kontena
2
+ module Machine
3
+ module Azure
4
+ class Logger
5
+ def info(msg)
6
+
7
+ end
8
+
9
+ def error_with_exit(msg)
10
+ puts msg.colorize(:red)
11
+ end
12
+
13
+ def warn(msg)
14
+ puts msg.colorize(:yellow)
15
+ end
16
+
17
+ def error(msg)
18
+ puts msg.colorize(:red)
19
+ end
20
+
21
+ def exception_message(msg)
22
+ puts msg.colorize(:red)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,126 @@
1
+ require 'fileutils'
2
+ require 'erb'
3
+ require 'open3'
4
+ require 'shell-spinner'
5
+
6
+ module Kontena
7
+ module Machine
8
+ module Azure
9
+ class MasterProvisioner
10
+ include RandomName
11
+
12
+ attr_reader :client, :http_client
13
+
14
+ # @param [String] subscription_id Azure subscription id
15
+ # @param [String] certificate Path to Azure management certificate
16
+ def initialize(subscription_id, certificate)
17
+
18
+ abort('Invalid management certificate') unless File.exists?(File.expand_path(certificate))
19
+
20
+ @client = ::Azure
21
+ client.management_certificate = certificate
22
+ client.subscription_id = subscription_id
23
+ client.vm_management.initialize_external_logger(Logger.new) # We don't want all the output
24
+ end
25
+
26
+ def run!(opts)
27
+ abort('Invalid ssh key') unless File.exists?(File.expand_path(opts[:ssh_key]))
28
+ if opts[:ssl_cert]
29
+ abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
30
+ ssl_cert = File.read(File.expand_path(opts[:ssl_cert]))
31
+ end
32
+ cloud_service_name = generate_cloud_service_name
33
+ vm_name = cloud_service_name
34
+ master_url = ''
35
+ ShellSpinner "Creating Azure Virtual Machine #{vm_name.colorize(:cyan)}" do
36
+ if opts[:virtual_network].nil?
37
+ location = opts[:location].downcase.gsub(' ', '-')
38
+ default_network_name = "kontena-#{location}"
39
+ create_virtual_network(default_network_name, opts[:location]) unless virtual_network_exist?(default_network_name)
40
+ opts[:virtual_network] = default_network_name
41
+ opts[:subnet] = 'subnet-1'
42
+ end
43
+
44
+ userdata_vars = {
45
+ ssl_cert: ssl_cert,
46
+ auth_server: opts[:auth_server],
47
+ version: opts[:version]
48
+ }
49
+
50
+ params = {
51
+ vm_name: vm_name,
52
+ vm_user: 'core',
53
+ location: opts[:location],
54
+ image: '2b171e93f07c4903bcad35bda10acf22__CoreOS-Stable-766.3.0',
55
+ custom_data: Base64.encode64(user_data(userdata_vars)),
56
+ ssh_key: opts[:ssh_key]
57
+ }
58
+
59
+ options = {
60
+ cloud_service_name: cloud_service_name,
61
+ deployment_name: vm_name,
62
+ virtual_network_name: opts[:virtual_network],
63
+ subnet_name: opts[:subnet],
64
+ tcp_endpoints: '80,443',
65
+ private_key_file: opts[:ssh_key],
66
+ ssh_port: 22,
67
+ vm_size: opts[:size],
68
+ }
69
+
70
+
71
+ virtual_machine = client.vm_management.create_virtual_machine(params,options)
72
+
73
+ if opts[:ssl_cert]
74
+ master_url = "https://#{virtual_machine.ipaddress}"
75
+ else
76
+ master_url = "http://#{virtual_machine.ipaddress}"
77
+ end
78
+
79
+ end
80
+ Excon.defaults[:ssl_verify_peer] = false
81
+ @http_client = Excon.new("#{master_url}", :connect_timeout => 10)
82
+
83
+ ShellSpinner "Waiting for #{vm_name.colorize(:cyan)} to start" do
84
+ sleep 5 until master_running?
85
+ end
86
+
87
+ puts "Kontena Master is now running at #{master_url}"
88
+ puts "Use #{"kontena login #{master_url}".colorize(:light_black)} to complete Kontena Master setup"
89
+ end
90
+
91
+ def erb(template, vars)
92
+ ERB.new(template).result(OpenStruct.new(vars).instance_eval { binding })
93
+ end
94
+
95
+ def user_data(vars)
96
+ cloudinit_template = File.join(__dir__ , '/cloudinit_master.yml')
97
+ erb(File.read(cloudinit_template), vars)
98
+ end
99
+
100
+ def master_running?
101
+ http_client.get(path: '/').status == 200
102
+ rescue
103
+ false
104
+ end
105
+
106
+ def generate_cloud_service_name
107
+ "kontena-master-#{generate_name}-#{rand(1..99)}"
108
+ end
109
+
110
+ def cloud_service(name)
111
+ client.cloud_service_management.get_cloud_service(name)
112
+ end
113
+
114
+ def virtual_network_exist?(name)
115
+ client.network_management.list_virtual_networks.find{|n| n.name == name}
116
+ end
117
+
118
+ def create_virtual_network(name, location)
119
+ address_space = ['10.0.0.0/20']
120
+ options = {subnet: [{:name => 'subnet-1', :ip_address=>'10.0.0.0', :cidr=>23}]}
121
+ client.network_management.set_network_configuration(name, location, address_space, options)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end