You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by su...@apache.org on 2014/07/02 19:36:50 UTC
[2/4] AMBARI-6176. Integrate python shell into Ambari-shell
module(subin)
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/ambari_shell.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/ambari_shell.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/ambari_shell.py
new file mode 100644
index 0000000..79af1a6
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/ambari_shell.py
@@ -0,0 +1,412 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import logging.handlers
+import sys
+import signal
+import json
+import time
+import pdb
+import os
+import stat
+import cmd
+import string
+import bz2
+import datetime
+# import traceback
+import getpass
+import argparse
+import readline
+import ConfigParser
+import StringIO
+import subprocess
+import textwrap
+
+import utils.displayutils
+import utils.osutils
+import utils.pluginutils
+from ambari_client.ambari_api import AmbariClient
+
+
+configFile = "/etc/ambari-shell/conf/ambari-shell.ini"
+
+
+formatstr = "%(levelname)s %(asctime)s %(filename)s:%(lineno)d - %(message)s"
+LOG_MAX_BYTES = 10000000
+LOG_BACKUP = 2
+
+SHELL_CONFIG = {
+ 'clustername': None,
+ 'hostname': 'localhost',
+ 'port': 8080,
+ 'username': 'admin',
+ 'password': 'admin',
+ 'display_type': 'table',
+ 'client': None,
+ 'configFile': configFile}
+
+########################################################################
+#
+# Utility methods
+#
+########################################################################
+
+
+def exit_gracefully(signum, frame):
+ # restore the original signal handler as otherwise evil things will happen
+ # in raw_input when CTRL+C is pressed, and our signal handler is not
+ # re-entrant
+ signal.signal(signal.SIGINT, original_sigint)
+ print "\nExiting"
+ sys.exit(1)
+
+ # restore the exit gracefully handler here
+ signal.signal(signal.SIGINT, exit_gracefully)
+
+
+def exit_gracefully1(signum, frame):
+ # restore the original signal handler as otherwise evil things will happen
+ # in raw_input when CTRL+C is pressed, and our signal handler is not
+ # re-entrant
+ signal.signal(signal.SIGQUIT, original_sigint)
+ print "\nExiting"
+ sys.exit(1)
+
+ # restore the exit gracefully handler here
+ signal.signal(signal.SIGQUIT, exit_gracefully)
+
+
+def resolve_config():
+ try:
+ config = ConfigParser.RawConfigParser()
+ if os.path.exists(configFile):
+ print "looking from " + configFile
+ config.read(configFile)
+ else:
+ raise Exception("No config found")
+ except Exception as err:
+ logging.warn(err)
+ print "found " + configFile
+ return config
+
+
+def get_log_level(loglevel):
+ loglev = loglevel.upper()
+ if loglev == "DEBUG":
+ return logging.DEBUG
+ elif loglev == "INFO":
+ return logging.INFO
+ elif loglev == "WARNING":
+ return logging.WARNING
+ elif loglev == "CRITICAL":
+ return logging.CRITICAL
+ elif loglev == "ERROR":
+ return logging.ERROR
+ elif loglev == "FATAL":
+ return logging.FATAL
+ else:
+ return logging.NOTSET
+
+
+def setup_logging(loglevel, logPath="./"):
+ try:
+ logging.root
+ curTimestamp = str(datetime.datetime.now())
+ ct = curTimestamp.split('.')[0]
+ curTime = ct.replace(':', '-')
+ datee = curTime.split(' ')[0]
+ timee = curTime.split(' ')[1]
+ # Set Log directory and log file name. Each run generates a new log
+ # file
+
+ logFile = logPath + 'ambaricli_' + datee + "_" + timee + '.log'
+ fh = open(logFile, 'w')
+ fh.write('*****************************************************\n')
+ fh.write(' Amabri Python CLI Log\n')
+ t = ' Timestamp: ' + ct + '\n'
+ fh.write(t)
+ fh.write('*****************************************************\n\n\n')
+ fh.close()
+ # Set the config for logging
+ logging.basicConfig(
+ filename=logFile,
+ format='%(asctime)s : %(levelname)s: %(message)s',
+ level=get_log_level(loglevel))
+ except IOError as e:
+ errStr = " I/O error({0}): {1}".format(e.errno, e.strerror)
+ print errStr
+ sys.exit(1)
+ except Exception as exception:
+ print exception
+ sys.exit(1)
+
+
+def getLogLevel(configg):
+ loglevel = "debug"
+ try:
+ loglevel = configg.get('python_shell', 'loglevel')
+ except Exception:
+ logging.error("No loglevel found ")
+ return loglevel
+ return loglevel
+
+
+def getLogPath(configg):
+ logPath = "./"
+ try:
+ logPath = configg.get('python_shell', 'log_folder')
+ except Exception:
+ logging.error("No log_folder found")
+ return logPath
+ return logPath
+
+
+def getPluginPath(configg):
+ cliplugin_path = "./"
+ try:
+ cliplugin_path = configg.get('python_shell', 'cliplugin_folder')
+ except Exception:
+ logging.error("No cliplugin_folder found")
+ return cliplugin_path
+ return cliplugin_path
+
+
+def getDefaultPluginPath(configg):
+ cliplugin_path = "./"
+ try:
+ cliplugin_path = configg.get('python_shell', 'default_plugin_folder')
+ except Exception:
+ logging.error("No default_plugin_folder found")
+ return cliplugin_path
+ return cliplugin_path
+
+
+def getCommandsDict(ppath, cliplugin_path):
+ default_dictt = utils.pluginutils.getPlugins(ppath)
+ logging.debug("pluginutils returned default plugins >> %s ", default_dictt)
+ dictt = utils.pluginutils.getPlugins(cliplugin_path)
+ logging.debug("pluginutils returned >> %s ", dictt)
+ if(not set(default_dictt).isdisjoint(set(dictt))):
+ common_commands = set(default_dictt).intersection(set(dictt))
+ common_commands = " & ".join(str(x) for x in common_commands)
+ logging.error(
+ "ERROR :plugins folder has duplicate commands already present in default commands")
+ logging.error(common_commands)
+ print "ERROR :plugins folder has duplicate command already present in default commands"
+ print "pls remove following commands from plugin folder >" + str(common_commands)
+ sys.exit(1)
+ default_dictt.update(dictt)
+ return default_dictt
+
+
+class CmdBase(cmd.Cmd):
+
+ """CLI .
+ """
+
+ intro = utils.displayutils.shellBanner()
+ prompt = 'ambari>'
+ http_proxy = ''
+ https_proxy = ''
+ # headers
+ doc_header = "Commands"
+ undoc_header = "Other Commands"
+
+ def __init__(self):
+ cmd.Cmd.__init__(self)
+
+ def do_EOF(self, line):
+ logging.info("====== do_EOF ======")
+ return True
+
+ def do_exit(self, line):
+ logging.info("====== do_exit ======")
+ return True
+
+ def postloop(self):
+ logging.info("====== exit ======")
+
+# def parseline(self, line):
+# print 'parseline(%s) =>' % line,
+# ret = cmd.Cmd.parseline(self, line)
+# print ret
+# return ret
+
+ def emptyline(self):
+ # print 'emptyline()'
+ # return cmd.Cmd.emptyline(self)
+ return
+
+ def default(self, line):
+ """Called on an input line when the command prefix is not recognized.
+
+ If this method is not overridden, it prints an error message and
+ returns.
+
+ """
+ self.stdout.write(
+ '*** Unknown command *** : %s \n type "help" to list all commands \n' %
+ line)
+
+
+class AmbariShell(CmdBase):
+
+ COMPONENTS = {}
+ SERVICES = None
+ CLUSTERS = None
+
+ def __init__(self):
+ CmdBase.__init__(self)
+ self.config = None
+ self.global_shell_config = SHELL_CONFIG
+
+ def preloop(self):
+ "Checks if the cluster was pre-defined"
+ self._set_prompt()
+
+ def _set_prompt(self):
+ if self.global_shell_config['clustername']:
+ self.prompt = "ambari-" + \
+ str(self.global_shell_config['clustername']) + ">"
+ logging.debug("found a cluster >" +
+ str(self.global_shell_config['clustername']))
+ else:
+ self.prompt = 'ambari>'
+
+ def postcmd(self, stop, line):
+ # print 'postcmd(%s, %s)' % (stop, line)
+ self._set_prompt()
+ return cmd.Cmd.postcmd(self, stop, line)
+
+ def setConfig(self, customConfig):
+ self.config = customConfig
+
+ # core code should begin here
+
+ def generate_output(self, headers, rows):
+ if self.global_shell_config['display_type'] == "table":
+ print utils.displayutils.display_table(headers, rows)
+
+ if self.global_shell_config['display_type'] == "csv":
+ utils.displayutils.createCSV(headers, rows)
+
+ if self.global_shell_config['display_type'] == "xml":
+ print utils.displayutils.createXML(headers, rows)
+
+#
+# The "main" function
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Ambari CLI')
+ parser.add_argument('-H', '--host', action='store', dest='host')
+ parser.add_argument(
+ '-p',
+ '--port',
+ action='store',
+ dest='port',
+ type=int,
+ default=8080)
+ parser.add_argument(
+ '-u',
+ '--user',
+ action='store',
+ dest='user',
+ default='admin')
+ parser.add_argument(
+ '-c',
+ '--clustername',
+ action='store',
+ dest='clustername')
+ parser.add_argument(
+ '--password',
+ action='store',
+ dest='password',
+ default='admin')
+ parser.add_argument(
+ '-d',
+ '--display_type',
+ action='store',
+ dest='display_type',
+ default='table')
+ parser.add_argument('-r', '--run', action='store', dest='run')
+ args = parser.parse_args()
+
+ # Check if a username was suplied, if not, prompt the user
+ if not args.host:
+ args.host = raw_input("Enter Ambari Server host: ")
+
+ if args.host:
+ SHELL_CONFIG['hostname'] = args.host
+ if args.clustername:
+ SHELL_CONFIG['clustername'] = args.clustername
+ if args.display_type:
+ SHELL_CONFIG['display_type'] = args.display_type
+
+ headers_dict = {'X-Requested-By': 'mycompany'}
+ client = AmbariClient(
+ SHELL_CONFIG['hostname'],
+ SHELL_CONFIG['port'],
+ SHELL_CONFIG['username'],
+ SHELL_CONFIG['password'],
+ version=1,
+ http_header=headers_dict)
+ SHELL_CONFIG['client'] = client
+
+ # do some plumbing
+ config = resolve_config()
+ logPath = getLogPath(config)
+ loglevel = getLogLevel(config)
+ cliplugin_path = getPluginPath(config)
+ dpath = getDefaultPluginPath(config)
+ setup_logging(loglevel, logPath)
+ # get ready to create a shell
+ utils.osutils.doclearScreen()
+ shell = AmbariShell()
+ logging.info("cliplugin_folder = %s", getPluginPath(config))
+ logging.info("SHELL_CONFIG = %s", str(SHELL_CONFIG))
+ # Get all commands
+
+ commands_dictt = getCommandsDict(dpath, cliplugin_path)
+ for k, v in commands_dictt.items():
+ setattr(AmbariShell, str(k), v)
+ shell.setConfig(config)
+
+ # Check if user is attempting non-interactive shell
+ if args.run:
+ print args.run
+ for command in args.run.split(';'):
+ shell.onecmd(command)
+ sys.exit(0)
+ else:
+ try:
+ shell.cmdloop()
+ except KeyboardInterrupt:
+ sys.stdout.write("\n")
+ sys.exit(0)
+ logging.info("finished")
+
+
+if __name__ == '__main__':
+ original_sigint = signal.getsignal(signal.SIGINT)
+ signal.signal(signal.SIGINT, exit_gracefully)
+ signal.signal(signal.SIGQUIT, exit_gracefully1)
+ signal.signal(signal.SIGTERM, exit_gracefully1)
+ main()
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/__init__.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/__init__.py
new file mode 100644
index 0000000..278df2e
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/__init__.py
@@ -0,0 +1,16 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/blueprint.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/blueprint.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/blueprint.py
new file mode 100644
index 0000000..4d65163
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/blueprint.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+LOG = logging.getLogger(__name__)
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/connect_cluster.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/connect_cluster.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/connect_cluster.py
new file mode 100644
index 0000000..c28d493
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/connect_cluster.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+LOG = logging.getLogger(__name__)
+
+
+def do_connect_cluster(self, cluster):
+
+ if not cluster:
+ self.help_connect_cluster()
+ return None
+
+ if not self.CLUSTERS:
+ clusters = [str(c.cluster_name).encode('ascii', 'ignore')
+ for c in self.global_shell_config['client'].get_all_clusters()]
+ self.CLUSTERS = clusters
+
+ if cluster not in self.CLUSTERS:
+ print "ERROR ! cluster %s not found " % str(cluster)
+ print " valid clusters are " + str(self.CLUSTERS)
+ return None
+ if self.global_shell_config['clustername']:
+ LOG.debug("old cluster = " + self.global_shell_config['clustername'])
+ self.global_shell_config['clustername'] = str(cluster)
+ else:
+ self.global_shell_config['clustername'] = cluster
+ self.prompt = "ambari-" + \
+ str(self.global_shell_config['clustername']) + ">"
+
+
+def help_connect_cluster(self):
+ print '\n'.join([' Usage:', ' connect_cluster <cluster_name>'])
+
+
+def do_disconnect_cluster(self, line):
+
+ if self.global_shell_config['clustername']:
+ LOG.debug("old cluster = " + self.global_shell_config['clustername'])
+ self.global_shell_config['clustername'] = None
+ self.prompt = "ambari>"
+
+
+def help_disconnect_cluster(self):
+ print '\n'.join([' Usage:', ' disconnect_cluster'])
+
+
+def complete_connect_cluster(self, pattern, line, start_index, end_index):
+ if not self.CLUSTERS:
+ clusters = [
+ (c.cluster_name).encode(
+ 'ascii',
+ 'ignore') for c in self.global_shell_config['client'].get_all_clusters()]
+ self.CLUSTERS = clusters
+
+ LOG.debug(
+ ("self.CLUSTERS = %s pattern = %s ") %
+ (str(
+ self.CLUSTERS),
+ pattern))
+ if pattern:
+ return [
+ c for c in self.CLUSTERS if c.startswith(pattern)]
+ else:
+ return self.CLUSTERS
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/create_cluster.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/create_cluster.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/create_cluster.py
new file mode 100644
index 0000000..f9947d7
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/create_cluster.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+
+LOG = logging.getLogger(__name__)
+
+
+def do_create_cluster(self, line):
+ # logging = self.LOG
+ print "TODO"
+ self.prompt = "ambari>"
+
+
+def help_create_cluster(self):
+ print '\n'.join([' Usage:', ' create_cluster <cluster_name>'])
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/service.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/service.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/service.py
new file mode 100644
index 0000000..d44769a
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/service.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+
+LOG = logging.getLogger(__name__)
+
+
+def do_start_service(self, service):
+ if not service:
+ self.help_stop_service()
+ return None
+ clustername = self.global_shell_config['clustername']
+ if not clustername:
+ print("Error! No cluster currently selected")
+ return None
+
+ if self.t_service_action(service=service, action="start"):
+ print("%s is being started" % (service))
+ else:
+ print("Error! cannot start service")
+ return
+
+
+def do_stop_service(self, service):
+ if not service:
+ self.help_start_service()
+ return None
+
+ clustername = self.global_shell_config['clustername']
+ if not clustername:
+ print("Error! No cluster currently selected")
+ return None
+
+ if self.t_service_action(service=service, action="stop"):
+ print("%s is being stopped" % (service))
+ else:
+ print("Error! cannot stop service")
+ return
+
+
+def help_stop_service(self):
+ print textwrap.dedent("""
+ Usage:
+ > stop_service <service_name>
+ """)
+
+
+def help_start_service(self):
+ print textwrap.dedent("""
+ Usage:
+ > start_service <service_name>
+ """)
+
+
+def complete_start_service(self, pattern, line, start_index, end_index):
+ return self.services_complete(pattern, line, start_index, end_index)
+
+
+def complete_stop_service(self, pattern, line, start_index, end_index):
+ client = self.global_shell_config['client']
+ clustername = self.global_shell_config['clustername']
+ if not clustername:
+ return None
+ else:
+ if not self.SERVICES:
+ services = [
+ s.service_name for s in client.get_cluster(clustername).get_all_services()]
+ self.SERVICES = services
+
+ if pattern:
+ return [s for s in self.SERVICES if s.startswith(pattern)]
+ else:
+ return self.SERVICES
+
+
+def services_complete(self, pattern, line, start_index, end_index, append=[]):
+ client = self.global_shell_config['client']
+ clustername = self.global_shell_config['clustername']
+ if not clustername:
+ return None
+ else:
+ if not self.SERVICES:
+ services = [
+ s.service_name for s in client.get_cluster(clustername).get_all_services()]
+ self.SERVICES = services
+
+ if pattern:
+ return [s for s in self.SERVICES + append if s.startswith(pattern)]
+ else:
+ return self.SERVICES + append
+
+
+def t_service_action(self, service, action):
+ try:
+ client = self.global_shell_config['client']
+ cluster = self.global_shell_config['clustername']
+ service = client.get_cluster(cluster).get_service(service)
+ except Exception:
+ print("Service not found")
+ return None
+
+ if action == "start":
+ service.start(message='started by Ambari python CLI')
+ if action == "stop":
+ service.stop(message='stopped by Ambari python CLI')
+ return True
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/shell_config.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/shell_config.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/shell_config.py
new file mode 100644
index 0000000..2facd02
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/shell_config.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+LOG = logging.getLogger(__name__)
+
+
+def do_get_shell_config(self, config_name):
+ rows = []
+ headers = ["KEY", "VAlUE"]
+ if not config_name:
+ for i in self.global_shell_config.items():
+ rows.append([i[0], i[1]])
+ else:
+ if config_name in self.global_shell_config.keys():
+ rows.append([config_name, self.global_shell_config[config_name]])
+
+ self.generate_output(headers, rows)
+
+
+def do_set_shell_config(self, config=None):
+ kv = config.split(" ")
+ if len(kv) != 2:
+ self.help_set_shell_config()
+ return
+ config_name = kv[0]
+ config_value = kv[1]
+ if config_name in self.global_shell_config.keys():
+ self.global_shell_config[config_name] = config_value
+
+ self.do_get_shell_config(config_name=None)
+
+
+def help_get_shell_config(self):
+ print textwrap.dedent("""
+ Usage:
+ > get_shell_config <config_name> get all shell config
+ """)
+
+
+def help_set_shell_config(self):
+ print textwrap.dedent("""
+ Usage:
+ > set_shell_config <config_name> <config_value> sets shell config
+ """)
+
+
+def complete_get_shell_config(self, pattern, line, start_index, end_index):
+ if pattern:
+ return [
+ c for c in self.global_shell_config.keys() if c.startswith(pattern)]
+ else:
+ return self.CLUSTERS
+
+
+def complete_set_shell_config(self, pattern, line, start_index, end_index):
+ if pattern:
+ return [
+ c for c in self.global_shell_config.keys() if c.startswith(pattern)]
+ else:
+ return self.CLUSTERS
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/show.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/show.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/show.py
new file mode 100644
index 0000000..584b40a
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/plugins/show.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+
+LOG = logging.getLogger(__name__)
+
+
+def help_show(self):
+ print textwrap.dedent("""
+ Usage:
+ > show clusters list clusters
+ > show hosts list hosts
+ > show stacks list stacks
+ > show services list services
+ > show requests list previous requests
+ > show blueprints list blueprints
+ """)
+
+
+def do_show(self, option):
+ """
+ Usage:
+ > show clusters list clusters
+ > show hosts list hosts
+ > show stacks list stacks
+ > show services list services
+ > show requests list previous requests
+ > show blueprints list blueprints
+ """
+ headers = []
+ rows = []
+ options = [
+ "clusters",
+ "stacks",
+ "status",
+ "services",
+ "hosts",
+ "requests",
+ "blueprints"]
+
+ if not option:
+ self.help_show()
+ return
+
+ if option not in options:
+ self.default(option)
+ return
+
+ client = self.global_shell_config['client']
+ clustername = self.global_shell_config['clustername']
+ # show clusters
+ if option == "clusters":
+ "Display list of clusters on system"
+ headers = ["CLUSTER NAME"]
+ clusters = client.get_all_clusters()
+ for cluster in clusters:
+ rows.append([cluster.cluster_name])
+
+ # show clusters
+ if option == "stacks":
+ "Display list of stacks on system"
+ headers = ["STACK NAME"]
+ stacks = client.get_stacks(True)
+ for stack in stacks:
+ rows.append([stack.stack_version])
+
+ if option == "blueprints":
+ "Display list of blueprints on system"
+ headers = ["BLUEPRINT NAME", "VERSION"]
+ blues = client.get_blueprint()
+ for b in blues:
+ rows.append([b.blueprint_name, b.stack_version])
+
+ if option == "status":
+ "Display list of stacks on system"
+ headers = ["HOST_NAME", "ROLE", "STATUS"]
+ if not clustername:
+ print("Error! No cluster currently selected")
+ return
+ else:
+ tasks = client.get_task_status(clustername, 2)
+ for task in tasks:
+ rows.append([task.host_name, task.role, task.status])
+
+ # show hosts
+ if option == "hosts":
+ "Display a list of hosts avaiable on the system"
+ headers = ["HOSTNAME", "IP ADDRESS"]
+ if not clustername:
+ for host in client.get_all_hosts():
+ rows.append([host.host_name, host.ip])
+ else:
+ c = client.get_cluster(clustername)
+ for host in c.get_all_hosts():
+ rows.append([host.host_name, host.ip])
+
+ if option == "requests":
+ headers = ["REQUEST-ID", "STATUS"]
+ if not clustername:
+ print("Error! No cluster currently selected")
+ return
+ else:
+ c = client.get_cluster(clustername)
+ for req in client.get_requests(clustername):
+ rows.append([req.id, req.request_status])
+
+ # show services
+ if option == "services":
+ "Show list of services on the cluster"
+ headers = ["SERVICE", "STATUS"]
+
+ if not clustername:
+ print("Error! No cluster currently selected")
+ return
+ else:
+ c = client.get_cluster(clustername)
+ for service in c.get_all_services():
+ rows.append([service.service_name, service.state])
+
+ self.generate_output(headers, rows)
+
+
+def complete_show(self, pattern, line, start_index, end_index):
+ show_commands = [
+ "clusters",
+ "hosts",
+ "services",
+ "stacks",
+ "blueprints",
+ "requests"]
+ if pattern:
+ return [c for c in show_commands if c.startswith(pattern)]
+ else:
+ return show_commands
+
+if __name__ == '__main__':
+ do_show(None, None)
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/__init__.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/__init__.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/__init__.py
new file mode 100644
index 0000000..278df2e
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/__init__.py
@@ -0,0 +1,16 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/displayutils.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/displayutils.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/displayutils.py
new file mode 100644
index 0000000..3c45e7f
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/displayutils.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import textwrap
+import cStringIO
+import operator
+from xml.etree import ElementTree as etree
+from functools import reduce
+
+
+LOG = logging.getLogger(__name__)
+
+
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+
+ def disable(self):
+ self.HEADER = ''
+ self.OKBLUE = ''
+ self.OKGREEN = ''
+ self.WARNING = ''
+ self.FAIL = ''
+
+
+__header__ = textwrap.dedent("""
+ ___ __ _
+ / _ | __ _ / / ___ _____(_)
+ / __ |/ ' \/ _ \/ _ `/ __/ /
+/_/ |_/_/_/_/_.__/\_,_/_/ /_/ CLI v%s
+""" % str(1))
+
+
+def shellBanner():
+ """
+ Prints the CLI Banner.
+ """
+ return __header__ + textwrap.dedent(
+ """
+ ====================================
+ Welcome to Ambari python CLI
+ type 'help' to list all commands..
+ ====================================
+ """)
+
+
+def createXML(headers, rows):
+ root = etree.Element('xmloutput')
+ for r in rows:
+ for h, relemt in zip(headers, r):
+
+ child = etree.Element(h.lower().replace(' ', '_'))
+ child.text = str(relemt)
+ root.append(child)
+
+ # pretty string
+ s = etree.tostring(root)
+ return s
+
+
+def createCSV(headers, rows):
+ headers = [x.lower().replace(' ', '_') for x in headers]
+ print(','.join(headers))
+ for r in rows:
+ print(','.join(r))
+
+
+def display_table(headers, rows):
+
+ delimiter = '='
+ delimiter1 = ' | '
+ output = cStringIO.StringIO()
+ temp_rows = [tuple(headers)] + rows
+ row_tuple = [(row,) for row in temp_rows]
+ # get max width
+ verticalrows = map(None, *reduce(operator.add, row_tuple))
+
+ if not rows:
+ widthList = [len(str(x)) for x in headers]
+ row_width = sum(widthList)
+ else:
+ widthList = [max([len(str(x)) for x in column])
+ for column in verticalrows]
+ row_width = sum(widthList)
+ header_line = delimiter * \
+ (row_width + len(delimiter1) * (len(widthList) - 1))
+
+ i = 0
+ for rr in row_tuple:
+ for row in rr:
+ print >> output, delimiter1.join(
+ [(str(x)).ljust(width) for (x, width) in zip(row, widthList)])
+ if i == 0:
+ print >> output, header_line
+ i = 9999
+ return output.getvalue()
+
+
+if __name__ == '__main__':
+ print createXML(['STACK NAME', ], [[u'HDP']])
+ createCSV(['STACK NAME', ], [[u'HDP']])
+ headers = ['First Name', 'Last Name', 'Age']
+ data = \
+ '''Sam ,Browne,21
+ Jhon,Browne,23
+ Adam,senio,21'''
+ rows = [row.strip().split(',') for row in data.splitlines()]
+ print display_table(headers, rows)
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/osutils.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/osutils.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/osutils.py
new file mode 100644
index 0000000..8aeaa34
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/osutils.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import os
+import sys
+import platform
+
+LOG = logging.getLogger(__name__)
+
+
+def clearScreen(operatingSys):
+ """
+ Function to clear the screen
+ Input : OS
+ """
+ logging.info('Entering..')
+
+ if operatingSys == 'Windows':
+ cmdClear = 'CLS'
+ elif operatingSys == 'Linux':
+ cmdClear = 'clear'
+ elif operatingSys == 'Darwin':
+ cmdClear = 'clear'
+ logging.debug('Running command : %s', cmdClear)
+ os.system(cmdClear)
+ logging.info('Exiting..')
+
+
+def getOperatingSystem():
+ logging.info('Entering..')
+ operatingSys = platform.system()
+ # sprint operatingSys
+ if not operatingSys:
+ logging.error('Operating system is NULL.')
+ return False, ''
+ else:
+ logging.debug('Got operating system : %s', operatingSys)
+ logging.info('Exiting..')
+ return True, operatingSys
+
+
+def doclearScreen():
+ # Determine the OS
+ result, operatingSys = getOperatingSystem()
+ if not result:
+ logging.error('Failed to determine Operating System. Exiting.')
+ sys.exit(1)
+ # clear the Screen
+ clearScreen(operatingSys)
+
+
+if __name__ == '__main__':
+ pass
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/pluginutils.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/pluginutils.py b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/pluginutils.py
new file mode 100644
index 0000000..fdcb97c
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/ambari_shell/utils/pluginutils.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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 logging
+import os
+import sys
+import inspect
+
+LOG = logging.getLogger(__name__)
+#------------------------------------------------------------------------------
+'''
+Function that searches for all plugins from a file
+Input : folder
+Output : dict
+'''
+#------------------------------------------------------------------------------
+
+
+def get_plugins(module):
+ logging.debug('[Module: %s]\n' % module.__name__)
+
+ plugin_method_map = {}
+ count = 0
+
+ for name in dir(module):
+ obj = getattr(module, name)
+ if inspect.isclass(obj):
+ count += 1
+ elif (inspect.ismethod(obj) or inspect.isfunction(obj)):
+ if obj.__name__.startswith("do_") or obj.__name__.startswith(
+ "help_") or obj.__name__.startswith("complete_") or obj.__name__.startswith("t_"):
+ logging.debug("%s ,%s ", obj.__name__, obj)
+ plugin_method_map.update({obj.__name__: obj})
+ count += 1
+ elif inspect.isbuiltin(obj):
+ count += 1
+ logging.debug(plugin_method_map)
+ if count == 0:
+ logging.debug('(No members)')
+
+ return plugin_method_map
+
+
+def import_modules(dirr):
+ module_list = []
+ for f in os.listdir(os.path.abspath(dirr)):
+ module_name, ext = os.path.splitext(f)
+ if ext == '.py' and module_name != "ambari_shell":
+ logging.debug('imported module: %s' % (module_name))
+ module = __import__(module_name)
+ module_list.append(module)
+
+ return module_list
+
+
+def getPlugins(foldername):
+ if os.path.isdir(foldername):
+ sys.path.append(foldername)
+ logging.debug('%s is a directory!' % (foldername))
+
+ mod_list = import_modules(foldername)
+ logging.debug(mod_list)
+
+ plugin_method_map = {}
+ for m in mod_list:
+ dictt = get_plugins(m)
+ if dictt:
+ plugin_method_map.update(dictt)
+
+ return plugin_method_map
+
+
+def getPluginsFromModules(modulename):
+ module = __import__(modulename)
+ logging.debug(module)
+
+ plugin_method_map = {}
+ dictt = get_plugins(module)
+ if dictt:
+ plugin_method_map.update(dictt)
+
+ return plugin_method_map
+
+if __name__ == "__main__":
+ print getPlugins("plug")
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/main/python/setup.py
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/main/python/setup.py b/ambari-shell/ambari-python-shell/src/main/python/setup.py
new file mode 100755
index 0000000..b67d872
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/main/python/setup.py
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+from setuptools import setup, find_packages
+
+from sys import version_info, platform
+
+if version_info[:2] > (2, 5):
+ install_requires = []
+else:
+ install_requires = ['simplejson >= 2.0.0']
+
+# Python 2.6 and below requires argparse
+if version_info[:2] < (2, 7):
+ install_requires += ['argparse']
+
+install_requires += ['ambari_client']
+setup(
+ name='ambari_shell',
+ author_email="ambari-dev@incubator.apache.org",
+ version="1.6.0-SNAPSHOT",
+ packages=['ambari_shell'],
+ install_requires=install_requires,
+ description='Ambari Python Shell',
+ license='Apache License 2.0'
+)
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/ambari-python-shell/src/packages/tarball/all.xml
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/src/packages/tarball/all.xml b/ambari-shell/ambari-python-shell/src/packages/tarball/all.xml
new file mode 100755
index 0000000..0e4f34b
--- /dev/null
+++ b/ambari-shell/ambari-python-shell/src/packages/tarball/all.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd">
+ <!--This 'all' id is not appended to the produced bundle because we do this:
+ http://maven.apache.org/plugins/maven-assembly-plugin/faq.html#required-classifiers
+ -->
+ <formats>
+ <format>dir</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/python</directory>
+ <outputDirectory>/</outputDirectory>
+ </fileSet>
+ </fileSets>
+</assembly>
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/assemblies/client.xml
----------------------------------------------------------------------
diff --git a/ambari-shell/assemblies/client.xml b/ambari-shell/assemblies/client.xml
new file mode 100644
index 0000000..20670cd
--- /dev/null
+++ b/ambari-shell/assemblies/client.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<assembly>
+</assembly>
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-shell/pom.xml b/ambari-shell/pom.xml
index a7e3400..947c9b9 100644
--- a/ambari-shell/pom.xml
+++ b/ambari-shell/pom.xml
@@ -1,14 +1,23 @@
<?xml version="1.0"?>
-<!-- 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.
- See accompanying LICENSE file. -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+
<parent>
<groupId>org.apache.ambari</groupId>
<artifactId>ambari-project</artifactId>
@@ -18,106 +27,33 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.ambari</groupId>
<artifactId>ambari-shell</artifactId>
- <packaging>jar</packaging>
- <name>Ambari Shell</name>
+ <packaging>pom</packaging>
<version>1.3.0-SNAPSHOT</version>
+ <name>Ambari Shell</name>
<description>Ambari Shell</description>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <start-class>org.apache.ambari.shell.AmbariShell</start-class>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.shell</groupId>
- <artifactId>spring-shell</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- </dependency>
- <dependency>
- <groupId>com.github.lalyos</groupId>
- <artifactId>jfiglet</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.ambari</groupId>
- <artifactId>groovy-client</artifactId>
- <version>1.3.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>1.9.5</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>jline</groupId>
- <artifactId>jline</artifactId>
- </dependency>
- <dependency>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-mapper-asl</artifactId>
- </dependency>
- </dependencies>
+ <modules>
+ <module>ambari-python-shell</module>
+ <module>ambari-groovy-shell</module>
+ </modules>
<build>
<plugins>
<plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.0</version>
- </plugin>
- <plugin>
- <groupId>org.apache.rat</groupId>
- <artifactId>apache-rat-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>src/main/resources/elephant.txt</exclude>
- <exclude>src/test/resources/2columns</exclude>
- <exclude>src/test/resources/3columns</exclude>
- <exclude>src/test/resources/testBlueprint.json</exclude>
- </excludes>
- </configuration>
- <executions>
- <execution>
- <phase>test</phase>
- <goals>
- <goal>check</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
- <skipAssembly>true</skipAssembly>
+ <tarLongFileMode>gnu</tarLongFileMode>
+ <descriptors>
+ <descriptor>assemblies/client.xml</descriptor>
+ </descriptors>
</configuration>
- </plugin>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>1.0.2.RELEASE</version>
<executions>
<execution>
+ <id>build-tarball</id>
+ <phase>prepare-package</phase>
<goals>
- <goal>repackage</goal>
+ <goal>single</goal>
</goals>
</execution>
</executions>
- <configuration>
- <mainClass>${start-class}</mainClass>
- </configuration>
</plugin>
<plugin>
<groupId>org.vafer</groupId>
@@ -132,9 +68,7 @@
</execution>
</executions>
<configuration>
- <controlDir>${basedir}/../../ambari-project/src/main/package/deb/control</controlDir>
- <skip>true</skip>
- <submodules>false</submodules>
+ <controlDir>${basedir}/../ambari-project/src/main/package/deb/control</controlDir>
</configuration>
</plugin>
</plugins>
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/src/main/java/org/apache/ambari/shell/AmbariShell.java
----------------------------------------------------------------------
diff --git a/ambari-shell/src/main/java/org/apache/ambari/shell/AmbariShell.java b/ambari-shell/src/main/java/org/apache/ambari/shell/AmbariShell.java
deleted file mode 100644
index e842620..0000000
--- a/ambari-shell/src/main/java/org/apache/ambari/shell/AmbariShell.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.ambari.shell;
-
-import org.apache.ambari.groovy.client.AmbariClient;
-import org.apache.ambari.shell.model.AmbariContext;
-import org.apache.ambari.shell.model.Hints;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.shell.CommandLine;
-import org.springframework.shell.core.JLineShellComponent;
-import org.springframework.shell.event.ShellStatus;
-import org.springframework.shell.event.ShellStatusListener;
-
-/**
- * Shell bootstrap.
- */
-@Configuration
-@ComponentScan(basePackageClasses = {AmbariShell.class})
-public class AmbariShell implements CommandLineRunner, ShellStatusListener {
-
- @Autowired
- private CommandLine commandLine;
- @Autowired
- private JLineShellComponent shell;
- @Autowired
- private AmbariContext context;
- @Autowired
- private AmbariClient client;
-
- @Override
- public void run(String... arg) throws Exception {
- String[] shellCommandsToExecute = commandLine.getShellCommandsToExecute();
- if (shellCommandsToExecute != null) {
- for (String cmd : shellCommandsToExecute) {
- if (!shell.executeScriptLine(cmd)) {
- break;
- }
- }
- System.exit(0);
- } else {
- shell.addShellStatusListener(this);
- shell.start();
- shell.promptLoop();
- shell.waitForComplete();
- }
- }
-
- @Override
- public void onShellStatusChange(ShellStatus oldStatus, ShellStatus newStatus) {
- if (newStatus.getStatus() == ShellStatus.Status.STARTED) {
- try {
- String cluster = client.getClusterName();
- boolean available = client.isBlueprintAvailable();
- if (cluster == null) {
- if (available) {
- context.setHint(Hints.BUILD_CLUSTER);
- } else {
- context.setHint(Hints.ADD_BLUEPRINT);
- }
- } else {
- context.setHint(Hints.PROGRESS);
- }
- context.setCluster(cluster);
- context.setBlueprintsAvailable(available);
- } catch (Exception e) {
- System.out.println(e.getMessage());
- shell.executeCommand("quit");
- }
- }
- }
-
-
- public static void main(String[] args) {
- if (args.length == 0) {
- System.out.println(
- "\nAmbari Shell: Interactive command line tool for managing Apache Ambari.\n\n" +
- "Usage:\n" +
- " java -jar ambari-shell.jar : Starts Ambari Shell in interactive mode.\n" +
- " java -jar ambari-shell.jar --cmdfile=<FILE> : Ambari Shell executes commands read from the file.\n\n" +
- "Options:\n" +
- " --ambari.host=<HOSTNAME> Hostname of the Ambari Server [default: localhost].\n" +
- " --ambari.port=<PORT> Port of the Ambari Server [default: 8080].\n" +
- " --ambari.user=<USER> Username of the Ambari admin [default: admin].\n" +
- " --ambari.password=<PASSWORD> Password of the Ambari admin [default: admin].\n\n" +
- "Note:\n" +
- " At least one option is mandatory."
- );
- System.exit(1);
- }
- new SpringApplicationBuilder(AmbariShell.class).showBanner(false).run(args);
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BasicCommands.java
----------------------------------------------------------------------
diff --git a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BasicCommands.java b/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BasicCommands.java
deleted file mode 100644
index 9babe12..0000000
--- a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BasicCommands.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.ambari.shell.commands;
-
-import static org.apache.ambari.shell.support.TableRenderer.renderMapValueMap;
-import static org.apache.ambari.shell.support.TableRenderer.renderSingleMap;
-
-import org.apache.ambari.groovy.client.AmbariClient;
-import org.apache.ambari.shell.model.AmbariContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.shell.core.CommandMarker;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-import org.springframework.stereotype.Component;
-
-/**
- * Basic commands used in the shell. Delegating the commands
- * to the Ambari Server via a Groovy based client.
- *
- * @see org.apache.ambari.groovy.client.AmbariClient
- */
-@Component
-public class BasicCommands implements CommandMarker {
-
- private AmbariClient client;
- private AmbariContext context;
-
- @Autowired
- public BasicCommands(AmbariClient client, AmbariContext context) {
- this.client = client;
- this.context = context;
- }
-
- /**
- * Checks whether the tasks command is available or not.
- *
- * @return true if its available false otherwise
- */
- @CliAvailabilityIndicator("tasks")
- public boolean isTasksCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- /**
- * Prints the tasks of the Ambari Server.
- *
- * @param id id of the request
- * @return task list
- */
- @CliCommand(value = "tasks", help = "Lists the Ambari tasks")
- public String tasks(
- @CliOption(key = "id", mandatory = false, help = "Id of the request; default is: 1", unspecifiedDefaultValue = "1") String id) {
- return renderSingleMap(client.getTaskMap(id), "TASK", "STATUS");
- }
-
- /**
- * Checks whether the service list command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("services list")
- public boolean isServiceListCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- /**
- * Prints the available service list of the Ambari Server.
- *
- * @return service list
- */
- @CliCommand(value = "services list", help = "Lists the available services")
- public String servicesList() {
- return renderSingleMap(client.getServicesMap(), "SERVICE", "STATE");
- }
-
- /**
- * Checks whether the service components command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("services components")
- public boolean isServiceComponentsCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- /**
- * Prints the service components of the Ambari Server.
- *
- * @return service component list
- */
- @CliCommand(value = "services components", help = "Lists all services with their components")
- public String serviceComponents() {
- return renderMapValueMap(client.getServiceComponentsMap(), "SERVICE", "COMPONENT", "STATE");
- }
-
- /**
- * Checks whether the debug on command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("debug on")
- public boolean isDebugOnCommandAvailable() {
- return !client.isDebugEnabled();
- }
-
- /**
- * Turns the debug on. From now on users will see the URLs of the API calls.
- *
- * @return status message
- */
- @CliCommand(value = "debug on", help = "Shows the URL of the API calls")
- public String debugOn() {
- client.setDebugEnabled(true);
- return "debug enabled";
- }
-
- /**
- * Checks whether the debug off command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("debug off")
- public boolean isDebugOffCommandAvailable() {
- return client.isDebugEnabled();
- }
-
- /**
- * Turns the debug off. URLs are not visible anymore.
- *
- * @return status message
- */
- @CliCommand(value = "debug off", help = "Stops showing the URL of the API calls")
- public String debugOff() {
- client.setDebugEnabled(false);
- return "debug disabled";
- }
-
- /**
- * Checks whether the hint command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("hint")
- public boolean isHintCommandAvailable() {
- return true;
- }
-
- /**
- * Provides some hints what you can do in the current context.
- *
- * @return hint message
- */
- @CliCommand(value = "hint", help = "Shows some hints")
- public String hint() {
- return context.getHint();
- }
-
- @CliAvailabilityIndicator("services stop")
- public boolean isServiceStopCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- @CliCommand(value = "services stop", help = "Stops all the running services")
- public String stopServices() {
- String message;
- try {
- client.stopAllServices();
- message = "Stopping all services..";
- } catch (Exception e) {
- message = "Cannot stop services";
- }
- return String.format("%s\n\n%s", message, servicesList());
- }
-
- @CliAvailabilityIndicator("services start")
- public boolean isServiceStartCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- @CliCommand(value = "services start", help = "Starts all the services")
- public String startServices() {
- String message;
- try {
- client.startAllServices();
- message = "Starting all services..";
- } catch (Exception e) {
- message = "Cannot start services";
- }
- return String.format("%s\n\n%s", message, servicesList());
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BlueprintCommands.java
----------------------------------------------------------------------
diff --git a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BlueprintCommands.java b/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BlueprintCommands.java
deleted file mode 100644
index 73000d0..0000000
--- a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/BlueprintCommands.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.ambari.shell.commands;
-
-import static org.apache.ambari.shell.support.TableRenderer.renderMultiValueMap;
-import static org.apache.ambari.shell.support.TableRenderer.renderSingleMap;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URL;
-
-import org.apache.ambari.groovy.client.AmbariClient;
-import org.apache.ambari.shell.completion.Blueprint;
-import org.apache.ambari.shell.model.AmbariContext;
-import org.apache.ambari.shell.model.Hints;
-import org.apache.commons.io.IOUtils;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.shell.core.CommandMarker;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-import org.springframework.stereotype.Component;
-
-/**
- * Blueprint related commands used in the shell.
- *
- * @see org.apache.ambari.groovy.client.AmbariClient
- */
-@Component
-public class BlueprintCommands implements CommandMarker {
-
- private AmbariClient client;
- private AmbariContext context;
- private ObjectMapper jsonMapper;
-
- @Autowired
- public BlueprintCommands(AmbariClient client, AmbariContext context, ObjectMapper jsonMapper) {
- this.client = client;
- this.context = context;
- this.jsonMapper = jsonMapper;
- }
-
- /**
- * Checks whether the blueprints command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("blueprint list")
- public boolean isBlueprintListCommandAvailable() {
- return context.areBlueprintsAvailable();
- }
-
- /**
- * Prints all the blueprints.
- *
- * @return list of blueprints
- */
- @CliCommand(value = "blueprint list", help = "Lists all known blueprints")
- public String listBlueprints() {
- return renderSingleMap(client.getBlueprintsMap(), "BLUEPRINT", "STACK");
- }
-
- /**
- * Checks whether the blueprint show command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator(value = "blueprint show")
- public boolean isBlueprintShowCommandAvailable() {
- return context.areBlueprintsAvailable();
- }
-
- /**
- * Shows the requested blueprint's details.
- *
- * @param id id of the blueprint
- * @return blueprint as formatted table
- */
- @CliCommand(value = "blueprint show", help = "Shows the blueprint by its id")
- public String showBlueprint(
- @CliOption(key = "id", mandatory = true, help = "Id of the blueprint") Blueprint id) {
- return renderMultiValueMap(client.getBlueprintMap(id.getName()), "HOSTGROUP", "COMPONENT");
- }
-
- /**
- * Checks whether the blueprint add command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator(value = "blueprint add")
- public boolean isBlueprintAddCommandAvailable() {
- return true;
- }
-
- /**
- * Adds a blueprint to the Ambari server either through an URL or from a file.
- * If both specified the file takes precedence.
- *
- * @param url -optional, URL containing the blueprint json
- * @param file - optional, file containing the blueprint json
- * @return status message
- */
- @CliCommand(value = "blueprint add", help = "Add a new blueprint with either --url or --file")
- public String addBlueprint(
- @CliOption(key = "url", mandatory = false, help = "URL of the blueprint to download from") String url,
- @CliOption(key = "file", mandatory = false, help = "File which contains the blueprint") File file) {
- String message;
- try {
- String json = file == null ? readContent(url) : readContent(file);
- if (json != null) {
- client.addBlueprint(json);
- context.setHint(Hints.BUILD_CLUSTER);
- context.setBlueprintsAvailable(true);
- message = String.format("Blueprint: '%s' has been added", getBlueprintName(json));
- } else {
- message = "No blueprint specified";
- }
- } catch (Exception e) {
- message = "Cannot add blueprint: " + e.getMessage();
- }
- return message;
- }
-
- /**
- * Checks whether the blueprint defaults command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator(value = "blueprint defaults")
- public boolean isBlueprintDefaultsAddCommandAvailable() {
- return !context.areBlueprintsAvailable();
- }
-
- /**
- * Adds two default blueprints to the Ambari server.
- *
- * @return status message
- */
- @CliCommand(value = "blueprint defaults", help = "Adds the default blueprints to Ambari")
- public String addBlueprint() {
- String message = "Default blueprints added";
- try {
- client.addDefaultBlueprints();
- context.setHint(Hints.BUILD_CLUSTER);
- context.setBlueprintsAvailable(true);
- } catch (Exception e) {
- message = "Failed to add the default blueprints: " + e.getMessage();
- }
- return message;
- }
-
- private String readContent(File file) {
- String content = null;
- try {
- content = IOUtils.toString(new FileInputStream(file));
- } catch (IOException e) {
- // not important
- }
- return content;
- }
-
- private String readContent(String url) {
- String content = null;
- try {
- content = IOUtils.toString(new URL(url));
- } catch (IOException e) {
- // not important
- }
- return content;
- }
-
- private String getBlueprintName(String json) {
- String result = "";
- try {
- result = jsonMapper.readTree(json.getBytes()).get("Blueprints").get("blueprint_name").asText();
- } catch (IOException e) {
- // not important
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ClusterCommands.java
----------------------------------------------------------------------
diff --git a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ClusterCommands.java b/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ClusterCommands.java
deleted file mode 100644
index dafdb85..0000000
--- a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ClusterCommands.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.ambari.shell.commands;
-
-import static org.apache.ambari.shell.support.TableRenderer.renderMultiValueMap;
-import static org.apache.ambari.shell.support.TableRenderer.renderSingleMap;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ambari.groovy.client.AmbariClient;
-import org.apache.ambari.shell.completion.Blueprint;
-import org.apache.ambari.shell.completion.Host;
-import org.apache.ambari.shell.flash.FlashService;
-import org.apache.ambari.shell.model.AmbariContext;
-import org.apache.ambari.shell.model.FocusType;
-import org.apache.ambari.shell.model.Hints;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.shell.core.CommandMarker;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-import org.springframework.stereotype.Component;
-
-import groovyx.net.http.HttpResponseException;
-
-/**
- * Cluster related commands used in the shell.
- *
- * @see org.apache.ambari.groovy.client.AmbariClient
- */
-@Component
-public class ClusterCommands implements CommandMarker {
-
- private AmbariClient client;
- private AmbariContext context;
- private FlashService flashService;
- private Map<String, List<String>> hostGroups;
-
- @Autowired
- public ClusterCommands(AmbariClient client, AmbariContext context, FlashService flashService) {
- this.client = client;
- this.context = context;
- this.flashService = flashService;
- }
-
- /**
- * Checks whether the cluster build command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("cluster build")
- public boolean isClusterBuildCommandAvailable() {
- return !context.isConnectedToCluster() && !context.isFocusOnClusterBuild() && context.areBlueprintsAvailable();
- }
-
- /**
- * Sets the focus on cluster building. Takes a blueprint id, if it does not exists it wont focus.
- * After focus the users are able to assign hosts to host groups.
- *
- * @param id id of the blueprint
- * @return prints the blueprint as formatted table if exists, otherwise error message
- */
- @CliCommand(value = "cluster build", help = "Starts to build a cluster")
- public String buildCluster(
- @CliOption(key = "blueprint", mandatory = true, help = "Id of the blueprint, use 'blueprints' command to see the list") Blueprint id) {
- String message;
- String blueprint = id.getName();
- if (client.doesBlueprintExist(blueprint)) {
- context.setFocus(blueprint, FocusType.CLUSTER_BUILD);
- context.setHint(Hints.ASSIGN_HOSTS);
- message = String.format("%s\n%s",
- renderSingleMap(client.getHostNames(), "HOSTNAME", "STATE"),
- renderMultiValueMap(client.getBlueprintMap(blueprint), "HOSTGROUP", "COMPONENT"));
- createNewHostGroups();
- } else {
- message = "Not a valid blueprint id";
- }
- return message;
- }
-
- /**
- * Checks whether the cluster assign command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("cluster assign")
- public boolean isAssignCommandAvailable() {
- return context.isFocusOnClusterBuild();
- }
-
- /**
- * Assign hosts to host groups provided in the blueprint.
- *
- * @param host host to assign
- * @param group which host group to
- * @return status message
- */
- @CliCommand(value = "cluster assign", help = "Assign host to host group")
- public String assign(
- @CliOption(key = "host", mandatory = true, help = "Fully qualified host name") Host host,
- @CliOption(key = "hostGroup", mandatory = true, help = "Host group which to assign the host") String group) {
- String message;
- String hostName = host.getName();
- if (client.getHostNames().keySet().contains(hostName)) {
- if (addHostToGroup(hostName, group)) {
- context.setHint(Hints.CREATE_CLUSTER);
- message = String.format("%s has been added to %s", hostName, group);
- } else {
- message = String.format("%s is not a valid host group", group);
- }
- } else {
- message = String.format("%s is not a valid hostname", hostName);
- }
- return message;
- }
-
- /**
- * Checks whether the cluster auto command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator(value = "cluster autoAssign")
- public boolean isClusterAutoAssignAvailable() {
- return context.isFocusOnClusterBuild() && !isHostAssigned();
- }
-
- /**
- * Tries to auto associate hosts to host groups.
- *
- * @return prints the auto assignments
- */
- @CliCommand(value = "cluster autoAssign", help = "Automatically assigns hosts to different host groups base on the provided strategy")
- public String autoAssign() {
- Map<String, List<String>> assignments = client.recommendAssignments(context.getFocusValue());
- if (!assignments.isEmpty()) {
- hostGroups = assignments;
- context.setHint(Hints.CREATE_CLUSTER);
- }
- return showAssignments();
- }
-
- /**
- * Checks whether the cluster preview command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("cluster preview")
- public boolean isClusterPreviewCommandAvailable() {
- return context.isFocusOnClusterBuild() && isHostAssigned();
- }
-
- /**
- * Shows the currently assigned hosts.
- *
- * @return formatted host - host group table
- */
- @CliCommand(value = "cluster preview", help = "Shows the currently assigned hosts")
- public String showAssignments() {
- return renderMultiValueMap(hostGroups, "HOSTGROUP", "HOST");
- }
-
- /**
- * Checks whether the cluster create command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("cluster create")
- public boolean isCreateClusterCommandAvailable() {
- return context.isFocusOnClusterBuild() && isHostAssigned();
- }
-
- /**
- * Creates a new cluster based on the provided host - host group associations and the selected blueprint.
- * If the cluster creation fails, deletes the cluster.
- *
- * @return status message
- */
- @CliCommand(value = "cluster create", help = "Create a cluster based on current blueprint and assigned hosts")
- public String createCluster(
- @CliOption(key = "exitOnFinish", mandatory = false, help = "Quits the shell when the cluster creation finishes") Boolean exit) {
- String message = "Successfully created the cluster";
- String blueprint = context.getFocusValue();
- try {
- client.createCluster(blueprint, blueprint, hostGroups);
- context.setCluster(blueprint);
- context.resetFocus();
- context.setHint(Hints.PROGRESS);
- flashService.showInstallProgress(exit == null ? false : exit);
- } catch (HttpResponseException e) {
- createNewHostGroups();
- message = "Failed to create the cluster: " + e.getMessage();
- try {
- deleteCluster(blueprint);
- } catch (HttpResponseException e1) {
- message += ". Failed to cleanup cluster creation: " + e1.getMessage();
- }
- }
- return message;
- }
-
- /**
- * Checks whether the cluster delete command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("cluster delete")
- public boolean isDeleteClusterCommandAvailable() {
- return context.isConnectedToCluster();
- }
-
- /**
- * Deletes the cluster.
- *
- * @return status message
- */
- @CliCommand(value = "cluster delete", help = "Delete the cluster")
- public String deleteCluster() {
- String message = "Successfully deleted the cluster";
- try {
- deleteCluster(context.getCluster());
- } catch (HttpResponseException e) {
- message = "Could not delete the cluster: " + e.getMessage();
- }
- return message;
- }
-
- /**
- * Checks whether the cluster reset command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator(value = "cluster reset")
- public boolean isClusterResetCommandAvailable() {
- return context.isFocusOnClusterBuild() && isHostAssigned();
- }
-
- @CliCommand(value = "cluster reset", help = "Clears the host - host group assignments")
- public void reset() {
- context.setHint(Hints.ASSIGN_HOSTS);
- createNewHostGroups();
- }
-
- private void deleteCluster(String id) throws HttpResponseException {
- client.deleteCluster(id);
- }
-
- private void createNewHostGroups() {
- Map<String, List<String>> groups = new HashMap<String, List<String>>();
- for (String hostGroup : client.getHostGroups(context.getFocusValue())) {
- groups.put(hostGroup, new ArrayList<String>());
- }
- this.hostGroups = groups;
- }
-
- private boolean addHostToGroup(String host, String group) {
- boolean result = true;
- List<String> hosts = hostGroups.get(group);
- if (hosts == null) {
- result = false;
- } else {
- hosts.add(host);
- }
- return result;
- }
-
- private boolean isHostAssigned() {
- boolean result = false;
- for (String group : hostGroups.keySet()) {
- if (!hostGroups.get(group).isEmpty()) {
- result = true;
- break;
- }
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8eceafc/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ElephantCommand.java
----------------------------------------------------------------------
diff --git a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ElephantCommand.java b/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ElephantCommand.java
deleted file mode 100644
index a236054..0000000
--- a/ambari-shell/src/main/java/org/apache/ambari/shell/commands/ElephantCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.ambari.shell.commands;
-
-import java.io.IOException;
-
-import org.apache.commons.io.IOUtils;
-import org.springframework.shell.core.CommandMarker;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.stereotype.Component;
-
-/**
- * Draws an elephant to the console.
- */
-@Component
-public class ElephantCommand implements CommandMarker {
-
- /**
- * Checks whether the hello command is available or not.
- *
- * @return true if available false otherwise
- */
- @CliAvailabilityIndicator("hello")
- public boolean isCommandAvailable() {
- return true;
- }
-
- /**
- * Prints an elephant to the console.
- *
- * @return elephant
- */
- @CliCommand(value = "hello", help = "Prints a simple elephant to the console")
- public String elephant() throws IOException {
- return IOUtils.toString(getClass().getResourceAsStream("/elephant.txt"));
- }
-}
\ No newline at end of file