class Kontena::Machine::Upcloud::MasterProvisioner

Attributes

http_client[R]
uc_client[R]

Public Class Methods

new(upcloud_username, upcloud_password) click to toggle source

@param [String] token Upcloud token

# File lib/kontena/machine/upcloud/master_provisioner.rb, line 17
def initialize(upcloud_username, upcloud_password)
  @uc_client = Kontena::Machine::Upcloud::Client.new(upcloud_username, upcloud_password)
end

Public Instance Methods

erb(template, vars) click to toggle source
# File lib/kontena/machine/upcloud/master_provisioner.rb, line 143
def erb(template, vars)
  ERB.new(template, nil, '%<>-').result(OpenStruct.new(vars).instance_eval { binding })
end
generate_name() click to toggle source
# File lib/kontena/machine/upcloud/master_provisioner.rb, line 133
def generate_name
  "kontena-master-#{super}-#{rand(1..9)}"
end
master_running?() click to toggle source
# File lib/kontena/machine/upcloud/master_provisioner.rb, line 137
def master_running?
  http_client.get(path: '/').status == 200
rescue
  false
end
run!(opts) click to toggle source
# File lib/kontena/machine/upcloud/master_provisioner.rb, line 21
def run!(opts)
  abort('Invalid ssh key') unless opts[:ssh_key].to_s.start_with?('ssh-')

  if opts[:ssl_cert]
    abort('Invalid ssl cert') unless File.exists?(File.expand_path(opts[:ssl_cert]))
    ssl_cert = File.read(File.expand_path(opts[:ssl_cert]))
  else
    spinner "Generating a self-signed SSL certificate" do
      ssl_cert = generate_self_signed_cert
    end
  end

  abort('CoreOS template not found on Upcloud') unless coreos_template = uc_client.find_template('CoreOS Stable')
  abort('Server plan not found on Upcloud') unless plan = uc_client.find_plan(opts[:plan])
  abort('Zone not found on Upcloud') unless uc_client.zone_exist?(opts[:zone])

  if opts[:name]
    server_name = opts[:name]
    hostname = opts[:name].start_with?('kontena-master') ? opts[:name] : "kontena-master-#{opts[:name]}"
  else
    hostname = generate_name
    server_name = hostname.sub('kontena-master-', '')
  end

  server_name = opts[:name]
  hostname = opts[:name] || generate_name

  userdata_vars = opts.merge(
      ssl_cert: ssl_cert,
      server_name: server_name
  )

  device_data = {
    server: {
      zone: opts[:zone],
      title: hostname,
      hostname: hostname,
      plan: plan[:name],
      vnc: 'off',
      timezone: 'UTC',
      user_data: user_data(userdata_vars),
      firewall: 'off',
      storage_devices: {
        storage_device: [
          {
            action: 'clone',
            storage: coreos_template[:uuid],
            title: "From template #{coreos_template[:title]}",
            size: plan[:storage_size],
            tier: 'maxiops'
          }
        ]
      },
      login_user: {
        create_password: 'no',
        username: 'root',
        ssh_keys: {
          ssh_key: [opts[:ssh_key]]
        }
      }
    }
  }.to_json

  spinner "Creating an Upcloud server #{hostname.colorize(:cyan)} " do
    response = uc_client.post('server', device_data)
    if response.has_key?(:error)
      abort("\nUpcloud server creation failed (#{response[:error].fetch(:error_message, '')})")
    end
    device_data = response[:server]

    until device_data && device_data.fetch(:state, nil).to_s == 'maintenance'
      device_data = uc_client.get("server/#{device[:uuid]}").fetch(:server, {}) rescue nil
      sleep 5
    end
  end

  device_public_ip = device_data[:ip_addresses][:ip_address].find do |ip|
    ip[:access].eql?('public') && ip[:family].eql?('IPv4')
  end

  abort('Server public ip not found, destroy manually.') unless device_public_ip

  master_url = "https://#{device_public_ip[:address]}"
  Excon.defaults[:ssl_verify_peer] = false
  @http_client = Excon.new("#{master_url}", :connect_timeout => 10)

  spinner "Waiting for #{hostname.colorize(:cyan)} to start" do
    sleep 1 until master_running?
  end

  master_version = nil
  spinner "Retrieving Kontena Master version" do
    master_version = JSON.parse(@http_client.get(path: '/').body)["version"] rescue nil
  end

  spinner "Kontena Master #{master_version} is now running at #{master_url}"

  {
    name: server_name,
    public_ip: device_public_ip[:address],
    provider: 'upcloud',
    version: master_version,
    code: opts[:initial_admin_code],
    ssl_certificate: (respond_to?(:certificate_public_key) && !opts[:ssl_cert]) ? certificate_public_key(ssl_cert) : nil
  }
end
user_data(vars) click to toggle source
# File lib/kontena/machine/upcloud/master_provisioner.rb, line 128
def user_data(vars)
  cloudinit_template = File.join(__dir__ , '/cloudinit_master.yml')
  erb(File.read(cloudinit_template), vars)
end