Skip to content

Commit

Permalink
first iteration at back porting glu console cli.
Browse files Browse the repository at this point in the history
broken and needs to be made more generic
  • Loading branch information
ypujante committed Dec 24, 2010
1 parent e147143 commit 1452593
Show file tree
Hide file tree
Showing 14 changed files with 677 additions and 19 deletions.
59 changes: 59 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,62 @@ Agreement will bring a legal action under this Agreement more than one year
after the cause of action arose. Each party waives its rights to a jury trial
in any resulting litigation.

=========================================================================
This product includes ProgressBar, which provides a text mode progressbar in python with
BSD License (http://code.google.com/p/python-progressbar/source/browse/progressbar/LICENSE):

progressbar - Text progressbar library for python
Copyright (c) 2008 Nilton Volpato

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

a. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
b. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
c. Neither the name of the author nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

=========================================================================
This product includes restkit, an HTTP resource kit for python (https://github.com/benoitc/restkit)
with the following license (https://github.com/benoitc/restkit/blob/master/LICENSE):

2008-2010 (c) Beno�t Chesneau <benoitc@e-engura.org>

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.
23 changes: 23 additions & 0 deletions console/org.linkedin.glu.console-cli/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2010 LinkedIn, 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.
*/

apply plugin: 'org.linkedin.release'
apply plugin: 'org.linkedin.cmdline'

cmdline {
// no dependency at all
dependsOn = null
}
33 changes: 33 additions & 0 deletions console/org.linkedin.glu.console-cli/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#
# Copyright 2010-2010 LinkedIn, 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.
#

import os
from setuptools import setup

setup(
name = "gluconsole",
version = "0.1",
author = "Manish Dubey",
author_email = "mdubey@linkedin.com",
description = ("GLU REST API"),
install_requires = ['restkit', 'progressbar'],
packages = ['gluconsole'],
scripts = ['src/cmdline/resources/bin/glu'],

package_dir = {
'gluconsole': 'src/cmdline/resources/lib/python/gluconsole'
},
)
240 changes: 240 additions & 0 deletions console/org.linkedin.glu.console-cli/src/cmdline/resources/bin/glu
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
#!/usr/bin/python

#
# Copyright 2010-2010 LinkedIn, 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.
#

#
# This script provides a way to communicate with GLU console via REST API.
# It provides high level actions (by constructing lower level REST calls to the console), such as:
# -- start (to start apps in a fabric)
# -- stop (to stop apps in a fabric)
# -- load (to load a new model for a fabric)
# -- status (to load a new model for a fabric)
#
# It used gluconsole.rest.Client, which encapsulates these methods.
#
import sys
import os
import getpass
import site

bin = os.path.abspath((os.path.dirname(sys.argv[0])))
lib = os.path.join(os.path.dirname(bin), 'lib', 'python')

site.addsitedir(lib)
site.addsitedir(os.path.join(lib, 'site-packages'))

import logging
logging.basicConfig(format="%(asctime)s [%(levelname)s] - %(name)s - %(message)s")

import gluconsole.rest
from optparse import OptionParser

def main():
log = logging.getLogger("glu")

# current username
user = getpass.getuser()

# command line parsing
usage = "usage: %prog <start|stop|load|status> [flags]"
parser = OptionParser(usage=usage, version="%prog 0.2")

# common options for all actions
parser.add_option("-d", "--debug", dest="debug",
action="store_true", default=False,
help="Turn on debug output")

parser.add_option("-c", "--console", dest="consoleurl",
action="store",
help="Url to GLU Console for the given fabric.")

parser.add_option("-f", "--fabric", dest="fabric",
action="store",
help="Perform action on a fabric")

parser.add_option("-U", "--user", dest="user",
action="store", default=user,
help="GLU user to use for authentication, defaults to " + user)

parser.add_option("-x", "--xpassword", dest="password",
action="store",
help="Password. Warning password will appear in clear in ps output. Use only for testing.")

parser.add_option("-X", "--xpasswordfile", dest="passwordfile",
action="store",
help="Read user password from passwordfile specified. Make sure to protect this file using unix permissions")

# controlling start/stop actions
parser.add_option("-a", "--all", dest="all",
default=False, action="store_true",
help="Perform action on all entries")

parser.add_option("-H", "--host", dest="host",
action="store",
help="Perform action on one or more host(s)")

parser.add_option("-I", "--instance", dest="instance",
action="store",
help="Perform action on one or more instance(s)")

parser.add_option("-p", "--parallel", dest="parallel",
action="store_true", default=False,
help="Perform action on all instances in parallel. Default is serial.")

parser.add_option("-n", "--dryrun", dest="dryrun",
action="store_true", default=False,
help="Do a dry run of your plan. No changes will be made. Default is false.")

# options for status action
parser.add_option("-s", "--systemFilter", dest="filter",
action="store",
help="Filter in DSL sytax for filtering the model. Applicable only with 'status' command. See 'Filter Syntax' section here: https://iwww.corp.linkedin.com/wiki/cf/display/ENGS/GLU+CLI+-+InDay+work ")

parser.add_option("-S", "--systemFilterFile", dest="filterFile",
action="store",
help="Filter file with filters in DSL sytax for filtering the model. Applicable only with 'status' command. See 'Filter Syntax' section here: https://iwww.corp.linkedin.com/wiki/cf/display/ENGS/GLU+CLI+-+InDay+work ")

parser.add_option("-l", "--live", dest="live",
action="store_true", default=False,
help="Show current model instead of expected model. Applicable only with 'status' command.")

parser.add_option("-b", "--beautify", dest="beautify",
action="store_true", default=False,
help="Pretty print the model.")

# options for load action
parser.add_option("-u", "--url", dest="systemUrl",
action="store",
help="Required if loading new system. ex: file:/tmp/root/system.json or http://localhost/system.json")

# get options provided on commandline. Remaining arg is 'action'
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("One action must be specified")
else:
action=args[0]

# validate options
if not options.fabric:
parser.error("Fabric must be specified")

if not options.consoleurl:
parser.error("Console URL must be specified")

if options.debug:
log.setLevel(logging.DEBUG)
gluconsole.rest.log.setLevel(logging.DEBUG)

if options.filter and options.filterFile:
parser.error("Only filter or filterFile must be specified, not both.")

# Only one of the following options can be specified.
# FWIW, argparse supports mutually exclusive groups.
exclusive_options = dict()

if options.cluster:
exclusive_options['cluster'] = True

if options.appname:
exclusive_options['appname'] = True

if options.host:
exclusive_options['host'] = True

if options.instance:
exclusive_options['instance'] = True

if options.filter or options.filterFile:
exclusive_options['filter'] = True

if options.all:
exclusive_options['all'] = True

if len(exclusive_options.keys()) > 1:
parser.error("Only one of: cluster, appname, host, instance, filter or all may be used.")

# validate manifest loading options, make sure everything we need is specified
manifestSpecified = False;
if options.manifestrelease or options.manifesturl:
manifestSpecified = True
if not options.manifesturl:
parser.error("Need to specify Manifest URL when specifying a release")
if not options.manifestrelease:
parser.error("Need to specify Manifest release when specifying a URL")
if not options.product:
parser.error("Need to specify Product when trying to load a new manifest")
if action == "load" and not manifestSpecified:
parser.error("Need to specify Manifest details for load action.")

# get user's and password
if options.password:
password = options.password
elif options.passwordfile:
with open(options.passwordfile, 'r') as fh:
password = fh.readline().strip()
else:
password = getpass.getpass("Enter " + options.user + "'s password: ")

filter = None

if options.filter:
filter = options.filter

if options.filterFile:
with open(options.filterFile, 'r') as fh:
filter = fh.read().strip()

# create client to process the request
log.info("Will run action '%s' on fabric '%s'" % (action, options.fabric))

client = gluconsole.rest.Client(fabric=options.fabric, url=options.consoleurl, username=options.user, password=password)

# now perform the action
result = "<unknown>"
if action in ("start", "stop", "bounce", "deploy", "undeploy", "redeploy"):

if manifestSpecified:
if not client.loadModel(options.manifestrelease, options.manifesturl, options.product):
log.critical("Model load failed")

if filter is None:
filter = client.generateSystemFilter(options.appname, options.cluster, options.host, options.instance)

result = client.executePlan(action, filter, options.parallel, options.dryrun)

elif action == "load":

result = client.loadModel(options.manifestrelease, options.manifesturl, options.product)

elif action == "status":

if manifestSpecified:
if not client.loadModel(options.manifestrelease, options.manifesturl, options.product):
log.critical("Model load failed");

if filter is None:
filter = client.generateSystemFilter(options.appname, options.cluster, options.host, options.instance)

result = client.status(options.live, options.legacy, options.beautify, filter)

else:
parser.error("Unknown action: " + action)

print result

if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright 2010-2010 LinkedIn, 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.
#
Loading

0 comments on commit 1452593

Please sign in to comment.