summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Woodson <kwoodson@redhat.com>2015-02-12 11:26:17 -0500
committerKenny Woodson <kwoodson@redhat.com>2015-02-12 11:26:17 -0500
commit698acd553375caf64cee821d8c1af3e468f9f4dd (patch)
tree3a4d5f3b4d53770ee3313fcd1beb6f946f935751
parentaafbcce3605b7f992ba4b73d67286dbb40461baa (diff)
parentd751d4d53a73a7cf7096e55777b1a7c321bb4732 (diff)
downloadopenshift-698acd553375caf64cee821d8c1af3e468f9f4dd.tar.gz
openshift-698acd553375caf64cee821d8c1af3e468f9f4dd.tar.bz2
openshift-698acd553375caf64cee821d8c1af3e468f9f4dd.tar.xz
openshift-698acd553375caf64cee821d8c1af3e468f9f4dd.zip
Merge pull request #55 from kwoodson/oscp
oscp tooling
-rw-r--r--bin/README_SHELL_COMPLETION12
-rw-r--r--bin/ansibleutil.py8
-rwxr-xr-xbin/oscp220
-rwxr-xr-xbin/ossh46
-rwxr-xr-xbin/ossh_bash_completion2
-rw-r--r--bin/ossh_zsh_completion2
6 files changed, 253 insertions, 37 deletions
diff --git a/bin/README_SHELL_COMPLETION b/bin/README_SHELL_COMPLETION
index e17b4b205..46ed7134c 100644
--- a/bin/README_SHELL_COMPLETION
+++ b/bin/README_SHELL_COMPLETION
@@ -1,8 +1,8 @@
-# ossh is an ssh replacement.
+# completion is available for ossh/oscp
-
-ossh uses a dynamic inventory cache in order to lookup hostnames and translate them
-to something meaningful such as an IP address or dns name.
+ossh/oscp uses a dynamic inventory cache in order to lookup
+hostnames and translate them to something meaningful
+such as an IP address or dns name.
This allows us to treat our servers as cattle and not as pets.
@@ -31,3 +31,7 @@ Once $fpath includes the _ossh_zsh_completion script then you should
run `exec zsh`. This will then allow you to call `ossh host[TAB]`
for a list of completions.
+Before completing the final step, zsh keeps its own cache in
+~/.zcompdump of the known functions and variables. In order to
+refresh with new variables and completion arrays you might need
+to `rm ~/.zcompdump` before running `exec zsh`.
diff --git a/bin/ansibleutil.py b/bin/ansibleutil.py
index b12b7b447..b9f37726e 100644
--- a/bin/ansibleutil.py
+++ b/bin/ansibleutil.py
@@ -17,7 +17,8 @@ class AnsibleUtil(object):
if args:
cmd.extend(args)
- env = {}
+ env = os.environ
+
p = subprocess.Popen(cmd, stderr=subprocess.PIPE,
stdout=subprocess.PIPE, env=env)
@@ -52,7 +53,7 @@ class AnsibleUtil(object):
return groups
- def build_host_dict(self, args=[]):
+ def build_host_dict_by_env(self, args=[]):
inv = self.get_inventory(args)
inst_by_env = {}
@@ -62,8 +63,5 @@ class AnsibleUtil(object):
host_id = "%s:%s" % (host['ec2_tag_Name'],host['ec2_id'])
inst_by_env[host['ec2_tag_environment']][host_id] = host
-
return inst_by_env
-
-
diff --git a/bin/oscp b/bin/oscp
new file mode 100755
index 000000000..a139ef38e
--- /dev/null
+++ b/bin/oscp
@@ -0,0 +1,220 @@
+#!/usr/bin/env python
+# vim: expandtab:tabstop=4:shiftwidth=4
+
+import argparse
+import ansibleutil
+import traceback
+import sys
+import os
+import re
+
+class Oscp(object):
+ def __init__(self):
+ self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
+ self.parse_cli_args()
+
+ # parse host and user
+ self.process_host()
+
+ self.ansible = ansibleutil.AnsibleUtil()
+
+ # get a dict of host inventory
+ if self.args.list:
+ self.get_hosts()
+ else:
+ self.get_hosts(True)
+
+ if (self.args.src == '' or self.args.dest == '') and not self.args.list:
+ self.parser.print_help()
+ return
+
+ if self.args.debug:
+ print self.host
+ print self.args
+
+ # perform the scp
+ if self.args.list:
+ self.list_hosts()
+ else:
+ self.scp()
+
+ def parse_cli_args(self):
+ parser = argparse.ArgumentParser(description='Openshift Online SSH Tool.')
+ parser.add_argument('-e', '--env',
+ action="store", help="Environment where this server exists.")
+ parser.add_argument('-d', '--debug', default=False,
+ action="store_true", help="debug mode")
+ parser.add_argument('-v', '--verbose', default=False,
+ action="store_true", help="Verbose?")
+ parser.add_argument('--list', default=False,
+ action="store_true", help="list out hosts")
+ parser.add_argument('-r', '--recurse', action='store_true', default=False,
+ help='Recursively copy files to or from destination.')
+ parser.add_argument('-o', '--ssh_opts', action='store',
+ help='options to pass to SSH.\n \
+ "-oPort=22,TCPKeepAlive=yes"')
+
+ parser.add_argument('src', nargs='?', default='')
+ parser.add_argument('dest',nargs='?', default='')
+
+ self.args = parser.parse_args()
+ self.parser = parser
+
+
+ def process_host(self):
+ '''Determine host name and user name for SSH.
+ '''
+ self.user = ''
+
+ # is the first param passed a valid file?
+ if os.path.isfile(self.args.src) or os.path.isdir(self.args.src):
+ self.local_src = True
+ self.host = self.args.dest
+ else:
+ self.local_src = False
+ self.host = self.args.src
+
+ if '@' in self.host:
+ re_host = re.compile("(.*@)(.*)(:.*$)")
+ else:
+ re_host = re.compile("(.*)(:.*$)")
+
+ search = re_host.search(self.host)
+
+ if search:
+ if len(search.groups()) > 2:
+ self.user = search.groups()[0]
+ self.host = search.groups()[1]
+ self.path = search.groups()[2]
+ else:
+ self.host = search.groups()[0]
+ self.path = search.groups()[1]
+
+ if self.args.env:
+ self.env = self.args.env
+ elif "." in self.host:
+ self.host, self.env = self.host.split(".")
+ else:
+ self.env = None
+
+ def get_hosts(self, cache_only=False):
+ '''Query our host inventory and return a dict where the format
+ equals:
+
+ dict['environment'] = [{'servername' : {}}, ]
+ '''
+ if cache_only:
+ self.host_inventory = self.ansible.build_host_dict_by_env(['--cache-only'])
+ else:
+ self.host_inventory = self.ansible.build_host_dict_by_env()
+
+ def select_host(self):
+ '''select host attempts to match the host specified
+ on the command line with a list of hosts.
+ '''
+ results = []
+ for env in self.host_inventory.keys():
+ for hostname, server_info in self.host_inventory[env].items():
+ if hostname.split(':')[0] == self.host:
+ results.append((hostname, server_info))
+
+ # attempt to select the correct environment if specified
+ if self.env:
+ results = filter(lambda result: result[1]['ec2_tag_environment'] == self.env, results)
+
+ if results:
+ return results
+ else:
+ print "Could not find specified host: %s." % self.host
+
+ # default - no results found.
+ return None
+
+ def list_hosts(self, limit=None):
+ '''Function to print out the host inventory.
+
+ Takes a single parameter to limit the number of hosts printed.
+ '''
+
+ if self.env:
+ results = self.select_host()
+ if len(results) == 1:
+ hostname, server_info = results[0]
+ sorted_keys = server_info.keys()
+ sorted_keys.sort()
+ for key in sorted_keys:
+ print '{0:<35} {1}'.format(key, server_info[key])
+ else:
+ for host_id, server_info in results[:limit]:
+ name = server_info['ec2_tag_Name']
+ ec2_id = server_info['ec2_id']
+ ip = server_info['ec2_ip_address']
+ print '{ec2_tag_Name:<35} {ec2_tag_environment:<8} {ec2_id:<15} {ec2_ip_address}'.format(**server_info)
+
+ if limit:
+ print
+ print 'Showing only the first %d results...' % limit
+ print
+
+ else:
+ for env, host_ids in self.host_inventory.items():
+ for host_id, server_info in host_ids.items():
+ name = server_info['ec2_tag_Name']
+ ec2_id = server_info['ec2_id']
+ ip = server_info['ec2_ip_address']
+ print '{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<15} {ec2_ip_address}'.format(**server_info)
+
+ def scp(self):
+ '''scp files to or from a specified host
+ '''
+ try:
+ # shell args start with the program name in position 1
+ scp_args = ['/usr/bin/scp']
+
+ if self.args.verbose:
+ scp_args.append('-v')
+
+ if self.args.recurse:
+ scp_args.append('-r')
+
+ if self.args.ssh_opts:
+ for arg in self.args.ssh_opts.split(","):
+ scp_args.append("-o%s" % arg)
+
+ results = self.select_host()
+
+ if self.args.debug: print results
+
+ if not results:
+ return # early exit, no results
+
+ if len(results) > 1:
+ print "Multiple results found for %s." % self.host
+ for result in results:
+ print "{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<10}".format(**result[1])
+ return # early exit, too many results
+
+ # Assume we have one and only one.
+ hostname, server_info = results[0]
+ dns = server_info['ec2_public_dns_name']
+
+ host_str = "%s%s%s" % (self.user, dns, self.path)
+
+ if self.local_src:
+ scp_args.append(self.args.src)
+ scp_args.append(host_str)
+ else:
+ scp_args.append(host_str)
+ scp_args.append(self.args.dest)
+
+ print "Running: %s\n" % ' '.join(scp_args)
+
+ os.execve('/usr/bin/scp', scp_args, os.environ)
+ except:
+ print traceback.print_exc()
+ print sys.exc_info()
+
+
+if __name__ == '__main__':
+ oscp = Oscp()
+
diff --git a/bin/ossh b/bin/ossh
index 0b48ca46c..6b04cb46e 100755
--- a/bin/ossh
+++ b/bin/ossh
@@ -24,15 +24,10 @@ class Ossh(object):
# parse host and user
self.process_host()
- if not self.args.list and not self.env:
- print "Please specify an environment."
- return
-
if self.args.host == '' and not self.args.list:
self.parser.print_help()
return
-
if self.args.debug:
print self.args
@@ -99,31 +94,28 @@ class Ossh(object):
dict['servername'] = dns_name
'''
if cache_only:
- self.host_inventory = self.ansible.build_host_dict(['--cache-only'])
+ self.host_inventory = self.ansible.build_host_dict_by_env(['--cache-only'])
else:
- self.host_inventory = self.ansible.build_host_dict()
+ self.host_inventory = self.ansible.build_host_dict_by_env()
- def select_host(self, regex=False):
+ def select_host(self):
'''select host attempts to match the host specified
on the command line with a list of hosts.
-
- if regex is specified then we will attempt to match
- all *{host_string}* equivalents.
'''
- re_host = re.compile(self.host)
-
results = []
- for hostname, server_info in self.host_inventory[self.env].items():
- if hostname.split(':')[0] == self.host:
- # an exact match, return it!
- return [(hostname, server_info)]
- elif re_host.search(hostname):
- results.append((hostname, server_info))
+ for env in self.host_inventory.keys():
+ for hostname, server_info in self.host_inventory[env].items():
+ if hostname.split(':')[0] == self.host:
+ results.append((hostname, server_info))
+
+ # attempt to select the correct environment if specified
+ if self.env:
+ results = filter(lambda result: result[1]['ec2_tag_environment'] == self.env, results)
if results:
return results
else:
- print "Could not find specified host: %s in %s" % (self.host, self.env)
+ print "Could not find specified host: %s." % self.host
# default - no results found.
return None
@@ -135,7 +127,7 @@ class Ossh(object):
'''
if self.env:
- results = self.select_host(True)
+ results = self.select_host()
if len(results) == 1:
hostname, server_info = results[0]
sorted_keys = server_info.keys()
@@ -179,16 +171,18 @@ class Ossh(object):
for arg in self.args.ssh_opts.split(","):
ssh_args.append("-o%s" % arg)
- result = self.select_host()
- if not result:
+ results = self.select_host()
+ if not results:
return # early exit, no results
- if len(result) > 1:
- self.list_hosts(10)
+ if len(results) > 1:
+ print "Multiple results found for %s." % self.host
+ for result in results:
+ print "{ec2_tag_Name:<35} {ec2_tag_environment:<5} {ec2_id:<10}".format(**result[1])
return # early exit, too many results
# Assume we have one and only one.
- hostname, server_info = result[0]
+ hostname, server_info = results[0]
dns = server_info['ec2_public_dns_name']
ssh_args.append(dns)
diff --git a/bin/ossh_bash_completion b/bin/ossh_bash_completion
index 0d0bdb0e6..6a95ce6ee 100755
--- a/bin/ossh_bash_completion
+++ b/bin/ossh_bash_completion
@@ -15,4 +15,4 @@ _ossh()
return 0
}
-complete -F _ossh ossh
+complete -F _ossh ossh oscp
diff --git a/bin/ossh_zsh_completion b/bin/ossh_zsh_completion
index f057ca8ce..6ab930dc4 100644
--- a/bin/ossh_zsh_completion
+++ b/bin/ossh_zsh_completion
@@ -1,4 +1,4 @@
-#compdef ossh
+#compdef ossh oscp
_ossh_known_hosts(){
if [[ -f ~/.ansible/tmp/multi_ec2_inventory.cache ]]; then