#!/usr/bin/env ruby
# Copyright 2011 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

require 'rhc-common'

#
# print help
#
def p_usage
    puts <<USAGE

Usage: #{$0}
Bind a registered rhcloud user to a domain in rhcloud.

  NOTE: to change ssh key, please alter your ~/.ssh/libra_id_rsa and
        ~/.ssh/libra_id_rsa.pub key, then re-run with --alter

  -n|--namespace   namespace   Namespace for your application(s) (alphanumeric - max #{RHC::Maxdlen} chars) (required)
  -l|--rhlogin     rhlogin     Red Hat login (RHN or OpenShift login with OpenShift Express access) (required)
  -p|--password    password    RHLogin password (optional, will prompt)
  -a|--alter                   Alter namespace (will change urls) and/or ssh key
  -d|--debug                   Print Debug info
  -h|--help                    Show Usage info

USAGE
exit 255
end

begin
    opts = GetoptLong.new(
        ["--debug", "-d", GetoptLong::NO_ARGUMENT],
        ["--help",  "-h", GetoptLong::NO_ARGUMENT],
        ["--rhlogin",  "-l", GetoptLong::REQUIRED_ARGUMENT],
        ["--password",  "-p", GetoptLong::REQUIRED_ARGUMENT],
        ["--namespace", "-n", GetoptLong::REQUIRED_ARGUMENT],
        ["--alter", "-a", GetoptLong::NO_ARGUMENT]
    )
    
    opt = {}
    opts.each do |o, a|
        opt[o[2..-1]] = a.to_s
    end
rescue Exception => e
  #puts e.message
    p_usage
end

# Pull in configs from files
libra_server = get_var('libra_server')
debug = get_var('debug') == 'false' ? nil : get_var('debug')


libra_kfile = "#{ENV['HOME']}/.ssh/libra_id_rsa"
libra_kpfile = "#{ENV['HOME']}/.ssh/libra_id_rsa.pub"

if opt["help"]
    p_usage
end

if opt["debug"]
    debug = true
end

if !RHC::check_namespace(opt['namespace'])
    p_usage
end

if !RHC::check_rhlogin(opt['rhlogin'])
    p_usage
end


if !opt["rhlogin"] || !opt["namespace"]
    p_usage
end

password = opt['password']
if !password
  password = RHC::get_password
end

#
# Add a new namespace to configs
#

def add_rhlogin_config(rhlogin, uuid)
    f = open(File.expand_path(@local_config_path), 'a')
    unless @local_config.get_value('default_rhlogin')
        f.puts("# Default rhlogin to use if none is specified")
        f.puts("default_rhlogin=#{rhlogin}")
        f.puts("")
    end
    f.close
end


#
# Check to see if a libra_id_rsa key exists, if not create it.
#

if File.readable?(libra_kfile)
    puts "OpenShift Express key found at #{libra_kfile}.  Reusing..."
else
    puts "Generating OpenShift Express ssh key to #{libra_kfile}"
    # Use system for interaction
    system("ssh-keygen -t rsa -f '#{libra_kfile}'")
end

ssh_key = File.open(libra_kpfile).gets.chomp.split(' ')[1]

puts "Contacting https://#{libra_server}"
data = {'namespace' => opt['namespace'],
                'rhlogin' => opt['rhlogin'],
                'ssh' => ssh_key}
if (opt['alter'])
  data['alter'] = "true"
  not_found_message = "A user with rhlogin '#{opt['rhlogin']}' does not have a registered domain.  Be sure to run rhc-create-domain without -a|--alter first."
  user_info = RHC::get_user_info(libra_server, opt['rhlogin'], password, @http, debug, true, not_found_message)
end
if debug
  data['debug'] = "true"
end
RHC::print_post_data(data, debug)
json_data = RHC::generate_json(data)

url = URI.parse("https://#{libra_server}/broker/domain")
response = RHC::http_post(@http, url, json_data, password)

if response.code == '200'
    begin
        json_resp = JSON.parse(response.body)
        RHC::print_response_success(json_resp, debug)
        json_rhlogininfo = JSON.parse(json_resp['data'])
        add_rhlogin_config(json_rhlogininfo['rhlogin'], json_rhlogininfo['uuid'])
    
        if opt['alter'] != ''
            puts <<EOF
Creation successful

You may now create an application.  Please make note of your local config file
in #{@local_config_path} which has been created and populated for you.

EOF
        else
            app_info = user_info['app_info']
            dns_success = true
            if !app_info.empty? && opt['namespace'] != user_info['user_info']['namespace']
              #
              # Confirm that the host(s) exist in DNS
              #
              puts "Now your new domain name(s) are being propagated worldwide (this might take a minute)..."
              # Allow DNS to propogate
              sleep 15
              app_info.each_key do |appname|
                  fqdn = "#{appname}-#{opt['namespace']}.#{user_info['user_info']['rhc_domain']}"
                  
                  # Now start checking for DNS
                  loop = 0
                  sleep_time = 2
                  while loop < RHC::Maxretries && !RHC::hostexist?(fqdn)
                      sleep sleep_time
                      loop+=1
                      puts "  retry # #{loop} - Waiting for DNS: #{fqdn}"
                      sleep_time = RHC::delay(sleep_time)
                  end
                  
                  if loop >= RHC::Maxretries
                      puts "Host could not be found: #{fqdn}"
                      dns_success = false
                  end
              end
            end
            if dns_success
              puts "Alteration successful.  You can use rhc-user-info to view any url changes."
            else
              puts "Alteration successful but at least one of the urls is still updating in DNS.  You can use rhc-user-info to view any url changes."
            end
            puts ""
        end
        exit 0
    rescue JSON::ParserError
        RHC::print_response_err(response, debug)
    end
else
    RHC::print_response_err(response, debug)
end
exit 254
