#!/usr/bin/env oo-ruby
#--
# Copyright 2010 Red Hat, Inc.
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++

def usage
  puts <<USAGE
== Synopsis

#{$0}: Add a frontend connection
  This command must be run as root.

== Usage

#{$0} --with-container-uuid UUID \\
               --with-container-name NAME \\
               --with-namespace NAMESPACE \\

== List of arguments
  -c|--with-container-uuid  gear_uuid   Unique identifier for the gear(required)
    |--with-namespace       namespace   Namespace of the application (required)
    |--with-container-name  gear_name   Name of the gear
  -p|--path                 path        Path component to route, "" means route entire app space
  -t|--target               target      Route target (IP:port/path)
  -o|--option               name=val    Route option
    |--websocket                        Enable web sockets on this route (--option "websocket=1")
    |--gone                             Return 410 GONE on this route (--option "gone=1")
    |--forbidden                        Return 403 FORBIDDEN on this route (--option "forbidden=1")
    |--noproxy                          Do not proxy this route (--option "noproxy=1")
    |--health                           Return the health check (--option "health=1")
    |--redirect                         Redirect route instead of proxy (--option "redirect=1")
    |--file                             Target is a file to send (--option "file=1")
    |--tohttps                          Issue a 302 REDIRECT to https (--option "https=1")
  -n|--dry-run                          Don't make changes, just do a dry run
  -q|--porcelain                        TODO: what does this do?
  -d|--debug                            Enable debug mode
  -h|--help                             Print this message

You may specify --path, --target and --option multiple times to
specify multiple routes.  Any instances of --target and --option will
affect the most recent --path.

Simple example, --path is implicitly set to ""
  --target "127.0.250.1:8080"

Complicated example with multiple targets
  --path "" --target "127.0.250.1:8080" --websocket --tohttps --path "/health" --health

USAGE
  exit 255
end

require 'rubygems'
require 'openshift-origin-node'
opts = GetoptLong.new(
    ["--with-container-uuid", "-c", GetoptLong::REQUIRED_ARGUMENT],
    ["--with-namespace",            GetoptLong::REQUIRED_ARGUMENT],
    ["--with-container-name",       GetoptLong::REQUIRED_ARGUMENT],
    ["--path",                "-p", GetoptLong::REQUIRED_ARGUMENT],
    ["--target",              "-t", GetoptLong::REQUIRED_ARGUMENT],
    ["--option",              "-o", GetoptLong::REQUIRED_ARGUMENT],
    ["--websocket",                 GetoptLong::NO_ARGUMENT],
    ["--gone",                      GetoptLong::NO_ARGUMENT],
    ["--forbidden",                 GetoptLong::NO_ARGUMENT],
    ["--noproxy",                   GetoptLong::NO_ARGUMENT],
    ["--health",                   GetoptLong::NO_ARGUMENT],
    ["--redirect",                  GetoptLong::NO_ARGUMENT],
    ["--file",                      GetoptLong::NO_ARGUMENT],
    ["--tohttps",                   GetoptLong::NO_ARGUMENT],
    ["--dry-run",             "-n", GetoptLong::NO_ARGUMENT],
    ["--porcelain",           "-q", GetoptLong::NO_ARGUMENT],
    ["--debug",               "-d", GetoptLong::NO_ARGUMENT],
    ["--help",                "-?", GetoptLong::NO_ARGUMENT]
)

connect_args=[]
connect_ent=nil


container_uuid = nil
container_name = nil
namespace = nil

begin
  opts.each do |k, v|
    case k
    when '--help'
      usage
    when '--with-container-uuid'
      container_uuid = v
    when '--with-container-name'
      container_name = v
    when '--with-namespace'
      namespace = v
    when '--dry-run'
      $dry_run = true
    when '--debug'
      $oo_debug = true
    when '--porcelain'
      $porcelain = true
    when '--path'
      if not connect_ent.nil?
        connect_args << connect_ent
      end
      connect_ent = [ v, "", {} ]
    when '--target'
      if connect_ent.nil?
        connect_ent = [ "", "", {} ]
      end
      connect_ent[1] = v
    when '--option'
      okey, oval = v.split('=')
      oval=1 if oval.nil?
      connect_ent[2][okey]=oval
    when '--websocket'
      connect_ent[2]['websocket']=1
    when '--gone'
      connect_ent[2]['gone']=1
    when '--forbidden'
      connect_ent[2]['forbidden']=1
    when '--noproxy'
      connect_ent[2]['noproxy']=1
    when '--health'
      connect_ent[2]['health']=1
    when '--redirect'
      connect_ent[2]['redirect']=1
    when '--file'
      connect_ent[2]['file']=1
    when '--tohttps'
      connect_ent[2]['tohttps']=1
    else
      usage
    end
  end
rescue GetoptLong::Error => e
  usage
end

unless container_uuid
  usage
end

if connect_ent.nil?
  usage
end

connect_args << connect_ent

begin
  frontend = OpenShift::FrontendHttpServer.new(container_uuid, container_name, namespace)
  frontend.connect(*connect_args)
rescue OpenShift::FrontendHttpServerExecException => e
  $stderr.puts(e.message + e.stdout + e.stderr)
  exit e.rc
rescue OpenShift::FrontendHttpServerException => e
  $stderr.puts(e.message)
  exit 129
rescue Exception => e
  $stderr.puts(e.message)
  exit -1
end
exit 0
