require 'json' module Kontena module Machine module Packet class MasterProvisioner include RandomName include Machine::CertHelper include PacketCommon include Kontena::Cli::Common attr_reader :client, :http_client # @param [String] token Packet token def initialize(token) @client = login(token) end def run!(opts) abort('Project does not exist in Packet') unless project = find_project(opts[:project]) abort('Facility does not exist in Packet') unless facility = find_facility(opts[:facility]) abort('Operating system coreos_stable does not exist in Packet') unless os = find_os('coreos_stable') abort('Device type does not exist in Packet') unless plan = find_plan(opts[:plan]) check_or_create_ssh_key(File.expand_path(opts[:ssh_key])) if opts[:ssh_key] 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 name = generate_name userdata_vars = opts.merge( ssl_cert: ssl_cert, server_name: name.sub('kontena-master-', '') ) device = project.new_device( hostname: name, facility: facility.to_hash, operating_system: os.to_hash, plan: plan.to_hash, billing_cycle: opts[:billing], locked: true, userdata: user_data(userdata_vars, 'cloudinit_master.yml') ) spinner "Creating a Packet device #{device.hostname.colorize(:cyan)} " do api_retry "Packet API reported an error, please try again" do response = client.create_device(device) raise response.body unless response.success? end until device && [:active, :provisioning, :powering_on].include?(device.state) device = find_device(project.id, device.hostname) rescue nil sleep 5 end end public_ip = device_public_ip(device) master_url = "https://#{public_ip['address']}" Excon.defaults[:ssl_verify_peer] = false @http_client = Excon.new("#{master_url}", :connect_timeout => 10) spinner "Waiting for #{device.hostname.colorize(:cyan)} to start (estimate 4 minutes)" do sleep 0.5 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}".colorize(:green) { name: name.sub('kontena-master-', ''), public_ip: public_ip['address'], code: opts[:initial_admin_code], provider: 'packet', version: master_version } end def generate_name "kontena-master-#{super}-#{rand(1..9)}" end def master_running? http_client.get(path: '/').status == 200 rescue false end end end end end