class Kontena::Cli::Vpn::CreateCommand

Public Instance Methods

execute() click to toggle source
# File lib/kontena/cli/vpn/create_command.rb, line 12
def execute
  require_api_url
  token = require_token
  preferred_node = node

  name = 'vpn'
  vpn = client(token).get("stacks/#{current_grid}/#{name}") rescue nil
  exit_with_error('Vpn stack already exists') if vpn

  node = find_node(token, preferred_node)

  vpn_ip = node_vpn_ip(node)
  data = {
    name: name,
    stack: 'krates/vpn',
    version: Kontena::Cli::VERSION,
    registry: 'file://',
    source: '---',
    expose: 'server',
    services: [
      name: 'server',
      stateful: true,
      image: 'krates/openvpn:latest',
      ports: [
        {
          container_port: '1194',
          node_port: '1194',
          protocol: 'udp'
        }
      ],
      cap_add: ['NET_ADMIN'],
      env: ["OVPN_SERVER_URL=udp://#{vpn_ip}:1194"],
      affinity: ["node==#{node['name']}"]
    ]
  }

  client(token).post("grids/#{current_grid}/stacks", data)
  deployment = client(token).post("stacks/#{current_grid}/#{name}/deploy", {})
  spinner "Deploying #{pastel.cyan(name)} service " do
    wait_for_deploy_to_finish(deployment)
  end
  spinner "Generating #{pastel.cyan(name)} keys (this will take a while) " do
    wait_for_configuration_to_finish(token)
  end
  puts "#{pastel.cyan(name)} service is now started (udp://#{vpn_ip}:1194)."
  puts "use 'kontena vpn config' to fetch OpenVPN client config to your machine."
end
find_node(token, preferred_node = nil) click to toggle source
# File lib/kontena/cli/vpn/create_command.rb, line 73
def find_node(token, preferred_node = nil)
  nodes = client(token).get("grids/#{current_grid}/nodes")

  if preferred_node.nil?
    node = nodes['nodes'].find{|n| n['connected'] && !n['public_ip'].to_s.empty?}
    exit_with_error('Cannot find any online nodes with public ip. If you want to connect with private address, please use --node and/or --ip options.') if node.nil?
  else
    node = nodes['nodes'].find{|n| n['connected'] && n['name'] == preferred_node }
    exit_with_error('Node not found') if node.nil?
  end
  node
end
node_vpn_ip(node) click to toggle source

@param [Hash] node @return [String]

# File lib/kontena/cli/vpn/create_command.rb, line 88
def node_vpn_ip(node)
  return ip unless ip.nil?

  # vagrant
  if node['labels'] && node['labels'].include?('provider=vagrant')
    node['private_ip'].to_s
  else
    node['public_ip'].to_s.empty? ? node['private_ip'].to_s : node['public_ip'].to_s
  end
end
wait_for_configuration_to_finish(token) click to toggle source
# File lib/kontena/cli/vpn/create_command.rb, line 60
def wait_for_configuration_to_finish(token)
  finished = false
  payload = {cmd: ['/usr/local/bin/ovpn_getclient', 'KONTENA_VPN_CLIENT']}
  service = client(require_token).get("services/#{current_grid}/vpn/server/containers", payload)['containers'][0]
  until finished
    sleep 3
    stdout, stderr = client(require_token).post("containers/#{service['id']}/exec", payload)
    finished = true if stdout.join('').include?('BEGIN PRIVATE KEY'.freeze)
  end

  finished
end