def __init__(self): if 'HIPCHAT_TOKEN' in os.environ: self.start_time = time.time() self.task_report = [] self.last_task = None self.last_task_changed = False self.last_task_count = 0 self.last_task_delta = 0 self.last_task_start = time.time() self.condensed_task_report = (os.getenv('HIPCHAT_CONDENSED', True) == True) self.room = os.getenv('HIPCHAT_ROOM', 'ansible') self.from_name = os.getenv('HIPCHAT_FROM', 'ansible') self.allow_notify = (os.getenv('HIPCHAT_NOTIFY') != 'false') try: self.hipchat_conn = hipchat.HipChat( token=os.getenv('HIPCHAT_TOKEN')) except Exception as e: utils.warning("Unable to connect to hipchat: {}".format(e)) self.hipchat_msg_prefix = os.getenv('HIPCHAT_MSG_PREFIX', '') self.hipchat_msg_color = os.getenv('HIPCHAT_MSG_COLOR', '') self.printed_playbook = False self.playbook_name = None self.enabled = True else: self.enabled = False
def __init__(self): self.disabled = truthy_string(os.getenv('ANSIBLE_AUDITLOG_DISABLED', 0)) self.log_logname = truthy_string( os.getenv('ANSIBLE_AUDITLOG_LOGNAME_ENABLED', 1)) logdir = os.getenv('ANSIBLE_AUDITLOG_LOGDIR', '/var/log/ansible') audit_vars = os.getenv('ANSIBLE_AUDITLOG_AUDIT_VARS', None) fail_mode = os.getenv('ANSIBLE_AUDITLOG_FAILMODE', 'warn') if self.disabled: utils.warning('Auditlog has been disabled!') return None # Example: version,my.nested.var if audit_vars: # Only allow alphanumeric + _ + . pattern = re.compile('[^\w.,]+', re.UNICODE) self.audit_vars = pattern.sub('', audit_vars).split(',') # convert to dict self.audit_vars = dict((el, 0) for el in self.audit_vars) else: self.audit_vars = {} try: self.logger = JsonAuditLogger(logdir=logdir) except Exception as e: msg = 'Unable to initialize audit logging: {}'.format(str(e)) self.disabled = True utils.warning(msg) if fail_mode == 'fail': print(str(e)) sys.exit(1)
def __init__(self): if "HIPCHAT_TOKEN" in os.environ: self.start_time = time.time() self.task_report = [] self.last_task = None self.last_task_changed = False self.last_task_count = 0 self.last_task_delta = 0 self.last_task_start = time.time() self.condensed_task_report = os.getenv("HIPCHAT_CONDENSED", True) == True self.room = os.getenv("HIPCHAT_ROOM", "ansible") self.from_name = os.getenv("HIPCHAT_FROM", "ansible") self.allow_notify = os.getenv("HIPCHAT_NOTIFY") != "false" try: self.hipchat_conn = hipchat.HipChat(token=os.getenv("HIPCHAT_TOKEN")) except Exception as e: utils.warning("Unable to connect to hipchat: {}".format(e)) self.hipchat_msg_prefix = os.getenv("HIPCHAT_MSG_PREFIX", "") self.hipchat_msg_color = os.getenv("HIPCHAT_MSG_COLOR", "") self.printed_playbook = False self.playbook_name = None self.enabled = True else: self.enabled = False
def __init__(self): self.enabled = "HIPCHAT_TOKEN" in os.environ if not self.enabled: return # make sure we got our imports if not hipchat: raise ImportError( "The hipchat plugin requires the hipchat Python module, " "which is not installed or was not found.") if not prettytable: raise ImportError( "The hipchat plugin requires the prettytable Python module, " "which is not installed or was not found.") self.start_time = time.time() self.task_report = [] self.last_task = None self.last_task_changed = False self.last_task_count = 0 self.last_task_delta = 0 self.last_task_start = time.time() self.condensed_task_report = (os.getenv('HIPCHAT_CONDENSED', True) == True) self.room = os.getenv('HIPCHAT_ROOM', 'ansible') self.from_name = os.getenv('HIPCHAT_FROM', 'ansible') self.allow_notify = (os.getenv('HIPCHAT_NOTIFY') != 'false') try: self.hipchat_conn = hipchat.HipChat( token=os.getenv('HIPCHAT_TOKEN')) except Exception as e: utils.warning("Unable to connect to hipchat: {}".format(e)) self.hipchat_msg_prefix = os.getenv('HIPCHAT_MSG_PREFIX', '') self.hipchat_msg_color = os.getenv('HIPCHAT_MSG_COLOR', '') self.printed_playbook = False self.playbook_name = None
def __init__(self): self.enabled = "HIPCHAT_TOKEN" in os.environ if not self.enabled: return # make sure we got our imports if not hipchat: raise ImportError( "The hipchat plugin requires the hipchat Python module, " "which is not installed or was not found." ) if not prettytable: raise ImportError( "The hipchat plugin requires the prettytable Python module, " "which is not installed or was not found." ) self.start_time = time.time() self.task_report = [] self.last_task = None self.last_task_changed = False self.last_task_count = 0 self.last_task_delta = 0 self.last_task_start = time.time() self.condensed_task_report = os.getenv("HIPCHAT_CONDENSED", True) == True self.room = os.getenv("HIPCHAT_ROOM", "ansible") self.from_name = os.getenv("HIPCHAT_FROM", "ansible") self.allow_notify = os.getenv("HIPCHAT_NOTIFY") != "false" try: self.hipchat_conn = hipchat.HipChat(token=os.getenv("HIPCHAT_TOKEN")) except Exception as e: utils.warning("Unable to connect to hipchat: {}".format(e)) self.hipchat_msg_prefix = os.getenv("HIPCHAT_MSG_PREFIX", "") self.hipchat_msg_color = os.getenv("HIPCHAT_MSG_COLOR", "") self.printed_playbook = False self.playbook_name = None
def __init__(self): self.opsmatic_http = get_config(p, "opsmatic", "opsmatic_http", "OPSMATIC_API_HTTP", "https://api.opsmatic.com") self.token = get_config(p, "opsmatic", "integration_token", "OPSMATIC_INTEGRATION_TOKEN", "") self.have_creds = self.token != "" if not self.have_creds: utils.warning("Opsmatic token is not set, so no events will be sent." "It can be set via the `integration_token` varibale in the [opsmatic] section of ansible.cfg" "OR via the OPSMATIC_INTEGRATION_TOKEN environment variable")
def set(self, key, value): self._cache[key] = value cachefile = "%s/%s" % (self._cache_dir, key) try: f = codecs.open(cachefile, 'w', encoding='utf-8') except (OSError,IOError), e: utils.warning("error while trying to write to %s : %s" % (cachefile, str(e)))
def has_expired(self, key): cachefile = "%s/%s" % (self._cache_dir, key) try: st = os.stat(cachefile) except (OSError,IOError), e: if e.errno == errno.ENOENT: return False else: utils.warning("error while trying to stat %s : %s" % (cachefile, str(e)))
def set(self, key, value): self._cache[key] = value cachefile = "%s/%s" % (self._cache_dir, key) try: #TODO: check if valid keys can have invalid FS chars, base32? f = open(cachefile, 'w') except (OSError,IOError), e: utils.warning("error while trying to read %s : %s" % (cachefile, str(e)))
def __init__(self): self.insights_token = os.getenv('NR_INSIGHTS_TOKEN') self.post_uri = os.getenv('NR_INSIGHTS_URI') self.user = getpass.getuser() if self.insights_token is None or self.post_uri is None: self.disabled = True utils.warning('New Relic Insights token or Post URI could not be loaded. The NR Insights ' 'token and URI can be provided using the `NR_INSIGHTS_TOKEN` and `NR_INSIGHTS_URI`' 'environment variables.')
def set(self, key, value): self._cache[key] = value cachefile = "%s/%s" % (self._cache_dir, key) try: #TODO: check if valid keys can have invalid FS chars, base32? f = open(cachefile, 'w') except (OSError, IOError), e: utils.warning("error while trying to read %s : %s" % (cachefile, str(e)))
def _send_hipchat(self, message, room=None, from_name=None, color=None, message_format="text"): if not room: room = self.room if not from_name: from_name = self.from_name if not color: color = self.hipchat_msg_color try: self.hipchat_conn.message_room(room, from_name, message, color=color, message_format=message_format) except Exception as e: utils.warning("Could not submit message to hipchat: {}".format(e))
def __init__(self, *args, **kwargs): self._timeout = float(C.CACHE_PLUGIN_TIMEOUT) self._cache = {} self._cache_dir = C.CACHE_PLUGIN_CONNECTION # expects a dir path if not os.path.exists(self._cache_dir): try: os.makedirs(self._cache_dir) except (OSError,IOError), e: utils.warning("error while trying to create cache dir %s : %s" % (self._cache_dir, str(e))) return None
def get(self, key): if key in self._cache: return self._cache.get(key) if self.has_expired(key): raise KeyError cachefile = "%s/%s" % (self._cache_dir, key) try: f = codecs.open(cachefile, 'r', encoding='utf-8') except (OSError,IOError), e: utils.warning("error while trying to read %s : %s" % (cachefile, str(e)))
def get(self, key): if key in self._cache: return self._cache.get(key) if self.has_expired(key): raise KeyError cachefile = "%s/%s" % (self._cache_dir, key) try: f = open( cachefile, 'r') except (OSError,IOError), e: utils.warning("error while trying to write to %s : %s" % (cachefile, str(e)))
def get(self, key): if key in self._cache: return self._cache.get(key) if self.has_expired(key): raise KeyError cachefile = "%s/%s" % (self._cache_dir, key) try: f = open(cachefile, 'r') except (OSError, IOError), e: utils.warning("error while trying to write to %s : %s" % (cachefile, str(e)))
def __init__(self, *args, **kwargs): self._timeout = float(C.CACHE_PLUGIN_TIMEOUT) self._cache = {} self._cache_dir = C.CACHE_PLUGIN_CONNECTION # expects a dir path if not os.path.exists(self._cache_dir): try: os.makedirs(self._cache_dir) except (OSError, IOError), e: utils.warning( "error while trying to create cache dir %s : %s" % (self._cache_dir, str(e))) return None
def __init__(self, *args, **kwargs): self._timeout = float(C.CACHE_PLUGIN_TIMEOUT) self._cache = {} self._cache_dir = os.path.expandvars(os.path.expanduser(C.CACHE_PLUGIN_CONNECTION)) # expects a dir path if not self._cache_dir: utils.exit("error, fact_caching_connection is not set, cannot use fact cache") if not os.path.exists(self._cache_dir): try: os.makedirs(self._cache_dir) except (OSError,IOError), e: utils.warning("error while trying to create cache dir %s : %s" % (self._cache_dir, str(e))) return None
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) if isinstance(terms, basestring): terms = [terms] validate_certs = kwargs.get('validate_certs', True) ret = [] for term in terms: try: response = open_url(term, validate_certs=validate_certs) except urllib2.URLError as e: utils.warning("Failed lookup url for %s : %s" % (term, str(e))) continue except urllib2.HTTPError as e: utils.warning("Received HTTP error for %s : %s" % (term, str(e))) continue except SSLValidationError as e: utils.warning( "Error validating the server's certificate for %s: %s" % (term, str(e))) continue except ConnectionError as e: utils.warning("Error connecting to %s: %s" % (term, str(e))) continue for line in response.read().splitlines(): ret.append(to_unicode(line)) return ret
def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) if isinstance(terms, basestring): terms = [ terms ] validate_certs = kwargs.get('validate_certs', True) ret = [] for term in terms: try: response = open_url(term, validate_certs=validate_certs) except urllib2.URLError as e: utils.warning("Failed lookup url for %s : %s" % (term, str(e))) continue except urllib2.HTTPError as e: utils.warning("Received HTTP error for %s : %s" % (term, str(e))) continue except SSLValidationError as e: utils.warning("Error validating the server's certificate for %s: %s" % (term, str(e))) continue except ConnectionError as e: utils.warning("Error connecting to %s: %s" % (term, str(e))) continue for line in response.read().splitlines(): ret.append(to_unicode(line)) return ret
def send_msg(self, msg): if not self.disabled: # JSON headers headers = { 'Content-type': 'application/json', 'Accept': 'text/plain' } # Send message to Slack endpoint try: response = requests.post(self.slack_endpoint, data=json.dumps(msg), headers=headers) except: utils.warning('Could not submit message to slack')
def contains(self, key): if key in self._cache: return True if self.has_expired(key): return False try: st = os.stat("%s/%s" % (self._cache_dir, key)) return True except (OSError,IOError), e: if e.errno == errno.ENOENT: return False else: utils.warning("error while trying to stat %s : %s" % (cachefile, str(e)))
def contains(self, key): if key in self._cache: return True if self.has_expired(key): return False try: st = os.stat("%s/%s" % (self._cache_dir, key)) return True except (OSError, IOError), e: if e.errno == errno.ENOENT: return False else: utils.warning("error while trying to stat %s : %s" % (cachefile, str(e)))
def send_msg(self, msg, notify=False): """Method for sending a message to Slack""" params = {} params['channel'] = self.channel params['username'] = self.username[:15] # max length is 15 params['text'] = msg url = ('%s%s' % (self.msg_uri, self.token)) try: data = json.dumps(params) req = urllib2.Request(url, data) response = urllib2.urlopen(req) return response.read() except: utils.warning('Could not submit message to Slack')
def send_msg(self, msg, msg_format='text', color='yellow', notify=False): """Method for sending a message to HipChat""" params = {} params['room_id'] = self.room params['from'] = self.from_name[:15] # max length is 15 params['message'] = msg params['message_format'] = msg_format params['color'] = color params['notify'] = int(notify) url = ('%s?auth_token=%s' % (self.msg_uri, self.token)) try: response = urllib2.urlopen(url, urllib.urlencode(params)) return response.read() except: utils.warning('Could not submit message to hipchat')
def send_msg(self, msg, msg_format='text', color='yellow', notify=False): """Method for sending a message to HipChat""" params = {} params['room_id'] = self.room params['from'] = self.from_name[:15] # max length is 15 params['message'] = msg params['message_format'] = msg_format params['color'] = color params['notify'] = int(self.allow_notify and notify) url = ('%s?auth_token=%s' % (self.msg_uri, self.token)) try: response = open_url(url, data=urllib.urlencode(params)) return response.read() except: utils.warning('Could not submit message to hipchat')
def __init__(self): if not HAS_PRETTYTABLE: self.disabled = True utils.warning('The `prettytable` python module is not installed. ' 'Disabling the HipChat callback plugin.') self.msg_uri = 'https://api.hipchat.com/v1/rooms/message' self.token = os.getenv('HIPCHAT_TOKEN') self.room = os.getenv('HIPCHAT_ROOM', 'ansible') self.from_name = os.getenv('HIPCHAT_FROM', 'ansible') if self.token is None: self.disabled = True utils.warning('HipChat token could not be loaded. The HipChat ' 'token can be provided using the `HIPCHAT_TOKEN` ' 'environment variable.') self.printed_playbook = False self.playbook_name = None
def __init__(self): if not HAS_PRETTYTABLE: self.disabled = True utils.warning('The `prettytable` python module is not installed. ' 'Disabling the HipChat callback plugin.') self.msg_uri = 'https://api.hipchat.com/v1/rooms/message' self.token = os.getenv('HIPCHAT_TOKEN') self.room = os.getenv('HIPCHAT_ROOM', 'ansible') self.from_name = os.getenv('HIPCHAT_FROM', 'ansible') self.allow_notify = (os.getenv('HIPCHAT_NOTIFY') != 'false') if self.token is None: self.disabled = True utils.warning('HipChat token could not be loaded. The HipChat ' 'token can be provided using the `HIPCHAT_TOKEN` ' 'environment variable.') self.printed_playbook = False self.playbook_name = None
def __init__(self, *args, **kwargs): self._timeout = float(C.CACHE_PLUGIN_TIMEOUT) self._cache = {} self._cache_dir = os.path.expandvars( os.path.expanduser( C.CACHE_PLUGIN_CONNECTION)) # expects a dir path if not self._cache_dir: utils.exit( "error, fact_caching_connection is not set, cannot use fact cache" ) if not os.path.exists(self._cache_dir): try: os.makedirs(self._cache_dir) except (OSError, IOError), e: utils.warning( "error while trying to create cache dir %s : %s" % (self._cache_dir, str(e))) return None
def _send_hipchat(self, message, room=None, from_name=None, color=None, message_format='text'): if not room: room = self.room if not from_name: from_name = self.from_name if not color: color = self.hipchat_msg_color try: self.hipchat_conn.message_room(room, from_name, message, color=color, message_format=message_format) except Exception as e: utils.warning("Could not submit message to hipchat: {}".format(e))
def __init__(self): if not HAS_PRETTYTABLE: self.disabled = True utils.warning('The `prettytable` python module is not installed. ' 'Disabling the Slack callback plugin.') self.msg_uri = 'https://hooks.slack.com/services/' self.token = os.getenv('SLACK_TOKEN') self.channel = os.getenv('SLACK_CHANNEL', '#ansible') self.username = os.getenv('SLACK_FROM', 'ansible') self.allow_notify = (os.getenv('SLACK_NOTIFY') != 'false') if self.token is None: self.disabled = True utils.warning('Slack token could not be loaded. The Slack ' 'token can be provided using the `SLACK_TOKEN` ' 'environment variable.') self.printed_playbook = False self.playbook_name = None self.template_name = 'Ansible Job'
def load_values(self): self.is_git_repo = self.__git_data('rev-parse --git-dir') == '.git' self.playbook = self.play.playbook self.inventory = self.playbook.inventory self.hosts = self.inventory.get_hosts() self.vars = self.playbook.extra_vars self.vars.update(self.inventory.get_variables(self.hosts[0].name)) self.slack_endpoint = self.vars.get('slack_endpoint') self.disabled = self.vars.get('disable_slack') self.playbook_name = os.path.basename(self.playbook.filename) self.host_list = self.inventory.host_list self.subset = ', '.join( self.inventory._subset) if self.inventory._subset else "--" self.tags = ', '.join( self.playbook.only_tags) if self.playbook.only_tags else "--" self.skip_tags = ', '.join( self.playbook.skip_tags) if self.playbook.skip_tags else "--" self.user = self.playbook.remote_user self.is_test = self.playbook.check self.run_id = datetime.now().isoformat() self.run_host = self.__get_run_host() self.ansible_version = utils.version_info(True)['string'] if self.is_git_repo: git_sha = self.__git_data('log -n1 --pretty=format:%H') git_decoration = self.__git_data('log -n1 --pretty=format:%d') git_dirty = self.__git_data('status --porcelain') self.git_sha = git_sha()[0] self.git_decoration = git_decoration()[0] self.git_dirty = git_dirty() self.git_repo_name = self.__git_repo_name() if self.disabled: utils.warning('Not posting to slack with disable_slack=yes')
def playbook_on_play_start(self, name): play_vars = merge_hash(self.play.vars, getattr(self.play, 'vars_file_vars', {})) play_vars = merge_hash(play_vars, getattr(self.playbook, 'extra_vars', {})) pem = play_vars.get('creds_ssh_private_key', None) if pem is None: return key = RSAKey.from_private_key(StringIO.StringIO(pem)) hexdigest = unpack('16B', key.get_fingerprint()) hexdigest = ':'.join(['%02x' % x for x in hexdigest]) display('Loading SSH private key %s' % hexdigest) pub = '%s %s %s' % (key.get_name(), key.get_base64(), self.KEY_COMMENT) for x in self.play.tasks() + self.play.handlers(): y = getattr(x, 'module_vars', None) if y: y['creds_ssh_public_key'] = pub ssh_agent = play_vars.get('creds_ssh_agent', True) if not ssh_agent: return msg = Message() msg.add_byte(chr(self.SSH2_AGENTC_ADD_IDENTITY)) msg.add_string(key.get_name()) msg.add_mpint(key.n) msg.add_mpint(key.e) msg.add_mpint(key.d) msg.add_mpint(0) msg.add_mpint(key.p) msg.add_mpint(key.q) msg.add_string(self.KEY_COMMENT) agent = Agent() if agent._conn: agent._send_message(msg) else: warning('Failed to connect to ssh-agent') agent.close()
def load_values(self): self.is_git_repo = self.__git_data('rev-parse --git-dir') == '.git' self.playbook = self.play.playbook self.inventory = self.playbook.inventory self.hosts = self.inventory.get_hosts() self.vars = self.playbook.extra_vars self.vars.update(self.inventory.get_variables(self.hosts[0].name)) self.slack_endpoint = self.vars.get('slack_endpoint') self.disabled = self.vars.get('disable_slack') self.playbook_name = os.path.basename(self.playbook.filename) self.host_list = self.inventory.host_list self.subset = ', '.join(self.inventory._subset) if self.inventory._subset else "--" self.tags = ', '.join(self.playbook.only_tags) if self.playbook.only_tags else "--" self.skip_tags = ', '.join(self.playbook.skip_tags) if self.playbook.skip_tags else "--" self.user = self.playbook.remote_user self.is_test = self.playbook.check self.run_id = datetime.now().isoformat() self.run_host = self.__get_run_host() self.ansible_version = utils.version_info(True)['string'] if self.is_git_repo: git_sha = self.__git_data('log -n1 --pretty=format:%H') git_decoration = self.__git_data('log -n1 --pretty=format:%d') git_dirty = self.__git_data('status --porcelain') self.git_sha = git_sha()[0] self.git_decoration = git_decoration()[0] self.git_dirty = git_dirty() self.git_repo_name = self.__git_repo_name() if self.disabled: utils.warning('Not posting to slack with disable_slack=yes')
def main(args): ''' run ansible-playbook operations ''' ## truiz: here I add options that will become parameters in the function ## truiz: extra vars is dict with the vars and values extra_vars = {'host': 'testing', 'vars_file': 'the_vars.yml'} print extra_vars ## truiz: this is just a list of playbooks playbooks = ['ansible/the_work.yml'] ## truiz: The file with hosts and their vars inventory_file = 'ansible/inventory' ## truiz: this could be an usefull parameter timeout = 10 # create parser for CLI options parser = utils.base_parser( constants=C, usage = "%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True ) parser.add_option('--vault-password', dest="vault_password", help="password for vault encrypted files") parser.add_option('--syntax-check', dest='syntax', action='store_true', help="perform a syntax check on the playbook, but do not execute it") parser.add_option('--list-tasks', dest='listtasks', action='store_true', help="list all tasks that would be executed") parser.add_option('--list-tags', dest='listtags', action='store_true', help="list all available tags") parser.add_option('--start-at-task', dest='start_at', help="start the playbook at the task matching this name") parser.add_option('--force-handlers', dest='force_handlers', default=C.DEFAULT_FORCE_HANDLERS, action='store_true', help="run handlers even if a task fails") parser.add_option('--flush-cache', dest='flush_cache', action='store_true', help="clear the fact cache") options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 # privlege escalation command line arguments need to be mutually exclusive # utils.check_mutually_exclusive_privilege(options, parser) # if (options.ask_vault_pass and options.vault_password_file): # parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive") sshpass = None becomepass = None vault_pass = None # options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS # if options.listhosts or options.syntax or options.listtasks or options.listtags: # (_, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass) # else: # options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS # # Never ask for an SSH password when we run with local connection # if options.connection == "local": # options.ask_pass = False # # set pe options # utils.normalize_become_options(options) # prompt_method = utils.choose_pass_prompt(options) # (sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, # become_ask_pass=options.become_ask_pass, # ask_vault_pass=options.ask_vault_pass, # become_method=prompt_method) # read vault_pass from a file # if not options.ask_vault_pass and options.vault_password_file: # vault_pass = utils.read_vault_file(options.vault_password_file) for playbook in playbooks: print playbook if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % playbook) if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError("the playbook: %s does not appear to be a file" % playbook) ## truiz: is better to pass the inventory file inventory = ansible.inventory.Inventory(inventory_file, vault_password=vault_pass) print options.inventory print inventory # Note: slightly wrong, this is written so that implicit localhost # (which is not returned in list_hosts()) is taken into account for # warning if inventory is empty. But it can't be taken into account for # checking if limit doesn't match any hosts. Instead we don't worry about # limit if only implicit localhost was in inventory to start with. # # Fix this in v2 no_hosts = False if len(inventory.list_hosts()) == 0: # Empty inventory utils.warning("provided hosts list is empty, only localhost is available") no_hosts = True #print options.subset #inventory.subset(options.subset) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit raise errors.AnsibleError("Specified --limit does not match any hosts") print options.become print options.become_user print options.remote_user print options.timeout print becomepass for playbook in playbooks: stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) print runner_cb pb = ansible.playbook.PlayBook( playbook=playbook, # module_path=options.module_path, inventory=inventory, # forks=options.forks, # remote_user=options.remote_user, # remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=timeout, # transport=options.connection, #become=options.become, become_method='sudo', become_user=options.become_user, # become_pass=becomepass, extra_vars=extra_vars, private_key_file=options.private_key_file, # only_tags=only_tags, # skip_tags=skip_tags, check=options.check, diff=options.diff, # vault_password=vault_pass, force_handlers=options.force_handlers, ) # if options.flush_cache: # display(callbacks.banner("FLUSHING FACT CACHE")) # pb.SETUP_CACHE.flush() # if options.listhosts or options.listtasks or options.syntax or options.listtags: # print '' # print 'playbook: %s' % playbook # print '' # playnum = 0 # for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs): # playnum += 1 # play = ansible.playbook.Play(pb, play_ds, play_basedir, # vault_password=pb.vault_password) # label = play.name # hosts = pb.inventory.list_hosts(play.hosts) # if options.listhosts: # print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts)) # for host in hosts: # print ' %s' % host # if options.listtags or options.listtasks: # print ' play #%d (%s):\tTAGS: [%s]' % (playnum, label,','.join(sorted(set(play.tags)))) # if options.listtags: # tags = [] # for task in pb.tasks_to_run_in_play(play): # tags.extend(task.tags) # print ' TASK TAGS: [%s]' % (', '.join(sorted(set(tags).difference(['untagged'])))) # if options.listtasks: # for task in pb.tasks_to_run_in_play(play): # if getattr(task, 'name', None) is not None: # # meta tasks have no names # print ' %s\tTAGS: [%s]' % (task.name, ', '.join(sorted(set(task.tags).difference(['untagged'])))) # if options.listhosts or options.listtasks or options.listtags: # print '' # continue # if options.syntax: # # if we've not exited by now then we are fine. # print 'Playbook Syntax is fine' # return 0 failed_hosts = [] unreachable_hosts = [] try: print "Before run" res = pb.run() print "After run" ## truiz: returns a resume of all work done print res hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if C.RETRY_FILES_ENABLED and len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % ( hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True ) display("%s : %s %s %s %s" % ( hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True ) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1
def __init__(self, play, ds, module_vars=None, default_vars=None, additional_conditions=None, role_name=None): ''' constructor loads from a task or handler datastructure ''' # meta directives are used to tell things like ansible/playbook to run # operations like handler execution. Meta tasks are not executed # normally. if 'meta' in ds: self.meta = ds['meta'] self.tags = [] return else: self.meta = None library = os.path.join(play.basedir, 'library') if os.path.exists(library): utils.plugins.module_finder.add_directory(library) for x in ds.keys(): # code to allow for saying "modulename: args" versus "action: modulename args" if x in utils.plugins.module_finder: if 'action' in ds: raise errors.AnsibleError("multiple actions specified in task %s" % (ds.get('name', ds['action']))) if isinstance(ds[x], dict): if 'args' in ds: raise errors.AnsibleError("can't combine args: and a dict for %s: in task %s" % (x, ds.get('name', "%s: %s" % (x, ds[x])))) ds['args'] = ds[x] ds[x] = '' elif ds[x] is None: ds[x] = '' if not isinstance(ds[x], basestring): raise errors.AnsibleError("action specified for task %s has invalid type %s" % (ds.get('name', "%s: %s" % (x, ds[x])), type(ds[x]))) ds['action'] = x + " " + ds[x] ds.pop(x) # code to allow "with_glob" and to reference a lookup plugin named glob elif x.startswith("with_"): if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unneccessary to use '{{' in loops, leave variables in loop expressions bare.") plugin_name = x.replace("with_","") if plugin_name in utils.plugins.lookup_loader: ds['items_lookup_plugin'] = plugin_name ds['items_lookup_terms'] = ds[x] ds.pop(x) else: raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name)) elif x in [ 'changed_when', 'failed_when', 'when']: if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unneccessary to use '{{' in conditionals, leave variables in loop expressions bare.") ds[x] = "jinja2_compare %s" % (ds[x]) elif x.startswith("when_"): utils.deprecated("The 'when_' conditional is a deprecated syntax as of 1.2. Switch to using the regular unified 'when' statements as described in ansibleworks.com/docs/.","1.5") if 'when' in ds: raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) when_name = x.replace("when_","") ds['when'] = "%s %s" % (when_name, ds[x]) ds.pop(x) elif not x in Task.VALID_KEYS: raise errors.AnsibleError("%s is not a legal parameter in an Ansible task or handler" % x) self.module_vars = module_vars self.default_vars = default_vars self.play = play # load various attributes self.name = ds.get('name', None) self.tags = [ 'all' ] self.register = ds.get('register', None) self.sudo = utils.boolean(ds.get('sudo', play.sudo)) self.environment = ds.get('environment', {}) self.role_name = role_name #Code to allow do until feature in a Task if 'until' in ds: if not ds.get('register'): raise errors.AnsibleError("register keyword is mandatory when using do until feature") self.module_vars['delay'] = ds.get('delay', 5) self.module_vars['retries'] = ds.get('retries', 3) self.module_vars['register'] = ds.get('register', None) self.until = "jinja2_compare %s" % (ds.get('until')) self.module_vars['until'] = utils.compile_when_to_only_if(self.until) # rather than simple key=value args on the options line, these represent structured data and the values # can be hashes and lists, not just scalars self.args = ds.get('args', {}) # get remote_user for task, then play, then playbook if ds.get('remote_user') is not None: self.remote_user = ds.get('remote_user') elif ds.get('remote_user', play.remote_user) is not None: self.remote_user = ds.get('remote_user', play.remote_user) else: self.remote_user = ds.get('remote_user', play.playbook.remote_user) if self.sudo: self.sudo_user = ds.get('sudo_user', play.sudo_user) self.sudo_pass = ds.get('sudo_pass', play.playbook.sudo_pass) else: self.sudo_user = None self.sudo_pass = None # Both are defined if ('action' in ds) and ('local_action' in ds): raise errors.AnsibleError("the 'action' and 'local_action' attributes can not be used together") # Both are NOT defined elif (not 'action' in ds) and (not 'local_action' in ds): raise errors.AnsibleError("'action' or 'local_action' attribute missing in task \"%s\"" % ds.get('name', '<Unnamed>')) # Only one of them is defined elif 'local_action' in ds: self.action = ds.get('local_action', '') self.delegate_to = '127.0.0.1' else: self.action = ds.get('action', '') self.delegate_to = ds.get('delegate_to', None) self.transport = ds.get('connection', ds.get('transport', play.transport)) if isinstance(self.action, dict): if 'module' not in self.action: raise errors.AnsibleError("'module' attribute missing from action in task \"%s\"" % ds.get('name', '%s' % self.action)) if self.args: raise errors.AnsibleError("'args' cannot be combined with dict 'action' in task \"%s\"" % ds.get('name', '%s' % self.action)) self.args = self.action self.action = self.args.pop('module') # delegate_to can use variables if not (self.delegate_to is None): # delegate_to: localhost should use local transport if self.delegate_to in ['127.0.0.1', 'localhost']: self.transport = 'local' # notified by is used by Playbook code to flag which hosts # need to run a notifier self.notified_by = [] # if no name is specified, use the action line as the name if self.name is None: self.name = self.action # load various attributes self.only_if = ds.get('only_if', 'True') if self.only_if != 'True': utils.deprecated("only_if is a very old feature and has been obsolete since 0.9, please switch to the 'when' conditional as described at http://ansibleworks.com/docs","1.5") self.when = ds.get('when', None) self.changed_when = ds.get('changed_when', None) if self.changed_when is not None: self.changed_when = utils.compile_when_to_only_if(self.changed_when) self.failed_when = ds.get('failed_when', None) if self.failed_when is not None: self.failed_when = utils.compile_when_to_only_if(self.failed_when) self.async_seconds = int(ds.get('async', 0)) # not async by default self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds self.notify = ds.get('notify', []) self.first_available_file = ds.get('first_available_file', None) self.items_lookup_plugin = ds.get('items_lookup_plugin', None) self.items_lookup_terms = ds.get('items_lookup_terms', None) self.ignore_errors = ds.get('ignore_errors', False) self.any_errors_fatal = ds.get('any_errors_fatal', play.any_errors_fatal) self.always_run = ds.get('always_run', False) # action should be a string if not isinstance(self.action, basestring): raise errors.AnsibleError("action is of type '%s' and not a string in task. name: %s" % (type(self.action).__name__, self.name)) # notify can be a string or a list, store as a list if isinstance(self.notify, basestring): self.notify = [ self.notify ] # split the action line into a module name + arguments tokens = self.action.split(None, 1) if len(tokens) < 1: raise errors.AnsibleError("invalid/missing action in task. name: %s" % self.name) self.module_name = tokens[0] self.module_args = '' if len(tokens) > 1: self.module_args = tokens[1] import_tags = self.module_vars.get('tags',[]) if type(import_tags) in [int,float]: import_tags = str(import_tags) elif type(import_tags) in [str,unicode]: # allow the user to list comma delimited tags import_tags = import_tags.split(",") # handle mutually incompatible options incompatibles = [ x for x in [ self.first_available_file, self.items_lookup_plugin ] if x is not None ] if len(incompatibles) > 1: raise errors.AnsibleError("with_(plugin), and first_available_file are mutually incompatible in a single task") # make first_available_file accessable to Runner code if self.first_available_file: self.module_vars['first_available_file'] = self.first_available_file if self.items_lookup_plugin is not None: self.module_vars['items_lookup_plugin'] = self.items_lookup_plugin self.module_vars['items_lookup_terms'] = self.items_lookup_terms # allow runner to see delegate_to option self.module_vars['delegate_to'] = self.delegate_to # make some task attributes accessible to Runner code self.module_vars['ignore_errors'] = self.ignore_errors self.module_vars['register'] = self.register self.module_vars['changed_when'] = self.changed_when self.module_vars['failed_when'] = self.failed_when self.module_vars['always_run'] = self.always_run # tags allow certain parts of a playbook to be run without running the whole playbook apply_tags = ds.get('tags', None) if apply_tags is not None: if type(apply_tags) in [ str, unicode ]: self.tags.append(apply_tags) elif type(apply_tags) in [ int, float ]: self.tags.append(str(apply_tags)) elif type(apply_tags) == list: self.tags.extend(apply_tags) self.tags.extend(import_tags) if self.when is not None: if self.only_if != 'True': raise errors.AnsibleError('when obsoletes only_if, only use one or the other') self.only_if = utils.compile_when_to_only_if(self.when) if additional_conditions: new_conditions = additional_conditions new_conditions.append(self.only_if) self.only_if = new_conditions
def __init__(self, play, ds, module_vars=None, play_vars=None, play_file_vars=None, role_vars=None, role_params=None, default_vars=None, additional_conditions=None, role_name=None): ''' constructor loads from a task or handler datastructure ''' # meta directives are used to tell things like ansible/playbook to run # operations like handler execution. Meta tasks are not executed # normally. if 'meta' in ds: self.meta = ds['meta'] self.tags = [] return else: self.meta = None library = os.path.join(play.basedir, 'library') if os.path.exists(library): utils.plugins.module_finder.add_directory(library) for x in ds.keys(): # code to allow for saying "modulename: args" versus "action: modulename args" if x in utils.plugins.module_finder: if 'action' in ds: raise errors.AnsibleError( "multiple actions specified in task: '%s' and '%s'" % (x, ds.get('name', ds['action']))) if isinstance(ds[x], dict): if 'args' in ds: raise errors.AnsibleError( "can't combine args: and a dict for %s: in task %s" % (x, ds.get('name', "%s: %s" % (x, ds[x])))) ds['args'] = ds[x] ds[x] = '' elif ds[x] is None: ds[x] = '' if not isinstance(ds[x], basestring): raise errors.AnsibleError( "action specified for task %s has invalid type %s" % (ds.get('name', "%s: %s" % (x, ds[x])), type(ds[x]))) ds['action'] = x + " " + ds[x] ds.pop(x) # code to allow "with_glob" and to reference a lookup plugin named glob elif x.startswith("with_"): if isinstance(ds[x], basestring): param = ds[x].strip() # Only a variable, no logic if (param.startswith('{{') and param.find('}}') == len(ds[x]) - 2 and param.find('|') == -1): utils.warning( "It is unnecessary to use '{{' in loops, leave variables in loop expressions bare." ) plugin_name = x.replace("with_", "") if plugin_name in utils.plugins.lookup_loader: ds['items_lookup_plugin'] = plugin_name ds['items_lookup_terms'] = ds[x] ds.pop(x) else: raise errors.AnsibleError( "cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name)) elif x in ['changed_when', 'failed_when', 'when']: if isinstance(ds[x], basestring): param = ds[x].strip() # Only a variable, no logic if (param.startswith('{{') and param.find('}}') == len(ds[x]) - 2 and param.find('|') == -1): utils.warning( "It is unnecessary to use '{{' in conditionals, leave variables in loop expressions bare." ) elif x.startswith("when_"): utils.deprecated( "The 'when_' conditional has been removed. Switch to using the regular unified 'when' statements as described on docs.ansible.com.", "1.5", removed=True) if 'when' in ds: raise errors.AnsibleError( "multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) when_name = x.replace("when_", "") ds['when'] = "%s %s" % (when_name, ds[x]) ds.pop(x) elif not x in Task.VALID_KEYS: raise errors.AnsibleError( "%s is not a legal parameter in an Ansible task or handler" % x) self.module_vars = module_vars self.play_vars = play_vars self.play_file_vars = play_file_vars self.role_vars = role_vars self.role_params = role_params self.default_vars = default_vars self.play = play # load various attributes self.name = ds.get('name', None) self.tags = ['all'] self.register = ds.get('register', None) self.sudo = utils.boolean(ds.get('sudo', play.sudo)) self.su = utils.boolean(ds.get('su', play.su)) self.environment = ds.get('environment', {}) self.role_name = role_name self.no_log = utils.boolean(ds.get('no_log', "false")) or self.play.no_log self.run_once = utils.boolean(ds.get('run_once', 'false')) #Code to allow do until feature in a Task if 'until' in ds: if not ds.get('register'): raise errors.AnsibleError( "register keyword is mandatory when using do until feature" ) self.module_vars['delay'] = ds.get('delay', 5) self.module_vars['retries'] = ds.get('retries', 3) self.module_vars['register'] = ds.get('register', None) self.until = ds.get('until') self.module_vars['until'] = self.until # rather than simple key=value args on the options line, these represent structured data and the values # can be hashes and lists, not just scalars self.args = ds.get('args', {}) # get remote_user for task, then play, then playbook if ds.get('remote_user') is not None: self.remote_user = ds.get('remote_user') elif ds.get('remote_user', play.remote_user) is not None: self.remote_user = ds.get('remote_user', play.remote_user) else: self.remote_user = ds.get('remote_user', play.playbook.remote_user) self.sudo_user = None self.sudo_pass = None self.su_user = None self.su_pass = None if self.sudo: self.sudo_user = ds.get('sudo_user', play.sudo_user) self.sudo_pass = ds.get('sudo_pass', play.playbook.sudo_pass) elif self.su: self.su_user = ds.get('su_user', play.su_user) self.su_pass = ds.get('su_pass', play.playbook.su_pass) # Fail out if user specifies a sudo param with a su param in a given play if (ds.get('sudo') or ds.get('sudo_user') or ds.get('sudo_pass')) and \ (ds.get('su') or ds.get('su_user') or ds.get('su_pass')): raise errors.AnsibleError( 'sudo params ("sudo", "sudo_user", "sudo_pass") ' 'and su params "su", "su_user", "su_pass") ' 'cannot be used together') # Both are defined if ('action' in ds) and ('local_action' in ds): raise errors.AnsibleError( "the 'action' and 'local_action' attributes can not be used together" ) # Both are NOT defined elif (not 'action' in ds) and (not 'local_action' in ds): raise errors.AnsibleError( "'action' or 'local_action' attribute missing in task \"%s\"" % ds.get('name', '<Unnamed>')) # Only one of them is defined elif 'local_action' in ds: self.action = ds.get('local_action', '') self.delegate_to = '127.0.0.1' else: self.action = ds.get('action', '') self.delegate_to = ds.get('delegate_to', None) self.transport = ds.get('connection', ds.get('transport', play.transport)) if isinstance(self.action, dict): if 'module' not in self.action: raise errors.AnsibleError( "'module' attribute missing from action in task \"%s\"" % ds.get('name', '%s' % self.action)) if self.args: raise errors.AnsibleError( "'args' cannot be combined with dict 'action' in task \"%s\"" % ds.get('name', '%s' % self.action)) self.args = self.action self.action = self.args.pop('module') # delegate_to can use variables if not (self.delegate_to is None): # delegate_to: localhost should use local transport if self.delegate_to in ['127.0.0.1', 'localhost']: self.transport = 'local' # notified by is used by Playbook code to flag which hosts # need to run a notifier self.notified_by = [] # if no name is specified, use the action line as the name if self.name is None: self.name = self.action # load various attributes self.when = ds.get('when', None) self.changed_when = ds.get('changed_when', None) self.failed_when = ds.get('failed_when', None) # combine the default and module vars here for use in templating all_vars = self.default_vars.copy() all_vars = utils.combine_vars(all_vars, self.play_vars) all_vars = utils.combine_vars(all_vars, self.play_file_vars) all_vars = utils.combine_vars(all_vars, self.role_vars) all_vars = utils.combine_vars(all_vars, self.module_vars) all_vars = utils.combine_vars(all_vars, self.role_params) self.async_seconds = ds.get('async', 0) # not async by default self.async_seconds = template.template_from_string( play.basedir, self.async_seconds, all_vars) self.async_seconds = int(self.async_seconds) self.async_poll_interval = ds.get('poll', 10) # default poll = 10 seconds self.async_poll_interval = template.template_from_string( play.basedir, self.async_poll_interval, all_vars) self.async_poll_interval = int(self.async_poll_interval) self.notify = ds.get('notify', []) self.first_available_file = ds.get('first_available_file', None) self.items_lookup_plugin = ds.get('items_lookup_plugin', None) self.items_lookup_terms = ds.get('items_lookup_terms', None) self.ignore_errors = ds.get('ignore_errors', False) self.any_errors_fatal = ds.get('any_errors_fatal', play.any_errors_fatal) self.always_run = ds.get('always_run', False) # action should be a string if not isinstance(self.action, basestring): raise errors.AnsibleError( "action is of type '%s' and not a string in task. name: %s" % (type(self.action).__name__, self.name)) # notify can be a string or a list, store as a list if isinstance(self.notify, basestring): self.notify = [self.notify] # split the action line into a module name + arguments try: tokens = split_args(self.action) except Exception, e: if "unbalanced" in str(e): raise errors.AnsibleError("There was an error while parsing the task %s.\n" % repr(self.action) + \ "Make sure quotes are matched or escaped properly") else: raise
def main(args): ''' run ansible-playbook operations ''' # create parser for CLI options parser = utils.base_parser( constants=C, usage = "%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True ) #parser.add_option('--vault-password', dest="vault_password", # help="password for vault encrypted files") parser.add_option('-t', '--tags', dest='tags', default='all', help="only run plays and tasks tagged with these values") parser.add_option('--skip-tags', dest='skip_tags', help="only run plays and tasks whose tags do not match these values") parser.add_option('--syntax-check', dest='syntax', action='store_true', help="perform a syntax check on the playbook, but do not execute it") parser.add_option('--list-tasks', dest='listtasks', action='store_true', help="list all tasks that would be executed") parser.add_option('--list-tags', dest='listtags', action='store_true', help="list all available tags") parser.add_option('--step', dest='step', action='store_true', help="one-step-at-a-time: confirm each task before running") parser.add_option('--start-at-task', dest='start_at', help="start the playbook at the task matching this name") parser.add_option('--force-handlers', dest='force_handlers', default=C.DEFAULT_FORCE_HANDLERS, action='store_true', help="run handlers even if a task fails") parser.add_option('--flush-cache', dest='flush_cache', action='store_true', help="clear the fact cache") options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 # privlege escalation command line arguments need to be mutually exclusive utils.check_mutually_exclusive_privilege(options, parser) if (options.ask_vault_pass and options.vault_password_file): parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive") sshpass = None becomepass = None vault_pass = None options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS if options.listhosts or options.syntax or options.listtasks or options.listtags: (_, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass) else: options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS # Never ask for an SSH password when we run with local connection if options.connection == "local": options.ask_pass = False # set pe options utils.normalize_become_options(options) prompt_method = utils.choose_pass_prompt(options) (sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, become_ask_pass=options.become_ask_pass, ask_vault_pass=options.ask_vault_pass, become_method=prompt_method) # read vault_pass from a file if not options.ask_vault_pass and options.vault_password_file: vault_pass = utils.read_vault_file(options.vault_password_file) extra_vars = utils.parse_extra_vars(options.extra_vars, vault_pass) only_tags = options.tags.split(",") skip_tags = options.skip_tags if options.skip_tags is not None: skip_tags = options.skip_tags.split(",") for playbook in args: if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % playbook) if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError("the playbook: %s does not appear to be a file" % playbook) inventory = ansible.inventory.Inventory(options.inventory, vault_password=vault_pass) # Note: slightly wrong, this is written so that implicit localhost # (which is not returned in list_hosts()) is taken into account for # warning if inventory is empty. But it can't be taken into account for # checking if limit doesn't match any hosts. Instead we don't worry about # limit if only implicit localhost was in inventory to start with. # # Fix this in v2 no_hosts = False if len(inventory.list_hosts()) == 0: # Empty inventory utils.warning("provided hosts list is empty, only localhost is available") no_hosts = True inventory.subset(options.subset) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit raise errors.AnsibleError("Specified --limit does not match any hosts") # run all playbooks specified on the command line for playbook in args: stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) if options.step: playbook_cb.step = options.step if options.start_at: playbook_cb.start_at = options.start_at runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) pb = ansible.playbook.PlayBook( playbook=playbook, module_path=options.module_path, inventory=inventory, forks=options.forks, remote_user=options.remote_user, remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=options.timeout, transport=options.connection, become=options.become, become_method=options.become_method, become_user=options.become_user, become_pass=becomepass, extra_vars=extra_vars, private_key_file=options.private_key_file, only_tags=only_tags, skip_tags=skip_tags, check=options.check, diff=options.diff, vault_password=vault_pass, force_handlers=options.force_handlers, ) if options.flush_cache: display(callbacks.banner("FLUSHING FACT CACHE")) pb.SETUP_CACHE.flush() if options.listhosts or options.listtasks or options.syntax or options.listtags: print '' print 'playbook: %s' % playbook print '' playnum = 0 for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs): playnum += 1 play = ansible.playbook.Play(pb, play_ds, play_basedir, vault_password=pb.vault_password) label = play.name hosts = pb.inventory.list_hosts(play.hosts) if options.listhosts: print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts)) for host in hosts: print ' %s' % host if options.listtags or options.listtasks: print ' play #%d (%s):\tTAGS: [%s]' % (playnum, label,','.join(sorted(set(play.tags)))) if options.listtags: tags = [] for task in pb.tasks_to_run_in_play(play): tags.extend(task.tags) print ' TASK TAGS: [%s]' % (', '.join(sorted(set(tags).difference(['untagged'])))) if options.listtasks: for task in pb.tasks_to_run_in_play(play): if getattr(task, 'name', None) is not None: # meta tasks have no names print ' %s\tTAGS: [%s]' % (task.name, ', '.join(sorted(set(task.tags).difference(['untagged'])))) if options.listhosts or options.listtasks or options.listtags: print '' continue if options.syntax: # if we've not exited by now then we are fine.. print 'Playbook Syntax is fine' return 0 failed_hosts = [] unreachable_hosts = [] try: pb.run() hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if C.RETRY_FILES_ENABLED and len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for runner_results in pb.stats.output(): for (host, value) in runner_results.get('dark', {}).iteritems(): print 'dark' print host print value for (host, value) in runner_results.get('contacted', {}).iteritems(): print 'contacted' print host print value # for msg in pb.stats.output(): # print msg for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % ( hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True ) display("%s : %s %s %s %s" % ( hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True ) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display(u"ERROR: %s" % utils.unicode.to_unicode(e, nonstring='simplerepr'), color='red') return 1
def __init__(self, play, ds, module_vars=None, default_vars=None, additional_conditions=None, role_name=None): ''' constructor loads from a task or handler datastructure ''' # meta directives are used to tell things like ansible/playbook to run # operations like handler execution. Meta tasks are not executed # normally. if 'meta' in ds: self.meta = ds['meta'] self.tags = [] return else: self.meta = None library = os.path.join(play.basedir, 'library') if os.path.exists(library): utils.plugins.module_finder.add_directory(library) for x in ds.keys(): # code to allow for saying "modulename: args" versus "action: modulename args" if x in utils.plugins.module_finder: if 'action' in ds: raise errors.AnsibleError("multiple actions specified in task: '%s' and '%s'" % (x, ds.get('name', ds['action']))) if isinstance(ds[x], dict): if 'args' in ds: raise errors.AnsibleError("can't combine args: and a dict for %s: in task %s" % (x, ds.get('name', "%s: %s" % (x, ds[x])))) ds['args'] = ds[x] ds[x] = '' elif ds[x] is None: ds[x] = '' if not isinstance(ds[x], basestring): raise errors.AnsibleError("action specified for task %s has invalid type %s" % (ds.get('name', "%s: %s" % (x, ds[x])), type(ds[x]))) ds['action'] = x + " " + ds[x] ds.pop(x) # code to allow "with_glob" and to reference a lookup plugin named glob elif x.startswith("with_"): if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unnecessary to use '{{' in loops, leave variables in loop expressions bare.") plugin_name = x.replace("with_","") if plugin_name in utils.plugins.lookup_loader: ds['items_lookup_plugin'] = plugin_name ds['items_lookup_terms'] = ds[x] ds.pop(x) else: raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name)) elif x in [ 'changed_when', 'failed_when', 'when']: if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unnecessary to use '{{' in conditionals, leave variables in loop expressions bare.") elif x.startswith("when_"): utils.deprecated("The 'when_' conditional has been removed. Switch to using the regular unified 'when' statements as described on docs.ansible.com.","1.5", removed=True) if 'when' in ds: raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) when_name = x.replace("when_","") ds['when'] = "%s %s" % (when_name, ds[x]) ds.pop(x) elif not x in Task.VALID_KEYS: raise errors.AnsibleError("%s is not a legal parameter in an Ansible task or handler" % x) self.module_vars = module_vars self.default_vars = default_vars self.play = play # load various attributes self.name = ds.get('name', None) self.tags = [ 'all' ] self.register = ds.get('register', None) self.sudo = utils.boolean(ds.get('sudo', play.sudo)) self.su = utils.boolean(ds.get('su', play.su)) self.environment = ds.get('environment', {}) self.role_name = role_name self.no_log = utils.boolean(ds.get('no_log', "false")) self.run_once = utils.boolean(ds.get('run_once', 'false')) #Code to allow do until feature in a Task if 'until' in ds: if not ds.get('register'): raise errors.AnsibleError("register keyword is mandatory when using do until feature") self.module_vars['delay'] = ds.get('delay', 5) self.module_vars['retries'] = ds.get('retries', 3) self.module_vars['register'] = ds.get('register', None) self.until = ds.get('until') self.module_vars['until'] = self.until # rather than simple key=value args on the options line, these represent structured data and the values # can be hashes and lists, not just scalars self.args = ds.get('args', {}) # get remote_user for task, then play, then playbook if ds.get('remote_user') is not None: self.remote_user = ds.get('remote_user') elif ds.get('remote_user', play.remote_user) is not None: self.remote_user = ds.get('remote_user', play.remote_user) else: self.remote_user = ds.get('remote_user', play.playbook.remote_user) self.sudo_user = None self.sudo_pass = None self.su_user = None self.su_pass = None if self.sudo: self.sudo_user = ds.get('sudo_user', play.sudo_user) self.sudo_pass = ds.get('sudo_pass', play.playbook.sudo_pass) elif self.su: self.su_user = ds.get('su_user', play.su_user) self.su_pass = ds.get('su_pass', play.playbook.su_pass) # Fail out if user specifies a sudo param with a su param in a given play if (ds.get('sudo') or ds.get('sudo_user') or ds.get('sudo_pass')) and \ (ds.get('su') or ds.get('su_user') or ds.get('su_pass')): raise errors.AnsibleError('sudo params ("sudo", "sudo_user", "sudo_pass") ' 'and su params "su", "su_user", "su_pass") ' 'cannot be used together') # Both are defined if ('action' in ds) and ('local_action' in ds): raise errors.AnsibleError("the 'action' and 'local_action' attributes can not be used together") # Both are NOT defined elif (not 'action' in ds) and (not 'local_action' in ds): raise errors.AnsibleError("'action' or 'local_action' attribute missing in task \"%s\"" % ds.get('name', '<Unnamed>')) # Only one of them is defined elif 'local_action' in ds: self.action = ds.get('local_action', '') self.delegate_to = '127.0.0.1' else: self.action = ds.get('action', '') self.delegate_to = ds.get('delegate_to', None) self.transport = ds.get('connection', ds.get('transport', play.transport)) if isinstance(self.action, dict): if 'module' not in self.action: raise errors.AnsibleError("'module' attribute missing from action in task \"%s\"" % ds.get('name', '%s' % self.action)) if self.args: raise errors.AnsibleError("'args' cannot be combined with dict 'action' in task \"%s\"" % ds.get('name', '%s' % self.action)) self.args = self.action self.action = self.args.pop('module') # delegate_to can use variables if not (self.delegate_to is None): # delegate_to: localhost should use local transport if self.delegate_to in ['127.0.0.1', 'localhost']: self.transport = 'local' # notified by is used by Playbook code to flag which hosts # need to run a notifier self.notified_by = [] # if no name is specified, use the action line as the name if self.name is None: self.name = self.action # load various attributes self.when = ds.get('when', None) self.changed_when = ds.get('changed_when', None) self.failed_when = ds.get('failed_when', None) # combine the default and module vars here for use in templating all_vars = self.default_vars.copy() all_vars = utils.combine_vars(all_vars, self.module_vars) self.async_seconds = ds.get('async', 0) # not async by default self.async_seconds = template.template_from_string(play.basedir, self.async_seconds, all_vars) self.async_seconds = int(self.async_seconds) self.async_poll_interval = ds.get('poll', 10) # default poll = 10 seconds self.async_poll_interval = template.template_from_string(play.basedir, self.async_poll_interval, all_vars) self.async_poll_interval = int(self.async_poll_interval) self.notify = ds.get('notify', []) self.first_available_file = ds.get('first_available_file', None) self.items_lookup_plugin = ds.get('items_lookup_plugin', None) self.items_lookup_terms = ds.get('items_lookup_terms', None) self.ignore_errors = ds.get('ignore_errors', False) self.any_errors_fatal = ds.get('any_errors_fatal', play.any_errors_fatal) self.always_run = ds.get('always_run', False) # action should be a string if not isinstance(self.action, basestring): raise errors.AnsibleError("action is of type '%s' and not a string in task. name: %s" % (type(self.action).__name__, self.name)) # notify can be a string or a list, store as a list if isinstance(self.notify, basestring): self.notify = [ self.notify ] # split the action line into a module name + arguments try: tokens = split_args(self.action) except Exception, e: if "unbalanced" in str(e): raise errors.AnsibleError("There was an error while parsing the task %s.\n" % repr(self.action) + \ "Make sure quotes are matched or escaped properly") else: raise
def __init__(self, playbook, ds, basedir, vault_password=None): ''' constructor loads from a play datastructure ''' for x in ds.keys(): if not x in Play.VALID_KEYS: raise errors.AnsibleError("%s is not a legal parameter of an Ansible Play" % x) # allow all playbook keys to be set by --extra-vars self.vars = ds.get('vars', {}) self.vars_prompt = ds.get('vars_prompt', {}) self.playbook = playbook self.vars = self._get_vars() self.vars_file_vars = dict() # these are vars read in from vars_files: self.role_vars = dict() # these are vars read in from vars/main.yml files in roles self.basedir = basedir self.roles = ds.get('roles', None) self.tags = ds.get('tags', None) self.vault_password = vault_password self.environment = ds.get('environment', {}) if self.tags is None: self.tags = [] elif type(self.tags) in [ str, unicode ]: self.tags = self.tags.split(",") elif type(self.tags) != list: self.tags = [] # make sure we have some special internal variables set, which # we use later when loading tasks and handlers load_vars = dict() load_vars['playbook_dir'] = os.path.abspath(self.basedir) if self.playbook.inventory.basedir() is not None: load_vars['inventory_dir'] = self.playbook.inventory.basedir() if self.playbook.inventory.src() is not None: load_vars['inventory_file'] = self.playbook.inventory.src() # We first load the vars files from the datastructure # so we have the default variables to pass into the roles self.vars_files = ds.get('vars_files', []) if not isinstance(self.vars_files, list): raise errors.AnsibleError('vars_files must be a list') processed_vars_files = self._update_vars_files_for_host(None) # now we load the roles into the datastructure self.included_roles = [] ds = self._load_roles(self.roles, ds) # and finally re-process the vars files as they may have been updated # by the included roles, but exclude any which have been processed self.vars_files = utils.list_difference(ds.get('vars_files', []), processed_vars_files) if not isinstance(self.vars_files, list): raise errors.AnsibleError('vars_files must be a list') self._update_vars_files_for_host(None) # template everything to be efficient, but do not pre-mature template # tasks/handlers as they may have inventory scope overrides. We also # create a set of temporary variables for templating, so we don't # trample on the existing vars structures _tasks = ds.pop('tasks', []) _handlers = ds.pop('handlers', []) temp_vars = utils.combine_vars(self.vars, self.vars_file_vars) temp_vars = utils.combine_vars(temp_vars, self.playbook.extra_vars) try: ds = template(basedir, ds, temp_vars) except errors.AnsibleError, e: utils.warning("non fatal error while trying to template play variables: %s" % (str(e)))
def __init__(self, play, ds, module_vars=None, default_vars=None, additional_conditions=None, role_name=None): ''' constructor loads from a task or handler datastructure ''' # meta directives are used to tell things like ansible/playbook to run # operations like handler execution. Meta tasks are not executed # normally. if 'meta' in ds: self.meta = ds['meta'] self.tags = [] return else: self.meta = None library = os.path.join(play.basedir, 'library') if os.path.exists(library): utils.plugins.module_finder.add_directory(library) for x in ds.keys(): # code to allow for saying "modulename: args" versus "action: modulename args" if x in utils.plugins.module_finder: if 'action' in ds: raise errors.AnsibleError("multiple actions specified in task %s" % (ds.get('name', ds['action']))) if isinstance(ds[x], dict): if 'args' in ds: raise errors.AnsibleError("can't combine args: and a dict for %s: in task %s" % (x, ds.get('name', "%s: %s" % (x, ds[x])))) ds['args'] = ds[x] ds[x] = '' elif ds[x] is None: ds[x] = '' if not isinstance(ds[x], basestring): raise errors.AnsibleError("action specified for task %s has invalid type %s" % (ds.get('name', "%s: %s" % (x, ds[x])), type(ds[x]))) ds['action'] = x + " " + ds[x] ds.pop(x) # code to allow "with_glob" and to reference a lookup plugin named glob elif x.startswith("with_"): if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unneccessary to use '{{' in loops, leave variables in loop expressions bare.") plugin_name = x.replace("with_","") if plugin_name in utils.plugins.lookup_loader: ds['items_lookup_plugin'] = plugin_name ds['items_lookup_terms'] = ds[x] ds.pop(x) else: raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name)) elif x in [ 'changed_when', 'failed_when', 'when']: if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): utils.warning("It is unneccessary to use '{{' in conditionals, leave variables in loop expressions bare.") elif x.startswith("when_"): utils.deprecated("The 'when_' conditional has been removed. Switch to using the regular unified 'when' statements as described in ansibleworks.com/docs/.","1.5", removed=True) if 'when' in ds: raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) when_name = x.replace("when_","") ds['when'] = "%s %s" % (when_name, ds[x]) ds.pop(x) elif not x in Task.VALID_KEYS: raise errors.AnsibleError("%s is not a legal parameter in an Ansible task or handler" % x) self.module_vars = module_vars self.default_vars = default_vars self.play = play # load various attributes self.name = ds.get('name', None) self.tags = [ 'all' ] self.register = ds.get('register', None) self.sudo = utils.boolean(ds.get('sudo', play.sudo)) self.environment = ds.get('environment', {}) self.role_name = role_name #Code to allow do until feature in a Task if 'until' in ds: if not ds.get('register'): raise errors.AnsibleError("register keyword is mandatory when using do until feature") self.module_vars['delay'] = ds.get('delay', 5) self.module_vars['retries'] = ds.get('retries', 3) self.module_vars['register'] = ds.get('register', None) self.until = ds.get('until') self.module_vars['until'] = self.until # rather than simple key=value args on the options line, these represent structured data and the values # can be hashes and lists, not just scalars self.args = ds.get('args', {}) # get remote_user for task, then play, then playbook if ds.get('remote_user') is not None: self.remote_user = ds.get('remote_user') elif ds.get('remote_user', play.remote_user) is not None: self.remote_user = ds.get('remote_user', play.remote_user) else: self.remote_user = ds.get('remote_user', play.playbook.remote_user) if self.sudo: self.sudo_user = ds.get('sudo_user', play.sudo_user) self.sudo_pass = ds.get('sudo_pass', play.playbook.sudo_pass) else: self.sudo_user = None self.sudo_pass = None # Both are defined if ('action' in ds) and ('local_action' in ds): raise errors.AnsibleError("the 'action' and 'local_action' attributes can not be used together") # Both are NOT defined elif (not 'action' in ds) and (not 'local_action' in ds): raise errors.AnsibleError("'action' or 'local_action' attribute missing in task \"%s\"" % ds.get('name', '<Unnamed>')) # Only one of them is defined elif 'local_action' in ds: self.action = ds.get('local_action', '') self.delegate_to = '127.0.0.1' else: self.action = ds.get('action', '') self.delegate_to = ds.get('delegate_to', None) self.transport = ds.get('connection', ds.get('transport', play.transport)) if isinstance(self.action, dict): if 'module' not in self.action: raise errors.AnsibleError("'module' attribute missing from action in task \"%s\"" % ds.get('name', '%s' % self.action)) if self.args: raise errors.AnsibleError("'args' cannot be combined with dict 'action' in task \"%s\"" % ds.get('name', '%s' % self.action)) self.args = self.action self.action = self.args.pop('module') # delegate_to can use variables if not (self.delegate_to is None): # delegate_to: localhost should use local transport if self.delegate_to in ['127.0.0.1', 'localhost']: self.transport = 'local' # notified by is used by Playbook code to flag which hosts # need to run a notifier self.notified_by = [] # if no name is specified, use the action line as the name if self.name is None: self.name = self.action # load various attributes self.when = ds.get('when', None) self.changed_when = ds.get('changed_when', None) self.failed_when = ds.get('failed_when', None) self.async_seconds = int(ds.get('async', 0)) # not async by default self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds self.notify = ds.get('notify', []) self.first_available_file = ds.get('first_available_file', None) self.items_lookup_plugin = ds.get('items_lookup_plugin', None) self.items_lookup_terms = ds.get('items_lookup_terms', None) self.ignore_errors = ds.get('ignore_errors', False) self.any_errors_fatal = ds.get('any_errors_fatal', play.any_errors_fatal) self.always_run = ds.get('always_run', False) # action should be a string if not isinstance(self.action, basestring): raise errors.AnsibleError("action is of type '%s' and not a string in task. name: %s" % (type(self.action).__name__, self.name)) # notify can be a string or a list, store as a list if isinstance(self.notify, basestring): self.notify = [ self.notify ] # split the action line into a module name + arguments tokens = self.action.split(None, 1) if len(tokens) < 1: raise errors.AnsibleError("invalid/missing action in task. name: %s" % self.name) self.module_name = tokens[0] self.module_args = '' if len(tokens) > 1: self.module_args = tokens[1] import_tags = self.module_vars.get('tags',[]) if type(import_tags) in [int,float]: import_tags = str(import_tags) elif type(import_tags) in [str,unicode]: # allow the user to list comma delimited tags import_tags = import_tags.split(",") # handle mutually incompatible options incompatibles = [ x for x in [ self.first_available_file, self.items_lookup_plugin ] if x is not None ] if len(incompatibles) > 1: raise errors.AnsibleError("with_(plugin), and first_available_file are mutually incompatible in a single task") # make first_available_file accessable to Runner code if self.first_available_file: self.module_vars['first_available_file'] = self.first_available_file if self.items_lookup_plugin is not None: self.module_vars['items_lookup_plugin'] = self.items_lookup_plugin self.module_vars['items_lookup_terms'] = self.items_lookup_terms # allow runner to see delegate_to option self.module_vars['delegate_to'] = self.delegate_to # make some task attributes accessible to Runner code self.module_vars['ignore_errors'] = self.ignore_errors self.module_vars['register'] = self.register self.module_vars['changed_when'] = self.changed_when self.module_vars['failed_when'] = self.failed_when self.module_vars['always_run'] = self.always_run # tags allow certain parts of a playbook to be run without running the whole playbook apply_tags = ds.get('tags', None) if apply_tags is not None: if type(apply_tags) in [ str, unicode ]: self.tags.append(apply_tags) elif type(apply_tags) in [ int, float ]: self.tags.append(str(apply_tags)) elif type(apply_tags) == list: self.tags.extend(apply_tags) self.tags.extend(import_tags) if additional_conditions: new_conditions = additional_conditions new_conditions.append(self.when) self.when = new_conditions
def main(args): ''' run ansible-playbook operations ''' ## truiz: here I add options that will become parameters in the function ## truiz: extra vars is dict with the vars and values extra_vars = {'host': 'testing', 'vars_file': 'the_vars.yml'} print extra_vars ## truiz: this is just a list of playbooks playbooks = ['ansible/the_work.yml'] ## truiz: The file with hosts and their vars inventory_file = 'ansible/inventory' ## truiz: this could be an usefull parameter timeout = 10 # create parser for CLI options parser = utils.base_parser(constants=C, usage="%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True) parser.add_option('--vault-password', dest="vault_password", help="password for vault encrypted files") parser.add_option( '--syntax-check', dest='syntax', action='store_true', help="perform a syntax check on the playbook, but do not execute it") parser.add_option('--list-tasks', dest='listtasks', action='store_true', help="list all tasks that would be executed") parser.add_option('--list-tags', dest='listtags', action='store_true', help="list all available tags") parser.add_option('--start-at-task', dest='start_at', help="start the playbook at the task matching this name") parser.add_option('--force-handlers', dest='force_handlers', default=C.DEFAULT_FORCE_HANDLERS, action='store_true', help="run handlers even if a task fails") parser.add_option('--flush-cache', dest='flush_cache', action='store_true', help="clear the fact cache") options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 # privlege escalation command line arguments need to be mutually exclusive # utils.check_mutually_exclusive_privilege(options, parser) # if (options.ask_vault_pass and options.vault_password_file): # parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive") sshpass = None becomepass = None vault_pass = None # options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS # if options.listhosts or options.syntax or options.listtasks or options.listtags: # (_, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass) # else: # options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS # # Never ask for an SSH password when we run with local connection # if options.connection == "local": # options.ask_pass = False # # set pe options # utils.normalize_become_options(options) # prompt_method = utils.choose_pass_prompt(options) # (sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, # become_ask_pass=options.become_ask_pass, # ask_vault_pass=options.ask_vault_pass, # become_method=prompt_method) # read vault_pass from a file # if not options.ask_vault_pass and options.vault_password_file: # vault_pass = utils.read_vault_file(options.vault_password_file) for playbook in playbooks: print playbook if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % playbook) if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError( "the playbook: %s does not appear to be a file" % playbook) ## truiz: is better to pass the inventory file inventory = ansible.inventory.Inventory(inventory_file, vault_password=vault_pass) print options.inventory print inventory # Note: slightly wrong, this is written so that implicit localhost # (which is not returned in list_hosts()) is taken into account for # warning if inventory is empty. But it can't be taken into account for # checking if limit doesn't match any hosts. Instead we don't worry about # limit if only implicit localhost was in inventory to start with. # # Fix this in v2 no_hosts = False if len(inventory.list_hosts()) == 0: # Empty inventory utils.warning( "provided hosts list is empty, only localhost is available") no_hosts = True #print options.subset #inventory.subset(options.subset) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit raise errors.AnsibleError("Specified --limit does not match any hosts") print options.become print options.become_user print options.remote_user print options.timeout print becomepass for playbook in playbooks: stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) print runner_cb pb = ansible.playbook.PlayBook( playbook=playbook, # module_path=options.module_path, inventory=inventory, # forks=options.forks, # remote_user=options.remote_user, # remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=timeout, # transport=options.connection, #become=options.become, become_method='sudo', become_user=options.become_user, # become_pass=becomepass, extra_vars=extra_vars, private_key_file=options.private_key_file, # only_tags=only_tags, # skip_tags=skip_tags, check=options.check, diff=options.diff, # vault_password=vault_pass, force_handlers=options.force_handlers, ) # if options.flush_cache: # display(callbacks.banner("FLUSHING FACT CACHE")) # pb.SETUP_CACHE.flush() # if options.listhosts or options.listtasks or options.syntax or options.listtags: # print '' # print 'playbook: %s' % playbook # print '' # playnum = 0 # for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs): # playnum += 1 # play = ansible.playbook.Play(pb, play_ds, play_basedir, # vault_password=pb.vault_password) # label = play.name # hosts = pb.inventory.list_hosts(play.hosts) # if options.listhosts: # print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts)) # for host in hosts: # print ' %s' % host # if options.listtags or options.listtasks: # print ' play #%d (%s):\tTAGS: [%s]' % (playnum, label,','.join(sorted(set(play.tags)))) # if options.listtags: # tags = [] # for task in pb.tasks_to_run_in_play(play): # tags.extend(task.tags) # print ' TASK TAGS: [%s]' % (', '.join(sorted(set(tags).difference(['untagged'])))) # if options.listtasks: # for task in pb.tasks_to_run_in_play(play): # if getattr(task, 'name', None) is not None: # # meta tasks have no names # print ' %s\tTAGS: [%s]' % (task.name, ', '.join(sorted(set(task.tags).difference(['untagged'])))) # if options.listhosts or options.listtasks or options.listtags: # print '' # continue # if options.syntax: # # if we've not exited by now then we are fine. # print 'Playbook Syntax is fine' # return 0 failed_hosts = [] unreachable_hosts = [] try: print "Before run" res = pb.run() print "After run" ## truiz: returns a resume of all work done print res hosts = sorted(pb.stats.processed.keys()) display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if C.RETRY_FILES_ENABLED and len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % (hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True) display("%s : %s %s %s %s" % (hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1