Merge pull request #18 from xoxys/refactoring

Refactoring
This commit is contained in:
Robert Kaussow 2019-04-15 12:10:12 +02:00 committed by GitHub
commit 825d4d11be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5441 changed files with 1434422 additions and 870 deletions

View File

@ -52,7 +52,7 @@ local PipelineTesting = {
commands: [
"pip install -r test-requirements.txt -qq",
"pip install -qq .",
"bandit -r ./ansiblelater",
"bandit -r ./ansiblelater -x ./ansiblelater/tests",
],
depends_on: [
"clone",

View File

@ -69,7 +69,7 @@ steps:
commands:
- pip install -r test-requirements.txt -qq
- pip install -qq .
- bandit -r ./ansiblelater
- bandit -r ./ansiblelater -x ./ansiblelater/tests
environment:
PY_COLORS: 1
depends_on:

8
.flake8 Normal file
View File

@ -0,0 +1,8 @@
[flake8]
# Temp disable Docstring checks D101, D102, D103, D107
ignore = E501, W503, F401, N813, D101, D102, D103, D107
max-line-length = 100
inline-quotes = double
exclude = .git,.tox,__pycache__,build,dist,tests,*.pyc,*.egg-info,.cache,.eggs
application-import-names = ansiblelater
format = ${cyan}%(path)s:%(row)d:%(col)d${reset}: ${red_bold}%(code)s${reset} %(text)s

41
.github/settings.yml vendored Normal file
View File

@ -0,0 +1,41 @@
repository:
name: ansible-later
description: Ansible - Lovely Automation Testing Framework
topics: ansible, ansible-later, ansible-review, best practice
private: false
has_issues: true
has_wiki: false
has_downloads: true
default_branch: master
allow_squash_merge: true
allow_merge_commit: true
allow_rebase_merge: true
labels:
- name: bug
color: d73a4a
description: Something isn't working
- name: duplicate
color: cfd3d7
description: This issue or pull request already exists
- name: enhancement
color: a2eeef
description: New feature or request
- name: good first issue
color: 7057ff
description: Good for newcomers
- name: help wanted
color: 008672
description: Extra attention is needed
- name: invalid
color: e4e669
description: This doesn't seem right
- name: question
color: d876e3
description: Further information is requested
- name: wontfix
color: ffffff
description: This will not be worked on

View File

@ -1,2 +1,22 @@
**BREAKING RELEASE**
ansible-later contains some fundamental restructuring and is not backward compatible
with old releases.
- BREAKING
- Switch configuration files to YAML
- Enable multi location configuration files [#14](https://github.com/xoxys/ansible-later/issues/14)
- ID's used in standards have to be unique (or not set)
- FEATURE
- Add optional JSON logging [#13](https://github.com/xoxys/ansible-later/issues/13)
- Add exclude options in config files [#16](https://github.com/xoxys/ansible-later/issues/16)
- Add multiprocessing for better perfomance [#12](https://github.com/xoxys/ansible-later/issues/12)
- ENHANCEMENT
- Respect `PY_COLORS` to get colorized output for nontty environments ([#10](https://github.com/xoxys/ansible-later/pull/10))
- Allow passing glob patterns to cli [#16](https://github.com/xoxys/ansible-later/issues/16)
- Rule settings (e.g. for yamllint) can be set in config file [#7](https://github.com/xoxys/ansible-later/issues/7)
- Remove simple print outputs and switch to python logging module [#13](https://github.com/xoxys/ansible-later/issues/13)
- Restructure log output for better readability [#13](https://github.com/xoxys/ansible-later/issues/13)
- Better loglevel control from cli (-vvv/-qqq) [#13](https://github.com/xoxys/ansible-later/issues/13)
- Better inventory file classification [#15](https://github.com/xoxys/ansible-later/issues/15)

209
README.md
View File

@ -13,28 +13,27 @@ for his work on ansible-review and ansible-lint.
it helps to have a coding or best practice guideline in place. This will make ansible roles more readable for all
maintainers and can reduce the troubleshooting time.
`ansible-later` does _**not**_ ensure that your role will work as expected.
`ansible-later` does _**not**_ ensure that your role will work as expected. For Deployment test you can use other tools
like [molecule](https://github.com/ansible/molecule).
The project name is an acronym for **L**ovely **A**utomation **TE**sting f**R**mework.
## Table of Content
- [ansible-later](#ansible-later)
- [Table of Content](#table-of-content)
- [Setup](#setup)
- [Using pip](#using-pip)
- [From source](#from-source)
- [Usage](#usage)
- [Configuration](#configuration)
- [Review a git repositories](#review-a-git-repositories)
- [Review a list of files](#review-a-list-of-files)
- [Buildin rules](#buildin-rules)
- [Build your own](#build-your-own)
- [The standards file](#the-standards-file)
- [Candidates](#candidates)
- [Minimal standards checks](#minimal-standards-checks)
- [License](#license)
- [Maintainers and Contributors](#maintainers-and-contributors)
- [Setup](#setup)
- [Using pip](#using-pip)
- [From source](#from-source)
- [Configuration](#configuration)
- [Default settings](#default-settings)
- [CLI Options](#cli-options)
- [Usage](#usage)
- [Buildin rules](#buildin-rules)
- [Build your own rules](#build-your-own-rules)
- [The standards file](#the-standards-file)
- [Candidates](#candidates)
- [Minimal standards checks](#minimal-standards-checks)
- [License](#license)
- [Maintainers and Contributors](#maintainers-and-contributors)
---
@ -54,9 +53,117 @@ sudo pip install ansible-later
```Shell
# Install dependency
git clone https://repourl
git clone https://github.com/xoxys/ansible-later
export PYTHONPATH=$PYTHONPATH:`pwd`/ansible-later/ansiblelater
export PATH=$PATH:`pwd`/ansible-later/ansiblelater/bin
export PATH=$PATH:`pwd`/ansible-later/bin
```
### Configuration
ansible-later comes with some default settigs which should be sufficent for most users to start,
but you can adjust most settings to your needs.
Changes can be made in a yaml configuration file or through cli options
which will be processed in the following order (last wins):
- default config (build-in)
- global config file (this will depend on your operating system)
- folderbased config file (`.later.yml` file in current working folder)
- cli options
Be careful! YAML Attributes will be overwritten while lists in any
config file will be merged.
To make it easier to review a singel file e.g. for debugging purpose, amsible-later
will ignore `exclude_files` and `ignore_dotfiles` options.
#### Default settings
```YAML
---
ansible:
# Add the name of used custom ansible modules.
# Otherwise ansible-later can't detect unknown modules
# and will through an error.
custom_modules: []
# Settings for variable formatting rule (ANSIBLE0004)
double-braces:
max-spaces-inside: 1
min-spaces-inside: 1
# Global logging configuration
# If you would like to force colored output (e.g. non-tty)
# set emvironment variable `PY_COLORS=1`
logging:
# You can enable json logging if a parsable output is required
json: False
# Possible options debug | info | warning | error | critical
level: "warning"
# Global settings for all defined rules
rules:
# list of files to exclude
exclude_files: []
# Examples:
# - molecule/
# - files/**/*.py
# List of Ansible rule ID's
# If empty all rules will be used.
filter: []
# All dotfiles (including hidden folders) are excluded by default.
# You can disable this setting and handle dotfiles by yourself with `exclude_files`.
ignore_dotfiles: True
# Path to the folder containing your custom standards file
standards: ansiblelater/data
# Block to control included yamlllint rules.
# See https://yamllint.readthedocs.io/en/stable/rules.html
yamllint:
colons:
max-spaces-after: 1
max-spaces-before: 0
document-start:
present: True
empty-lines:
max: 1
max-end: 1
max-start: 0
hyphens:
max-spaces-after: 1
indentation:
check-multi-line-strings: False
indent-sequences: True
spaces: 2
```
#### CLI Options
You can get all available cli options by running `ansible-later --help`:
```Shell
$ ansible-later --help
usage: ansible-later [-h] [-c CONFIG_FILE] [-r RULES.STANDARDS]
[-s RULES.FILTER] [-v] [-q] [--version]
[rules.files [rules.files ...]]
Validate ansible files against best pratice guideline
positional arguments:
rules.files
optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE
location of configuration file
-r RULES.STANDARDS, --rules RULES.STANDARDS
location of standards rules
-s RULES.FILTER, --standards RULES.FILTER
limit standards to specific ID's
-v increase log level
-q decrease log level
--version show program's version number and exit
```
### Usage
@ -65,26 +172,23 @@ export PATH=$PATH:`pwd`/ansible-later/ansiblelater/bin
ansible-later FILES
```
Where FILES is a space delimited list of files to review.
ansible-later is _not_ recursive and won't descend
into child folders; it just processes the list of files you give it.
Passing a folder in with the list of files will elicit a warning:
Where FILES is a space delimited list of files to review. You can also pass glob
patterns to ansible-later:
```Shell
WARN: Couldn't classify file ./foldername
# Review single files
ansible-later meta/main.yml tasks/install.yml
# Review all yml files (including subfolders)
ansible-later **/*.yml
```
ansible-later will review inventory files, role
files, python code (modules, plugins) and playbooks.
ansible-later will review inventory files, role f0iles, python code (modules, plugins)
and playbooks.
- The goal is that each file that changes in a
changeset should be reviewable simply by passing
those files as the arguments to ansible-later.
- Roles are slightly harder, and sub-roles are yet
harder still (currently just using `-R` to process
roles works very well, but doesn't examine the
structure of the role)
- Using `{{ playbook_dir }}` in sub roles is so far
very hard.
- This should work against various repository styles
@ -93,42 +197,7 @@ files, python code (modules, plugins) and playbooks.
- per-playbook repository
- It should work with roles requirement files and with local roles
#### Configuration
If your standards (and optionally inhouse rules) are set up, create
a configuration file in the appropriate location (this will depend on
your operating system)
The location can be found by using `ansible-later` with no arguments.
You can override the configuration file location with the `-c` flag.
```INI
[rules]
standards = /path/to/your/standards/rules
```
The standards directory can be overridden with the `-d` argument.
#### Review a git repositories
- `git ls-files | xargs ansible-later` works well in
a roles repo to review the whole role. But it will
review the whole of other repos too.
- `git ls-files *[^LICENSE,.md] | xargs ansible-later`
works like the first example but excludes some
unnecessary files.
- `git diff branch_to_compare | ansible-later` will
review only the changes between the branches and
surrounding context.
#### Review a list of files
- `find . -type f | xargs ansible-later` will review
all files in the current folder (and all subfolders),
even if they're not checked into git
#### Buildin rules
### Buildin rules
Reviews are nothing without some rules or standards against which to review. ansible-later
comes with a couple of built-in checks explained in the following table.
@ -160,7 +229,7 @@ comes with a couple of built-in checks explained in the following table.
| check_become_user | ANSIBLE0015 | `become` should be always used combined with `become_user`. | |
| check_filter_separation | ANSIBLE0016 | Jinja2 filters should be separated with spaces. | |
### Build your own
### Build your own rules
#### The standards file
@ -173,7 +242,9 @@ Create a file called standards.py (this can import other modules)
from ansiblelater include Standard, Result
tasks_are_uniquely_named = Standard(dict(
# ID's are optional but if you use ID's they have to be unique
id="ANSIBLE0003",
# Short description of the standard goal
name="Tasks and handlers must be uniquely named within a single file",
check=check_unique_named_task,
version="0.1",
@ -229,7 +300,7 @@ which contains some meta informations and is an instance of one of following obj
| HostVars | all files (including subdirs) within the parent dir `host_vars` |
| Meta | all files within the parent dir `meta` |
| Code | all files within the parent dir `library`, `lookup_plugins`, `callback_plugins` and `filter_plugins` or python files (`.py`) |
| Inventory | all files within the parent dir `inventory` and `inventory` or `hosts` in filename |
| Inventory | all files within the parent dir `inventories` and `inventory` or `hosts` as filename |
| Rolesfile | all files with `rolesfile` or `requirements` in filename |
| Makefile | all files with `Makefile` in filename |
| Template | all files (including subdirs) within the parent dir `templates` or jinja2 files (`.j2`) |

View File

@ -1,313 +1,13 @@
"""Default package."""
__author__ = "Robert Kaussow"
__project__ = "ansible-later"
__version__ = "0.1.5"
__version__ = "0.2.0"
__license__ = "MIT"
__maintainer__ = "Robert Kaussow"
__email__ = "mail@geeklabor.de"
__status__ = "Production"
from ansiblelater import logger
import re
import os
import codecs
import ansible
from distutils.version import LooseVersion
from ansiblelater.utils import info, warn, abort, error
from ansiblelater.utils import read_standards
from ansiblelater.utils import get_property
from ansiblelater.utils import standards_latest
from ansiblelater.utils import is_line_in_ranges
from ansiblelater.utils import lines_ranges
try:
# Ansible 2.4 import of module loader
from ansible.plugins.loader import module_loader
except ImportError:
try:
from ansible.plugins import module_loader
except ImportError:
from ansible.utils import module_finder as module_loader
class AnsibleReviewFormatter(object):
def format(self, match):
formatstr = u"{0}:{1}: [{2}] {3} {4}"
return formatstr.format(match.filename,
match.linenumber,
match.rule.id,
match.message,
match.line
)
class Standard(object):
def __init__(self, standard_dict):
if 'id' not in standard_dict:
standard_dict.update(id='')
else:
standard_dict.update(id='[{}] '.format(standard_dict.get("id")))
self.id = standard_dict.get("id")
self.name = standard_dict.get("name")
self.version = standard_dict.get("version")
self.check = standard_dict.get("check")
self.types = standard_dict.get("types")
def __repr__(self):
return "Standard: %s (version: %s, types: %s)" % (
self.name, self.version, self.types)
class Error(object):
def __init__(self, lineno, message):
self.lineno = lineno
self.message = message
def __repr__(self):
if self.lineno:
return "%s: %s" % (self.lineno, self.message)
else:
return " %s" % (self.message)
class Result(object):
def __init__(self, candidate, errors=None):
self.candidate = candidate
self.errors = errors or []
def message(self):
return "\n".join(["{0}:{1}".format(self.candidate, error)
for error in self.errors])
class Candidate(object):
def __init__(self, filename):
self.path = filename
self.binary = False
self.vault = False
try:
self.version = find_version(filename)
with codecs.open(filename, mode='rb', encoding='utf-8') as f:
if f.readline().startswith("$ANSIBLE_VAULT"):
self.vault = True
except UnicodeDecodeError:
self.binary = True
self.filetype = type(self).__name__.lower()
self.expected_version = True
def review(self, settings, lines=None):
return candidate_review(self, settings, lines)
def __repr__(self):
return "%s (%s)" % (type(self).__name__, self.path)
def __getitem__(self, item):
return self.__dict__.get(item)
class RoleFile(Candidate):
def __init__(self, filename):
super(RoleFile, self).__init__(filename)
self.version = None
parentdir = os.path.dirname(os.path.abspath(filename))
while parentdir != os.path.dirname(parentdir):
meta_file = os.path.join(parentdir, "meta", "main.yml")
if os.path.exists(meta_file):
self.version = find_version(meta_file)
if self.version:
break
parentdir = os.path.dirname(parentdir)
role_modules = os.path.join(parentdir, 'library')
if os.path.exists(role_modules):
module_loader.add_directory(role_modules)
class Playbook(Candidate):
pass
class Task(RoleFile):
def __init__(self, filename):
super(Task, self).__init__(filename)
self.filetype = 'tasks'
class Handler(RoleFile):
def __init__(self, filename):
super(Handler, self).__init__(filename)
self.filetype = 'handlers'
class Vars(Candidate):
pass
class Unversioned(Candidate):
def __init__(self, filename):
super(Unversioned, self).__init__(filename)
self.expected_version = False
class InventoryVars(Unversioned):
pass
class HostVars(InventoryVars):
pass
class GroupVars(InventoryVars):
pass
class RoleVars(RoleFile):
pass
class Meta(RoleFile):
pass
class Inventory(Unversioned):
pass
class Code(Unversioned):
pass
class Template(RoleFile):
pass
class Doc(Unversioned):
pass
# For ease of checking files for tabs
class Makefile(Unversioned):
pass
class File(RoleFile):
pass
class Rolesfile(Unversioned):
pass
def classify(filename):
parentdir = os.path.basename(os.path.dirname(filename))
if parentdir in ['tasks']:
return Task(filename)
if parentdir in ['handlers']:
return Handler(filename)
if parentdir in ['vars', 'defaults']:
return RoleVars(filename)
if 'group_vars' in filename.split(os.sep):
return GroupVars(filename)
if 'host_vars' in filename.split(os.sep):
return HostVars(filename)
if parentdir in ['meta']:
return Meta(filename)
if parentdir in ['library', 'lookup_plugins', 'callback_plugins',
'filter_plugins'] or filename.endswith('.py'):
return Code(filename)
if 'inventory' in filename or 'hosts' in filename or parentdir in ['inventory']:
return Inventory(filename)
if 'rolesfile' in filename or 'requirements' in filename:
return Rolesfile(filename)
if 'Makefile' in filename:
return Makefile(filename)
if 'templates' in filename.split(os.sep) or filename.endswith('.j2'):
return Template(filename)
if 'files' in filename.split(os.sep):
return File(filename)
if filename.endswith('.yml') or filename.endswith('.yaml'):
return Playbook(filename)
if 'README' in filename:
return Doc(filename)
return None
def candidate_review(candidate, settings, lines=None):
errors = 0
standards = read_standards(settings)
if getattr(standards, 'ansible_min_version', None) and \
LooseVersion(standards.ansible_min_version) > LooseVersion(ansible.__version__):
raise SystemExit("Standards require ansible version %s (current version %s). "
"Please upgrade ansible." %
(standards.ansible_min_version, ansible.__version__))
if getattr(standards, 'ansible_review_min_version', None) and \
LooseVersion(standards.ansible_review_min_version) > LooseVersion(
get_property("__version__")):
raise SystemExit("Standards require ansible-later version %s (current version %s). "
"Please upgrade ansible-later." %
(standards.ansible_review_min_version, get_property("__version__")))
if not candidate.version:
candidate.version = standards_latest(standards.standards)
if candidate.expected_version:
if isinstance(candidate, RoleFile):
warn("%s %s is in a role that contains a meta/main.yml without a declared "
"standards version. "
"Using latest standards version %s" %
(type(candidate).__name__, candidate.path, candidate.version),
settings)
else:
warn("%s %s does not present standards version. "
"Using latest standards version %s" %
(type(candidate).__name__, candidate.path, candidate.version),
settings)
info("%s %s declares standards version %s" %
(type(candidate).__name__, candidate.path, candidate.version),
settings)
for standard in standards.standards:
if type(candidate).__name__.lower() not in standard.types:
continue
if settings.standards_filter and standard.name not in settings.standards_filter:
continue
result = standard.check(candidate, settings)
if not result:
abort("Standard '%s' returns an empty result object." %
(standard.check.__name__))
for err in [err for err in result.errors
if not err.lineno or is_line_in_ranges(err.lineno, lines_ranges(lines))]:
if not standard.version:
warn("{id}Best practice '{name}' not met:\n{path}:{error}".format(
id=standard.id, name=standard.name, path=candidate.path, error=err), settings)
elif LooseVersion(standard.version) > LooseVersion(candidate.version):
warn("{id}Future standard '{name}' not met:\n{path}:{error}".format(
id=standard.id, name=standard.name, path=candidate.path, error=err), settings)
else:
error("{id}Standard '{name}' not met:\n{path}:{error}".format(
id=standard.id, name=standard.name, path=candidate.path, error=err))
errors = errors + 1
if not result.errors:
if not standard.version:
info("Best practice '%s' met" % standard.name, settings)
elif LooseVersion(standard.version) > LooseVersion(candidate.version):
info("Future standard '%s' met" % standard.name, settings)
else:
info("Standard '%s' met" % standard.name, settings)
return errors
def find_version(filename, version_regex=r"^# Standards:\s*([\d.]+)"):
version_re = re.compile(version_regex)
with codecs.open(filename, mode='rb', encoding='utf-8') as f:
for line in f:
match = version_re.match(line)
if match:
return match.group(1)
return None
LOG = logger.get_logger("ansiblelater")

View File

@ -1,79 +1,65 @@
#!/usr/bin/env python
"""Main program."""
import logging
import optparse
import os
import sys
from appdirs import AppDirs
from pkg_resources import resource_filename
from ansiblelater import classify
from ansiblelater.utils import info, warn, read_config, get_property
import argparse
import multiprocessing
from ansiblelater import LOG
from ansiblelater import __version__
from ansiblelater import logger
from ansiblelater.command import base
from ansiblelater.command import candidates
def main():
config_dir = AppDirs("ansible-later").user_config_dir
default_config_file = os.path.join(config_dir, "config.ini")
"""Run main program."""
parser = argparse.ArgumentParser(
description="Validate ansible files against best pratice guideline")
parser.add_argument("-c", "--config", dest="config_file",
help="location of configuration file")
parser.add_argument("-r", "--rules", dest="rules.standards",
help="location of standards rules")
parser.add_argument("-s", "--standards", dest="rules.filter", action="append",
help="limit standards to specific ID's")
parser.add_argument("-v", dest="logging.level", action="append_const", const=-1,
help="increase log level")
parser.add_argument("-q", dest="logging.level", action="append_const",
const=1, help="decrease log level")
parser.add_argument("rules.files", nargs="*")
parser.add_argument("--version", action="version", version="%(prog)s {}".format(__version__))
parser = optparse.OptionParser("%prog playbook_file|role_file|inventory_file",
version="%prog " + get_property("__version__"))
parser.add_option('-c', dest='configfile', default=default_config_file,
help="Location of configuration file: [%s]" % default_config_file)
parser.add_option('-d', dest='rulesdir',
help="Location of standards rules")
parser.add_option('-q', dest='log_level', action="store_const", default=logging.WARN,
const=logging.ERROR, help="Only output errors")
parser.add_option('-s', dest='standards_filter', action='append',
help="limit standards to specific names")
parser.add_option('-v', dest='log_level', action="store_const", default=logging.WARN,
const=logging.INFO, help="Show more verbose output")
args = parser.parse_args().__dict__
options, args = parser.parse_args(sys.argv[1:])
settings = read_config(options.configfile)
settings = base.get_settings(args)
config = settings.config
# Merge CLI options with config options. CLI options override config options.
for key, value in options.__dict__.items():
if value:
setattr(settings, key, value)
logger.update_logger(LOG, config["logging"]["level"], config["logging"]["json"])
if os.path.exists(settings.configfile):
info("Using configuration file: %s" % settings.configfile, settings)
else:
warn("No configuration file found at %s" % settings.configfile, settings, file=sys.stderr)
if not settings.rulesdir:
rules_dir = os.path.join(resource_filename('ansiblelater', 'examples'))
warn("Using example standards found at %s" % rules_dir, settings, file=sys.stderr)
settings.rulesdir = rules_dir
files = config["rules"]["files"]
standards = base.get_standards(config["rules"]["standards"])
if len(args) == 0:
candidates = []
for root, dirs, files in os.walk("."):
for filename in files:
candidates.append(os.path.join(root, filename))
else:
candidates = args
errors = 0
for filename in candidates:
if ':' in filename:
(filename, lines) = filename.split(":")
else:
lines = None
candidate = classify(filename)
workers = multiprocessing.cpu_count() - 2
p = multiprocessing.Pool(workers)
for filename in files:
lines = None
candidate = candidates.classify(filename, settings, standards)
if candidate:
if candidate.binary:
info("Not reviewing binary file %s" % filename, settings)
LOG.info("Not reviewing binary file %s" % filename)
continue
if candidate.vault:
info("Not reviewing vault file %s" % filename, settings)
LOG.info("Not reviewing vault file %s" % filename)
continue
if lines:
info("Reviewing %s lines %s" % (candidate, lines), settings)
LOG.info("Reviewing %s lines %s" % (candidate, lines))
else:
info("Reviewing all of %s" % candidate, settings)
errors = errors + candidate.review(settings, lines)
LOG.info("Reviewing all of %s" % candidate)
p.imap(candidate.review, (settings, lines,))
else:
info("Couldn't classify file %s" % filename, settings)
return errors
LOG.info("Couldn't classify file %s" % filename)
p.close()
p.join()
if __name__ == "__main__":

View File

@ -0,0 +1 @@
# noqa

View File

@ -0,0 +1,59 @@
"""Base methods."""
import importlib
import os
import sys
from distutils.version import LooseVersion
import ansible
import toolz
from ansiblelater import settings
from ansiblelater import utils
def get_settings(args):
"""
Get new settings object.
:param args: cli args from argparse
:returns: Settings object
"""
config = settings.Settings(
args=args,
)
return config
def get_standards(filepath):
sys.path.append(os.path.abspath(os.path.expanduser(filepath)))
try:
standards = importlib.import_module("standards")
except ImportError as e:
utils.sysexit_with_message(
"Could not import standards from directory %s: %s" % (filepath, str(e)))
if getattr(standards, "ansible_min_version", None) and \
LooseVersion(standards.ansible_min_version) > LooseVersion(ansible.__version__):
utils.sysexit_with_message("Standards require ansible version %s (current version %s). "
"Please upgrade ansible." %
(standards.ansible_min_version, ansible.__version__))
if getattr(standards, "ansible_review_min_version", None) and \
LooseVersion(standards.ansible_review_min_version) > LooseVersion(
utils.get_property("__version__")):
utils.sysexit_with_message(
"Standards require ansible-later version %s (current version %s). "
"Please upgrade ansible-later." %
(standards.ansible_review_min_version, utils.get_property("__version__")))
normalized_std = (list(toolz.remove(lambda x: x.id == "", standards.standards)))
unique_std = len(list(toolz.unique(normalized_std, key=lambda x: x.id)))
all_std = len(normalized_std)
if not all_std == unique_std:
utils.sysexit_with_message(
"Detect duplicate ID's in standards definition. Please use unique ID's only.")
return standards.standards

View File

@ -0,0 +1,322 @@
"""Review candidates."""
import codecs
import copy
import os
import re
from distutils.version import LooseVersion
from six import iteritems
from ansiblelater import LOG
from ansiblelater import utils
from ansiblelater.logger import flag_extra
try:
# Ansible 2.4 import of module loader
from ansible.plugins.loader import module_loader
except ImportError:
try:
from ansible.plugins import module_loader
except ImportError:
from ansible.utils import module_finder as module_loader
class Candidate(object):
"""
Meta object for all files which later has to process.
Each file passed to later will be classified by type and
bundled with necessary meta informations for rule processing.
"""
def __init__(self, filename, settings={}, standards=[]):
self.path = filename
self.binary = False
self.vault = False
self.filetype = type(self).__name__.lower()
self.expected_version = True
self.standards = self._get_standards(settings, standards)
try:
with codecs.open(filename, mode="rb", encoding="utf-8") as f:
if f.readline().startswith("$ANSIBLE_VAULT"):
self.vault = True
except UnicodeDecodeError:
self.binary = True
self.version = self._get_version(settings)
def _get_version(self, settings):
path = self.path
version = None
if not self.binary:
if isinstance(self, RoleFile):
parentdir = os.path.dirname(os.path.abspath(self.path))
while parentdir != os.path.dirname(parentdir):
meta_file = os.path.join(parentdir, "meta", "main.yml")
if os.path.exists(meta_file):
path = meta_file
break
parentdir = os.path.dirname(parentdir)
version_re = re.compile(r"^# Standards:\s*([\d.]+)")
with codecs.open(path, mode="rb", encoding="utf-8") as f:
for line in f:
match = version_re.match(line)
if match:
version = match.group(1)
if not version:
version = utils.standards_latest(self.standards)
if self.expected_version:
if isinstance(self, RoleFile):
LOG.warning(
"%s %s is in a role that contains a meta/main.yml without a declared "
"standards version. "
"Using latest standards version %s" %
(type(self).__name__, self.path, version))
else:
LOG.warning(
"%s %s does not present standards version. "
"Using latest standards version %s" %
(type(self).__name__, self.path, version))
else:
LOG.info("%s %s declares standards version %s" %
(type(self).__name__, self.path, version))
return version
def _get_standards(self, settings, standards):
target_standards = []
limits = settings.config["rules"]["filter"]
if limits:
for standard in standards:
if standard.id in limits:
target_standards.append(standard)
else:
target_standards = standards
return target_standards
def review(self, settings, lines=None):
errors = 0
for standard in self.standards:
if type(self).__name__.lower() not in standard.types:
continue
result = standard.check(self, settings.config)
if not result:
utils.sysexit_with_message("Standard '{}' returns an empty result object.".format(
standard.check.__name__))
labels = {"tag": "review", "standard": standard.name, "file": self.path, "passed": True}
if standard.id and standard.id.strip():
labels["id"] = standard.id
for err in [err for err in result.errors
if not err.lineno or utils.is_line_in_ranges(err.lineno, utils.lines_ranges(lines))]: # noqa
err_labels = copy.copy(labels)
err_labels["passed"] = False
if isinstance(err, Error):
err_labels.update(err.to_dict())
if not standard.version:
LOG.warning("{id}Best practice '{name}' not met:\n{path}:{error}".format(
id=self._format_id(standard.id),
name=standard.name,
path=self.path,
error=err), extra=flag_extra(err_labels))
elif LooseVersion(standard.version) > LooseVersion(self.version):
LOG.warning("{id}Future standard '{name}' not met:\n{path}:{error}".format(
id=self._format_id(standard.id),
name=standard.name,
path=self.path,
error=err), extra=flag_extra(err_labels))
else:
LOG.error("{id}Standard '{name}' not met:\n{path}:{error}".format(
id=self._format_id(standard.id),
name=standard.name,
path=self.path,
error=err), extra=flag_extra(err_labels))
errors = errors + 1
def _format_id(self, standard_id):
if standard_id and standard_id.strip():
standard_id = "[{id}] ".format(id=standard_id.strip())
return standard_id
def __repr__(self): # noqa
return "%s (%s)" % (type(self).__name__, self.path)
def __getitem__(self, item): # noqa
return self.__dict__.get(item)
class RoleFile(Candidate):
def __init__(self, filename, settings={}, standards=[]):
super(RoleFile, self).__init__(filename, settings, standards)
parentdir = os.path.dirname(os.path.abspath(filename))
while parentdir != os.path.dirname(parentdir):
role_modules = os.path.join(parentdir, "library")
if os.path.exists(role_modules):
module_loader.add_directory(role_modules)
break
parentdir = os.path.dirname(parentdir)
class Playbook(Candidate):
pass
class Task(RoleFile):
def __init__(self, filename, settings={}, standards=[]):
super(Task, self).__init__(filename, settings, standards)
self.filetype = "tasks"
class Handler(RoleFile):
def __init__(self, filename, settings={}, standards=[]):
super(Handler, self).__init__(filename, settings, standards)
self.filetype = "handlers"
class Vars(Candidate):
pass
class Unversioned(Candidate):
def __init__(self, filename, settings={}, standards=[]):
super(Unversioned, self).__init__(filename, settings, standards)
self.expected_version = False
class InventoryVars(Unversioned):
pass
class HostVars(InventoryVars):
pass
class GroupVars(InventoryVars):
pass
class RoleVars(RoleFile):
pass
class Meta(RoleFile):
pass
class Inventory(Unversioned):
pass
class Code(Unversioned):
pass
class Template(RoleFile):
pass
class Doc(Unversioned):
pass
class Makefile(Unversioned):
pass
class File(RoleFile):
pass
class Rolesfile(Unversioned):
pass
class Error(object):
"""Default error object created if a rule failed."""
def __init__(self, lineno, message, error_type=None, **kwargs):
"""
Initialize a new error object and returns None.
:param lineno: Line number where the error from de rule occures
:param message: Detailed error description provided by the rule
"""
self.lineno = lineno
self.message = message
self.kwargs = kwargs
for (key, value) in iteritems(kwargs):
setattr(self, key, value)
def __repr__(self): # noqa
if self.lineno:
return "%s: %s" % (self.lineno, self.message)
else:
return " %s" % (self.message)
def to_dict(self):
result = dict(lineno=self.lineno, message=self.message)
for (key, value) in iteritems(self.kwargs):
result[key] = value
return result
class Result(object):
def __init__(self, candidate, errors=None):
self.candidate = candidate
self.errors = errors or []
def message(self):
return "\n".join(["{0}:{1}".format(self.candidate, error)
for error in self.errors])
def classify(filename, settings={}, standards=[]):
parentdir = os.path.basename(os.path.dirname(filename))
basename = os.path.basename(filename)
if parentdir in ["tasks"]:
return Task(filename, settings, standards)
if parentdir in ["handlers"]:
return Handler(filename, settings, standards)
if parentdir in ["vars", "defaults"]:
return RoleVars(filename, settings, standards)
if "group_vars" in filename.split(os.sep):
return GroupVars(filename, settings, standards)
if "host_vars" in filename.split(os.sep):
return HostVars(filename, settings, standards)
if parentdir in ["meta"]:
return Meta(filename, settings, standards)
if parentdir in ["library", "lookup_plugins", "callback_plugins",
"filter_plugins"] or filename.endswith(".py"):
return Code(filename, settings, standards)
if "inventory" == basename or "hosts" == basename or parentdir in ["inventories"]:
return Inventory(filename, settings, standards)
if "rolesfile" in basename or "requirements" in basename:
return Rolesfile(filename, settings, standards)
if "Makefile" in basename:
return Makefile(filename, settings, standards)
if "templates" in filename.split(os.sep) or basename.endswith(".j2"):
return Template(filename, settings, standards)
if "files" in filename.split(os.sep):
return File(filename, settings, standards)
if basename.endswith(".yml") or basename.endswith(".yaml"):
return Playbook(filename, settings, standards)
if "README" in basename:
return Doc(filename, settings, standards)
return None

View File

@ -1,30 +1,30 @@
from ansiblelater import Standard
"""Example standards definition."""
from ansiblelater.rules.yamlfiles import check_yaml_empty_lines
from ansiblelater.rules.yamlfiles import check_yaml_indent
from ansiblelater.rules.yamlfiles import check_yaml_hyphens
from ansiblelater.rules.yamlfiles import check_yaml_document_start
from ansiblelater.rules.yamlfiles import check_yaml_colons
from ansiblelater.rules.yamlfiles import check_yaml_file
from ansiblelater.rules.yamlfiles import check_yaml_has_content
from ansiblelater.rules.yamlfiles import check_native_yaml
from ansiblelater.rules.taskfiles import check_line_between_tasks
from ansiblelater.rules.ansiblefiles import check_become_user
from ansiblelater.rules.ansiblefiles import check_braces_spaces
from ansiblelater.rules.ansiblefiles import check_command_has_changes
from ansiblelater.rules.ansiblefiles import check_command_instead_of_module
from ansiblelater.rules.ansiblefiles import check_compare_to_literal_bool
from ansiblelater.rules.ansiblefiles import check_empty_string_compare
from ansiblelater.rules.ansiblefiles import check_filter_separation
from ansiblelater.rules.ansiblefiles import check_install_use_latest
from ansiblelater.rules.ansiblefiles import check_literal_bool_format
from ansiblelater.rules.ansiblefiles import check_name_format
from ansiblelater.rules.ansiblefiles import check_named_task
from ansiblelater.rules.ansiblefiles import check_shell_instead_command
from ansiblelater.rules.ansiblefiles import check_unique_named_task
from ansiblelater.rules.rolefiles import check_meta_main
from ansiblelater.rules.rolefiles import check_scm_in_src
from ansiblelater.rules.ansiblefiles import check_unique_named_task
from ansiblelater.rules.ansiblefiles import check_named_task
from ansiblelater.rules.ansiblefiles import check_name_format
from ansiblelater.rules.ansiblefiles import check_braces_spaces
from ansiblelater.rules.ansiblefiles import check_command_instead_of_module
from ansiblelater.rules.ansiblefiles import check_install_use_latest
from ansiblelater.rules.ansiblefiles import check_shell_instead_command
from ansiblelater.rules.ansiblefiles import check_command_has_changes
from ansiblelater.rules.ansiblefiles import check_empty_string_compare
from ansiblelater.rules.ansiblefiles import check_compare_to_literal_bool
from ansiblelater.rules.ansiblefiles import check_literal_bool_format
from ansiblelater.rules.ansiblefiles import check_become_user
from ansiblelater.rules.ansiblefiles import check_filter_separation
from ansiblelater.rules.taskfiles import check_line_between_tasks
from ansiblelater.rules.yamlfiles import check_native_yaml
from ansiblelater.rules.yamlfiles import check_yaml_colons
from ansiblelater.rules.yamlfiles import check_yaml_document_start
from ansiblelater.rules.yamlfiles import check_yaml_empty_lines
from ansiblelater.rules.yamlfiles import check_yaml_file
from ansiblelater.rules.yamlfiles import check_yaml_has_content
from ansiblelater.rules.yamlfiles import check_yaml_hyphens
from ansiblelater.rules.yamlfiles import check_yaml_indent
from ansiblelater.standard import Standard
tasks_should_be_separated = Standard(dict(
id="ANSIBLE0001",
@ -225,8 +225,8 @@ use_yaml_rather_than_key_value = Standard(dict(
))
ansible_min_version = '2.1'
ansible_review_min_version = '0.1.0'
ansible_min_version = "2.5"
ansible_review_min_version = "0.1.0"
standards = [

View File

@ -1,23 +1,25 @@
"""Custom exceptions."""
import re
# Custom exceptions
class LaterError(Exception):
"""Generic exception for later"""
"""Generic exception for later."""
def __init__(self, msg, original):
"""Initialize new exception."""
super(LaterError, self).__init__(msg + (": %s" % original))
self.original = original
class LaterAnsibleError(Exception):
"""Wrapper for ansible syntax errors"""
"""Wrapper for ansible syntax errors."""
def __init__(self, msg, original):
lines = original.message.splitlines()
line_no = re.search('line(.*?),', lines[2])
column_no = re.search('column(.*?),', lines[2])
line_no = re.search("line(.*?),", lines[2])
column_no = re.search("column(.*?),", lines[2])
self.message = lines[0]
self.line = line_no.group(1).strip()

183
ansiblelater/logger.py Normal file
View File

@ -0,0 +1,183 @@
"""Global logging helpers."""
import logging
import os
import sys
import colorama
from ansible.module_utils.parsing.convert_bool import boolean as to_bool
from pythonjsonlogger import jsonlogger
from six import iteritems
CONSOLE_FORMAT = "%(levelname)s: %(message)s"
JSON_FORMAT = "(asctime) (levelname) (message)"
def _should_do_markup():
py_colors = os.environ.get("PY_COLORS", None)
if py_colors is not None:
return to_bool(py_colors, strict=False)
return sys.stdout.isatty() and os.environ.get("TERM") != "dumb"
colorama.init(autoreset=True, strip=not _should_do_markup())
def flag_extra(extra):
"""Ensure extra args are prefixed."""
flagged = dict()
if isinstance(extra, dict):
for key, value in iteritems(extra):
flagged["later_" + key] = value
return flagged
class LogFilter(object):
"""A custom log filter which excludes log messages above the logged level."""
def __init__(self, level):
"""
Initialize a new custom log filter.
:param level: Log level limit
:returns: None
"""
self.__level = level
def filter(self, logRecord): # noqa
# https://docs.python.org/3/library/logging.html#logrecord-attributes
return logRecord.levelno <= self.__level
class MultilineFormatter(logging.Formatter):
"""Logging Formatter to reset color after newline characters."""
def format(self, record): # noqa
record.msg = record.msg.replace("\n", "\n{}... ".format(colorama.Style.RESET_ALL))
return logging.Formatter.format(self, record)
class MultilineJsonFormatter(jsonlogger.JsonFormatter):
"""Logging Formatter to remove newline characters."""
def format(self, record): # noqa
record.msg = record.msg.replace("\n", " ")
return jsonlogger.JsonFormatter.format(self, record)
def get_logger(name=None, level=logging.DEBUG, json=False):
"""
Build a logger with the given name and returns the logger.
:param name: The name for the logger. This is usually the module name, `__name__`.
:param level: Initialize the new logger with given log level.
:param json: Boolean flag to enable json formatted log output.
:return: logger object
"""
logger = logging.getLogger(name)
logger.setLevel(level)
logger.addHandler(_get_error_handler(json=json))
logger.addHandler(_get_warn_handler(json=json))
logger.addHandler(_get_info_handler(json=json))
logger.addHandler(_get_critical_handler(json=json))
logger.propagate = False
return logger
def update_logger(logger, level=None, json=None):
"""Update logger configuration to change logging settings."""
for handler in logger.handlers[:]:
logger.removeHandler(handler)
logger.setLevel(level)
logger.addHandler(_get_error_handler(json=json))
logger.addHandler(_get_warn_handler(json=json))
logger.addHandler(_get_info_handler(json=json))
logger.addHandler(_get_critical_handler(json=json))
def _get_error_handler(json=False):
handler = logging.StreamHandler(sys.stderr)
handler.setLevel(logging.ERROR)
handler.addFilter(LogFilter(logging.ERROR))
handler.setFormatter(MultilineFormatter(error(CONSOLE_FORMAT)))
if json:
handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT))
return handler
def _get_warn_handler(json=False):
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.WARN)
handler.addFilter(LogFilter(logging.WARN))
handler.setFormatter(MultilineFormatter(warn(CONSOLE_FORMAT)))
if json:
handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT))
return handler
def _get_info_handler(json=False):
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
handler.addFilter(LogFilter(logging.INFO))
handler.setFormatter(MultilineFormatter(info(CONSOLE_FORMAT)))
if json:
handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT))
return handler
def _get_critical_handler(json=False):
handler = logging.StreamHandler(sys.stderr)
handler.setLevel(logging.CRITICAL)
handler.addFilter(LogFilter(logging.CRITICAL))
handler.setFormatter(MultilineFormatter(critical(CONSOLE_FORMAT)))
if json:
handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT))
return handler
def critical(message):
"""Format critical messages and return string."""
return color_text(colorama.Fore.RED, "{}".format(message))
def error(message):
"""Format error messages and return string."""
return color_text(colorama.Fore.RED, "{}".format(message))
def warn(message):
"""Format warn messages and return string."""
return color_text(colorama.Fore.YELLOW, "{}".format(message))
def info(message):
"""Format info messages and return string."""
return color_text(colorama.Fore.BLUE, "{}".format(message))
def color_text(color, msg):
"""
Colorize strings.
:param color: colorama color settings
:param msg: string to colorize
:returns: string
"""
return "{}{}{}".format(color, msg, colorama.Style.RESET_ALL)

View File

@ -0,0 +1 @@
# noqa

View File

@ -1,16 +1,21 @@
import re
import os
"""Checks related to ansible specific best practices."""
import os
import re
from collections import defaultdict
from ansiblelater import Result, Error
from ansiblelater.command.candidates import Error
from ansiblelater.command.candidates import Result
from ansiblelater.utils import count_spaces
from ansiblelater.utils.rulehelper import (get_normalized_tasks,
get_normalized_yaml)
from ansiblelater.utils.rulehelper import get_normalized_tasks
from ansiblelater.utils.rulehelper import get_normalized_yaml
def check_braces_spaces(candidate, settings):
yamllines, errors = get_normalized_yaml(candidate, settings)
description = "no suitable numbers of spaces (required: 1)"
conf = settings["ansible"]["double-braces"]
description = "no suitable numbers of spaces (min: {min} max: {max})".format(
min=conf["min-spaces-inside"], max=conf["max-spaces-inside"])
matches = []
braces = re.compile("{{(.*?)}}")
@ -23,25 +28,29 @@ def check_braces_spaces(candidate, settings):
matches.append((i, item))
for i, line in matches:
leading, trailing = count_spaces(line)
[leading, trailing] = count_spaces(line)
sum_spaces = leading + trailing
if not leading == 1 or not trailing == 1:
if (
(sum_spaces < conf["min-spaces-inside"] * 2)
or (sum_spaces > conf["min-spaces-inside"] * 2)
):
errors.append(Error(i, description))
return Result(candidate.path, errors)
def check_named_task(candidate, settings):
tasks, errors = get_normalized_tasks(candidate, settings)
nameless_tasks = ['meta', 'debug', 'include_role', 'import_role',
'include_tasks', 'import_tasks', 'include_vars',
'block']
nameless_tasks = ["meta", "debug", "include_role", "import_role",
"include_tasks", "import_tasks", "include_vars",
"block"]
description = "module '%s' used without name attribute"
if not errors:
for task in tasks:
module = task["action"]["__ansible_module__"]
if 'name' not in task and module not in nameless_tasks:
errors.append(Error(task['__line__'], description % module))
if "name" not in task and module not in nameless_tasks:
errors.append(Error(task["__line__"], description % module))
return Result(candidate.path, errors)
@ -53,8 +62,8 @@ def check_name_format(candidate, settings):
if not errors:
for task in tasks:
if 'name' in task:
namelines[task['name']].append(task['__line__'])
if "name" in task:
namelines[task["name"]].append(task["__line__"])
for (name, lines) in namelines.items():
if not name[0].isupper():
errors.append(Error(lines[-1], description % name))
@ -70,8 +79,8 @@ def check_unique_named_task(candidate, settings):
if not errors:
for task in tasks:
if 'name' in task:
namelines[task['name']].append(task['__line__'])
if "name" in task:
namelines[task["name"]].append(task["__line__"])
for (name, lines) in namelines.items():
if len(lines) > 1:
errors.append(Error(lines[-1], description % name))
@ -81,28 +90,28 @@ def check_unique_named_task(candidate, settings):
def check_command_instead_of_module(candidate, settings):
tasks, errors = get_normalized_tasks(candidate, settings)
commands = ['command', 'shell', 'raw']
commands = ["command", "shell", "raw"]
modules = {
'git': 'git', 'hg': 'hg', 'curl': 'get_url or uri', 'wget': 'get_url or uri',
'svn': 'subversion', 'service': 'service', 'mount': 'mount',
'rpm': 'yum or rpm_key', 'yum': 'yum', 'apt-get': 'apt-get',
'unzip': 'unarchive', 'tar': 'unarchive', 'chkconfig': 'service',
'rsync': 'synchronize', 'supervisorctl': 'supervisorctl', 'systemctl': 'systemd',
'sed': 'template or lineinfile'
"git": "git", "hg": "hg", "curl": "get_url or uri", "wget": "get_url or uri",
"svn": "subversion", "service": "service", "mount": "mount",
"rpm": "yum or rpm_key", "yum": "yum", "apt-get": "apt-get",
"unzip": "unarchive", "tar": "unarchive", "chkconfig": "service",
"rsync": "synchronize", "supervisorctl": "supervisorctl", "systemctl": "systemd",
"sed": "template or lineinfile"
}
description = "%s command used in place of %s module"
if not errors:
for task in tasks:
if task["action"]["__ansible_module__"] in commands:
if 'cmd' in task['action']:
if "cmd" in task["action"]:
first_cmd_arg = task["action"]["cmd"].split()[0]
else:
first_cmd_arg = task["action"]["__ansible_arguments__"][0]
executable = os.path.basename(first_cmd_arg)
if (first_cmd_arg and executable in modules
and task['action'].get('warn', True) and 'register' not in task):
and task["action"].get("warn", True) and "register" not in task):
errors.append(
Error(task["__line__"], description % (executable, modules[executable])))
@ -111,10 +120,10 @@ def check_command_instead_of_module(candidate, settings):
def check_install_use_latest(candidate, settings):
tasks, errors = get_normalized_tasks(candidate, settings)
package_managers = ['yum', 'apt', 'dnf', 'homebrew', 'pacman', 'openbsd_package', 'pkg5',
'portage', 'pkgutil', 'slackpkg', 'swdepot', 'zypper', 'bundler', 'pip',
'pear', 'npm', 'yarn', 'gem', 'easy_install', 'bower', 'package', 'apk',
'openbsd_pkg', 'pkgng', 'sorcery', 'xbps']
package_managers = ["yum", "apt", "dnf", "homebrew", "pacman", "openbsd_package", "pkg5",
"portage", "pkgutil", "slackpkg", "swdepot", "zypper", "bundler", "pip",
"pear", "npm", "yarn", "gem", "easy_install", "bower", "package", "apk",
"openbsd_pkg", "pkgng", "sorcery", "xbps"]
description = "package installs should use state=present with or without a version"
if not errors:
@ -132,14 +141,14 @@ def check_shell_instead_command(candidate, settings):
if not errors:
for task in tasks:
if task["action"]["__ansible_module__"] == 'shell':
if 'cmd' in task['action']:
if task["action"]["__ansible_module__"] == "shell":
if "cmd" in task["action"]:
cmd = task["action"].get("cmd", [])
else:
cmd = ' '.join(task["action"].get("__ansible_arguments__", []))
cmd = " ".join(task["action"].get("__ansible_arguments__", []))
unjinja = re.sub(r"\{\{[^\}]*\}\}", "JINJA_VAR", cmd)
if not any([ch in unjinja for ch in '&|<>;$\n*[]{}?']):
if not any([ch in unjinja for ch in "&|<>;$\n*[]{}?"]):
errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors)
@ -147,7 +156,7 @@ def check_shell_instead_command(candidate, settings):
def check_command_has_changes(candidate, settings):
tasks, errors = get_normalized_tasks(candidate, settings)
commands = ['command', 'shell', 'raw']
commands = ["command", "shell", "raw"]
description = "commands should either read information (and thus set changed_when) or not " \
"do something if it has already been done (using creates/removes) " \
"or only do it if another check has a particular result (when)"
@ -155,10 +164,10 @@ def check_command_has_changes(candidate, settings):
if not errors:
for task in tasks:
if task["action"]["__ansible_module__"] in commands:
if ('changed_when' not in task and 'when' not in task
and 'when' not in task['__ansible_action_meta__']
and 'creates' not in task['action']
and 'removes' not in task['action']):
if ("changed_when" not in task and "when" not in task
and "when" not in task["__ansible_action_meta__"]
and "creates" not in task["action"]
and "removes" not in task["action"]):
errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors)
@ -166,8 +175,8 @@ def check_command_has_changes(candidate, settings):
def check_empty_string_compare(candidate, settings):
yamllines, errors = get_normalized_yaml(candidate, settings)
description = 'use `when: var` rather than `when: var != ""` (or ' \
'conversely `when: not var` rather than `when: var == ""`)'
description = "use `when: var` rather than `when: var != ""` (or " \
"conversely `when: not var` rather than `when: var == ""`)"
empty_string_compare = re.compile("[=!]= ?[\"'][\"']")
@ -202,7 +211,7 @@ def check_delegate_to_localhost(candidate, settings):
if not errors:
for task in tasks:
if task.get('delegate_to') == 'localhost':
if task.get("delegate_to") == "localhost":
errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors)
@ -225,12 +234,12 @@ def check_literal_bool_format(candidate, settings):
def check_become_user(candidate, settings):
tasks, errors = get_normalized_tasks(candidate, settings)
description = "the task has 'become:' enabled but 'become_user:' is missing"
true_value = [True, 'true', 'True', 'TRUE', 'yes', 'Yes', 'YES']
true_value = [True, "true", "True", "TRUE", "yes", "Yes", "YES"]
if not errors:
gen = (task for task in tasks if 'become' in task)
gen = (task for task in tasks if "become" in task)
for task in gen:
if task["become"] in true_value and 'become_user' not in task.keys():
if task["become"] in true_value and "become_user" not in task.keys():
errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors)

View File

@ -1,7 +1,11 @@
"""Checks related to ansible roles files."""
from nested_lookup import nested_lookup
from ansiblelater import Error, Result
from ansiblelater.utils.rulehelper import get_raw_yaml, get_tasks
from ansiblelater.command.candidates import Error
from ansiblelater.command.candidates import Result
from ansiblelater.utils.rulehelper import get_raw_yaml
from ansiblelater.utils.rulehelper import get_tasks
def check_meta_main(candidate, settings):
@ -23,7 +27,7 @@ def check_scm_in_src(candidate, settings):
if not errors:
for role in roles:
if '+' in role.get('src'):
errors.append(Error(role['__line__'], description))
if "+" in role.get("src"):
errors.append(Error(role["__line__"], description))
return Result(candidate.path, errors)

View File

@ -1,8 +1,10 @@
import re
"""Checks related to ansible task files."""
import re
from collections import defaultdict
from ansiblelater import Error, Result
from ansiblelater.command.candidates import Error
from ansiblelater.command.candidates import Result
from ansiblelater.utils.rulehelper import get_normalized_yaml

View File

@ -1,12 +1,15 @@
"""Checks related to generic YAML syntax (yamllint)."""
import codecs
import yaml
import os
from ansiblelater import Result
from ansiblelater import Error
import yaml
from ansiblelater.command.candidates import Error
from ansiblelater.command.candidates import Result
from ansiblelater.utils.rulehelper import get_action_tasks
from ansiblelater.utils.rulehelper import get_normalized_yaml
from ansiblelater.utils.rulehelper import get_normalized_task
from ansiblelater.utils.rulehelper import get_normalized_yaml
from ansiblelater.utils.rulehelper import run_yamllint
@ -31,46 +34,50 @@ def check_native_yaml(candidate, settings):
errors.extend(error)
break
action = normal_form['action']['__ansible_module__']
arguments = normal_form['action']['__ansible_arguments__']
# Cope with `set_fact` where task['set_fact'] is None
action = normal_form["action"]["__ansible_module__"]
arguments = normal_form["action"]["__ansible_arguments__"]
# Cope with `set_fact` where task["set_fact"] is None
if not task.get(action):
continue
if isinstance(task[action], dict):
continue
# strip additional newlines off task[action]
if task[action].strip().split() != arguments:
errors.append(Error(task['__line__'], description))
errors.append(Error(task["__line__"], description))
return Result(candidate.path, errors)
def check_yaml_empty_lines(candidate, settings):
options = "rules: {empty-lines: {max: 1, max-start: 0, max-end: 1}}"
errors = run_yamllint(candidate, settings, options)
options = "rules: {{empty-lines: {conf}}}".format(
conf=settings["yamllint"]["empty-lines"])
errors = run_yamllint(candidate.path, options)
return Result(candidate.path, errors)
def check_yaml_indent(candidate, settings):
options = "rules: {indentation: {spaces: 2, check-multi-line-strings: false, indent-sequences: true}}"
errors = run_yamllint(candidate, settings, options)
options = "rules: {{indentation: {conf}}}".format(
conf=settings["yamllint"]["indentation"])
errors = run_yamllint(candidate.path, options)
return Result(candidate.path, errors)
def check_yaml_hyphens(candidate, settings):
options = "rules: {hyphens: {max-spaces-after: 1}}"
errors = run_yamllint(candidate, settings, options)
options = "rules: {{hyphens: {conf}}}".format(
conf=settings["yamllint"]["hyphens"])
errors = run_yamllint(candidate.path, options)
return Result(candidate.path, errors)
def check_yaml_document_start(candidate, settings):
options = "rules: {document-start: {present: true}}"
errors = run_yamllint(candidate, settings, options)
options = "rules: {{document-start: {conf}}}".format(
conf=settings["yamllint"]["document-start"])
errors = run_yamllint(candidate.path, options)
return Result(candidate.path, errors)
def check_yaml_colons(candidate, settings):
options = "rules: {colons: {max-spaces-before: 0, max-spaces-after: 1}}"
errors = run_yamllint(candidate, settings, options)
options = "rules: {{colons: {conf}}}"
errors = run_yamllint(candidate.path, options)
return Result(candidate.path, errors)
@ -82,7 +89,7 @@ def check_yaml_file(candidate, settings):
errors.append(
Error(None, "file does not have a .yml extension"))
elif os.path.isfile(filename) and os.path.splitext(filename)[1][1:] == "yml":
with codecs.open(filename, mode='rb', encoding='utf-8') as f:
with codecs.open(filename, mode="rb", encoding="utf-8") as f:
try:
yaml.safe_load(f)
except Exception as e:

174
ansiblelater/settings.py Normal file
View File

@ -0,0 +1,174 @@
"""Global settings object definition."""
import os
import anyconfig
import pathspec
from appdirs import AppDirs
from jsonschema._utils import format_as_index
from pkg_resources import resource_filename
from ansiblelater import utils
config_dir = AppDirs("ansible-later").user_config_dir
default_config_file = os.path.join(config_dir, "config.yml")
class Settings(object):
"""
Create an object with all necessary settings.
Settings are loade from multiple locations in defined order (last wins):
- default settings defined by `self._get_defaults()`
- yaml config file, defaults to OS specific user config dir (https://pypi.org/project/appdirs/)
- provides cli parameters
"""
def __init__(self, args={}, config_file=default_config_file):
"""
Initialize a new settings class.
:param args: An optional dict of options, arguments and commands from the CLI.
:param config_file: An optional path to a yaml config file.
:returns: None
"""
self.config_file = config_file
self.schema = None
self.args_files = False
self.args = self._set_args(args)
self.config = self._get_config()
self._update_filelist()
def _set_args(self, args):
defaults = self._get_defaults()
self.config_file = args.get("config_file") or default_config_file
args.pop("config_file", None)
tmp_args = dict(filter(lambda item: item[1] is not None, args.items()))
tmp_dict = {}
for key, value in tmp_args.items():
tmp_dict = utils.add_dict_branch(tmp_dict, key.split("."), value)
# Override correct log level from argparse
levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
log_level = levels.index(defaults["logging"]["level"])
if tmp_dict.get("logging"):
for adjustment in tmp_dict["logging"]["level"]:
log_level = min(len(levels) - 1, max(log_level + adjustment, 0))
tmp_dict["logging"]["level"] = levels[log_level]
if len(tmp_dict["rules"]["files"]) == 0:
tmp_dict["rules"]["files"] = ["*"]
else:
tmp_dict["rules"]["files"] = tmp_dict["rules"]["files"]
self.args_files = True
return tmp_dict
def _get_config(self):
defaults = self._get_defaults()
source_files = []
source_files.append(self.config_file)
source_files.append(os.path.relpath(
os.path.normpath(os.path.join(os.getcwd(), ".later.yml"))))
cli_options = self.args
for config in source_files:
if config and os.path.exists(config):
with utils.open_file(config) as stream:
s = stream.read()
sdict = utils.safe_load(s)
if self._validate(sdict):
sdict["logging"]["level"] = sdict["logging"]["level"].upper()
anyconfig.merge(defaults, sdict, ac_merge=anyconfig.MS_DICTS)
if cli_options and self._validate(cli_options):
anyconfig.merge(defaults, cli_options, ac_merge=anyconfig.MS_DICTS)
return defaults
def _get_defaults(self):
rules_dir = os.path.join(resource_filename("ansiblelater", "data"))
defaults = {
"rules": {
"standards": rules_dir,
"filter": [],
"ignore_dotfiles": True,
"exclude_files": []
},
"logging": {
"level": "WARNING",
"json": False
},
"ansible": {
"custom_modules": [],
"double-braces": {
"min-spaces-inside": 1,
"max-spaces-inside": 1,
},
},
"yamllint": {
"empty-lines": {
"max": 1,
"max-start": 0,
"max-end": 1,
},
"indentation": {
"spaces": 2,
"check-multi-line-strings": False,
"indent-sequences": True,
},
"hyphens": {
"max-spaces-after": 1
},
"document-start": {
"present": True
},
"colons": {
"max-spaces-before": 0,
"max-spaces-after": 1
},
},
}
self.schema = anyconfig.gen_schema(defaults)
return defaults
def _validate(self, config):
try:
anyconfig.validate(config, self.schema, ac_schema_safe=False)
return True
except Exception as e:
schema_error = "Failed validating '{validator}' in schema{schema}".format(
validator=e.validator,
schema=format_as_index(list(e.relative_schema_path)[:-1])
)
utils.sysexit_with_message("{schema}: {msg}".format(schema=schema_error, msg=e.message))
def _update_filelist(self):
includes = self.config["rules"]["files"]
excludes = self.config["rules"]["exclude_files"]
ignore_dotfiles = self.config["rules"]["ignore_dotfiles"]
if ignore_dotfiles and not self.args_files:
excludes.append(".*")
else:
del excludes[:]
filelist = []
for root, dirs, files in os.walk("."):
for filename in files:
filelist.append(
os.path.relpath(os.path.normpath(os.path.join(root, filename))))
valid = []
includespec = pathspec.PathSpec.from_lines("gitwildmatch", includes)
excludespec = pathspec.PathSpec.from_lines("gitwildmatch", excludes)
for item in filelist:
if includespec.match_file(item) and not excludespec.match_file(item):
valid.append(item)
self.config["rules"]["files"] = valid

28
ansiblelater/standard.py Normal file
View File

@ -0,0 +1,28 @@
"""Standard definition."""
class Standard(object):
"""
Standard definition for all defined rules.
Later lookup the config file for a path to a rules directory
or fallback to default `ansiblelater/data/*`.
"""
def __init__(self, standard_dict):
"""
Initialize a new standard object and returns None.
:param standard_dict: Dictionary object containing all neseccary attributes
"""
self.id = standard_dict.get("id", "")
self.name = standard_dict.get("name")
self.version = standard_dict.get("version")
self.check = standard_dict.get("check")
self.types = standard_dict.get("types")
def __repr__(self): # noqa
return "Standard: %s (version: %s, types: %s)" % (
self.name, self.version, self.types)

View File

@ -0,0 +1,90 @@
"""Test logging module."""
from __future__ import print_function
import colorama
from ansiblelater import logger
def test_flag_extra():
extra = {}
extra.update(foo="bar")
flagged = logger.flag_extra(extra)
assert flagged.get("later_foo") == "bar"
def test_critical(capsys, mocker):
log = logger.get_logger("test_critical")
log.critical("foo")
_, stderr = capsys.readouterr()
print("{}{}{}".format(colorama.Fore.RED, "CRITICAL: foo".rstrip(),
colorama.Style.RESET_ALL))
x, _ = capsys.readouterr()
assert x == stderr
def test_error(capsys, mocker):
log = logger.get_logger("test_error")
log.error("foo")
_, stderr = capsys.readouterr()
print("{}{}{}".format(colorama.Fore.RED, "ERROR: foo".rstrip(),
colorama.Style.RESET_ALL))
x, _ = capsys.readouterr()
assert x == stderr
def test_warn(capsys, mocker):
log = logger.get_logger("test_warn")
log.warning("foo")
stdout, _ = capsys.readouterr()
print("{}{}{}".format(colorama.Fore.YELLOW, "WARNING: foo".rstrip(),
colorama.Style.RESET_ALL))
x, _ = capsys.readouterr()
assert x == stdout
def test_info(capsys, mocker):
log = logger.get_logger("test_info")
log.info("foo")
stdout, _ = capsys.readouterr()
print("{}{}{}".format(colorama.Fore.BLUE, "INFO: foo".rstrip(),
colorama.Style.RESET_ALL))
x, _ = capsys.readouterr()
assert x == stdout
def test_markup_detection_pycolors0(monkeypatch):
monkeypatch.setenv("PY_COLORS", "0")
assert not logger._should_do_markup()
def test_markup_detection_pycolors1(monkeypatch):
monkeypatch.setenv("PY_COLORS", "1")
assert logger._should_do_markup()
def test_markup_detection_tty_yes(mocker):
mocker.patch("sys.stdout.isatty", return_value=True)
mocker.patch("os.environ", {"TERM": "xterm"})
assert logger._should_do_markup()
mocker.resetall()
mocker.stopall()
def test_markup_detection_tty_no(mocker):
mocker.patch("os.environ", {})
mocker.patch("sys.stdout.isatty", return_value=False)
assert not logger._should_do_markup()
mocker.resetall()
mocker.stopall()

View File

@ -0,0 +1,25 @@
import pytest
from ansiblelater import settings
@pytest.fixture
def settings_instance():
c = settings.Settings(args={"rules": {"files": []}})
return c
def test_args_member(settings_instance):
x = {"rules": {"files": ["*"]}}
assert x == settings_instance.args
def test_args_setter(settings_instance):
default = {"rules.files": ["dummy"], "config_file": "conf.yml"}
x = {"rules": {"files": ["dummy"]}}
s = settings_instance._set_args(default)
assert x == s

View File

@ -1,53 +1,24 @@
"""Global utils collection."""
from __future__ import print_function
import importlib
import logging
import contextlib
import os
import sys
import re
import colorama
import sys
from distutils.version import LooseVersion
from ansible.module_utils.parsing.convert_bool import boolean as to_bool
import yaml
from ansiblelater import logger
try:
import ConfigParser as configparser
import ConfigParser as configparser # noqa
except ImportError:
import configparser
import configparser # noqa
def should_do_markup():
py_colors = os.environ.get('PY_COLORS', None)
if py_colors is not None:
return to_bool(py_colors, strict=False)
return sys.stdout.isatty() and os.environ.get('TERM') != 'dumb'
colorama.init(autoreset=True, strip=not should_do_markup())
def abort(message, file=sys.stderr):
return color_text(colorama.Fore.RED, "FATAL: {}".format(message))
sys.exit(1)
def error(message, file=sys.stderr):
return color_text(colorama.Fore.RED, "ERROR: {}".format(message))
def warn(message, settings, file=sys.stdout):
if settings.log_level <= logging.WARNING:
return color_text(colorama.Fore.YELLOW, "WARN: {}".format(message))
def info(message, settings, file=sys.stdout):
if settings.log_level <= logging.INFO:
return color_text(colorama.Fore.BLUE, "INFO: {}".format(message))
def color_text(color, msg):
print('{}{}{}'.format(color, msg, colorama.Style.RESET_ALL))
LOG = logger.get_logger(__name__)
def count_spaces(c_string):
@ -72,7 +43,7 @@ def get_property(prop):
parentdir = os.path.dirname(currentdir)
result = re.search(
r'{}\s*=\s*[\'"]([^\'"]*)[\'"]'.format(prop),
open(os.path.join(parentdir, '__init__.py')).read())
open(os.path.join(parentdir, "__init__.py")).read())
return result.group(1)
@ -95,35 +66,48 @@ def is_line_in_ranges(line, ranges):
return not ranges or any([line in r for r in ranges])
def read_standards(settings):
if not settings.rulesdir:
abort("Standards directory is not set on command line or in configuration file - aborting")
sys.path.append(os.path.abspath(os.path.expanduser(settings.rulesdir)))
def safe_load(string):
"""
Parse the provided string returns a dict.
:param string: A string to be parsed.
:returns: dict
"""
try:
standards = importlib.import_module('standards')
except ImportError as e:
abort("Could not import standards from directory %s: %s" % (settings.rulesdir, str(e)))
return standards
return yaml.safe_load(string) or {}
except yaml.scanner.ScannerError as e:
print(str(e))
def read_config(config_file):
config = configparser.RawConfigParser({'standards': None})
config.read(config_file)
@contextlib.contextmanager
def open_file(filename, mode="r"):
"""
Open the provide file safely and returns a file type.
return Settings(config, config_file)
:param filename: A string containing an absolute path to the file to open.
:param mode: A string describing the way in which the file will be used.
:returns: file type
"""
with open(filename, mode) as stream:
yield stream
class Settings(object):
def __init__(self, config, config_file):
self.rulesdir = None
self.custom_modules = []
self.log_level = None
self.standards_filter = None
def add_dict_branch(tree, vector, value):
key = vector[0]
tree[key] = value \
if len(vector) == 1 \
else add_dict_branch(tree[key] if key in tree else {},
vector[1:],
value)
return tree
if config.has_section('rules'):
self.rulesdir = config.get('rules', 'standards')
if config.has_section('ansible'):
modules = config.get('ansible', 'custom_modules')
self.custom_modules = [x.strip() for x in modules.split(',')]
self.configfile = config_file
def sysexit(code=1):
sys.exit(code)
def sysexit_with_message(msg, code=1):
LOG.critical(msg)
sysexit(code)

View File

@ -1,23 +1,26 @@
import codecs
import yaml
"""Abstracted methods to simplify role writeup."""
import codecs
from collections import defaultdict
import yaml
from yamllint import linter
from yamllint.config import YamlLintConfig
# Workaround for import errors with ansble 2.1 and 2.3
from ansible.parsing.dataloader import DataLoader
from ansiblelater import Error
from .yamlhelper import normalize_task
from ansiblelater.command.candidates import Error
from ansiblelater.exceptions import LaterAnsibleError
from ansiblelater.exceptions import LaterError
from .yamlhelper import action_tasks
from .yamlhelper import parse_yaml_linenumbers
from .yamlhelper import normalize_task
from .yamlhelper import normalized_yaml
from .exceptions import LaterError, LaterAnsibleError
from .yamlhelper import parse_yaml_linenumbers
def get_tasks(candidate, settings):
errors = []
try:
with codecs.open(candidate.path, mode='rb', encoding='utf-8') as f:
with codecs.open(candidate.path, mode="rb", encoding="utf-8") as f:
yamllines = parse_yaml_linenumbers(f, candidate.path)
except LaterError as ex:
@ -33,7 +36,7 @@ def get_action_tasks(candidate, settings):
tasks = []
errors = []
try:
with codecs.open(candidate.path, mode='rb', encoding='utf-8') as f:
with codecs.open(candidate.path, mode="rb", encoding="utf-8") as f:
yamllines = parse_yaml_linenumbers(f, candidate.path)
if yamllines:
@ -51,7 +54,7 @@ def get_normalized_task(task, candidate, settings):
normalized = None
errors = []
try:
normalized = normalize_task(task, candidate.path, settings.custom_modules)
normalized = normalize_task(task, candidate.path, settings["ansible"]["custom_modules"])
except LaterError as ex:
e = ex.original
errors.append(Error(e.problem_mark.line + 1, "syntax error: %s" % (e.problem)))
@ -65,19 +68,20 @@ def get_normalized_tasks(candidate, settings):
normalized = []
errors = []
try:
with codecs.open(candidate.path, mode='rb', encoding='utf-8') as f:
with codecs.open(candidate.path, mode="rb", encoding="utf-8") as f:
yamllines = parse_yaml_linenumbers(f, candidate.path)
if yamllines:
tasks = action_tasks(yamllines, candidate)
for task in tasks:
# An empty `tags` block causes `None` to be returned if
# the `or []` is not present - `task.get('tags', [])`
# the `or []` is not present - `task.get("tags", [])`
# does not suffice.
if 'skip_ansible_lint' in (task.get('tags') or []):
if "skip_ansible_lint" in (task.get("tags") or []):
# No need to normalize_task if we are skipping it.
continue
normalized.append(normalize_task(task, candidate.path, settings.custom_modules))
normalized.append(
normalize_task(task, candidate.path, settings["ansible"]["custom_modules"]))
except LaterError as ex:
e = ex.original
@ -112,7 +116,7 @@ def get_raw_yaml(candidate, settings):
errors = []
try:
with codecs.open(candidate.path, mode='rb', encoding='utf-8') as f:
with codecs.open(candidate.path, mode="rb", encoding="utf-8") as f:
content = yaml.safe_load(f)
except LaterError as ex:
@ -122,10 +126,10 @@ def get_raw_yaml(candidate, settings):
return content, errors
def run_yamllint(candidate, settings, options="extends: default"):
def run_yamllint(path, options="extends: default"):
errors = []
try:
with codecs.open(candidate.path, mode='rb', encoding='utf-8') as f:
with codecs.open(path, mode="rb", encoding="utf-8") as f:
for problem in linter.run(f, YamlLintConfig(options)):
errors.append(Error(problem.line, problem.desc))
except LaterError as ex:

View File

@ -1,3 +1,5 @@
"""Utils for YAML file operations."""
# Copyright (c) 2013-2014 Will Thames <will@thames.id.au>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@ -18,17 +20,27 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import codecs
import glob
import imp
import os
import codecs
import inspect
import os
import six
import ansible.parsing.mod_args
import six
import yaml
from ansible import constants
from ansible.errors import AnsibleError
from .exceptions import LaterError, LaterAnsibleError
from ansible.errors import AnsibleParserError
from ansible.parsing.dataloader import DataLoader
from ansible.parsing.mod_args import ModuleArgsParser
from ansible.parsing.yaml.constructor import AnsibleConstructor
from ansible.parsing.yaml.loader import AnsibleLoader
from ansible.template import Templar
from yaml.composer import Composer
from ansiblelater.exceptions import LaterAnsibleError
from ansiblelater.exceptions import LaterError
try:
# Try to import the Ansible 2 module first, it's the future-proof one
@ -38,25 +50,15 @@ except ImportError:
# Fallback on the Ansible 1.9 module
from ansible.module_utils.splitter import split_args
import yaml
from yaml.composer import Composer
from ansible.parsing.dataloader import DataLoader
from ansible.template import Templar
from ansible.parsing.mod_args import ModuleArgsParser
from ansible.parsing.yaml.constructor import AnsibleConstructor
from ansible.parsing.yaml.loader import AnsibleLoader
from ansible.errors import AnsibleParserError
# ansible-later doesn't need/want to know about encrypted secrets, but it needs
# Ansible 2.3+ allows encrypted secrets within yaml files, so we pass a string
# as the password to enable such yaml files to be opened and parsed successfully.
DEFAULT_VAULT_PASSWORD = 'x'
DEFAULT_VAULT_PASSWORD = "x"
def parse_yaml_from_file(filepath):
dl = DataLoader()
if hasattr(dl, 'set_vault_password'):
if hasattr(dl, "set_vault_password"):
dl.set_vault_password(DEFAULT_VAULT_PASSWORD)
return dl.load_from_file(filepath)
@ -79,28 +81,28 @@ try:
except ImportError:
from ansible.plugins.loader import module_loader
LINE_NUMBER_KEY = '__line__'
FILENAME_KEY = '__file__'
LINE_NUMBER_KEY = "__line__"
FILENAME_KEY = "__file__"
VALID_KEYS = [
'name', 'action', 'when', 'async', 'poll', 'notify',
'first_available_file', 'include', 'import_playbook',
'tags', 'register', 'ignore_errors', 'delegate_to',
'local_action', 'transport', 'remote_user', 'sudo',
'sudo_user', 'sudo_pass', 'when', 'connection', 'environment', 'args', 'always_run',
'any_errors_fatal', 'changed_when', 'failed_when', 'check_mode', 'delay',
'retries', 'until', 'su', 'su_user', 'su_pass', 'no_log', 'run_once',
'become', 'become_user', 'become_method', FILENAME_KEY,
"name", "action", "when", "async", "poll", "notify",
"first_available_file", "include", "import_playbook",
"tags", "register", "ignore_errors", "delegate_to",
"local_action", "transport", "remote_user", "sudo",
"sudo_user", "sudo_pass", "when", "connection", "environment", "args", "always_run",
"any_errors_fatal", "changed_when", "failed_when", "check_mode", "delay",
"retries", "until", "su", "su_user", "su_pass", "no_log", "run_once",
"become", "become_user", "become_method", FILENAME_KEY,
]
BLOCK_NAME_TO_ACTION_TYPE_MAP = {
'tasks': 'task',
'handlers': 'handler',
'pre_tasks': 'task',
'post_tasks': 'task',
'block': 'meta',
'rescue': 'meta',
'always': 'meta',
"tasks": "task",
"handlers": "handler",
"pre_tasks": "task",
"post_tasks": "task",
"block": "meta",
"rescue": "meta",
"always": "meta",
}
@ -108,9 +110,9 @@ def load_plugins(directory):
result = []
fh = None
for pluginfile in glob.glob(os.path.join(directory, '[A-Za-z]*.py')):
for pluginfile in glob.glob(os.path.join(directory, "[A-Za-z]*.py")):
pluginname = os.path.basename(pluginfile.replace('.py', ''))
pluginname = os.path.basename(pluginfile.replace(".py", ""))
try:
fh, filename, desc = imp.find_module(pluginname, [directory])
mod = imp.load_module(pluginname, fh, filename, desc)
@ -124,9 +126,9 @@ def load_plugins(directory):
def tokenize(line):
tokens = line.lstrip().split(" ")
if tokens[0] == '-':
if tokens[0] == "-":
tokens = tokens[1:]
if tokens[0] == 'action:' or tokens[0] == 'local_action:':
if tokens[0] == "action:" or tokens[0] == "local_action:":
tokens = tokens[1:]
command = tokens[0].replace(":", "")
@ -155,8 +157,8 @@ def _playbook_items(pb_data):
def find_children(playbook, playbook_dir):
if not os.path.exists(playbook[0]):
return []
if playbook[1] == 'role':
playbook_ds = {'roles': [{'role': playbook[0]}]}
if playbook[1] == "role":
playbook_ds = {"roles": [{"role": playbook[0]}]}
else:
try:
playbook_ds = parse_yaml_from_file(playbook[0])
@ -167,24 +169,24 @@ def find_children(playbook, playbook_dir):
items = _playbook_items(playbook_ds)
for item in items:
for child in play_children(basedir, item, playbook[1], playbook_dir):
if "$" in child['path'] or "{{" in child['path']:
if "$" in child["path"] or "{{" in child["path"]:
continue
valid_tokens = list()
for token in split_args(child['path']):
if '=' in token:
for token in split_args(child["path"]):
if "=" in token:
break
valid_tokens.append(token)
path = ' '.join(valid_tokens)
path = " ".join(valid_tokens)
results.append({
'path': path_dwim(basedir, path),
'type': child['type']
"path": path_dwim(basedir, path),
"type": child["type"]
})
return results
def template(basedir, value, vars, fail_on_undefined=False, **kwargs):
def template(basedir, value, variables, fail_on_undefined=False, **kwargs):
try:
value = ansible_template(os.path.abspath(basedir), value, vars,
value = ansible_template(os.path.abspath(basedir), value, variables,
**dict(kwargs, fail_on_undefined=fail_on_undefined))
# Hack to skip the following exception when using to_json filter on a variable.
# I guess the filter doesn't like empty vars...
@ -196,18 +198,18 @@ def template(basedir, value, vars, fail_on_undefined=False, **kwargs):
def play_children(basedir, item, parent_type, playbook_dir):
delegate_map = {
'tasks': _taskshandlers_children,
'pre_tasks': _taskshandlers_children,
'post_tasks': _taskshandlers_children,
'block': _taskshandlers_children,
'include': _include_children,
'import_playbook': _include_children,
'roles': _roles_children,
'dependencies': _roles_children,
'handlers': _taskshandlers_children,
"tasks": _taskshandlers_children,
"pre_tasks": _taskshandlers_children,
"post_tasks": _taskshandlers_children,
"block": _taskshandlers_children,
"include": _include_children,
"import_playbook": _include_children,
"roles": _roles_children,
"dependencies": _roles_children,
"handlers": _taskshandlers_children,
}
(k, v) = item
play_library = os.path.join(os.path.abspath(basedir), 'library')
play_library = os.path.join(os.path.abspath(basedir), "library")
_load_library_if_exists(play_library)
if k in delegate_map:
@ -225,35 +227,35 @@ def _include_children(basedir, k, v, parent_type):
(command, args, kwargs) = tokenize("{0}: {1}".format(k, v))
result = path_dwim(basedir, args[0])
if not os.path.exists(result) and not basedir.endswith('tasks'):
result = path_dwim(os.path.join(basedir, '..', 'tasks'), v)
return [{'path': result, 'type': parent_type}]
if not os.path.exists(result) and not basedir.endswith("tasks"):
result = path_dwim(os.path.join(basedir, "..", "tasks"), v)
return [{"path": result, "type": parent_type}]
def _taskshandlers_children(basedir, k, v, parent_type):
results = []
for th in v:
if 'include' in th:
append_children(th['include'], basedir, k, parent_type, results)
elif 'include_tasks' in th:
append_children(th['include_tasks'], basedir, k, parent_type, results)
elif 'import_playbook' in th:
append_children(th['import_playbook'], basedir, k, parent_type, results)
elif 'import_tasks' in th:
append_children(th['import_tasks'], basedir, k, parent_type, results)
elif 'import_role' in th:
results.extend(_roles_children(basedir, k, [th['import_role'].get('name')], parent_type,
main=th['import_role'].get('tasks_from', 'main')))
elif 'include_role' in th:
results.extend(_roles_children(basedir, k, [th['include_role'].get('name')],
if "include" in th:
append_children(th["include"], basedir, k, parent_type, results)
elif "include_tasks" in th:
append_children(th["include_tasks"], basedir, k, parent_type, results)
elif "import_playbook" in th:
append_children(th["import_playbook"], basedir, k, parent_type, results)
elif "import_tasks" in th:
append_children(th["import_tasks"], basedir, k, parent_type, results)
elif "import_role" in th:
results.extend(_roles_children(basedir, k, [th["import_role"].get("name")], parent_type,
main=th["import_role"].get("tasks_from", "main")))
elif "include_role" in th:
results.extend(_roles_children(basedir, k, [th["include_role"].get("name")],
parent_type,
main=th['include_role'].get('tasks_from', 'main')))
elif 'block' in th:
results.extend(_taskshandlers_children(basedir, k, th['block'], parent_type))
if 'rescue' in th:
results.extend(_taskshandlers_children(basedir, k, th['rescue'], parent_type))
if 'always' in th:
results.extend(_taskshandlers_children(basedir, k, th['always'], parent_type))
main=th["include_role"].get("tasks_from", "main")))
elif "block" in th:
results.extend(_taskshandlers_children(basedir, k, th["block"], parent_type))
if "rescue" in th:
results.extend(_taskshandlers_children(basedir, k, th["rescue"], parent_type))
if "always" in th:
results.extend(_taskshandlers_children(basedir, k, th["always"], parent_type))
return results
@ -261,28 +263,28 @@ def append_children(taskhandler, basedir, k, parent_type, results):
# when taskshandlers_children is called for playbooks, the
# actual type of the included tasks is the section containing the
# include, e.g. tasks, pre_tasks, or handlers.
if parent_type == 'playbook':
if parent_type == "playbook":
playbook_section = k
else:
playbook_section = parent_type
results.append({
'path': path_dwim(basedir, taskhandler),
'type': playbook_section
"path": path_dwim(basedir, taskhandler),
"type": playbook_section
})
def _roles_children(basedir, k, v, parent_type, main='main'):
def _roles_children(basedir, k, v, parent_type, main="main"):
results = []
for role in v:
if isinstance(role, dict):
if 'role' in role or 'name' in role:
if 'tags' not in role or 'skip_ansible_later' not in role['tags']:
if "role" in role or "name" in role:
if "tags" not in role or "skip_ansible_later" not in role["tags"]:
results.extend(_look_for_role_files(basedir,
role.get('role', role.get('name')),
role.get("role", role.get("name")),
main=main))
else:
raise SystemExit('role dict {0} does not contain a "role" '
'or "name" key'.format(role))
raise SystemExit("role dict {0} does not contain a 'role' "
"or 'name' key".format(role))
else:
results.extend(_look_for_role_files(basedir, role, main=main))
return results
@ -298,13 +300,13 @@ def _rolepath(basedir, role):
possible_paths = [
# if included from a playbook
path_dwim(basedir, os.path.join('roles', role)),
path_dwim(basedir, os.path.join("roles", role)),
path_dwim(basedir, role),
# if included from roles/[role]/meta/main.yml
path_dwim(
basedir, os.path.join('..', '..', '..', 'roles', role)
basedir, os.path.join("..", "..", "..", "roles", role)
),
path_dwim(basedir, os.path.join('..', '..', role))
path_dwim(basedir, os.path.join("..", "..", role))
]
if constants.DEFAULT_ROLES_PATH:
@ -321,33 +323,33 @@ def _rolepath(basedir, role):
break
if role_path:
_load_library_if_exists(os.path.join(role_path, 'library'))
_load_library_if_exists(os.path.join(role_path, "library"))
return role_path
def _look_for_role_files(basedir, role, main='main'):
def _look_for_role_files(basedir, role, main="main"):
role_path = _rolepath(basedir, role)
if not role_path:
return []
results = []
for th in ['tasks', 'handlers', 'meta']:
for ext in ('.yml', '.yaml'):
for th in ["tasks", "handlers", "meta"]:
for ext in (".yml", ".yaml"):
thpath = os.path.join(role_path, th, main + ext)
if os.path.exists(thpath):
results.append({'path': thpath, 'type': th})
results.append({"path": thpath, "type": th})
break
return results
def rolename(filepath):
idx = filepath.find('roles/')
idx = filepath.find("roles/")
if idx < 0:
return ''
return ""
role = filepath[idx + 6:]
role = role[:role.find('/')]
role = role[:role.find("/")]
return role
@ -357,11 +359,11 @@ def _kv_to_dict(v):
def normalize_task(task, filename, custom_modules=[]):
'''Ensures tasks have an action key and strings are converted to python objects'''
ansible_action_type = task.get('__ansible_action_type__', 'task')
ansible_action_meta = task.get('__ansible_action_meta__', dict())
if '__ansible_action_type__' in task:
del(task['__ansible_action_type__'])
"""Ensure tasks have an action key and strings are converted to python objects."""
ansible_action_type = task.get("__ansible_action_type__", "task")
ansible_action_meta = task.get("__ansible_action_meta__", dict())
if "__ansible_action_type__" in task:
del(task["__ansible_action_type__"])
normalized = dict()
# TODO: Workaround for custom modules
@ -370,53 +372,53 @@ def normalize_task(task, filename, custom_modules=[]):
ansible.parsing.mod_args.BUILTIN_TASKS = frozenset(builtin)
mod_arg_parser = ModuleArgsParser(task)
try:
action, arguments, normalized['delegate_to'] = mod_arg_parser.parse()
action, arguments, normalized["delegate_to"] = mod_arg_parser.parse()
except AnsibleParserError as e:
raise LaterAnsibleError("syntax error", e)
# denormalize shell -> command conversion
if '_uses_shell' in arguments:
action = 'shell'
del(arguments['_uses_shell'])
if "_uses_shell" in arguments:
action = "shell"
del(arguments["_uses_shell"])
for (k, v) in list(task.items()):
if k in ('action', 'local_action', 'args', 'delegate_to') or k == action:
# we don't want to re-assign these values, which were
if k in ("action", "local_action", "args", "delegate_to") or k == action:
# we don"t want to re-assign these values, which were
# determined by the ModuleArgsParser() above
continue
else:
normalized[k] = v
normalized['action'] = dict(__ansible_module__=action)
normalized["action"] = dict(__ansible_module__=action)
if '_raw_params' in arguments:
normalized['action']['__ansible_arguments__'] = arguments['_raw_params'].split(' ')
del(arguments['_raw_params'])
if "_raw_params" in arguments:
normalized["action"]["__ansible_arguments__"] = arguments["_raw_params"].split(" ")
del(arguments["_raw_params"])
else:
normalized['action']['__ansible_arguments__'] = list()
normalized['action'].update(arguments)
normalized["action"]["__ansible_arguments__"] = list()
normalized["action"].update(arguments)
normalized[FILENAME_KEY] = filename
normalized['__ansible_action_type__'] = ansible_action_type
normalized['__ansible_action_meta__'] = ansible_action_meta
normalized["__ansible_action_type__"] = ansible_action_type
normalized["__ansible_action_meta__"] = ansible_action_meta
return normalized
def action_tasks(yaml, file):
tasks = list()
if file['filetype'] in ['tasks', 'handlers']:
tasks = add_action_type(yaml, file['filetype'])
if file["filetype"] in ["tasks", "handlers"]:
tasks = add_action_type(yaml, file["filetype"])
else:
tasks.extend(extract_from_list(yaml, ['tasks', 'handlers', 'pre_tasks', 'post_tasks']))
tasks.extend(extract_from_list(yaml, ["tasks", "handlers", "pre_tasks", "post_tasks"]))
# Add sub-elements of block/rescue/always to tasks list
tasks.extend(extract_from_list(tasks, ['block', 'rescue', 'always']))
tasks.extend(extract_from_list(tasks, ["block", "rescue", "always"]))
# Remove block/rescue/always elements from tasks list
block_rescue_always = ('block', 'rescue', 'always')
block_rescue_always = ("block", "rescue", "always")
tasks[:] = [task for task in tasks if all(k not in task for k in block_rescue_always)]
return [task for task in tasks if set(
['include', 'include_tasks', 'import_playbook', 'import_tasks']).isdisjoint(task.keys())]
["include", "include_tasks", "import_playbook", "import_tasks"]).isdisjoint(task.keys())]
def task_to_str(task):
@ -434,12 +436,12 @@ def extract_from_list(blocks, candidates):
results = list()
for block in blocks:
for candidate in candidates:
delete_meta_keys = [candidate, '__line__', '__file__', '__ansible_action_type__']
delete_meta_keys = [candidate, "__line__", "__file__", "__ansible_action_type__"]
if isinstance(block, dict) and candidate in block:
if isinstance(block[candidate], list):
meta_data = dict(block)
for key in delete_meta_keys:
del meta_data[key]
meta_data.pop(key, None)
results.extend(add_action_type(block[candidate], candidate, meta_data))
elif block[candidate] is not None:
raise RuntimeError(
@ -451,19 +453,20 @@ def extract_from_list(blocks, candidates):
def add_action_type(actions, action_type, action_meta=None):
results = list()
for action in actions:
action['__ansible_action_type__'] = BLOCK_NAME_TO_ACTION_TYPE_MAP[action_type]
action["__ansible_action_type__"] = BLOCK_NAME_TO_ACTION_TYPE_MAP[action_type]
if action_meta:
action['__ansible_action_meta__'] = action_meta
action["__ansible_action_meta__"] = action_meta
results.append(action)
return results
def parse_yaml_linenumbers(data, filename):
"""Parses yaml as ansible.utils.parse_yaml but with linenumbers.
"""
Parse yaml as ansible.utils.parse_yaml but with linenumbers.
The line numbers are stored in each node's LINE_NUMBER_KEY key.
"""
"""
def compose_node(parent, index):
# the line number where the previous token has ended (plus empty lines)
line = loader.line
@ -473,7 +476,7 @@ def parse_yaml_linenumbers(data, filename):
def construct_mapping(node, deep=False):
mapping = AnsibleConstructor.construct_mapping(loader, node, deep=deep)
if hasattr(node, '__line__'):
if hasattr(node, "__line__"):
mapping[LINE_NUMBER_KEY] = node.__line__
else:
mapping[LINE_NUMBER_KEY] = mapping._line_number
@ -482,14 +485,17 @@ def parse_yaml_linenumbers(data, filename):
try:
kwargs = {}
if 'vault_password' in inspect.getargspec(AnsibleLoader.__init__).args:
kwargs['vault_password'] = DEFAULT_VAULT_PASSWORD
if "vault_password" in inspect.getargspec(AnsibleLoader.__init__).args:
kwargs["vault_password"] = DEFAULT_VAULT_PASSWORD
loader = AnsibleLoader(data, **kwargs)
loader.compose_node = compose_node
loader.construct_mapping = construct_mapping
data = loader.get_single_data()
except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e:
raise LaterError("syntax error", e)
except (yaml.composer.ComposerError) as e:
e.problem = "{} {}".format(e.context, e.problem)
raise LaterError("syntax error", e)
return data
@ -498,7 +504,7 @@ def normalized_yaml(file, options):
removes = []
try:
with codecs.open(file, mode='rb', encoding='utf-8') as f:
with codecs.open(file, mode="rb", encoding="utf-8") as f:
lines = list(enumerate(f.readlines(), start=1))
for i, line in lines:

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python
import sys
import ansiblelater.__main__
sys.exit(ansiblelater.__main__.main())

78
env_27/bin/activate Normal file
View File

@ -0,0 +1,78 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
unset -f pydoc >/dev/null 2>&1
# reset old environment variables
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi
if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/Users/rkau2905/Devel/python/private/ansible-later/env_27"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
_OLD_VIRTUAL_PS1="$PS1"
if [ "x" != x ] ; then
PS1="$PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
fi
export PS1
fi
# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc
pydoc () {
python -m pydoc "$@"
}
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi

42
env_27/bin/activate.csh Normal file
View File

@ -0,0 +1,42 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
set newline='\
'
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/Users/rkau2905/Devel/python/private/ansible-later/env_27"
set _OLD_VIRTUAL_PATH="$PATH:q"
setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q"
if ("" != "") then
set env_name = ""
else
set env_name = "$VIRTUAL_ENV:t:q"
endif
# Could be in a non-interactive environment,
# in which case, $prompt is undefined and we wouldn't
# care about the prompt anyway.
if ( $?prompt ) then
set _OLD_VIRTUAL_PROMPT="$prompt:q"
if ( "$prompt:q" =~ *"$newline:q"* ) then
:
else
set prompt = "[$env_name:q] $prompt:q"
endif
endif
unset env_name
alias pydoc python -m pydoc
rehash

76
env_27/bin/activate.fish Normal file
View File

@ -0,0 +1,76 @@
# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
# Do not run it directly.
function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
# Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
set -l fish_function_path
# Erase virtualenv's `fish_prompt` and restore the original.
functions -e fish_prompt
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
end
set -e VIRTUAL_ENV
if test "$argv[1]" != 'nondestructive'
# Self-destruct!
functions -e pydoc
functions -e deactivate
end
end
# Unset irrelevant variables.
deactivate nondestructive
set -gx VIRTUAL_ENV "/Users/rkau2905/Devel/python/private/ansible-later/env_27"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# Unset `$PYTHONHOME` if set.
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
function pydoc
python -m pydoc $argv
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# Copy the current `fish_prompt` function as `_old_fish_prompt`.
functions -c fish_prompt _old_fish_prompt
function fish_prompt
# Save the current $status, for fish_prompts that display it.
set -l old_status $status
# Prompt override provided?
# If not, just prepend the environment name.
if test -n ""
printf '%s%s' "" (set_color normal)
else
printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV")
end
# Restore the original $status
echo "exit $old_status" | source
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

150
env_27/bin/activate.ps1 Normal file
View File

@ -0,0 +1,150 @@
# This file must be dot sourced from PoSh; you cannot run it
# directly. Do this: . ./activate.ps1
# FIXME: clean up unused vars.
$script:THIS_PATH = $myinvocation.mycommand.path
$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent
$script:DIR_NAME = split-path $BASE_DIR -Leaf
function global:deactivate ( [switch] $NonDestructive ){
if ( test-path variable:_OLD_VIRTUAL_PATH ) {
$env:PATH = $variable:_OLD_VIRTUAL_PATH
remove-variable "_OLD_VIRTUAL_PATH" -scope global
}
if ( test-path function:_old_virtual_prompt ) {
$function:prompt = $function:_old_virtual_prompt
remove-item function:\_old_virtual_prompt
}
if ($env:VIRTUAL_ENV) {
$old_env = split-path $env:VIRTUAL_ENV -leaf
remove-item env:VIRTUAL_ENV -erroraction silentlycontinue
}
if ( !$NonDestructive ) {
# Self destruct!
remove-item function:deactivate
}
}
# unset irrelevant variables
deactivate -nondestructive
$VIRTUAL_ENV = $BASE_DIR
$env:VIRTUAL_ENV = $VIRTUAL_ENV
$global:_OLD_VIRTUAL_PATH = $env:PATH
$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH
if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) {
function global:_old_virtual_prompt { "" }
$function:_old_virtual_prompt = $function:prompt
function global:prompt {
# Add a prefix to the current prompt, but don't discard it.
write-host "($(split-path $env:VIRTUAL_ENV -leaf)) " -nonewline
& $function:_old_virtual_prompt
}
}
# SIG # Begin signature block
# MIISeAYJKoZIhvcNAQcCoIISaTCCEmUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUS5reBwSg3zOUwhXf2jPChZzf
# yPmggg6tMIIGcDCCBFigAwIBAgIBJDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQG
# EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
# Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
# dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjIwMTQ2WhcNMTcxMDI0MjIw
# MTQ2WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
# BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
# BAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgT2JqZWN0
# IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyiOLIjUemqAbPJ1J
# 0D8MlzgWKbr4fYlbRVjvhHDtfhFN6RQxq0PjTQxRgWzwFQNKJCdU5ftKoM5N4YSj
# Id6ZNavcSa6/McVnhDAQm+8H3HWoD030NVOxbjgD/Ih3HaV3/z9159nnvyxQEckR
# ZfpJB2Kfk6aHqW3JnSvRe+XVZSufDVCe/vtxGSEwKCaNrsLc9pboUoYIC3oyzWoU
# TZ65+c0H4paR8c8eK/mC914mBo6N0dQ512/bkSdaeY9YaQpGtW/h/W/FkbQRT3sC
# pttLVlIjnkuY4r9+zvqhToPjxcfDYEf+XD8VGkAqle8Aa8hQ+M1qGdQjAye8OzbV
# uUOw7wIDAQABo4IB6TCCAeUwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
# AQYwHQYDVR0OBBYEFNBOD0CZbLhLGW87KLjg44gHNKq3MB8GA1UdIwQYMBaAFE4L
# 7xqkQFulF2mHMMo0aEPQQa7yMD0GCCsGAQUFBwEBBDEwLzAtBggrBgEFBQcwAoYh
# aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3J0MFsGA1UdHwRUMFIwJ6Al
# oCOGIWh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3Nmc2NhLmNybDAnoCWgI4YhaHR0
# cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMIGABgNVHSAEeTB3MHUGCysG
# AQQBgbU3AQIBMGYwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
# L3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
# L2ludGVybWVkaWF0ZS5wZGYwEQYJYIZIAYb4QgEBBAQDAgABMFAGCWCGSAGG+EIB
# DQRDFkFTdGFydENvbSBDbGFzcyAyIFByaW1hcnkgSW50ZXJtZWRpYXRlIE9iamVj
# dCBTaWduaW5nIENlcnRpZmljYXRlczANBgkqhkiG9w0BAQUFAAOCAgEAcnMLA3Va
# N4OIE9l4QT5OEtZy5PByBit3oHiqQpgVEQo7DHRsjXD5H/IyTivpMikaaeRxIv95
# baRd4hoUcMwDj4JIjC3WA9FoNFV31SMljEZa66G8RQECdMSSufgfDYu1XQ+cUKxh
# D3EtLGGcFGjjML7EQv2Iol741rEsycXwIXcryxeiMbU2TPi7X3elbwQMc4JFlJ4B
# y9FhBzuZB1DV2sN2irGVbC3G/1+S2doPDjL1CaElwRa/T0qkq2vvPxUgryAoCppU
# FKViw5yoGYC+z1GaesWWiP1eFKAL0wI7IgSvLzU3y1Vp7vsYaxOVBqZtebFTWRHt
# XjCsFrrQBngt0d33QbQRI5mwgzEp7XJ9xu5d6RVWM4TPRUsd+DDZpBHm9mszvi9g
# VFb2ZG7qRRXCSqys4+u/NLBPbXi/m/lU00cODQTlC/euwjk9HQtRrXQ/zqsBJS6U
# J+eLGw1qOfj+HVBl/ZQpfoLk7IoWlRQvRL1s7oirEaqPZUIWY/grXq9r6jDKAp3L
# ZdKQpPOnnogtqlU4f7/kLjEJhrrc98mrOWmVMK/BuFRAfQ5oDUMnVmCzAzLMjKfG
# cVW/iMew41yfhgKbwpfzm3LBr1Zv+pEBgcgW6onRLSAn3XHM0eNtz+AkxH6rRf6B
# 2mYhLEEGLapH8R1AMAo4BbVFOZR5kXcMCwowggg1MIIHHaADAgECAgIEuDANBgkq
# hkiG9w0BAQUFADCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0
# ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcx
# ODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUg
# T2JqZWN0IENBMB4XDTExMTIwMzE1MzQxOVoXDTEzMTIwMzE0NTgwN1owgYwxIDAe
# BgNVBA0TFzU4MTc5Ni1HaDd4Zkp4a3hRU0lPNEUwMQswCQYDVQQGEwJERTEPMA0G
# A1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xFjAUBgNVBAMTDUphbm5pcyBM
# ZWlkZWwxITAfBgkqhkiG9w0BCQEWEmphbm5pc0BsZWlkZWwuaW5mbzCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMcPeABYdN7nPq/AkZ/EkyUBGx/l2Yui
# Lfm8ZdLG0ulMb/kQL3fRY7sUjYPyn9S6PhqqlFnNoGHJvbbReCdUC9SIQYmOEjEA
# raHfb7MZU10NjO4U2DdGucj2zuO5tYxKizizOJF0e4yRQZVxpUGdvkW/+GLjCNK5
# L7mIv3Z1dagxDKHYZT74HXiS4VFUwHF1k36CwfM2vsetdm46bdgSwV+BCMmZICYT
# IJAS9UQHD7kP4rik3bFWjUx08NtYYFAVOd/HwBnemUmJe4j3IhZHr0k1+eDG8hDH
# KVvPgLJIoEjC4iMFk5GWsg5z2ngk0LLu3JZMtckHsnnmBPHQK8a3opUNd8hdMNJx
# gOwKjQt2JZSGUdIEFCKVDqj0FmdnDMPfwy+FNRtpBMl1sz78dUFhSrnM0D8NXrqa
# 4rG+2FoOXlmm1rb6AFtpjAKksHRpYcPk2DPGWp/1sWB+dUQkS3gOmwFzyqeTuXpT
# 0juqd3iAxOGx1VRFQ1VHLLf3AzV4wljBau26I+tu7iXxesVucSdsdQu293jwc2kN
# xK2JyHCoZH+RyytrwS0qw8t7rMOukU9gwP8mn3X6mgWlVUODMcHTULjSiCEtvyZ/
# aafcwjUbt4ReEcnmuZtWIha86MTCX7U7e+cnpWG4sIHPnvVTaz9rm8RyBkIxtFCB
# nQ3FnoQgyxeJAgMBAAGjggOdMIIDmTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIH
# gDAuBgNVHSUBAf8EJDAiBggrBgEFBQcDAwYKKwYBBAGCNwIBFQYKKwYBBAGCNwoD
# DTAdBgNVHQ4EFgQUWyCgrIWo8Ifvvm1/YTQIeMU9nc8wHwYDVR0jBBgwFoAU0E4P
# QJlsuEsZbzsouODjiAc0qrcwggIhBgNVHSAEggIYMIICFDCCAhAGCysGAQQBgbU3
# AQICMIIB/zAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9s
# aWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50
# ZXJtZWRpYXRlLnBkZjCB9wYIKwYBBQUHAgIwgeowJxYgU3RhcnRDb20gQ2VydGlm
# aWNhdGlvbiBBdXRob3JpdHkwAwIBARqBvlRoaXMgY2VydGlmaWNhdGUgd2FzIGlz
# c3VlZCBhY2NvcmRpbmcgdG8gdGhlIENsYXNzIDIgVmFsaWRhdGlvbiByZXF1aXJl
# bWVudHMgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeSwgcmVsaWFuY2Ugb25seSBm
# b3IgdGhlIGludGVuZGVkIHB1cnBvc2UgaW4gY29tcGxpYW5jZSBvZiB0aGUgcmVs
# eWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4wgZwGCCsGAQUFBwICMIGPMCcWIFN0YXJ0
# Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMCAQIaZExpYWJpbGl0eSBhbmQg
# d2FycmFudGllcyBhcmUgbGltaXRlZCEgU2VlIHNlY3Rpb24gIkxlZ2FsIGFuZCBM
# aW1pdGF0aW9ucyIgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeS4wNgYDVR0fBC8w
# LTAroCmgJ4YlaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0YzItY3JsLmNybDCB
# iQYIKwYBBQUHAQEEfTB7MDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5zdGFydHNz
# bC5jb20vc3ViL2NsYXNzMi9jb2RlL2NhMEAGCCsGAQUFBzAChjRodHRwOi8vYWlh
# LnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MyLmNvZGUuY2EuY3J0MCMGA1Ud
# EgQcMBqGGGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tLzANBgkqhkiG9w0BAQUFAAOC
# AQEAhrzEV6zwoEtKjnFRhCsjwiPykVpo5Eiye77Ve801rQDiRKgSCCiW6g3HqedL
# OtaSs65Sj2pm3Viea4KR0TECLcbCTgsdaHqw2x1yXwWBQWZEaV6EB05lIwfr94P1
# SFpV43zkuc+bbmA3+CRK45LOcCNH5Tqq7VGTCAK5iM7tvHwFlbQRl+I6VEL2mjpF
# NsuRjDOVrv/9qw/a22YJ9R7Y1D0vUSs3IqZx2KMUaYDP7H2mSRxJO2nADQZBtriF
# gTyfD3lYV12MlIi5CQwe3QC6DrrfSMP33i5Wa/OFJiQ27WPxmScYVhiqozpImFT4
# PU9goiBv9RKXdgTmZE1PN0NQ5jGCAzUwggMxAgEBMIGTMIGMMQswCQYDVQQGEwJJ
# TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
# YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
# MiBQcmltYXJ5IEludGVybWVkaWF0ZSBPYmplY3QgQ0ECAgS4MAkGBSsOAwIaBQCg
# eDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE
# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJ
# BDEWBBRVGw0FDSiaIi38dWteRUAg/9Pr6DANBgkqhkiG9w0BAQEFAASCAgCInvOZ
# FdaNFzbf6trmFDZKMojyx3UjKMCqNjHVBbuKY0qXwFC/ElYDV1ShJ2CBZbdurydO
# OQ6cIQ0KREOCwmX/xB49IlLHHUxNhEkVv7HGU3EKAFf9IBt9Yr7jikiR9cjIsfHK
# 4cjkoKJL7g28yEpLLkHt1eo37f1Ga9lDWEa5Zq3U5yX+IwXhrUBm1h8Xr033FhTR
# VEpuSz6LHtbrL/zgJnCzJ2ahjtJoYevdcWiNXffosJHFaSfYDDbiNsPRDH/1avmb
# 5j/7BhP8BcBaR6Fp8tFbNGIcWHHGcjqLMnTc4w13b7b4pDhypqElBa4+lCmwdvv9
# GydYtRgPz8GHeoBoKj30YBlMzRIfFYaIFGIC4Ai3UEXkuH9TxYohVbGm/W0Kl4Lb
# RJ1FwiVcLcTOJdgNId2vQvKc+jtNrjcg5SP9h2v/C4aTx8tyc6tE3TOPh2f9b8DL
# S+SbVArJpuJqrPTxDDoO1QNjTgLcdVYeZDE+r/NjaGZ6cMSd8db3EaG3ijD/0bud
# SItbm/OlNVbQOFRR76D+ZNgPcU5iNZ3bmvQQIg6aSB9MHUpIE/SeCkNl9YeVk1/1
# GFULgNMRmIYP4KLvu9ylh5Gu3hvD5VNhH6+FlXANwFy07uXks5uF8mfZVxVCnodG
# xkNCx+6PsrA5Z7WP4pXcmYnMn97npP/Q9EHJWw==
# SIG # End signature block

View File

@ -0,0 +1,36 @@
"""By using execfile(this_file, dict(__file__=this_file)) you will
activate this virtualenv environment.
This can be used when you must use an existing Python interpreter, not
the virtualenv bin/python
"""
try:
__file__
except NameError:
raise AssertionError(
"You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))"
)
import os
import site
import sys
old_os_path = os.environ.get("PATH", "")
os.environ["PATH"] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if sys.platform == "win32":
site_packages = os.path.join(base, "Lib", "site-packages")
else:
site_packages = os.path.join(base, "lib", "python%s" % sys.version[:3], "site-packages")
prev_sys_path = list(sys.path)
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path

163
env_27/bin/ansible Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-config Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

328
env_27/bin/ansible-connection Executable file
View File

@ -0,0 +1,328 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# Copyright: (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
pass
import fcntl
import hashlib
import os
import signal
import socket
import sys
import time
import traceback
import errno
import json
from contextlib import contextmanager
from ansible import constants as C
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.six import PY3
from ansible.module_utils.six.moves import cPickle, StringIO
from ansible.module_utils.connection import Connection, ConnectionError, send_data, recv_data
from ansible.module_utils.service import fork_process
from ansible.playbook.play_context import PlayContext
from ansible.plugins.loader import connection_loader
from ansible.utils.path import unfrackpath, makedirs_safe
from ansible.utils.display import Display
from ansible.utils.jsonrpc import JsonRpcServer
def read_stream(byte_stream):
size = int(byte_stream.readline().strip())
data = byte_stream.read(size)
if len(data) < size:
raise Exception("EOF found before data was complete")
data_hash = to_text(byte_stream.readline().strip())
if data_hash != hashlib.sha1(data).hexdigest():
raise Exception("Read {0} bytes, but data did not match checksum".format(size))
# restore escaped loose \r characters
data = data.replace(br'\r', b'\r')
return data
@contextmanager
def file_lock(lock_path):
"""
Uses contextmanager to create and release a file lock based on the
given path. This allows us to create locks using `with file_lock()`
to prevent deadlocks related to failure to unlock properly.
"""
lock_fd = os.open(lock_path, os.O_RDWR | os.O_CREAT, 0o600)
fcntl.lockf(lock_fd, fcntl.LOCK_EX)
yield
fcntl.lockf(lock_fd, fcntl.LOCK_UN)
os.close(lock_fd)
class ConnectionProcess(object):
'''
The connection process wraps around a Connection object that manages
the connection to a remote device that persists over the playbook
'''
def __init__(self, fd, play_context, socket_path, original_path, ansible_playbook_pid=None):
self.play_context = play_context
self.socket_path = socket_path
self.original_path = original_path
self.fd = fd
self.exception = None
self.srv = JsonRpcServer()
self.sock = None
self.connection = None
self._ansible_playbook_pid = ansible_playbook_pid
def start(self, variables):
try:
messages = list()
result = {}
messages.append('control socket path is %s' % self.socket_path)
# If this is a relative path (~ gets expanded later) then plug the
# key's path on to the directory we originally came from, so we can
# find it now that our cwd is /
if self.play_context.private_key_file and self.play_context.private_key_file[0] not in '~/':
self.play_context.private_key_file = os.path.join(self.original_path, self.play_context.private_key_file)
self.connection = connection_loader.get(self.play_context.connection, self.play_context, '/dev/null',
ansible_playbook_pid=self._ansible_playbook_pid)
self.connection.set_options(var_options=variables)
self.connection._connect()
self.connection._socket_path = self.socket_path
self.srv.register(self.connection)
messages.extend(sys.stdout.getvalue().splitlines())
messages.append('connection to remote device started successfully')
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.bind(self.socket_path)
self.sock.listen(1)
messages.append('local domain socket listeners started successfully')
except Exception as exc:
result['error'] = to_text(exc)
result['exception'] = traceback.format_exc()
finally:
result['messages'] = messages
self.fd.write(json.dumps(result))
self.fd.close()
def run(self):
try:
while self.connection.connected:
signal.signal(signal.SIGALRM, self.connect_timeout)
signal.signal(signal.SIGTERM, self.handler)
signal.alarm(self.connection.get_option('persistent_connect_timeout'))
self.exception = None
(s, addr) = self.sock.accept()
signal.alarm(0)
signal.signal(signal.SIGALRM, self.command_timeout)
while True:
data = recv_data(s)
if not data:
break
signal.alarm(self.connection.get_option('persistent_command_timeout'))
resp = self.srv.handle_request(data)
signal.alarm(0)
send_data(s, to_bytes(resp))
s.close()
except Exception as e:
# socket.accept() will raise EINTR if the socket.close() is called
if hasattr(e, 'errno'):
if e.errno != errno.EINTR:
self.exception = traceback.format_exc()
else:
self.exception = traceback.format_exc()
finally:
# allow time for any exception msg send over socket to receive at other end before shutting down
time.sleep(0.1)
# when done, close the connection properly and cleanup the socket file so it can be recreated
self.shutdown()
def connect_timeout(self, signum, frame):
msg = 'persistent connection idle timeout triggered, timeout value is %s secs.\nSee the timeout setting options in the Network Debug and ' \
'Troubleshooting Guide.' % self.connection.get_option('persistent_connect_timeout')
display.display(msg, log_only=True)
raise Exception(msg)
def command_timeout(self, signum, frame):
msg = 'command timeout triggered, timeout value is %s secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide.'\
% self.connection.get_option('persistent_command_timeout')
display.display(msg, log_only=True)
raise Exception(msg)
def handler(self, signum, frame):
msg = 'signal handler called with signal %s.' % signum
display.display(msg, log_only=True)
raise Exception(msg)
def shutdown(self):
""" Shuts down the local domain socket
"""
lock_path = unfrackpath("%s/.ansible_pc_lock_%s" % os.path.split(self.socket_path))
if os.path.exists(self.socket_path):
try:
if self.sock:
self.sock.close()
if self.connection:
self.connection.close()
except:
pass
finally:
if os.path.exists(self.socket_path):
os.remove(self.socket_path)
setattr(self.connection, '_socket_path', None)
setattr(self.connection, '_connected', False)
if os.path.exists(lock_path):
os.remove(lock_path)
display.display('shutdown complete', log_only=True)
def main():
""" Called to initiate the connect to the remote device
"""
rc = 0
result = {}
messages = list()
socket_path = None
# Need stdin as a byte stream
if PY3:
stdin = sys.stdin.buffer
else:
stdin = sys.stdin
# Note: update the below log capture code after Display.display() is refactored.
saved_stdout = sys.stdout
sys.stdout = StringIO()
try:
# read the play context data via stdin, which means depickling it
vars_data = read_stream(stdin)
init_data = read_stream(stdin)
if PY3:
pc_data = cPickle.loads(init_data, encoding='bytes')
variables = cPickle.loads(vars_data, encoding='bytes')
else:
pc_data = cPickle.loads(init_data)
variables = cPickle.loads(vars_data)
play_context = PlayContext()
play_context.deserialize(pc_data)
display.verbosity = play_context.verbosity
except Exception as e:
rc = 1
result.update({
'error': to_text(e),
'exception': traceback.format_exc()
})
if rc == 0:
ssh = connection_loader.get('ssh', class_only=True)
ansible_playbook_pid = sys.argv[1]
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user, play_context.connection, ansible_playbook_pid)
# create the persistent connection dir if need be and create the paths
# which we will be using later
tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR)
makedirs_safe(tmp_path)
socket_path = unfrackpath(cp % dict(directory=tmp_path))
lock_path = unfrackpath("%s/.ansible_pc_lock_%s" % os.path.split(socket_path))
with file_lock(lock_path):
if not os.path.exists(socket_path):
messages.append('local domain socket does not exist, starting it')
original_path = os.getcwd()
r, w = os.pipe()
pid = fork_process()
if pid == 0:
try:
os.close(r)
wfd = os.fdopen(w, 'w')
process = ConnectionProcess(wfd, play_context, socket_path, original_path, ansible_playbook_pid)
process.start(variables)
except Exception:
messages.append(traceback.format_exc())
rc = 1
if rc == 0:
process.run()
else:
process.shutdown()
sys.exit(rc)
else:
os.close(w)
rfd = os.fdopen(r, 'r')
data = json.loads(rfd.read())
messages.extend(data.pop('messages'))
result.update(data)
else:
messages.append('found existing local domain socket, using it!')
conn = Connection(socket_path)
conn.set_options(var_options=variables)
pc_data = to_text(init_data)
try:
messages.extend(conn.update_play_context(pc_data))
except Exception as exc:
# Only network_cli has update_play context, so missing this is
# not fatal e.g. netconf
if isinstance(exc, ConnectionError) and getattr(exc, 'code', None) == -32601:
pass
else:
result.update({
'error': to_text(exc),
'exception': traceback.format_exc()
})
messages.append(sys.stdout.getvalue())
result.update({
'messages': messages,
'socket_path': socket_path
})
sys.stdout = saved_stdout
if 'exception' in result:
rc = 1
sys.stderr.write(json.dumps(result))
else:
rc = 0
sys.stdout.write(json.dumps(result))
sys.exit(rc)
if __name__ == '__main__':
display = Display()
main()

163
env_27/bin/ansible-console Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-doc Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-galaxy Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-inventory Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

12
env_27/bin/ansible-later Executable file
View File

@ -0,0 +1,12 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'ansible-later','console_scripts','ansible-later'
__requires__ = 'ansible-later'
import re
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(
load_entry_point('ansible-later', 'console_scripts', 'ansible-later')()
)

163
env_27/bin/ansible-playbook Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-pull Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

163
env_27/bin/ansible-vault Executable file
View File

@ -0,0 +1,163 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import shutil
import sys
import traceback
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.module_utils._text import to_text
# Used for determining if the system is running a new enough python version
# and should only restrict on our documented minimum versions
_PY3_MIN = sys.version_info[:2] >= (3, 5)
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
_PY_MIN = _PY3_MIN or _PY2_MIN
if not _PY_MIN:
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
class LastResort(object):
# OUTPUT OF LAST RESORT
def display(self, msg, log_only=None):
print(msg, file=sys.stderr)
def error(self, msg, wrap_text=None):
print(msg, file=sys.stderr)
if __name__ == '__main__':
display = LastResort()
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
import ansible.constants as C
from ansible.utils.display import Display
except AnsibleOptionsError as e:
display.error(to_text(e), wrap_text=False)
sys.exit(5)
cli = None
me = os.path.basename(sys.argv[0])
try:
display = Display()
display.debug("starting run")
sub = None
target = me.split('-')
if target[-1][0].isdigit():
# Remove any version or python version info as downstreams
# sometimes add that
target = target[:-1]
if len(target) > 1:
sub = target[1]
myclass = "%sCLI" % sub.capitalize()
elif target[0] == 'ansible':
sub = 'adhoc'
myclass = 'AdHocCLI'
else:
raise AnsibleError("Unknown Ansible alias: %s" % me)
try:
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
except ImportError as e:
# ImportError members have changed in py3
if 'msg' in dir(e):
msg = e.msg
else:
msg = e.message
if msg.endswith(' %s' % sub):
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
else:
raise
try:
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
except UnicodeError:
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
exit_code = 6
else:
cli = mycli(args)
cli.parse()
exit_code = cli.run()
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_text(e), wrap_text=False)
exit_code = 5
except AnsibleParserError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 4
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
except AnsibleError as e:
display.error(to_text(e), wrap_text=False)
exit_code = 1
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
except Exception as e:
if C.DEFAULT_DEBUG:
# Show raw stacktraces in debug mode, It also allow pdb to
# enter post mortem mode.
raise
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
log_only = False
if hasattr(e, 'orig_exc'):
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
why = to_text(e.orig_exc)
if to_text(e) != why:
display.vvv('\noriginal msg: %s' % why)
else:
display.display("to see the full traceback, use -vvv")
log_only = True
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
exit_code = 250
finally:
# Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)

10
env_27/bin/anyconfig_cli Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from anyconfig.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/bandit Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from bandit.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/bandit-baseline Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from bandit.cli.baseline import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from bandit.cli.config_generator import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/coverage Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from coverage.cmdline import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/coverage-2.7 Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from coverage.cmdline import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/coverage2 Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from coverage.cmdline import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
env_27/bin/easy_install Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
env_27/bin/easy_install-2.7 Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/flake8 Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from flake8.main.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/isort Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from isort.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/jsonschema Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from jsonschema.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/pbr Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pbr.cmd.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
env_27/bin/pip Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
env_27/bin/pip2 Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
env_27/bin/pip2.7 Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/py.test Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pytest import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/pycodestyle Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pycodestyle import _main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(_main())

10
env_27/bin/pydocstyle Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pydocstyle.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/pyflakes Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pyflakes.api import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/pytest Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pytest import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

BIN
env_27/bin/python Executable file

Binary file not shown.

78
env_27/bin/python-config Executable file
View File

@ -0,0 +1,78 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
import sys
import getopt
import sysconfig
valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags',
'ldflags', 'help']
if sys.version_info >= (3, 2):
valid_opts.insert(-1, 'extension-suffix')
valid_opts.append('abiflags')
if sys.version_info >= (3, 3):
valid_opts.append('configdir')
def exit_with_usage(code=1):
sys.stderr.write("Usage: {0} [{1}]\n".format(
sys.argv[0], '|'.join('--'+opt for opt in valid_opts)))
sys.exit(code)
try:
opts, args = getopt.getopt(sys.argv[1:], '', valid_opts)
except getopt.error:
exit_with_usage()
if not opts:
exit_with_usage()
pyver = sysconfig.get_config_var('VERSION')
getvar = sysconfig.get_config_var
opt_flags = [flag for (flag, val) in opts]
if '--help' in opt_flags:
exit_with_usage(code=0)
for opt in opt_flags:
if opt == '--prefix':
print(sysconfig.get_config_var('prefix'))
elif opt == '--exec-prefix':
print(sysconfig.get_config_var('exec_prefix'))
elif opt in ('--includes', '--cflags'):
flags = ['-I' + sysconfig.get_path('include'),
'-I' + sysconfig.get_path('platinclude')]
if opt == '--cflags':
flags.extend(getvar('CFLAGS').split())
print(' '.join(flags))
elif opt in ('--libs', '--ldflags'):
abiflags = getattr(sys, 'abiflags', '')
libs = ['-lpython' + pyver + abiflags]
libs += getvar('LIBS').split()
libs += getvar('SYSLIBS').split()
# add the prefix/lib/pythonX.Y/config dir, but only if there is no
# shared library in prefix/lib/.
if opt == '--ldflags':
if not getvar('Py_ENABLE_SHARED'):
libs.insert(0, '-L' + getvar('LIBPL'))
if not getvar('PYTHONFRAMEWORK'):
libs.extend(getvar('LINKFORSHARED').split())
print(' '.join(libs))
elif opt == '--extension-suffix':
ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
if ext_suffix is None:
ext_suffix = sysconfig.get_config_var('SO')
print(ext_suffix)
elif opt == '--abiflags':
if not getattr(sys, 'abiflags', None):
exit_with_usage()
print(sys.abiflags)
elif opt == '--configdir':
print(sysconfig.get_config_var('LIBPL'))

1
env_27/bin/python2 Symbolic link
View File

@ -0,0 +1 @@
python

1
env_27/bin/python2.7 Symbolic link
View File

@ -0,0 +1 @@
python

68
env_27/bin/unidiff Executable file
View File

@ -0,0 +1,68 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
from __future__ import print_function, unicode_literals
import argparse
import codecs
import sys
from unidiff import DEFAULT_ENCODING, PatchSet
PY2 = sys.version_info[0] == 2
DESCRIPTION = """Unified diff metadata.
Examples:
$ git diff | unidiff
$ hg diff | unidiff --show-diff
$ unidiff -f patch.diff
"""
def get_parser():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=DESCRIPTION)
parser.add_argument('--show-diff', action="store_true", default=False,
dest='show_diff', help='output diff to stdout')
parser.add_argument('-f', '--file', dest='diff_file',
type=argparse.FileType('r'),
help='if not specified, read diff data from stdin')
return parser
if __name__ == '__main__':
parser = get_parser()
args = parser.parse_args()
encoding = DEFAULT_ENCODING
if args.diff_file:
diff_file = args.diff_file
else:
encoding = sys.stdin.encoding or encoding
diff_file = sys.stdin
if PY2:
diff_file = codecs.getreader(encoding)(diff_file)
patch = PatchSet(diff_file)
if args.show_diff:
print(patch)
print()
print('Summary')
print('-------')
additions = 0
deletions = 0
for f in patch:
additions += f.added
deletions += f.removed
print('%s:' % f.path, '+%d additions,' % f.added,
'-%d deletions' % f.removed)
print()
print('%d modified file(s), %d added file(s), %d removed file(s)' % (
len(patch.modified_files), len(patch.added_files),
len(patch.removed_files)))
print('Total: %d addition(s), %d deletion(s)' % (additions, deletions))

11
env_27/bin/wheel Executable file
View File

@ -0,0 +1,11 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from wheel.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
env_27/bin/yamllint Executable file
View File

@ -0,0 +1,10 @@
#!/Users/rkau2905/Devel/python/private/ansible-later/env_27/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from yamllint.cli import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(run())

1
env_27/include/python2.7 Symbolic link
View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_weakrefset.py

1
env_27/lib/python2.7/abc.py Symbolic link
View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/abc.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/codecs.py

1
env_27/lib/python2.7/config Symbolic link
View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py

View File

@ -0,0 +1,116 @@
import imp
import os
import sys
import warnings
# opcode is not a virtualenv module, so we can use it to find the stdlib
# Important! To work on pypy, this must be a module that resides in the
# lib-python/modified-x.y.z directory
import opcode
dirname = os.path.dirname
distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils")
if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)):
warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?")
else:
__path__.insert(0, distutils_path) # noqa: F821
real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY))
# Copy the relevant attributes
try:
__revision__ = real_distutils.__revision__
except AttributeError:
pass
__version__ = real_distutils.__version__
from distutils import dist, sysconfig # isort:skip
try:
basestring
except NameError:
basestring = str
# patch build_ext (distutils doesn't know how to get the libs directory
# path on windows - it hardcodes the paths around the patched sys.prefix)
if sys.platform == "win32":
from distutils.command.build_ext import build_ext as old_build_ext
class build_ext(old_build_ext):
def finalize_options(self):
if self.library_dirs is None:
self.library_dirs = []
elif isinstance(self.library_dirs, basestring):
self.library_dirs = self.library_dirs.split(os.pathsep)
self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs"))
old_build_ext.finalize_options(self)
from distutils.command import build_ext as build_ext_module
build_ext_module.build_ext = build_ext
# distutils.dist patches:
old_find_config_files = dist.Distribution.find_config_files
def find_config_files(self):
found = old_find_config_files(self)
if os.name == "posix":
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"
user_filename = os.path.join(sys.prefix, user_filename)
if os.path.isfile(user_filename):
for item in list(found):
if item.endswith("pydistutils.cfg"):
found.remove(item)
found.append(user_filename)
return found
dist.Distribution.find_config_files = find_config_files
# distutils.sysconfig patches:
old_get_python_inc = sysconfig.get_python_inc
def sysconfig_get_python_inc(plat_specific=0, prefix=None):
if prefix is None:
prefix = sys.real_prefix
return old_get_python_inc(plat_specific, prefix)
sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__
sysconfig.get_python_inc = sysconfig_get_python_inc
old_get_python_lib = sysconfig.get_python_lib
def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
if standard_lib and prefix is None:
prefix = sys.real_prefix
return old_get_python_lib(plat_specific, standard_lib, prefix)
sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__
sysconfig.get_python_lib = sysconfig_get_python_lib
old_get_config_vars = sysconfig.get_config_vars
def sysconfig_get_config_vars(*args):
real_vars = old_get_config_vars(*args)
if sys.platform == "win32":
lib_dir = os.path.join(sys.real_prefix, "libs")
if isinstance(real_vars, dict) and "LIBDIR" not in real_vars:
real_vars["LIBDIR"] = lib_dir # asked for all
elif isinstance(real_vars, list) and "LIBDIR" in args:
real_vars = real_vars + [lib_dir] # asked for list
return real_vars
sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__
sysconfig.get_config_vars = sysconfig_get_config_vars

View File

@ -0,0 +1,6 @@
# This is a config file local to this virtualenv installation
# You may include options that will be used by all distutils commands,
# and by easy_install. For instance:
#
# [easy_install]
# find_links = http://mylocalsite

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/fnmatch.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/genericpath.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/linecache.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/locale.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ntpath.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7

1
env_27/lib/python2.7/os.py Symbolic link
View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py

View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py

1
env_27/lib/python2.7/re.py Symbolic link
View File

@ -0,0 +1 @@
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py

View File

@ -0,0 +1,31 @@
Metadata-Version: 2.1
Name: GitPython
Version: 2.1.11
Summary: Python Git Library
Home-page: https://github.com/gitpython-developers/GitPython
Author: Sebastian Thiel, Michael Trier
Author-email: byronimo@gmail.com, mtrier@gmail.com
License: BSD License
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Requires: gitdb2 (>=2.0.0)
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
Requires-Dist: gitdb2 (>=2.0.0)
GitPython is a python library used to interact with Git repositories

Some files were not shown because too many files have changed in this diff Show More