| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # coding: utf-8 | 2 # coding: utf-8 |
| 3 | 3 |
| 4 import sys | 4 import sys |
| 5 import os | 5 import os |
| 6 import os.path | |
|
Felix Dahlke
2015/03/03 16:43:32
Not necessary, we're already importing os. Looks l
mathias
2015/03/04 12:32:37
Agreed, the explicit os.path import will be remove
| |
| 7 import re | 6 import re |
| 8 import subprocess | 7 import subprocess |
| 9 import getopt | 8 import getopt |
| 10 import yaml | 9 import yaml |
| 11 | 10 |
| 12 def usage(): | 11 def usage(): |
| 13 print >>sys.stderr, ''' | 12 print >>sys.stderr, ''' |
| 14 Usage: %s [-u <user>] [-h <host>|<group>] [-i] ... <command> | 13 Usage: %s [-u <user>] [-h <host>|<group>] [-i] ... <command> |
| 15 | 14 |
| 16 Runs a command on the given hosts or groups of hosts. | 15 Runs a command on the given hosts or groups of hosts. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 46 def getValidHosts(): | 45 def getValidHosts(): |
| 47 dirname = os.path.dirname(sys.argv[0]) | 46 dirname = os.path.dirname(sys.argv[0]) |
| 48 path_name = os.path.join(dirname, "hiera", "private", "hosts.yaml") | 47 path_name = os.path.join(dirname, "hiera", "private", "hosts.yaml") |
| 49 with open(path_name, 'rb') as handle: | 48 with open(path_name, 'rb') as handle: |
| 50 config = yaml.load(handle) | 49 config = yaml.load(handle) |
| 51 servers = config.get('servers', {}) | 50 servers = config.get('servers', {}) |
| 52 return servers | 51 return servers |
| 53 | 52 |
| 54 def resolveHostList(hosts): | 53 def resolveHostList(hosts): |
| 55 | 54 |
| 56 host_names = set(str(item) for item in hosts) | |
|
Wladimir Palant
2015/03/03 20:00:19
Given that hosts is a list of string, this seems e
mathias
2015/03/04 12:32:37
"Given that hosts is a list of string" <- this is
Felix Dahlke
2015/03/04 14:27:53
Nit: The parentheses are now not necessary anymore
Wladimir Palant
2015/03/04 15:14:11
This isn't a library function you wrote here, it i
mathias
2015/03/04 18:13:51
Done.
mathias
2015/03/04 18:13:51
Done.
| |
| 57 result = set() | 55 result = set() |
| 58 | 56 |
| 59 try: | 57 try: |
| 60 valid_hosts = getValidHosts() | 58 valid_hosts = getValidHosts() |
|
Felix Dahlke
2015/03/03 16:43:32
Host validation doesn't make _that_ much sense any
Wladimir Palant
2015/03/03 20:00:19
Indeed, that's something we discussed previously -
mathias
2015/03/04 12:32:37
This version does two jobs at the same time; valid
Felix Dahlke
2015/03/04 14:27:53
For the record: I actually prefer Wladimir's sugge
Wladimir Palant
2015/03/04 15:14:11
Actually, changing the current validation code to
mathias
2015/03/04 18:13:51
@Felix
As I wrote before, this is actually intende
Felix Dahlke
2015/03/09 23:14:51
Didn't realise this, but yeah, the catch clause st
| |
| 61 except Warning as error: | 59 except Warning as error: |
| 62 print >>sys.stderr, 'Warning: failed to determine valid hosts:', error | 60 print >>sys.stderr, 'Warning: failed to determine valid hosts:', error |
| 63 result.update(host_names) | 61 result.update(hosts) |
| 64 else: | 62 else: |
| 65 for name in host_names: | 63 for name in hosts: |
| 66 chunk = tuple( | 64 chunk = [ |
| 67 item[1].get('dns', item[0]) for item in valid_hosts.items() | 65 value.get('dns', key) for (key, value) in valid_hosts.items() |
|
Wladimir Palant
2015/03/03 20:00:19
for (key, value) in valid_hosts.iteritems() please
mathias
2015/03/04 12:32:37
Done.
To answer your question: There is no need
Wladimir Palant
2015/03/04 15:14:11
The difference between a list and a tuple isn't th
mathias
2015/03/04 18:13:51
This has already been changed in the current patch
| |
| 68 | 66 |
| 69 if name == item[0] | 67 if name == key |
| 70 or name == '*' | 68 or name == '*' |
| 71 or name == item[1].get('dns', None) | 69 or name == value.get('dns', None) |
| 72 or name in item[1]['ip'] | 70 or name in value.get('groups', ()) |
|
mathias
2015/02/26 18:41:23
While resolving IPs would be a nice feature, this
mathias
2015/03/04 12:32:37
Done.
| |
| 73 or name in item[1].get('groups', ()) | 71 ] |
| 74 ) | |
| 75 | 72 |
| 76 if len(chunk) == 0: | 73 if len(chunk) == 0: |
| 77 print >>sys.stderr, 'Warning: failed to recognize host or group', name | 74 print >>sys.stderr, 'Warning: failed to recognize host or group', name |
| 78 else: | 75 else: |
| 79 result.update(chunk) | 76 result.update(chunk) |
| 80 | 77 |
| 81 return result | 78 return result |
| 82 | 79 |
| 83 def runCommand(user, host, command, ignore_errors=False): | 80 def runCommand(user, host, command, ignore_errors=False): |
| 84 if not isinstance(command, list): | 81 if not isinstance(command, list): |
| 85 command = [command] | 82 command = [command] |
| 86 command = ["ssh"] + (["-l", user] if user else []) + [host] + command | 83 command = ["ssh"] + (["-l", user] if user else []) + [host] + command |
| 87 if ignore_errors: | 84 if ignore_errors: |
| 88 subprocess.call(command) | 85 subprocess.call(command) |
| 89 else: | 86 else: |
| 90 subprocess.check_call(command) | 87 subprocess.check_call(command) |
| 91 | 88 |
| 92 if __name__ == "__main__": | 89 if __name__ == "__main__": |
| 93 user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) | 90 user, hosts, ignore_errors, args = parseOptions(sys.argv[1:]) |
| 94 selectedHosts = resolveHostList(hosts) | 91 selectedHosts = resolveHostList(hosts) |
| 95 if len(selectedHosts) == 0: | 92 if len(selectedHosts) == 0: |
| 96 print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' | 93 print >>sys.stderr, 'No valid hosts or groups specified, nothing to do' |
| 97 sys.exit(0) | 94 sys.exit(0) |
| 98 for host in selectedHosts: | 95 for host in selectedHosts: |
| 99 print >>sys.stderr, 'Running on %s...' % host | 96 print >>sys.stderr, 'Running on %s...' % host |
| 100 runCommand(user, host, args, ignore_errors=ignore_errors) | 97 runCommand(user, host, args, ignore_errors=ignore_errors) |
| LEFT | RIGHT |