mirror of
https://github.com/thegeeklab/ansible-later.git
synced 2024-09-27 17:58:15 +00:00
add missing dependencies and fix drone pipeline
This commit is contained in:
parent
f0f5e20a23
commit
04dec26a3a
@ -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",
|
||||
|
@ -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
8
.flake8
Normal 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
|
@ -37,7 +37,6 @@ class Candidate(object):
|
||||
self.filetype = type(self).__name__.lower()
|
||||
self.expected_version = True
|
||||
self.standards = self._get_standards(settings, standards)
|
||||
self.version = self._get_version(settings)
|
||||
|
||||
try:
|
||||
with codecs.open(filename, mode="rb", encoding="utf-8") as f:
|
||||
@ -46,7 +45,13 @@ class Candidate(object):
|
||||
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):
|
||||
@ -55,10 +60,7 @@ class Candidate(object):
|
||||
path = meta_file
|
||||
break
|
||||
parentdir = os.path.dirname(parentdir)
|
||||
else:
|
||||
path = self.path
|
||||
|
||||
version = None
|
||||
version_re = re.compile(r"^# Standards:\s*([\d.]+)")
|
||||
|
||||
with codecs.open(path, mode="rb", encoding="utf-8") as f:
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""Global settings object definition."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import anyconfig
|
||||
@ -58,7 +57,7 @@ class Settings(object):
|
||||
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"] = logging.getLevelName(levels[log_level])
|
||||
tmp_dict["logging"]["level"] = levels[log_level]
|
||||
|
||||
if len(tmp_dict["rules"]["files"]) == 0:
|
||||
tmp_dict["rules"]["files"] = "*"
|
||||
|
78
env_27/bin/activate
Normal file
78
env_27/bin/activate
Normal 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
42
env_27/bin/activate.csh
Normal 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
76
env_27/bin/activate.fish
Normal 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
150
env_27/bin/activate.ps1
Normal 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
|
36
env_27/bin/activate_this.py
Normal file
36
env_27/bin/activate_this.py
Normal 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
163
env_27/bin/ansible
Executable 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
163
env_27/bin/ansible-config
Executable 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
328
env_27/bin/ansible-connection
Executable 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
163
env_27/bin/ansible-console
Executable 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
163
env_27/bin/ansible-doc
Executable 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
163
env_27/bin/ansible-galaxy
Executable 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
163
env_27/bin/ansible-inventory
Executable 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
12
env_27/bin/ansible-later
Executable 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
163
env_27/bin/ansible-playbook
Executable 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
163
env_27/bin/ansible-pull
Executable 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
163
env_27/bin/ansible-vault
Executable 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
10
env_27/bin/anyconfig_cli
Executable 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())
|
11
env_27/bin/easy_install
Executable file
11
env_27/bin/easy_install
Executable 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
11
env_27/bin/easy_install-2.7
Executable 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
10
env_27/bin/flake8
Executable 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/jsonschema
Executable file
10
env_27/bin/jsonschema
Executable 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())
|
11
env_27/bin/pip
Executable file
11
env_27/bin/pip
Executable 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
11
env_27/bin/pip2
Executable 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
11
env_27/bin/pip2.7
Executable 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/pycodestyle
Executable file
10
env_27/bin/pycodestyle
Executable 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/pyflakes
Executable file
10
env_27/bin/pyflakes
Executable 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())
|
BIN
env_27/bin/python
Executable file
BIN
env_27/bin/python
Executable file
Binary file not shown.
78
env_27/bin/python-config
Executable file
78
env_27/bin/python-config
Executable 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
1
env_27/bin/python2
Symbolic link
@ -0,0 +1 @@
|
||||
python
|
1
env_27/bin/python2.7
Symbolic link
1
env_27/bin/python2.7
Symbolic link
@ -0,0 +1 @@
|
||||
python
|
68
env_27/bin/unidiff
Executable file
68
env_27/bin/unidiff
Executable 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
11
env_27/bin/wheel
Executable 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
10
env_27/bin/yamllint
Executable 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
1
env_27/include/python2.7
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
|
1
env_27/lib/python2.7/UserDict.py
Symbolic link
1
env_27/lib/python2.7/UserDict.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py
|
1
env_27/lib/python2.7/_abcoll.py
Symbolic link
1
env_27/lib/python2.7/_abcoll.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py
|
1
env_27/lib/python2.7/_weakrefset.py
Symbolic link
1
env_27/lib/python2.7/_weakrefset.py
Symbolic link
@ -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
1
env_27/lib/python2.7/abc.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/abc.py
|
1
env_27/lib/python2.7/codecs.py
Symbolic link
1
env_27/lib/python2.7/codecs.py
Symbolic link
@ -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
1
env_27/lib/python2.7/config
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config
|
1
env_27/lib/python2.7/copy_reg.py
Symbolic link
1
env_27/lib/python2.7/copy_reg.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py
|
116
env_27/lib/python2.7/distutils/__init__.py
Normal file
116
env_27/lib/python2.7/distutils/__init__.py
Normal 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
|
6
env_27/lib/python2.7/distutils/distutils.cfg
Normal file
6
env_27/lib/python2.7/distutils/distutils.cfg
Normal 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
|
1
env_27/lib/python2.7/encodings
Symbolic link
1
env_27/lib/python2.7/encodings
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings
|
1
env_27/lib/python2.7/fnmatch.py
Symbolic link
1
env_27/lib/python2.7/fnmatch.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/fnmatch.py
|
1
env_27/lib/python2.7/genericpath.py
Symbolic link
1
env_27/lib/python2.7/genericpath.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/genericpath.py
|
1
env_27/lib/python2.7/lib-dynload
Symbolic link
1
env_27/lib/python2.7/lib-dynload
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload
|
1
env_27/lib/python2.7/linecache.py
Symbolic link
1
env_27/lib/python2.7/linecache.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/linecache.py
|
1
env_27/lib/python2.7/locale.py
Symbolic link
1
env_27/lib/python2.7/locale.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/locale.py
|
0
env_27/lib/python2.7/no-global-site-packages.txt
Normal file
0
env_27/lib/python2.7/no-global-site-packages.txt
Normal file
1
env_27/lib/python2.7/ntpath.py
Symbolic link
1
env_27/lib/python2.7/ntpath.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ntpath.py
|
1
env_27/lib/python2.7/orig-prefix.txt
Normal file
1
env_27/lib/python2.7/orig-prefix.txt
Normal file
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7
|
1
env_27/lib/python2.7/os.py
Symbolic link
1
env_27/lib/python2.7/os.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py
|
1
env_27/lib/python2.7/posixpath.py
Symbolic link
1
env_27/lib/python2.7/posixpath.py
Symbolic link
@ -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
1
env_27/lib/python2.7/re.py
Symbolic link
@ -0,0 +1 @@
|
||||
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,31 @@
|
||||
Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,67 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Jinja2
|
||||
Version: 2.10.1
|
||||
Summary: A small but fast and easy to use stand-alone template engine written in pure python.
|
||||
Home-page: http://jinja.pocoo.org/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
License: BSD
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||
Requires-Dist: MarkupSafe (>=0.23)
|
||||
Provides-Extra: i18n
|
||||
Requires-Dist: Babel (>=0.8) ; extra == 'i18n'
|
||||
|
||||
|
||||
Jinja2
|
||||
~~~~~~
|
||||
|
||||
Jinja2 is a template engine written in pure Python. It provides a
|
||||
`Django`_ inspired non-XML syntax but supports inline expressions and
|
||||
an optional `sandboxed`_ environment.
|
||||
|
||||
Nutshell
|
||||
--------
|
||||
|
||||
Here a small example of a Jinja template::
|
||||
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Memberlist{% endblock %}
|
||||
{% block content %}
|
||||
<ul>
|
||||
{% for user in users %}
|
||||
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
Philosophy
|
||||
----------
|
||||
|
||||
Application logic is for the controller but don't try to make the life
|
||||
for the template designer too hard by giving him too few functionality.
|
||||
|
||||
For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
|
||||
|
||||
.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security)
|
||||
.. _Django: https://www.djangoproject.com/
|
||||
.. _Jinja2 webpage: http://jinja.pocoo.org/
|
||||
.. _documentation: http://jinja.pocoo.org/2/documentation/
|
||||
|
||||
|
@ -0,0 +1,59 @@
|
||||
Jinja2-2.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Jinja2-2.10.1.dist-info/LICENSE,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554
|
||||
Jinja2-2.10.1.dist-info/METADATA,sha256=rx0eN8lX8iq8-YVppmCzV1Qx4y3Pj9IWi08mXUCrewI,2227
|
||||
Jinja2-2.10.1.dist-info/RECORD,,
|
||||
Jinja2-2.10.1.dist-info/WHEEL,sha256=HX-v9-noUkyUoxyZ1PMSuS7auUxDAR4VBdoYLqD0xws,110
|
||||
Jinja2-2.10.1.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72
|
||||
Jinja2-2.10.1.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7
|
||||
jinja2/__init__.py,sha256=V1D-JHQKklZseXOMA-uAW7-BeKe_TfPpOFi9-dV04ZA,2616
|
||||
jinja2/__init__.pyc,,
|
||||
jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596
|
||||
jinja2/_compat.pyc,,
|
||||
jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726
|
||||
jinja2/_identifier.pyc,,
|
||||
jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144
|
||||
jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878
|
||||
jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794
|
||||
jinja2/bccache.pyc,,
|
||||
jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386
|
||||
jinja2/compiler.pyc,,
|
||||
jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626
|
||||
jinja2/constants.pyc,,
|
||||
jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045
|
||||
jinja2/debug.pyc,,
|
||||
jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400
|
||||
jinja2/defaults.pyc,,
|
||||
jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849
|
||||
jinja2/environment.pyc,,
|
||||
jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428
|
||||
jinja2/exceptions.pyc,,
|
||||
jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500
|
||||
jinja2/ext.pyc,,
|
||||
jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528
|
||||
jinja2/filters.pyc,,
|
||||
jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197
|
||||
jinja2/idtracking.pyc,,
|
||||
jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559
|
||||
jinja2/lexer.pyc,,
|
||||
jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382
|
||||
jinja2/loaders.pyc,,
|
||||
jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340
|
||||
jinja2/meta.pyc,,
|
||||
jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308
|
||||
jinja2/nativetypes.pyc,,
|
||||
jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853
|
||||
jinja2/nodes.pyc,,
|
||||
jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722
|
||||
jinja2/optimizer.pyc,,
|
||||
jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875
|
||||
jinja2/parser.pyc,,
|
||||
jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755
|
||||
jinja2/runtime.pyc,,
|
||||
jinja2/sandbox.py,sha256=UmX8hVjdaERCbA3RXBwrV1f-beA23KmijG5kzPJyU4A,17106
|
||||
jinja2/sandbox.pyc,,
|
||||
jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237
|
||||
jinja2/tests.pyc,,
|
||||
jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629
|
||||
jinja2/utils.pyc,,
|
||||
jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316
|
||||
jinja2/visitor.pyc,,
|
@ -0,0 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
[babel.extractors]
|
||||
jinja2 = jinja2.ext:babel_extract[i18n]
|
||||
|
@ -0,0 +1 @@
|
||||
jinja2
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,28 @@
|
||||
Copyright 2010 Pallets
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,103 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: MarkupSafe
|
||||
Version: 1.1.1
|
||||
Summary: Safely add untrusted strings to HTML/XML markup.
|
||||
Home-page: https://palletsprojects.com/p/markupsafe/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
Maintainer: The Pallets Team
|
||||
Maintainer-email: contact@palletsprojects.com
|
||||
License: BSD-3-Clause
|
||||
Project-URL: Code, https://github.com/pallets/markupsafe
|
||||
Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues
|
||||
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
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
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
|
||||
|
||||
MarkupSafe
|
||||
==========
|
||||
|
||||
MarkupSafe implements a text object that escapes characters so it is
|
||||
safe to use in HTML and XML. Characters that have special meanings are
|
||||
replaced so that they display as the actual characters. This mitigates
|
||||
injection attacks, meaning untrusted user input can safely be displayed
|
||||
on a page.
|
||||
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Install and update using `pip`_:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
pip install -U MarkupSafe
|
||||
|
||||
.. _pip: https://pip.pypa.io/en/stable/quickstart/
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from markupsafe import Markup, escape
|
||||
>>> # escape replaces special characters and wraps in Markup
|
||||
>>> escape('<script>alert(document.cookie);</script>')
|
||||
Markup(u'<script>alert(document.cookie);</script>')
|
||||
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
||||
>>> Markup('<strong>Hello</strong>')
|
||||
Markup('<strong>hello</strong>')
|
||||
>>> escape(Markup('<strong>Hello</strong>'))
|
||||
Markup('<strong>hello</strong>')
|
||||
>>> # Markup is a text subclass (str on Python 3, unicode on Python 2)
|
||||
>>> # methods and operators escape their arguments
|
||||
>>> template = Markup("Hello <em>%s</em>")
|
||||
>>> template % '"World"'
|
||||
Markup('Hello <em>"World"</em>')
|
||||
|
||||
|
||||
Donate
|
||||
------
|
||||
|
||||
The Pallets organization develops and supports MarkupSafe and other
|
||||
libraries that use it. In order to grow the community of contributors
|
||||
and users, and allow the maintainers to devote more time to the
|
||||
projects, `please donate today`_.
|
||||
|
||||
.. _please donate today: https://palletsprojects.com/donate
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
* Website: https://palletsprojects.com/p/markupsafe/
|
||||
* Documentation: https://markupsafe.palletsprojects.com/
|
||||
* License: `BSD-3-Clause <https://github.com/pallets/markupsafe/blob/master/LICENSE.rst>`_
|
||||
* Releases: https://pypi.org/project/MarkupSafe/
|
||||
* Code: https://github.com/pallets/markupsafe
|
||||
* Issue tracker: https://github.com/pallets/markupsafe/issues
|
||||
* Test status:
|
||||
|
||||
* Linux, Mac: https://travis-ci.org/pallets/markupsafe
|
||||
* Windows: https://ci.appveyor.com/project/pallets/markupsafe
|
||||
|
||||
* Test coverage: https://codecov.io/gh/pallets/markupsafe
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
MarkupSafe-1.1.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||
MarkupSafe-1.1.1.dist-info/METADATA,sha256=tYljLDaWFctZWfLXDP5ju_68TOlbQzJHNnaaX5-HYsA,3570
|
||||
MarkupSafe-1.1.1.dist-info/RECORD,,
|
||||
MarkupSafe-1.1.1.dist-info/WHEEL,sha256=QxB7VA6yWRa_kkOPUXf8_8tuQuhnGxzF7TcwNarQG6Q,109
|
||||
MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
||||
markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126
|
||||
markupsafe/__init__.pyc,,
|
||||
markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558
|
||||
markupsafe/_compat.pyc,,
|
||||
markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690
|
||||
markupsafe/_constants.pyc,,
|
||||
markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873
|
||||
markupsafe/_native.pyc,,
|
||||
markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884
|
||||
markupsafe/_speedups.so,sha256=kaCCUiEMqpZtO5MSk_96ntDI9al0vtyk_31K4miFZvU,27108
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp27-cp27m-macosx_10_6_intel
|
||||
|
@ -0,0 +1 @@
|
||||
markupsafe
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,174 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
@ -0,0 +1,196 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: PyNaCl
|
||||
Version: 1.3.0
|
||||
Summary: Python binding to the Networking and Cryptography (NaCl) library
|
||||
Home-page: https://github.com/pyca/pynacl/
|
||||
Author: The PyNaCl developers
|
||||
Author-email: cryptography-dev@python.org
|
||||
License: Apache License 2.0
|
||||
Platform: UNKNOWN
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
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
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Provides-Extra: docs
|
||||
Provides-Extra: tests
|
||||
Requires-Dist: six
|
||||
Requires-Dist: cffi (>=1.4.1)
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx (>=1.6.5); extra == 'docs'
|
||||
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
||||
Provides-Extra: tests
|
||||
Requires-Dist: pytest (!=3.3.0,>=3.2.1); extra == 'tests'
|
||||
Requires-Dist: hypothesis (>=3.27.0); extra == 'tests'
|
||||
|
||||
===============================================
|
||||
PyNaCl: Python binding to the libsodium library
|
||||
===============================================
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/pynacl.svg
|
||||
:target: https://pypi.org/project/PyNaCl/
|
||||
:alt: Latest Version
|
||||
|
||||
.. image:: https://travis-ci.org/pyca/pynacl.svg?branch=master
|
||||
:target: https://travis-ci.org/pyca/pynacl
|
||||
|
||||
.. image:: https://codecov.io/github/pyca/pynacl/coverage.svg?branch=master
|
||||
:target: https://codecov.io/github/pyca/pynacl?branch=master
|
||||
|
||||
PyNaCl is a Python binding to `libsodium`_, which is a fork of the
|
||||
`Networking and Cryptography library`_. These libraries have a stated goal of
|
||||
improving usability, security and speed. It supports Python 2.7 and 3.4+ as
|
||||
well as PyPy 2.6+.
|
||||
|
||||
.. _libsodium: https://github.com/jedisct1/libsodium
|
||||
.. _Networking and Cryptography library: https://nacl.cr.yp.to/
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Digital signatures
|
||||
* Secret-key encryption
|
||||
* Public-key encryption
|
||||
* Hashing and message authentication
|
||||
* Password based key derivation and password hashing
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Binary wheel install
|
||||
--------------------
|
||||
|
||||
PyNaCl ships as a binary wheel on OS X, Windows and Linux ``manylinux1`` [#many]_ ,
|
||||
so all dependencies are included. Make sure you have an up-to-date pip
|
||||
and run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install pynacl
|
||||
|
||||
Linux source build
|
||||
------------------
|
||||
|
||||
PyNaCl relies on `libsodium`_, a portable C library. A copy is bundled
|
||||
with PyNaCl so to install you can run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install pynacl
|
||||
|
||||
If you'd prefer to use the version of ``libsodium`` provided by your
|
||||
distribution, you can disable the bundled copy during install by running:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ SODIUM_INSTALL=system pip install pynacl
|
||||
|
||||
.. warning:: Usage of the legacy ``easy_install`` command provided by setuptools
|
||||
is generally discouraged, and is completely unsupported in PyNaCl's case.
|
||||
|
||||
.. _libsodium: https://github.com/jedisct1/libsodium
|
||||
|
||||
.. [#many] `manylinux1 wheels <https://www.python.org/dev/peps/pep-0513/>`_
|
||||
are built on a baseline linux environment based on Centos 5.11
|
||||
and should work on most x86 and x86_64 glibc based linux environments.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.3.0 2018-09-26
|
||||
----------------
|
||||
|
||||
* Added support for Python 3.7.
|
||||
* Update ``libsodium`` to 1.0.16.
|
||||
* Run and test all code examples in PyNaCl docs through sphinx's
|
||||
doctest builder.
|
||||
* Add low-level bindings for chacha20-poly1305 AEAD constructions.
|
||||
* Add low-level bindings for the chacha20-poly1305 secretstream constructions.
|
||||
* Add low-level bindings for ed25519ph pre-hashed signing construction.
|
||||
* Add low-level bindings for constant-time increment and addition
|
||||
on fixed-precision big integers represented as little-endian
|
||||
byte sequences.
|
||||
* Add low-level bindings for the ISO/IEC 7816-4 compatible padding API.
|
||||
* Add low-level bindings for libsodium's crypto_kx... key exchange
|
||||
construction.
|
||||
* Set hypothesis deadline to None in tests/test_pwhash.py to avoid
|
||||
incorrect test failures on slower processor architectures. GitHub
|
||||
issue #370
|
||||
|
||||
1.2.1 - 2017-12-04
|
||||
------------------
|
||||
|
||||
* Update hypothesis minimum allowed version.
|
||||
* Infrastructure: add proper configuration for readthedocs builder
|
||||
runtime environment.
|
||||
|
||||
1.2.0 - 2017-11-01
|
||||
------------------
|
||||
|
||||
* Update ``libsodium`` to 1.0.15.
|
||||
* Infrastructure: add jenkins support for automatic build of
|
||||
``manylinux1`` binary wheels
|
||||
* Added support for ``SealedBox`` construction.
|
||||
* Added support for ``argon2i`` and ``argon2id`` password hashing constructs
|
||||
and restructured high-level password hashing implementation to expose
|
||||
the same interface for all hashers.
|
||||
* Added support for 128 bit ``siphashx24`` variant of ``siphash24``.
|
||||
* Added support for ``from_seed`` APIs for X25519 keypair generation.
|
||||
* Dropped support for Python 3.3.
|
||||
|
||||
1.1.2 - 2017-03-31
|
||||
------------------
|
||||
|
||||
* reorder link time library search path when using bundled
|
||||
libsodium
|
||||
|
||||
1.1.1 - 2017-03-15
|
||||
------------------
|
||||
|
||||
* Fixed a circular import bug in ``nacl.utils``.
|
||||
|
||||
1.1.0 - 2017-03-14
|
||||
------------------
|
||||
|
||||
* Dropped support for Python 2.6.
|
||||
* Added ``shared_key()`` method on ``Box``.
|
||||
* You can now pass ``None`` to ``nonce`` when encrypting with ``Box`` or
|
||||
``SecretBox`` and it will automatically generate a random nonce.
|
||||
* Added support for ``siphash24``.
|
||||
* Added support for ``blake2b``.
|
||||
* Added support for ``scrypt``.
|
||||
* Update ``libsodium`` to 1.0.11.
|
||||
* Default to the bundled ``libsodium`` when compiling.
|
||||
* All raised exceptions are defined mixing-in
|
||||
``nacl.exceptions.CryptoError``
|
||||
|
||||
1.0.1 - 2016-01-24
|
||||
------------------
|
||||
|
||||
* Fix an issue with absolute paths that prevented the creation of wheels.
|
||||
|
||||
1.0 - 2016-01-23
|
||||
----------------
|
||||
|
||||
* PyNaCl has been ported to use the new APIs available in cffi 1.0+.
|
||||
Due to this change we no longer support PyPy releases older than 2.6.
|
||||
* Python 3.2 support has been dropped.
|
||||
* Functions to convert between Ed25519 and Curve25519 keys have been added.
|
||||
|
||||
0.3.0 - 2015-03-04
|
||||
------------------
|
||||
|
||||
* The low-level API (`nacl.c.*`) has been changed to match the
|
||||
upstream NaCl C/C++ conventions (as well as those of other NaCl bindings).
|
||||
The order of arguments and return values has changed significantly. To
|
||||
avoid silent failures, `nacl.c` has been removed, and replaced with
|
||||
`nacl.bindings` (with the new argument ordering). If you have code which
|
||||
calls these functions (e.g. `nacl.c.crypto_box_keypair()`), you must review
|
||||
the new docstrings and update your code/imports to match the new
|
||||
conventions.
|
||||
|
||||
|
@ -0,0 +1,65 @@
|
||||
PyNaCl-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
PyNaCl-1.3.0.dist-info/LICENSE.txt,sha256=0xdK1j5yHUydzLitQyCEiZLTFDabxGMZcgtYAskVP-k,9694
|
||||
PyNaCl-1.3.0.dist-info/METADATA,sha256=pl3lEk7jyuFK7MNHloWA3m28tYU6xHI-S4le43id_x8,6632
|
||||
PyNaCl-1.3.0.dist-info/RECORD,,
|
||||
PyNaCl-1.3.0.dist-info/WHEEL,sha256=F1TCjYjTFxks-nqiDpERoLzySPhR94sDPjBYFZlcSxk,109
|
||||
PyNaCl-1.3.0.dist-info/top_level.txt,sha256=wfdEOI_G2RIzmzsMyhpqP17HUh6Jcqi99to9aHLEslo,13
|
||||
nacl/__init__.py,sha256=PS9BuXZoCwSvrDpB8HXldTHnA6lb4y00IRi3uqdW5_E,1170
|
||||
nacl/__init__.pyc,,
|
||||
nacl/_sodium.so,sha256=Rc6lNbEnFWTq2gjp4TmnvSXd1n97w59z2YmGShGcRkI,749348
|
||||
nacl/bindings/__init__.py,sha256=dNH1zFjW87qszsld5oy6xMf2S1w2v_qshQwYHp66pz4,14943
|
||||
nacl/bindings/__init__.pyc,,
|
||||
nacl/bindings/crypto_aead.py,sha256=DE5zdi09GeHZxvmrhHtxVuTqF61y1cs8trTGh_6uP8Q,17335
|
||||
nacl/bindings/crypto_aead.pyc,,
|
||||
nacl/bindings/crypto_box.py,sha256=hbHJetr9id5OvkbJwJoeqRQAhqSIGwWC2aXRAF5oPE4,9708
|
||||
nacl/bindings/crypto_box.pyc,,
|
||||
nacl/bindings/crypto_generichash.py,sha256=-e4b4DaopLBQHhEjLSjEoumy5fOs4QdTb-hou1S34C4,8010
|
||||
nacl/bindings/crypto_generichash.pyc,,
|
||||
nacl/bindings/crypto_hash.py,sha256=7Xp4mpXr4cpn-hAOU66KlYVUCVHP6deT0v_eW4UZZXo,2243
|
||||
nacl/bindings/crypto_hash.pyc,,
|
||||
nacl/bindings/crypto_kx.py,sha256=2Gjxu5c7IKAwW2MOJa9zEn1EgpIVQ0tbZQs33REZb38,6937
|
||||
nacl/bindings/crypto_kx.pyc,,
|
||||
nacl/bindings/crypto_pwhash.py,sha256=lWhEFKmXzFhKnzzxtWDwozs0CseZDkGgTJaI4YQ5rak,16898
|
||||
nacl/bindings/crypto_pwhash.pyc,,
|
||||
nacl/bindings/crypto_scalarmult.py,sha256=VA2khmlUrnR24KK0CAdDw2dQ0jiYkku9-_NA-f1p21c,1803
|
||||
nacl/bindings/crypto_scalarmult.pyc,,
|
||||
nacl/bindings/crypto_secretbox.py,sha256=luvzB3lwBwXxKm63e9nA2neGtOXeeG8R9SyWEckIqdI,2864
|
||||
nacl/bindings/crypto_secretbox.pyc,,
|
||||
nacl/bindings/crypto_secretstream.py,sha256=gdKinW10jP3CZ51hanE40s6e39rz8iuajdXTSBSKVcM,10474
|
||||
nacl/bindings/crypto_secretstream.pyc,,
|
||||
nacl/bindings/crypto_shorthash.py,sha256=eVUE8byB1RjI0AoHib5BdZSSLtSqtdIcHgPCPWf2OZM,2189
|
||||
nacl/bindings/crypto_shorthash.pyc,,
|
||||
nacl/bindings/crypto_sign.py,sha256=uA0RdHM4vsBDNhph2f7fcuI_9K8vvW-4hNHjajTIVU0,9641
|
||||
nacl/bindings/crypto_sign.pyc,,
|
||||
nacl/bindings/randombytes.py,sha256=eThts6s-9xBXOl3GNzT57fV1dZUhzPjjAmAVIUHfcrc,988
|
||||
nacl/bindings/randombytes.pyc,,
|
||||
nacl/bindings/sodium_core.py,sha256=52z0K7y6Ge6IlXcysWDVN7UdYcTOij6v0Cb0OLo8_Qc,1079
|
||||
nacl/bindings/sodium_core.pyc,,
|
||||
nacl/bindings/utils.py,sha256=jOKsDbsjxN9v_HI8DOib72chyU3byqbynXxbiV909-g,4420
|
||||
nacl/bindings/utils.pyc,,
|
||||
nacl/encoding.py,sha256=tOiyIQVVpGU6A4Lzr0tMuqomhc_Aj0V_c1t56a-ZtPw,1928
|
||||
nacl/encoding.pyc,,
|
||||
nacl/exceptions.py,sha256=SG0BNtXnzmppI9in6xMTSizh1ryfgUIvIVMQv_A0bs8,1858
|
||||
nacl/exceptions.pyc,,
|
||||
nacl/hash.py,sha256=4DKlmqpWOZJLhzTPk7_JSGXQ32lJULsS3AzJCGsibus,5928
|
||||
nacl/hash.pyc,,
|
||||
nacl/hashlib.py,sha256=gMxOu-lIlKYr3ywSCjsJRBksYgpU2dvXgaAEfQz7PEg,3909
|
||||
nacl/hashlib.pyc,,
|
||||
nacl/public.py,sha256=-nwQof5ov-wSSdvvoXh-FavTtjfpRnYykZkatNKyLd0,13442
|
||||
nacl/public.pyc,,
|
||||
nacl/pwhash/__init__.py,sha256=CN0mP6yteSYp3ui-DyWR1vjULNrXVN_gQ72CmTPoao0,2695
|
||||
nacl/pwhash/__init__.pyc,,
|
||||
nacl/pwhash/_argon2.py,sha256=Eu3-juLws3_v1gNy5aeSVPEwuRVFdGOrfeF0wPH9VHA,1878
|
||||
nacl/pwhash/_argon2.pyc,,
|
||||
nacl/pwhash/argon2i.py,sha256=EpheK0UHJvZYca_EMhhOcX5GXaOr0xCjFDTIgmSCSDo,4598
|
||||
nacl/pwhash/argon2i.pyc,,
|
||||
nacl/pwhash/argon2id.py,sha256=IqNm5RQNEd1Z9F-bEWT-_Y9noU26QoTR5YdWONg1uuI,4610
|
||||
nacl/pwhash/argon2id.pyc,,
|
||||
nacl/pwhash/scrypt.py,sha256=F9iUKbzZUMG2ZXuuk70p4KXI_nItue3VA39zmwOESE8,6025
|
||||
nacl/pwhash/scrypt.pyc,,
|
||||
nacl/secret.py,sha256=jf4WuUjnnXTekZ2elGgQozZl6zGzxGY_0Nw0fwehUlg,5430
|
||||
nacl/secret.pyc,,
|
||||
nacl/signing.py,sha256=ZwA1l31ZgOIw_sAjiUPkzEo07uYYi8SE7Ni0G_R8ksQ,7302
|
||||
nacl/signing.pyc,,
|
||||
nacl/utils.py,sha256=hhmIriBM7Bwyh3beTrqVqDDucai5gXlSliAMVrxIHPI,1691
|
||||
nacl/utils.pyc,,
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.31.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp27-cp27m-macosx_10_6_intel
|
||||
|
@ -0,0 +1,2 @@
|
||||
_sodium
|
||||
nacl
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2017-2019 Ingy döt Net
|
||||
Copyright (c) 2006-2016 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,40 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: PyYAML
|
||||
Version: 5.1
|
||||
Summary: YAML parser and emitter for Python
|
||||
Home-page: https://github.com/yaml/pyyaml
|
||||
Author: Kirill Simonov
|
||||
Author-email: xi@resolvent.net
|
||||
License: MIT
|
||||
Download-URL: https://pypi.org/project/PyYAML/
|
||||
Platform: Any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
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
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Text Processing :: Markup
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
|
||||
YAML is a data serialization format designed for human readability
|
||||
and interaction with scripting languages. PyYAML is a YAML parser
|
||||
and emitter for Python.
|
||||
|
||||
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
|
||||
support, capable extension API, and sensible error messages. PyYAML
|
||||
supports standard YAML tags and provides Python-specific tags that
|
||||
allow to represent an arbitrary Python object.
|
||||
|
||||
PyYAML is applicable for a broad range of tasks from complex
|
||||
configuration files to object serialization and persistence.
|
||||
|
@ -0,0 +1,40 @@
|
||||
PyYAML-5.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
PyYAML-5.1.dist-info/LICENSE,sha256=oq25yVm3l0lKDvgL32DiLbJ0nuPgwJCFVuPrVI-WfFY,1101
|
||||
PyYAML-5.1.dist-info/METADATA,sha256=33vAx8vSzjUMXGHO2jp0u8tvgkRqfAH3-OEDSpjfIx8,1704
|
||||
PyYAML-5.1.dist-info/RECORD,,
|
||||
PyYAML-5.1.dist-info/WHEEL,sha256=X60NSjsla4d4ueip-xFdVMnfiCIypBW0CA59NCWilHY,110
|
||||
PyYAML-5.1.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11
|
||||
yaml/__init__.py,sha256=Ke2gASae4i0HLUxbz8l2CUR3__qpspvBBI1gltOxQbE,12182
|
||||
yaml/__init__.pyc,,
|
||||
yaml/composer.py,sha256=TtvWJCaffdVHhHx_muLguloDUwg1NUbo-GlJ0me6xuA,4923
|
||||
yaml/composer.pyc,,
|
||||
yaml/constructor.py,sha256=HrBLwPOrijfcmurB4Ww71xrTtMKehs0-xh3NNlQzveY,26834
|
||||
yaml/constructor.pyc,,
|
||||
yaml/cyaml.py,sha256=6MZKSJHTWwoct5urK9qbGXAhM1xz_Boawlf5SVMC85o,3842
|
||||
yaml/cyaml.pyc,,
|
||||
yaml/dumper.py,sha256=yMFwlojOY-M4EMUT8FiROY2QC2GAGQO7Iiky0xBlJFc,2833
|
||||
yaml/dumper.pyc,,
|
||||
yaml/emitter.py,sha256=09BwSivdd4BbPgx2rbFcoMOa9H1yZxqY1YILjOXvFeo,43427
|
||||
yaml/emitter.pyc,,
|
||||
yaml/error.py,sha256=7K-NdIv0qNKPKbnXxEg0L_b9K7nYDORr3rzm8_b-iBY,2559
|
||||
yaml/error.pyc,,
|
||||
yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445
|
||||
yaml/events.pyc,,
|
||||
yaml/loader.py,sha256=T61DzDkbfResZoQfVy1U3vN0_mKFyBALB9et-478-w4,2055
|
||||
yaml/loader.pyc,,
|
||||
yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440
|
||||
yaml/nodes.pyc,,
|
||||
yaml/parser.py,sha256=sgXahZA3DkySYnaC4D_zcl3l2y4Y5R40icWtdwkF_NE,25542
|
||||
yaml/parser.pyc,,
|
||||
yaml/reader.py,sha256=y6cj-OcZjnFDO1u6Blmi-tKoi-3Pjvmo2PikMnO5FFc,6850
|
||||
yaml/reader.pyc,,
|
||||
yaml/representer.py,sha256=BaJcXjs4a1yjYMnCKxJ39TZlWahVu2OE7K6dEEy0Bqo,17791
|
||||
yaml/representer.pyc,,
|
||||
yaml/resolver.py,sha256=5Z3boiMikL6Qt6fS5Mt8fHym0GxbW7CMT2f2fnD1ZPQ,9122
|
||||
yaml/resolver.pyc,,
|
||||
yaml/scanner.py,sha256=Umb0oXZGFIf814tr_CUPPfKfeWUZj9ucqz06q20v0Fg,52027
|
||||
yaml/scanner.pyc,,
|
||||
yaml/serializer.py,sha256=tRsRwfu5E9fpLU7LY3vBQf2prt77hwnYlMt5dnBJLig,4171
|
||||
yaml/serializer.pyc,,
|
||||
yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573
|
||||
yaml/tokens.pyc,,
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp27-cp27m-macosx_10_13_intel
|
||||
|
@ -0,0 +1,2 @@
|
||||
_yaml
|
||||
yaml
|
@ -0,0 +1 @@
|
||||
__version__ = '0.14.11'
|
@ -0,0 +1,675 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,183 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: ansible
|
||||
Version: 2.7.10
|
||||
Summary: Radically simple IT automation
|
||||
Home-page: https://ansible.com/
|
||||
Author: Ansible, Inc.
|
||||
Author-email: info@ansible.com
|
||||
License: GPLv3+
|
||||
Project-URL: Source Code, https://github.com/ansible/ansible
|
||||
Project-URL: CI: Shippable, https://app.shippable.com/github/ansible/ansible
|
||||
Project-URL: Code of Conduct, https://docs.ansible.com/ansible/latest/community/code_of_conduct.html
|
||||
Project-URL: Documentation, https://docs.ansible.com/ansible/
|
||||
Project-URL: Bug Tracker, https://github.com/ansible/ansible/issues
|
||||
Project-URL: Mailing lists, https://docs.ansible.com/ansible/latest/community/communication.html#mailing-list-information
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Information Technology
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Topic :: System :: Installation/Setup
|
||||
Classifier: Topic :: System :: Systems Administration
|
||||
Classifier: Topic :: Utilities
|
||||
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*
|
||||
Requires-Dist: jinja2
|
||||
Requires-Dist: PyYAML
|
||||
Requires-Dist: paramiko
|
||||
Requires-Dist: cryptography
|
||||
Requires-Dist: setuptools
|
||||
Provides-Extra: azure
|
||||
Requires-Dist: packaging ; extra == 'azure'
|
||||
Requires-Dist: requests[security] ; extra == 'azure'
|
||||
Requires-Dist: azure-cli-core (==2.0.35) ; extra == 'azure'
|
||||
Requires-Dist: azure-cli-nspkg (==3.0.2) ; extra == 'azure'
|
||||
Requires-Dist: azure-common (==1.1.11) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-batch (==4.1.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-compute (==2.1.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-containerinstance (==0.4.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-containerregistry (==2.0.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-containerservice (==3.0.1) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-dns (==1.2.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-keyvault (==0.40.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-marketplaceordering (==0.1.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-monitor (==0.5.2) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-network (==1.7.1) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-nspkg (==2.0.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-rdbms (==1.2.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-resource (==1.2.2) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-sql (==0.7.1) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-storage (==1.5.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-trafficmanager (==0.50.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-mgmt-web (==0.32.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-nspkg (==2.0.0) ; extra == 'azure'
|
||||
Requires-Dist: azure-storage (==0.35.1) ; extra == 'azure'
|
||||
Requires-Dist: msrest (==0.4.29) ; extra == 'azure'
|
||||
Requires-Dist: msrestazure (==0.4.31) ; extra == 'azure'
|
||||
Requires-Dist: azure-keyvault (==1.0.0a1) ; extra == 'azure'
|
||||
Requires-Dist: azure-graphrbac (==0.40.0) ; extra == 'azure'
|
||||
|
||||
|PyPI version| |Docs badge| |Chat badge| |Build Status|
|
||||
|
||||
*******
|
||||
Ansible
|
||||
*******
|
||||
|
||||
Ansible is a radically simple IT automation system. It handles
|
||||
configuration-management, application deployment, cloud provisioning,
|
||||
ad-hoc task-execution, and multinode orchestration -- including
|
||||
trivializing things like zero-downtime rolling updates with load
|
||||
balancers.
|
||||
|
||||
Read the documentation and more at https://ansible.com/
|
||||
|
||||
You can find installation instructions
|
||||
`here <https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html>`_ for a
|
||||
variety of platforms.
|
||||
|
||||
Most users should probably install a released version of Ansible from ``pip``, a package manager or
|
||||
our `release repository <https://releases.ansible.com/ansible/>`_. `Officially supported
|
||||
<https://www.ansible.com/ansible-engine>`_ builds of Ansible are also available. Some power users
|
||||
run directly from the development branch - while significant efforts are made to ensure that
|
||||
``devel`` is reasonably stable, you're more likely to encounter breaking changes when running
|
||||
Ansible this way.
|
||||
|
||||
Design Principles
|
||||
=================
|
||||
|
||||
* Have a dead simple setup process and a minimal learning curve.
|
||||
* Manage machines very quickly and in parallel.
|
||||
* Avoid custom-agents and additional open ports, be agentless by
|
||||
leveraging the existing SSH daemon.
|
||||
* Describe infrastructure in a language that is both machine and human
|
||||
friendly.
|
||||
* Focus on security and easy auditability/review/rewriting of content.
|
||||
* Manage new remote machines instantly, without bootstrapping any
|
||||
software.
|
||||
* Allow module development in any dynamic language, not just Python.
|
||||
* Be usable as non-root.
|
||||
* Be the easiest IT automation system to use, ever.
|
||||
|
||||
Get Involved
|
||||
============
|
||||
|
||||
* Read `Community
|
||||
Information <https://docs.ansible.com/ansible/latest/community>`_ for all
|
||||
kinds of ways to contribute to and interact with the project,
|
||||
including mailing list information and how to submit bug reports and
|
||||
code to Ansible.
|
||||
* All code submissions are done through pull requests to the ``devel`` branch.
|
||||
* Feel free to talk to us before making larger changes
|
||||
to avoid duplicate efforts. This not only helps everyone
|
||||
know what's going on, it also helps save time and effort if we decide
|
||||
some changes are needed.
|
||||
* Users list:
|
||||
`ansible-project <https://groups.google.com/group/ansible-project>`_
|
||||
* Development list:
|
||||
`ansible-devel <https://groups.google.com/group/ansible-devel>`_
|
||||
* Announcement list:
|
||||
`ansible-announce <https://groups.google.com/group/ansible-announce>`_
|
||||
-- read only
|
||||
* irc.freenode.net: #ansible
|
||||
* For the full list of Email Lists, IRC channels see the
|
||||
`Communication page <https://docs.ansible.com/ansible/latest/community/communication.html>`_
|
||||
|
||||
Branch Info
|
||||
===========
|
||||
|
||||
* Releases are named after Led Zeppelin songs. (Releases prior to 2.0
|
||||
were named after Van Halen songs.)
|
||||
* The ``devel`` branch corresponds to the release actively under
|
||||
development.
|
||||
* The ``stable-2.x`` branches exist for current releases.
|
||||
* Various release-X.Y branches exist for previous releases.
|
||||
* For information about the active branches see the
|
||||
`Ansible release and maintenance <https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html>`_ page.
|
||||
* We'd love to have your contributions, read the `Community
|
||||
Guide <https://docs.ansible.com/ansible/latest/community>`_ for notes on
|
||||
how to get started.
|
||||
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
Based on team and community feedback, an initial roadmap will be published for a major or minor version (ex: 2.0, 2.1).
|
||||
Subminor versions will generally not have roadmaps published.
|
||||
|
||||
The `Ansible Roadmap page <https://docs.ansible.com/ansible/devel/roadmap/>`_ details what is planned and how to influence the roadmap.
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Ansible was created by `Michael DeHaan <https://github.com/mpdehaan>`_
|
||||
(michael.dehaan/gmail/com) and has contributions from over 3700 users
|
||||
(and growing). Thanks everyone!
|
||||
|
||||
`Ansible <https://www.ansible.com>`_ is sponsored by `Red Hat, Inc.
|
||||
<https://www.redhat.com>`_
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
GNU General Public License v3.0
|
||||
|
||||
See `COPYING <COPYING>`_ to see the full text.
|
||||
|
||||
.. |PyPI version| image:: https://img.shields.io/pypi/v/ansible.svg
|
||||
:target: https://pypi.org/project/ansible
|
||||
.. |Docs badge| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg
|
||||
:target: https://docs.ansible.com/ansible/latest/
|
||||
.. |Build Status| image:: https://api.shippable.com/projects/573f79d02a8192902e20e34b/badge?branch=devel
|
||||
:target: https://app.shippable.com/projects/573f79d02a8192902e20e34b
|
||||
.. |Chat badge| image:: https://img.shields.io/badge/chat-IRC-brightgreen.svg
|
||||
:target: https://docs.ansible.com/ansible/latest/community/communication.html
|
||||
|
||||
|
6411
env_27/lib/python2.7/site-packages/ansible-2.7.10.dist-info/RECORD
Normal file
6411
env_27/lib/python2.7/site-packages/ansible-2.7.10.dist-info/RECORD
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: cp27-none-any
|
||||
|
@ -0,0 +1 @@
|
||||
ansible
|
@ -0,0 +1,2 @@
|
||||
/Users/rkau2905/Devel/python/private/ansible-later
|
||||
.
|
28
env_27/lib/python2.7/site-packages/ansible/__init__.py
Normal file
28
env_27/lib/python2.7/site-packages/ansible/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
# (c) 2012-2014, 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/>.
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
# Note: Do not add any code to this file. The ansible module may be
|
||||
# a namespace package when using Ansible-2.1+ Anything in this file may not be
|
||||
# available if one of the other packages in the namespace is loaded first.
|
||||
#
|
||||
# This is for backwards compat. Code should be ported to get these from
|
||||
# ansible.release instead of from here.
|
||||
from ansible.release import __version__, __author__
|
820
env_27/lib/python2.7/site-packages/ansible/cli/__init__.py
Normal file
820
env_27/lib/python2.7/site-packages/ansible/cli/__init__.py
Normal file
@ -0,0 +1,820 @@
|
||||
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.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/>.
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import getpass
|
||||
import operator
|
||||
import optparse
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import yaml
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import ansible
|
||||
from ansible import constants as C
|
||||
from ansible.errors import AnsibleOptionsError, AnsibleError
|
||||
from ansible.inventory.manager import InventoryManager
|
||||
from ansible.module_utils.six import with_metaclass, string_types
|
||||
from ansible.module_utils._text import to_bytes, to_text
|
||||
from ansible.parsing.dataloader import DataLoader
|
||||
from ansible.release import __version__
|
||||
from ansible.utils.path import unfrackpath
|
||||
from ansible.utils.vars import load_extra_vars, load_options_vars
|
||||
from ansible.vars.manager import VariableManager
|
||||
from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class SortedOptParser(optparse.OptionParser):
|
||||
'''Optparser which sorts the options by opt before outputting --help'''
|
||||
|
||||
def format_help(self, formatter=None, epilog=None):
|
||||
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
||||
return optparse.OptionParser.format_help(self, formatter=None)
|
||||
|
||||
|
||||
# Note: Inherit from SortedOptParser so that we get our format_help method
|
||||
class InvalidOptsParser(SortedOptParser):
|
||||
'''Ignore invalid options.
|
||||
|
||||
Meant for the special case where we need to take care of help and version
|
||||
but may not know the full range of options yet. (See it in use in set_action)
|
||||
'''
|
||||
def __init__(self, parser):
|
||||
# Since this is special purposed to just handle help and version, we
|
||||
# take a pre-existing option parser here and set our options from
|
||||
# that. This allows us to give accurate help based on the given
|
||||
# option parser.
|
||||
SortedOptParser.__init__(self, usage=parser.usage,
|
||||
option_list=parser.option_list,
|
||||
option_class=parser.option_class,
|
||||
conflict_handler=parser.conflict_handler,
|
||||
description=parser.description,
|
||||
formatter=parser.formatter,
|
||||
add_help_option=False,
|
||||
prog=parser.prog,
|
||||
epilog=parser.epilog)
|
||||
self.version = parser.version
|
||||
|
||||
def _process_long_opt(self, rargs, values):
|
||||
try:
|
||||
optparse.OptionParser._process_long_opt(self, rargs, values)
|
||||
except optparse.BadOptionError:
|
||||
pass
|
||||
|
||||
def _process_short_opts(self, rargs, values):
|
||||
try:
|
||||
optparse.OptionParser._process_short_opts(self, rargs, values)
|
||||
except optparse.BadOptionError:
|
||||
pass
|
||||
|
||||
|
||||
class CLI(with_metaclass(ABCMeta, object)):
|
||||
''' code behind bin/ansible* programs '''
|
||||
|
||||
VALID_ACTIONS = []
|
||||
|
||||
_ITALIC = re.compile(r"I\(([^)]+)\)")
|
||||
_BOLD = re.compile(r"B\(([^)]+)\)")
|
||||
_MODULE = re.compile(r"M\(([^)]+)\)")
|
||||
_URL = re.compile(r"U\(([^)]+)\)")
|
||||
_CONST = re.compile(r"C\(([^)]+)\)")
|
||||
|
||||
PAGER = 'less'
|
||||
|
||||
# -F (quit-if-one-screen) -R (allow raw ansi control chars)
|
||||
# -S (chop long lines) -X (disable termcap init and de-init)
|
||||
LESS_OPTS = 'FRSX'
|
||||
SKIP_INVENTORY_DEFAULTS = False
|
||||
|
||||
def __init__(self, args, callback=None):
|
||||
"""
|
||||
Base init method for all command line programs
|
||||
"""
|
||||
|
||||
self.args = args
|
||||
self.options = None
|
||||
self.parser = None
|
||||
self.action = None
|
||||
self.callback = callback
|
||||
|
||||
def set_action(self):
|
||||
"""
|
||||
Get the action the user wants to execute from the sys argv list.
|
||||
"""
|
||||
for i in range(0, len(self.args)):
|
||||
arg = self.args[i]
|
||||
if arg in self.VALID_ACTIONS:
|
||||
self.action = arg
|
||||
del self.args[i]
|
||||
break
|
||||
|
||||
if not self.action:
|
||||
# if we're asked for help or version, we don't need an action.
|
||||
# have to use a special purpose Option Parser to figure that out as
|
||||
# the standard OptionParser throws an error for unknown options and
|
||||
# without knowing action, we only know of a subset of the options
|
||||
# that could be legal for this command
|
||||
tmp_parser = InvalidOptsParser(self.parser)
|
||||
tmp_options, tmp_args = tmp_parser.parse_args(self.args)
|
||||
if not(hasattr(tmp_options, 'help') and tmp_options.help) or (hasattr(tmp_options, 'version') and tmp_options.version):
|
||||
raise AnsibleOptionsError("Missing required action")
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Actually runs a child defined method using the execute_<action> pattern
|
||||
"""
|
||||
fn = getattr(self, "execute_%s" % self.action)
|
||||
fn()
|
||||
|
||||
@abstractmethod
|
||||
def run(self):
|
||||
"""Run the ansible command
|
||||
|
||||
Subclasses must implement this method. It does the actual work of
|
||||
running an Ansible command.
|
||||
"""
|
||||
|
||||
display.vv(to_text(self.parser.get_version()))
|
||||
|
||||
if C.CONFIG_FILE:
|
||||
display.v(u"Using %s as config file" % to_text(C.CONFIG_FILE))
|
||||
else:
|
||||
display.v(u"No config file found; using defaults")
|
||||
|
||||
# warn about deprecated config options
|
||||
for deprecated in C.config.DEPRECATED:
|
||||
name = deprecated[0]
|
||||
why = deprecated[1]['why']
|
||||
if 'alternatives' in deprecated[1]:
|
||||
alt = ', use %s instead' % deprecated[1]['alternatives']
|
||||
else:
|
||||
alt = ''
|
||||
ver = deprecated[1]['version']
|
||||
display.deprecated("%s option, %s %s" % (name, why, alt), version=ver)
|
||||
|
||||
@staticmethod
|
||||
def split_vault_id(vault_id):
|
||||
# return (before_@, after_@)
|
||||
# if no @, return whole string as after_
|
||||
if '@' not in vault_id:
|
||||
return (None, vault_id)
|
||||
|
||||
parts = vault_id.split('@', 1)
|
||||
ret = tuple(parts)
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def build_vault_ids(vault_ids, vault_password_files=None,
|
||||
ask_vault_pass=None, create_new_password=None,
|
||||
auto_prompt=True):
|
||||
vault_password_files = vault_password_files or []
|
||||
vault_ids = vault_ids or []
|
||||
|
||||
# convert vault_password_files into vault_ids slugs
|
||||
for password_file in vault_password_files:
|
||||
id_slug = u'%s@%s' % (C.DEFAULT_VAULT_IDENTITY, password_file)
|
||||
|
||||
# note this makes --vault-id higher precendence than --vault-password-file
|
||||
# if we want to intertwingle them in order probably need a cli callback to populate vault_ids
|
||||
# used by --vault-id and --vault-password-file
|
||||
vault_ids.append(id_slug)
|
||||
|
||||
# if an action needs an encrypt password (create_new_password=True) and we dont
|
||||
# have other secrets setup, then automatically add a password prompt as well.
|
||||
# prompts cant/shouldnt work without a tty, so dont add prompt secrets
|
||||
if ask_vault_pass or (not vault_ids and auto_prompt):
|
||||
|
||||
id_slug = u'%s@%s' % (C.DEFAULT_VAULT_IDENTITY, u'prompt_ask_vault_pass')
|
||||
vault_ids.append(id_slug)
|
||||
|
||||
return vault_ids
|
||||
|
||||
# TODO: remove the now unused args
|
||||
@staticmethod
|
||||
def setup_vault_secrets(loader, vault_ids, vault_password_files=None,
|
||||
ask_vault_pass=None, create_new_password=False,
|
||||
auto_prompt=True):
|
||||
# list of tuples
|
||||
vault_secrets = []
|
||||
|
||||
# Depending on the vault_id value (including how --ask-vault-pass / --vault-password-file create a vault_id)
|
||||
# we need to show different prompts. This is for compat with older Towers that expect a
|
||||
# certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
|
||||
prompt_formats = {}
|
||||
|
||||
# If there are configured default vault identities, they are considered 'first'
|
||||
# so we prepend them to vault_ids (from cli) here
|
||||
|
||||
vault_password_files = vault_password_files or []
|
||||
if C.DEFAULT_VAULT_PASSWORD_FILE:
|
||||
vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)
|
||||
|
||||
if create_new_password:
|
||||
prompt_formats['prompt'] = ['New vault password (%(vault_id)s): ',
|
||||
'Confirm vew vault password (%(vault_id)s): ']
|
||||
# 2.3 format prompts for --ask-vault-pass
|
||||
prompt_formats['prompt_ask_vault_pass'] = ['New Vault password: ',
|
||||
'Confirm New Vault password: ']
|
||||
else:
|
||||
prompt_formats['prompt'] = ['Vault password (%(vault_id)s): ']
|
||||
# The format when we use just --ask-vault-pass needs to match 'Vault password:\s*?$'
|
||||
prompt_formats['prompt_ask_vault_pass'] = ['Vault password: ']
|
||||
|
||||
vault_ids = CLI.build_vault_ids(vault_ids,
|
||||
vault_password_files,
|
||||
ask_vault_pass,
|
||||
create_new_password,
|
||||
auto_prompt=auto_prompt)
|
||||
|
||||
for vault_id_slug in vault_ids:
|
||||
vault_id_name, vault_id_value = CLI.split_vault_id(vault_id_slug)
|
||||
if vault_id_value in ['prompt', 'prompt_ask_vault_pass']:
|
||||
|
||||
# --vault-id some_name@prompt_ask_vault_pass --vault-id other_name@prompt_ask_vault_pass will be a little
|
||||
# confusing since it will use the old format without the vault id in the prompt
|
||||
built_vault_id = vault_id_name or C.DEFAULT_VAULT_IDENTITY
|
||||
|
||||
# choose the prompt based on --vault-id=prompt or --ask-vault-pass. --ask-vault-pass
|
||||
# always gets the old format for Tower compatibility.
|
||||
# ie, we used --ask-vault-pass, so we need to use the old vault password prompt
|
||||
# format since Tower needs to match on that format.
|
||||
prompted_vault_secret = PromptVaultSecret(prompt_formats=prompt_formats[vault_id_value],
|
||||
vault_id=built_vault_id)
|
||||
|
||||
# a empty or invalid password from the prompt will warn and continue to the next
|
||||
# without erroring globablly
|
||||
try:
|
||||
prompted_vault_secret.load()
|
||||
except AnsibleError as exc:
|
||||
display.warning('Error in vault password prompt (%s): %s' % (vault_id_name, exc))
|
||||
raise
|
||||
|
||||
vault_secrets.append((built_vault_id, prompted_vault_secret))
|
||||
|
||||
# update loader with new secrets incrementally, so we can load a vault password
|
||||
# that is encrypted with a vault secret provided earlier
|
||||
loader.set_vault_secrets(vault_secrets)
|
||||
continue
|
||||
|
||||
# assuming anything else is a password file
|
||||
display.vvvvv('Reading vault password file: %s' % vault_id_value)
|
||||
# read vault_pass from a file
|
||||
file_vault_secret = get_file_vault_secret(filename=vault_id_value,
|
||||
vault_id=vault_id_name,
|
||||
loader=loader)
|
||||
|
||||
# an invalid password file will error globally
|
||||
try:
|
||||
file_vault_secret.load()
|
||||
except AnsibleError as exc:
|
||||
display.warning('Error in vault password file loading (%s): %s' % (vault_id_name, exc))
|
||||
raise
|
||||
|
||||
if vault_id_name:
|
||||
vault_secrets.append((vault_id_name, file_vault_secret))
|
||||
else:
|
||||
vault_secrets.append((C.DEFAULT_VAULT_IDENTITY, file_vault_secret))
|
||||
|
||||
# update loader with as-yet-known vault secrets
|
||||
loader.set_vault_secrets(vault_secrets)
|
||||
|
||||
return vault_secrets
|
||||
|
||||
def ask_passwords(self):
|
||||
''' prompt for connection and become passwords if needed '''
|
||||
|
||||
op = self.options
|
||||
sshpass = None
|
||||
becomepass = None
|
||||
become_prompt = ''
|
||||
|
||||
become_prompt_method = "BECOME" if C.AGNOSTIC_BECOME_PROMPT else op.become_method.upper()
|
||||
|
||||
try:
|
||||
if op.ask_pass:
|
||||
sshpass = getpass.getpass(prompt="SSH password: ")
|
||||
become_prompt = "%s password[defaults to SSH password]: " % become_prompt_method
|
||||
if sshpass:
|
||||
sshpass = to_bytes(sshpass, errors='strict', nonstring='simplerepr')
|
||||
else:
|
||||
become_prompt = "%s password: " % become_prompt_method
|
||||
|
||||
if op.become_ask_pass:
|
||||
becomepass = getpass.getpass(prompt=become_prompt)
|
||||
if op.ask_pass and becomepass == '':
|
||||
becomepass = sshpass
|
||||
if becomepass:
|
||||
becomepass = to_bytes(becomepass)
|
||||
except EOFError:
|
||||
pass
|
||||
|
||||
return (sshpass, becomepass)
|
||||
|
||||
def normalize_become_options(self):
|
||||
''' this keeps backwards compatibility with sudo/su self.options '''
|
||||
self.options.become_ask_pass = self.options.become_ask_pass or self.options.ask_sudo_pass or self.options.ask_su_pass or C.DEFAULT_BECOME_ASK_PASS
|
||||
self.options.become_user = self.options.become_user or self.options.sudo_user or self.options.su_user or C.DEFAULT_BECOME_USER
|
||||
|
||||
def _dep(which):
|
||||
display.deprecated('The %s command line option has been deprecated in favor of the "become" command line arguments' % which, '2.9')
|
||||
|
||||
if self.options.become:
|
||||
pass
|
||||
elif self.options.sudo:
|
||||
self.options.become = True
|
||||
self.options.become_method = 'sudo'
|
||||
_dep('sudo')
|
||||
elif self.options.su:
|
||||
self.options.become = True
|
||||
self.options.become_method = 'su'
|
||||
_dep('su')
|
||||
|
||||
# other deprecations:
|
||||
if self.options.ask_sudo_pass or self.options.sudo_user:
|
||||
_dep('sudo')
|
||||
if self.options.ask_su_pass or self.options.su_user:
|
||||
_dep('su')
|
||||
|
||||
def validate_conflicts(self, vault_opts=False, runas_opts=False, fork_opts=False, vault_rekey_opts=False):
|
||||
''' check for conflicting options '''
|
||||
|
||||
op = self.options
|
||||
|
||||
if vault_opts:
|
||||
# Check for vault related conflicts
|
||||
if (op.ask_vault_pass and op.vault_password_files):
|
||||
self.parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
|
||||
|
||||
if vault_rekey_opts:
|
||||
if (op.new_vault_id and op.new_vault_password_file):
|
||||
self.parser.error("--new-vault-password-file and --new-vault-id are mutually exclusive")
|
||||
|
||||
if runas_opts:
|
||||
# Check for privilege escalation conflicts
|
||||
if ((op.su or op.su_user) and (op.sudo or op.sudo_user) or
|
||||
(op.su or op.su_user) and (op.become or op.become_user) or
|
||||
(op.sudo or op.sudo_user) and (op.become or op.become_user)):
|
||||
|
||||
self.parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') and su arguments ('--su', '--su-user', and '--ask-su-pass') "
|
||||
"and become arguments ('--become', '--become-user', and '--ask-become-pass') are exclusive of each other")
|
||||
|
||||
if fork_opts:
|
||||
if op.forks < 1:
|
||||
self.parser.error("The number of processes (--forks) must be >= 1")
|
||||
|
||||
@staticmethod
|
||||
def unfrack_paths(option, opt, value, parser):
|
||||
paths = getattr(parser.values, option.dest)
|
||||
if paths is None:
|
||||
paths = []
|
||||
|
||||
if isinstance(value, string_types):
|
||||
paths[:0] = [unfrackpath(x) for x in value.split(os.pathsep) if x]
|
||||
elif isinstance(value, list):
|
||||
paths[:0] = [unfrackpath(x) for x in value if x]
|
||||
else:
|
||||
pass # FIXME: should we raise options error?
|
||||
|
||||
setattr(parser.values, option.dest, paths)
|
||||
|
||||
@staticmethod
|
||||
def unfrack_path(option, opt, value, parser):
|
||||
if value != '-':
|
||||
setattr(parser.values, option.dest, unfrackpath(value))
|
||||
else:
|
||||
setattr(parser.values, option.dest, value)
|
||||
|
||||
@staticmethod
|
||||
def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,
|
||||
async_opts=False, connect_opts=False, subset_opts=False, check_opts=False, inventory_opts=False, epilog=None, fork_opts=False,
|
||||
runas_prompt_opts=False, desc=None, basedir_opts=False, vault_rekey_opts=False):
|
||||
''' create an options parser for most ansible scripts '''
|
||||
|
||||
# base opts
|
||||
parser = SortedOptParser(usage, version=CLI.version("%prog"), description=desc, epilog=epilog)
|
||||
parser.add_option('-v', '--verbose', dest='verbosity', default=C.DEFAULT_VERBOSITY, action="count",
|
||||
help="verbose mode (-vvv for more, -vvvv to enable connection debugging)")
|
||||
|
||||
if inventory_opts:
|
||||
parser.add_option('-i', '--inventory', '--inventory-file', dest='inventory', action="append",
|
||||
help="specify inventory host path or comma separated host list. --inventory-file is deprecated")
|
||||
parser.add_option('--list-hosts', dest='listhosts', action='store_true',
|
||||
help='outputs a list of matching hosts; does not execute anything else')
|
||||
parser.add_option('-l', '--limit', default=C.DEFAULT_SUBSET, dest='subset',
|
||||
help='further limit selected hosts to an additional pattern')
|
||||
|
||||
if module_opts:
|
||||
parser.add_option('-M', '--module-path', dest='module_path', default=None,
|
||||
help="prepend colon-separated path(s) to module library (default=%s)" % C.DEFAULT_MODULE_PATH,
|
||||
action="callback", callback=CLI.unfrack_paths, type='str')
|
||||
if runtask_opts:
|
||||
parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append",
|
||||
help="set additional variables as key=value or YAML/JSON, if filename prepend with @", default=[])
|
||||
|
||||
if fork_opts:
|
||||
parser.add_option('-f', '--forks', dest='forks', default=C.DEFAULT_FORKS, type='int',
|
||||
help="specify number of parallel processes to use (default=%s)" % C.DEFAULT_FORKS)
|
||||
|
||||
if vault_opts:
|
||||
parser.add_option('--ask-vault-pass', default=C.DEFAULT_ASK_VAULT_PASS, dest='ask_vault_pass', action='store_true',
|
||||
help='ask for vault password')
|
||||
parser.add_option('--vault-password-file', default=[], dest='vault_password_files',
|
||||
help="vault password file", action="callback", callback=CLI.unfrack_paths, type='string')
|
||||
parser.add_option('--vault-id', default=[], dest='vault_ids', action='append', type='string',
|
||||
help='the vault identity to use')
|
||||
|
||||
if vault_rekey_opts:
|
||||
parser.add_option('--new-vault-password-file', default=None, dest='new_vault_password_file',
|
||||
help="new vault password file for rekey", action="callback", callback=CLI.unfrack_path, type='string')
|
||||
parser.add_option('--new-vault-id', default=None, dest='new_vault_id', type='string',
|
||||
help='the new vault identity to use for rekey')
|
||||
|
||||
if subset_opts:
|
||||
parser.add_option('-t', '--tags', dest='tags', default=C.TAGS_RUN, action='append',
|
||||
help="only run plays and tasks tagged with these values")
|
||||
parser.add_option('--skip-tags', dest='skip_tags', default=C.TAGS_SKIP, action='append',
|
||||
help="only run plays and tasks whose tags do not match these values")
|
||||
|
||||
if output_opts:
|
||||
parser.add_option('-o', '--one-line', dest='one_line', action='store_true',
|
||||
help='condense output')
|
||||
parser.add_option('-t', '--tree', dest='tree', default=None,
|
||||
help='log output to this directory')
|
||||
|
||||
if connect_opts:
|
||||
connect_group = optparse.OptionGroup(parser, "Connection Options", "control as whom and how to connect to hosts")
|
||||
connect_group.add_option('-k', '--ask-pass', default=C.DEFAULT_ASK_PASS, dest='ask_pass', action='store_true',
|
||||
help='ask for connection password')
|
||||
connect_group.add_option('--private-key', '--key-file', default=C.DEFAULT_PRIVATE_KEY_FILE, dest='private_key_file',
|
||||
help='use this file to authenticate the connection', action="callback", callback=CLI.unfrack_path, type='string')
|
||||
connect_group.add_option('-u', '--user', default=C.DEFAULT_REMOTE_USER, dest='remote_user',
|
||||
help='connect as this user (default=%s)' % C.DEFAULT_REMOTE_USER)
|
||||
connect_group.add_option('-c', '--connection', dest='connection', default=C.DEFAULT_TRANSPORT,
|
||||
help="connection type to use (default=%s)" % C.DEFAULT_TRANSPORT)
|
||||
connect_group.add_option('-T', '--timeout', default=C.DEFAULT_TIMEOUT, type='int', dest='timeout',
|
||||
help="override the connection timeout in seconds (default=%s)" % C.DEFAULT_TIMEOUT)
|
||||
connect_group.add_option('--ssh-common-args', default='', dest='ssh_common_args',
|
||||
help="specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)")
|
||||
connect_group.add_option('--sftp-extra-args', default='', dest='sftp_extra_args',
|
||||
help="specify extra arguments to pass to sftp only (e.g. -f, -l)")
|
||||
connect_group.add_option('--scp-extra-args', default='', dest='scp_extra_args',
|
||||
help="specify extra arguments to pass to scp only (e.g. -l)")
|
||||
connect_group.add_option('--ssh-extra-args', default='', dest='ssh_extra_args',
|
||||
help="specify extra arguments to pass to ssh only (e.g. -R)")
|
||||
|
||||
parser.add_option_group(connect_group)
|
||||
|
||||
runas_group = None
|
||||
rg = optparse.OptionGroup(parser, "Privilege Escalation Options", "control how and which user you become as on target hosts")
|
||||
if runas_opts:
|
||||
runas_group = rg
|
||||
# priv user defaults to root later on to enable detecting when this option was given here
|
||||
runas_group.add_option("-s", "--sudo", default=C.DEFAULT_SUDO, action="store_true", dest='sudo',
|
||||
help="run operations with sudo (nopasswd) (deprecated, use become)")
|
||||
runas_group.add_option('-U', '--sudo-user', dest='sudo_user', default=None,
|
||||
help='desired sudo user (default=root) (deprecated, use become)')
|
||||
runas_group.add_option('-S', '--su', default=C.DEFAULT_SU, action='store_true',
|
||||
help='run operations with su (deprecated, use become)')
|
||||
runas_group.add_option('-R', '--su-user', default=None,
|
||||
help='run operations with su as this user (default=%s) (deprecated, use become)' % C.DEFAULT_SU_USER)
|
||||
|
||||
# consolidated privilege escalation (become)
|
||||
runas_group.add_option("-b", "--become", default=C.DEFAULT_BECOME, action="store_true", dest='become',
|
||||
help="run operations with become (does not imply password prompting)")
|
||||
runas_group.add_option('--become-method', dest='become_method', default=C.DEFAULT_BECOME_METHOD, type='choice', choices=C.BECOME_METHODS,
|
||||
help="privilege escalation method to use (default=%s), valid choices: [ %s ]" %
|
||||
(C.DEFAULT_BECOME_METHOD, ' | '.join(C.BECOME_METHODS)))
|
||||
runas_group.add_option('--become-user', default=None, dest='become_user', type='string',
|
||||
help='run operations as this user (default=%s)' % C.DEFAULT_BECOME_USER)
|
||||
|
||||
if runas_opts or runas_prompt_opts:
|
||||
if not runas_group:
|
||||
runas_group = rg
|
||||
runas_group.add_option('--ask-sudo-pass', default=C.DEFAULT_ASK_SUDO_PASS, dest='ask_sudo_pass', action='store_true',
|
||||
help='ask for sudo password (deprecated, use become)')
|
||||
runas_group.add_option('--ask-su-pass', default=C.DEFAULT_ASK_SU_PASS, dest='ask_su_pass', action='store_true',
|
||||
help='ask for su password (deprecated, use become)')
|
||||
runas_group.add_option('-K', '--ask-become-pass', default=False, dest='become_ask_pass', action='store_true',
|
||||
help='ask for privilege escalation password')
|
||||
|
||||
if runas_group:
|
||||
parser.add_option_group(runas_group)
|
||||
|
||||
if async_opts:
|
||||
parser.add_option('-P', '--poll', default=C.DEFAULT_POLL_INTERVAL, type='int', dest='poll_interval',
|
||||
help="set the poll interval if using -B (default=%s)" % C.DEFAULT_POLL_INTERVAL)
|
||||
parser.add_option('-B', '--background', dest='seconds', type='int', default=0,
|
||||
help='run asynchronously, failing after X seconds (default=N/A)')
|
||||
|
||||
if check_opts:
|
||||
parser.add_option("-C", "--check", default=False, dest='check', action='store_true',
|
||||
help="don't make any changes; instead, try to predict some of the changes that may occur")
|
||||
parser.add_option('--syntax-check', dest='syntax', action='store_true',
|
||||
help="perform a syntax check on the playbook, but do not execute it")
|
||||
parser.add_option("-D", "--diff", default=C.DIFF_ALWAYS, dest='diff', action='store_true',
|
||||
help="when changing (small) files and templates, show the differences in those files; works great with --check")
|
||||
|
||||
if meta_opts:
|
||||
parser.add_option('--force-handlers', default=C.DEFAULT_FORCE_HANDLERS, dest='force_handlers', action='store_true',
|
||||
help="run handlers even if a task fails")
|
||||
parser.add_option('--flush-cache', dest='flush_cache', action='store_true',
|
||||
help="clear the fact cache for every host in inventory")
|
||||
|
||||
if basedir_opts:
|
||||
parser.add_option('--playbook-dir', default=None, dest='basedir', action='store',
|
||||
help="Since this tool does not use playbooks, use this as a subsitute playbook directory."
|
||||
"This sets the relative path for many features including roles/ group_vars/ etc.")
|
||||
return parser
|
||||
|
||||
@abstractmethod
|
||||
def parse(self):
|
||||
"""Parse the command line args
|
||||
|
||||
This method parses the command line arguments. It uses the parser
|
||||
stored in the self.parser attribute and saves the args and options in
|
||||
self.args and self.options respectively.
|
||||
|
||||
Subclasses need to implement this method. They will usually create
|
||||
a base_parser, add their own options to the base_parser, and then call
|
||||
this method to do the actual parsing. An implementation will look
|
||||
something like this::
|
||||
|
||||
def parse(self):
|
||||
parser = super(MyCLI, self).base_parser(usage="My Ansible CLI", inventory_opts=True)
|
||||
parser.add_option('--my-option', dest='my_option', action='store')
|
||||
self.parser = parser
|
||||
super(MyCLI, self).parse()
|
||||
# If some additional transformations are needed for the
|
||||
# arguments and options, do it here.
|
||||
"""
|
||||
|
||||
self.options, self.args = self.parser.parse_args(self.args[1:])
|
||||
|
||||
# process tags
|
||||
if hasattr(self.options, 'tags') and not self.options.tags:
|
||||
# optparse defaults does not do what's expected
|
||||
self.options.tags = ['all']
|
||||
if hasattr(self.options, 'tags') and self.options.tags:
|
||||
tags = set()
|
||||
for tag_set in self.options.tags:
|
||||
for tag in tag_set.split(u','):
|
||||
tags.add(tag.strip())
|
||||
self.options.tags = list(tags)
|
||||
|
||||
# process skip_tags
|
||||
if hasattr(self.options, 'skip_tags') and self.options.skip_tags:
|
||||
skip_tags = set()
|
||||
for tag_set in self.options.skip_tags:
|
||||
for tag in tag_set.split(u','):
|
||||
skip_tags.add(tag.strip())
|
||||
self.options.skip_tags = list(skip_tags)
|
||||
|
||||
# process inventory options except for CLIs that require their own processing
|
||||
if hasattr(self.options, 'inventory') and not self.SKIP_INVENTORY_DEFAULTS:
|
||||
|
||||
if self.options.inventory:
|
||||
|
||||
# should always be list
|
||||
if isinstance(self.options.inventory, string_types):
|
||||
self.options.inventory = [self.options.inventory]
|
||||
|
||||
# Ensure full paths when needed
|
||||
self.options.inventory = [unfrackpath(opt, follow=False) if ',' not in opt else opt for opt in self.options.inventory]
|
||||
else:
|
||||
self.options.inventory = C.DEFAULT_HOST_LIST
|
||||
|
||||
@staticmethod
|
||||
def version(prog):
|
||||
''' return ansible version '''
|
||||
result = "{0} {1}".format(prog, __version__)
|
||||
gitinfo = CLI._gitinfo()
|
||||
if gitinfo:
|
||||
result = result + " {0}".format(gitinfo)
|
||||
result += "\n config file = %s" % C.CONFIG_FILE
|
||||
if C.DEFAULT_MODULE_PATH is None:
|
||||
cpath = "Default w/o overrides"
|
||||
else:
|
||||
cpath = C.DEFAULT_MODULE_PATH
|
||||
result = result + "\n configured module search path = %s" % cpath
|
||||
result = result + "\n ansible python module location = %s" % ':'.join(ansible.__path__)
|
||||
result = result + "\n executable location = %s" % sys.argv[0]
|
||||
result = result + "\n python version = %s" % ''.join(sys.version.splitlines())
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def version_info(gitinfo=False):
|
||||
''' return full ansible version info '''
|
||||
if gitinfo:
|
||||
# expensive call, user with care
|
||||
ansible_version_string = CLI.version('')
|
||||
else:
|
||||
ansible_version_string = __version__
|
||||
ansible_version = ansible_version_string.split()[0]
|
||||
ansible_versions = ansible_version.split('.')
|
||||
for counter in range(len(ansible_versions)):
|
||||
if ansible_versions[counter] == "":
|
||||
ansible_versions[counter] = 0
|
||||
try:
|
||||
ansible_versions[counter] = int(ansible_versions[counter])
|
||||
except Exception:
|
||||
pass
|
||||
if len(ansible_versions) < 3:
|
||||
for counter in range(len(ansible_versions), 3):
|
||||
ansible_versions.append(0)
|
||||
return {'string': ansible_version_string.strip(),
|
||||
'full': ansible_version,
|
||||
'major': ansible_versions[0],
|
||||
'minor': ansible_versions[1],
|
||||
'revision': ansible_versions[2]}
|
||||
|
||||
@staticmethod
|
||||
def _git_repo_info(repo_path):
|
||||
''' returns a string containing git branch, commit id and commit date '''
|
||||
result = None
|
||||
if os.path.exists(repo_path):
|
||||
# Check if the .git is a file. If it is a file, it means that we are in a submodule structure.
|
||||
if os.path.isfile(repo_path):
|
||||
try:
|
||||
gitdir = yaml.safe_load(open(repo_path)).get('gitdir')
|
||||
# There is a possibility the .git file to have an absolute path.
|
||||
if os.path.isabs(gitdir):
|
||||
repo_path = gitdir
|
||||
else:
|
||||
repo_path = os.path.join(repo_path[:-4], gitdir)
|
||||
except (IOError, AttributeError):
|
||||
return ''
|
||||
f = open(os.path.join(repo_path, "HEAD"))
|
||||
line = f.readline().rstrip("\n")
|
||||
if line.startswith("ref:"):
|
||||
branch_path = os.path.join(repo_path, line[5:])
|
||||
else:
|
||||
branch_path = None
|
||||
f.close()
|
||||
if branch_path and os.path.exists(branch_path):
|
||||
branch = '/'.join(line.split('/')[2:])
|
||||
f = open(branch_path)
|
||||
commit = f.readline()[:10]
|
||||
f.close()
|
||||
else:
|
||||
# detached HEAD
|
||||
commit = line[:10]
|
||||
branch = 'detached HEAD'
|
||||
branch_path = os.path.join(repo_path, "HEAD")
|
||||
|
||||
date = time.localtime(os.stat(branch_path).st_mtime)
|
||||
if time.daylight == 0:
|
||||
offset = time.timezone
|
||||
else:
|
||||
offset = time.altzone
|
||||
result = "({0} {1}) last updated {2} (GMT {3:+04d})".format(branch, commit, time.strftime("%Y/%m/%d %H:%M:%S", date), int(offset / -36))
|
||||
else:
|
||||
result = ''
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def _gitinfo():
|
||||
basedir = os.path.join(os.path.dirname(__file__), '..', '..', '..')
|
||||
repo_path = os.path.join(basedir, '.git')
|
||||
result = CLI._git_repo_info(repo_path)
|
||||
submodules = os.path.join(basedir, '.gitmodules')
|
||||
if not os.path.exists(submodules):
|
||||
return result
|
||||
f = open(submodules)
|
||||
for line in f:
|
||||
tokens = line.strip().split(' ')
|
||||
if tokens[0] == 'path':
|
||||
submodule_path = tokens[2]
|
||||
submodule_info = CLI._git_repo_info(os.path.join(basedir, submodule_path, '.git'))
|
||||
if not submodule_info:
|
||||
submodule_info = ' not found - use git submodule update --init ' + submodule_path
|
||||
result += "\n {0}: {1}".format(submodule_path, submodule_info)
|
||||
f.close()
|
||||
return result
|
||||
|
||||
def pager(self, text):
|
||||
''' find reasonable way to display text '''
|
||||
# this is a much simpler form of what is in pydoc.py
|
||||
if not sys.stdout.isatty():
|
||||
display.display(text, screen_only=True)
|
||||
elif 'PAGER' in os.environ:
|
||||
if sys.platform == 'win32':
|
||||
display.display(text, screen_only=True)
|
||||
else:
|
||||
self.pager_pipe(text, os.environ['PAGER'])
|
||||
else:
|
||||
p = subprocess.Popen('less --version', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
p.communicate()
|
||||
if p.returncode == 0:
|
||||
self.pager_pipe(text, 'less')
|
||||
else:
|
||||
display.display(text, screen_only=True)
|
||||
|
||||
@staticmethod
|
||||
def pager_pipe(text, cmd):
|
||||
''' pipe text through a pager '''
|
||||
if 'LESS' not in os.environ:
|
||||
os.environ['LESS'] = CLI.LESS_OPTS
|
||||
try:
|
||||
cmd = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout)
|
||||
cmd.communicate(input=to_bytes(text))
|
||||
except IOError:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tty_ify(cls, text):
|
||||
|
||||
t = cls._ITALIC.sub("`" + r"\1" + "'", text) # I(word) => `word'
|
||||
t = cls._BOLD.sub("*" + r"\1" + "*", t) # B(word) => *word*
|
||||
t = cls._MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word]
|
||||
t = cls._URL.sub(r"\1", t) # U(word) => word
|
||||
t = cls._CONST.sub("`" + r"\1" + "'", t) # C(word) => `word'
|
||||
|
||||
return t
|
||||
|
||||
@staticmethod
|
||||
def _play_prereqs(options):
|
||||
|
||||
# all needs loader
|
||||
loader = DataLoader()
|
||||
|
||||
basedir = getattr(options, 'basedir', False)
|
||||
if basedir:
|
||||
loader.set_basedir(basedir)
|
||||
|
||||
vault_ids = options.vault_ids
|
||||
default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST
|
||||
vault_ids = default_vault_ids + vault_ids
|
||||
|
||||
vault_secrets = CLI.setup_vault_secrets(loader,
|
||||
vault_ids=vault_ids,
|
||||
vault_password_files=options.vault_password_files,
|
||||
ask_vault_pass=options.ask_vault_pass,
|
||||
auto_prompt=False)
|
||||
loader.set_vault_secrets(vault_secrets)
|
||||
|
||||
# create the inventory, and filter it based on the subset specified (if any)
|
||||
inventory = InventoryManager(loader=loader, sources=options.inventory)
|
||||
|
||||
# create the variable manager, which will be shared throughout
|
||||
# the code, ensuring a consistent view of global variables
|
||||
variable_manager = VariableManager(loader=loader, inventory=inventory)
|
||||
|
||||
if hasattr(options, 'basedir'):
|
||||
if options.basedir:
|
||||
variable_manager.safe_basedir = True
|
||||
else:
|
||||
variable_manager.safe_basedir = True
|
||||
|
||||
# load vars from cli options
|
||||
variable_manager.extra_vars = load_extra_vars(loader=loader, options=options)
|
||||
variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False))
|
||||
|
||||
return loader, inventory, variable_manager
|
||||
|
||||
@staticmethod
|
||||
def get_host_list(inventory, subset, pattern='all'):
|
||||
|
||||
no_hosts = False
|
||||
if len(inventory.list_hosts()) == 0:
|
||||
# Empty inventory
|
||||
if C.LOCALHOST_WARNING:
|
||||
display.warning("provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'")
|
||||
no_hosts = True
|
||||
|
||||
inventory.subset(subset)
|
||||
|
||||
hosts = inventory.list_hosts(pattern)
|
||||
if len(hosts) == 0 and no_hosts is False:
|
||||
raise AnsibleError("Specified hosts and/or --limit does not match any hosts")
|
||||
|
||||
return hosts
|
188
env_27/lib/python2.7/site-packages/ansible/cli/adhoc.py
Normal file
188
env_27/lib/python2.7/site-packages/ansible/cli/adhoc.py
Normal file
@ -0,0 +1,188 @@
|
||||
# (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
|
||||
|
||||
########################################################
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.cli import CLI
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.executor.task_queue_manager import TaskQueueManager
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.parsing.splitter import parse_kv
|
||||
from ansible.playbook import Playbook
|
||||
from ansible.playbook.play import Play
|
||||
from ansible.plugins.loader import get_all_plugin_loaders
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
########################################################
|
||||
|
||||
class AdHocCLI(CLI):
|
||||
''' is an extra-simple tool/framework/API for doing 'remote things'.
|
||||
this command allows you to define and run a single task 'playbook' against a set of hosts
|
||||
'''
|
||||
|
||||
def parse(self):
|
||||
''' create an options parser for bin/ansible '''
|
||||
|
||||
self.parser = CLI.base_parser(
|
||||
usage='%prog <host-pattern> [options]',
|
||||
runas_opts=True,
|
||||
inventory_opts=True,
|
||||
async_opts=True,
|
||||
output_opts=True,
|
||||
connect_opts=True,
|
||||
check_opts=True,
|
||||
runtask_opts=True,
|
||||
vault_opts=True,
|
||||
fork_opts=True,
|
||||
module_opts=True,
|
||||
basedir_opts=True,
|
||||
desc="Define and run a single task 'playbook' against a set of hosts",
|
||||
epilog="Some modules do not make sense in Ad-Hoc (include, meta, etc)",
|
||||
)
|
||||
|
||||
# options unique to ansible ad-hoc
|
||||
self.parser.add_option('-a', '--args', dest='module_args',
|
||||
help="module arguments", default=C.DEFAULT_MODULE_ARGS)
|
||||
self.parser.add_option('-m', '--module-name', dest='module_name',
|
||||
help="module name to execute (default=%s)" % C.DEFAULT_MODULE_NAME,
|
||||
default=C.DEFAULT_MODULE_NAME)
|
||||
|
||||
super(AdHocCLI, self).parse()
|
||||
|
||||
if len(self.args) < 1:
|
||||
raise AnsibleOptionsError("Missing target hosts")
|
||||
elif len(self.args) > 1:
|
||||
raise AnsibleOptionsError("Extraneous options or arguments")
|
||||
|
||||
display.verbosity = self.options.verbosity
|
||||
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)
|
||||
|
||||
def _play_ds(self, pattern, async_val, poll):
|
||||
check_raw = self.options.module_name in ('command', 'win_command', 'shell', 'win_shell', 'script', 'raw')
|
||||
return dict(
|
||||
name="Ansible Ad-Hoc",
|
||||
hosts=pattern,
|
||||
gather_facts='no',
|
||||
tasks=[dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args, check_raw=check_raw)), async_val=async_val,
|
||||
poll=poll)]
|
||||
)
|
||||
|
||||
def run(self):
|
||||
''' create and execute the single task playbook '''
|
||||
|
||||
super(AdHocCLI, self).run()
|
||||
|
||||
# only thing left should be host pattern
|
||||
pattern = to_text(self.args[0], errors='surrogate_or_strict')
|
||||
|
||||
sshpass = None
|
||||
becomepass = None
|
||||
|
||||
self.normalize_become_options()
|
||||
(sshpass, becomepass) = self.ask_passwords()
|
||||
passwords = {'conn_pass': sshpass, 'become_pass': becomepass}
|
||||
|
||||
# dynamically load any plugins
|
||||
get_all_plugin_loaders()
|
||||
|
||||
loader, inventory, variable_manager = self._play_prereqs(self.options)
|
||||
|
||||
try:
|
||||
hosts = CLI.get_host_list(inventory, self.options.subset, pattern)
|
||||
except AnsibleError:
|
||||
if self.options.subset:
|
||||
raise
|
||||
else:
|
||||
hosts = []
|
||||
display.warning("No hosts matched, nothing to do")
|
||||
|
||||
if self.options.listhosts:
|
||||
display.display(' hosts (%d):' % len(hosts))
|
||||
for host in hosts:
|
||||
display.display(' %s' % host)
|
||||
return 0
|
||||
|
||||
if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
|
||||
err = "No argument passed to %s module" % self.options.module_name
|
||||
if pattern.endswith(".yml"):
|
||||
err = err + ' (did you mean to run ansible-playbook?)'
|
||||
raise AnsibleOptionsError(err)
|
||||
|
||||
# Avoid modules that don't work with ad-hoc
|
||||
if self.options.module_name in ('import_playbook',):
|
||||
raise AnsibleOptionsError("'%s' is not a valid action for ad-hoc commands" % self.options.module_name)
|
||||
|
||||
play_ds = self._play_ds(pattern, self.options.seconds, self.options.poll_interval)
|
||||
play = Play().load(play_ds, variable_manager=variable_manager, loader=loader)
|
||||
|
||||
# used in start callback
|
||||
playbook = Playbook(loader)
|
||||
playbook._entries.append(play)
|
||||
playbook._file_name = '__adhoc_playbook__'
|
||||
|
||||
if self.callback:
|
||||
cb = self.callback
|
||||
elif self.options.one_line:
|
||||
cb = 'oneline'
|
||||
# Respect custom 'stdout_callback' only with enabled 'bin_ansible_callbacks'
|
||||
elif C.DEFAULT_LOAD_CALLBACK_PLUGINS and C.DEFAULT_STDOUT_CALLBACK != 'default':
|
||||
cb = C.DEFAULT_STDOUT_CALLBACK
|
||||
else:
|
||||
cb = 'minimal'
|
||||
|
||||
run_tree = False
|
||||
if self.options.tree:
|
||||
C.DEFAULT_CALLBACK_WHITELIST.append('tree')
|
||||
C.TREE_DIR = self.options.tree
|
||||
run_tree = True
|
||||
|
||||
# now create a task queue manager to execute the play
|
||||
self._tqm = None
|
||||
try:
|
||||
self._tqm = TaskQueueManager(
|
||||
inventory=inventory,
|
||||
variable_manager=variable_manager,
|
||||
loader=loader,
|
||||
options=self.options,
|
||||
passwords=passwords,
|
||||
stdout_callback=cb,
|
||||
run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS,
|
||||
run_tree=run_tree,
|
||||
)
|
||||
|
||||
self._tqm.send_callback('v2_playbook_on_start', playbook)
|
||||
|
||||
result = self._tqm.run(play)
|
||||
|
||||
self._tqm.send_callback('v2_playbook_on_stats', self._tqm._stats)
|
||||
finally:
|
||||
if self._tqm:
|
||||
self._tqm.cleanup()
|
||||
if loader:
|
||||
loader.cleanup_all_tmp_files()
|
||||
|
||||
return result
|
174
env_27/lib/python2.7/site-packages/ansible/cli/config.py
Normal file
174
env_27/lib/python2.7/site-packages/ansible/cli/config.py
Normal file
@ -0,0 +1,174 @@
|
||||
# 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
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
from ansible.cli import CLI
|
||||
from ansible.config.manager import ConfigManager, Setting, find_ini_config_file
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.module_utils._text import to_native, to_text
|
||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
||||
from ansible.utils.color import stringc
|
||||
from ansible.utils.path import unfrackpath
|
||||
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class ConfigCLI(CLI):
|
||||
""" Config command line class """
|
||||
|
||||
VALID_ACTIONS = ("view", "dump", "list") # TODO: edit, update, search
|
||||
|
||||
def __init__(self, args, callback=None):
|
||||
|
||||
self.config_file = None
|
||||
self.config = None
|
||||
super(ConfigCLI, self).__init__(args, callback)
|
||||
|
||||
def parse(self):
|
||||
|
||||
self.parser = CLI.base_parser(
|
||||
usage="usage: %%prog [%s] [--help] [options] [ansible.cfg]" % "|".join(self.VALID_ACTIONS),
|
||||
epilog="\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]),
|
||||
desc="View, edit, and manage ansible configuration.",
|
||||
)
|
||||
self.parser.add_option('-c', '--config', dest='config_file', help="path to configuration file, defaults to first file found in precedence.")
|
||||
|
||||
self.set_action()
|
||||
|
||||
# options specific to self.actions
|
||||
if self.action == "list":
|
||||
self.parser.set_usage("usage: %prog list [options] ")
|
||||
if self.action == "dump":
|
||||
self.parser.add_option('--only-changed', dest='only_changed', action='store_true',
|
||||
help="Only show configurations that have changed from the default")
|
||||
elif self.action == "update":
|
||||
self.parser.add_option('-s', '--setting', dest='setting', help="config setting, the section defaults to 'defaults'")
|
||||
self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] -s '[section.]setting=value'")
|
||||
elif self.action == "search":
|
||||
self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] <search term>")
|
||||
|
||||
self.options, self.args = self.parser.parse_args()
|
||||
display.verbosity = self.options.verbosity
|
||||
|
||||
def run(self):
|
||||
|
||||
super(ConfigCLI, self).run()
|
||||
|
||||
if self.options.config_file:
|
||||
self.config_file = unfrackpath(self.options.config_file, follow=False)
|
||||
self.config = ConfigManager(self.config_file)
|
||||
else:
|
||||
self.config = ConfigManager()
|
||||
self.config_file = find_ini_config_file()
|
||||
|
||||
if self.config_file:
|
||||
try:
|
||||
if not os.path.exists(self.config_file):
|
||||
raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
|
||||
elif not os.path.isfile(self.config_file):
|
||||
raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))
|
||||
|
||||
os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
|
||||
except:
|
||||
if self.action in ['view']:
|
||||
raise
|
||||
elif self.action in ['edit', 'update']:
|
||||
display.warning("File does not exist, used empty file: %s" % self.config_file)
|
||||
|
||||
elif self.action == 'view':
|
||||
raise AnsibleError('Invalid or no config file was supplied')
|
||||
|
||||
self.execute()
|
||||
|
||||
def execute_update(self):
|
||||
'''
|
||||
Updates a single setting in the specified ansible.cfg
|
||||
'''
|
||||
raise AnsibleError("Option not implemented yet")
|
||||
|
||||
# pylint: disable=unreachable
|
||||
if self.options.setting is None:
|
||||
raise AnsibleOptionsError("update option requries a setting to update")
|
||||
|
||||
(entry, value) = self.options.setting.split('=')
|
||||
if '.' in entry:
|
||||
(section, option) = entry.split('.')
|
||||
else:
|
||||
section = 'defaults'
|
||||
option = entry
|
||||
subprocess.call([
|
||||
'ansible',
|
||||
'-m', 'ini_file',
|
||||
'localhost',
|
||||
'-c', 'local',
|
||||
'-a', '"dest=%s section=%s option=%s value=%s backup=yes"' % (self.config_file, section, option, value)
|
||||
])
|
||||
|
||||
def execute_view(self):
|
||||
'''
|
||||
Displays the current config file
|
||||
'''
|
||||
try:
|
||||
with open(self.config_file, 'rb') as f:
|
||||
self.pager(to_text(f.read(), errors='surrogate_or_strict'))
|
||||
except Exception as e:
|
||||
raise AnsibleError("Failed to open config file: %s" % to_native(e))
|
||||
|
||||
def execute_edit(self):
|
||||
'''
|
||||
Opens ansible.cfg in the default EDITOR
|
||||
'''
|
||||
raise AnsibleError("Option not implemented yet")
|
||||
|
||||
# pylint: disable=unreachable
|
||||
try:
|
||||
editor = shlex.split(os.environ.get('EDITOR', 'vi'))
|
||||
editor.append(self.config_file)
|
||||
subprocess.call(editor)
|
||||
except Exception as e:
|
||||
raise AnsibleError("Failed to open editor: %s" % to_native(e))
|
||||
|
||||
def execute_list(self):
|
||||
'''
|
||||
list all current configs reading lib/constants.py and shows env and config file setting names
|
||||
'''
|
||||
self.pager(to_text(yaml.dump(self.config.get_configuration_definitions(), Dumper=AnsibleDumper), errors='surrogate_or_strict'))
|
||||
|
||||
def execute_dump(self):
|
||||
'''
|
||||
Shows the current settings, merges ansible.cfg if specified
|
||||
'''
|
||||
# FIXME: deal with plugins, not just base config
|
||||
text = []
|
||||
defaults = self.config.get_configuration_definitions().copy()
|
||||
for setting in self.config.data.get_settings():
|
||||
if setting.name in defaults:
|
||||
defaults[setting.name] = setting
|
||||
|
||||
for setting in sorted(defaults):
|
||||
if isinstance(defaults[setting], Setting):
|
||||
if defaults[setting].origin == 'default':
|
||||
color = 'green'
|
||||
else:
|
||||
color = 'yellow'
|
||||
msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value)
|
||||
else:
|
||||
color = 'green'
|
||||
msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default'))
|
||||
if not self.options.only_changed or color == 'yellow':
|
||||
text.append(stringc(msg, color))
|
||||
|
||||
self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
|
442
env_27/lib/python2.7/site-packages/ansible/cli/console.py
Normal file
442
env_27/lib/python2.7/site-packages/ansible/cli/console.py
Normal file
@ -0,0 +1,442 @@
|
||||
# (c) 2014, Nandor Sivok <dominis@haxor.hu>
|
||||
# (c) 2016, Redhat Inc
|
||||
#
|
||||
# ansible-console 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-console 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
|
||||
|
||||
########################################################
|
||||
# ansible-console is an interactive REPL shell for ansible
|
||||
# with built-in tab completion for all the documented modules
|
||||
#
|
||||
# Available commands:
|
||||
# cd - change host/group (you can use host patterns eg.: app*.dc*:!app01*)
|
||||
# list - list available hosts in the current path
|
||||
# forks - change fork
|
||||
# become - become
|
||||
# ! - forces shell module instead of the ansible module (!yum update -y)
|
||||
|
||||
import atexit
|
||||
import cmd
|
||||
import getpass
|
||||
import readline
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.cli import CLI
|
||||
from ansible.executor.task_queue_manager import TaskQueueManager
|
||||
from ansible.module_utils._text import to_native, to_text
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.parsing.splitter import parse_kv
|
||||
from ansible.playbook.play import Play
|
||||
from ansible.plugins.loader import module_loader, fragment_loader
|
||||
from ansible.utils import plugin_docs
|
||||
from ansible.utils.color import stringc
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class ConsoleCLI(CLI, cmd.Cmd):
|
||||
''' a REPL that allows for running ad-hoc tasks against a chosen inventory (based on dominis' ansible-shell).'''
|
||||
|
||||
modules = []
|
||||
ARGUMENTS = {'host-pattern': 'A name of a group in the inventory, a shell-like glob '
|
||||
'selecting hosts in inventory or any combination of the two separated by commas.'}
|
||||
|
||||
# use specific to console, but fallback to highlight for backwards compatibility
|
||||
NORMAL_PROMPT = C.COLOR_CONSOLE_PROMPT or C.COLOR_HIGHLIGHT
|
||||
|
||||
def __init__(self, args):
|
||||
|
||||
super(ConsoleCLI, self).__init__(args)
|
||||
|
||||
self.intro = 'Welcome to the ansible console.\nType help or ? to list commands.\n'
|
||||
|
||||
self.groups = []
|
||||
self.hosts = []
|
||||
self.pattern = None
|
||||
self.variable_manager = None
|
||||
self.loader = None
|
||||
self.passwords = dict()
|
||||
|
||||
self.modules = None
|
||||
cmd.Cmd.__init__(self)
|
||||
|
||||
def parse(self):
|
||||
self.parser = CLI.base_parser(
|
||||
usage='%prog [<host-pattern>] [options]',
|
||||
runas_opts=True,
|
||||
inventory_opts=True,
|
||||
connect_opts=True,
|
||||
check_opts=True,
|
||||
vault_opts=True,
|
||||
fork_opts=True,
|
||||
module_opts=True,
|
||||
basedir_opts=True,
|
||||
desc="REPL console for executing Ansible tasks.",
|
||||
epilog="This is not a live session/connection, each task executes in the background and returns it's results."
|
||||
)
|
||||
|
||||
# options unique to shell
|
||||
self.parser.add_option('--step', dest='step', action='store_true',
|
||||
help="one-step-at-a-time: confirm each task before running")
|
||||
|
||||
self.parser.set_defaults(cwd='*')
|
||||
|
||||
super(ConsoleCLI, self).parse()
|
||||
|
||||
display.verbosity = self.options.verbosity
|
||||
self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)
|
||||
|
||||
def get_names(self):
|
||||
return dir(self)
|
||||
|
||||
def cmdloop(self):
|
||||
try:
|
||||
cmd.Cmd.cmdloop(self)
|
||||
except KeyboardInterrupt:
|
||||
self.do_exit(self)
|
||||
|
||||
def set_prompt(self):
|
||||
login_user = self.options.remote_user or getpass.getuser()
|
||||
self.selected = self.inventory.list_hosts(self.options.cwd)
|
||||
prompt = "%s@%s (%d)[f:%s]" % (login_user, self.options.cwd, len(self.selected), self.options.forks)
|
||||
if self.options.become and self.options.become_user in [None, 'root']:
|
||||
prompt += "# "
|
||||
color = C.COLOR_ERROR
|
||||
else:
|
||||
prompt += "$ "
|
||||
color = self.NORMAL_PROMPT
|
||||
self.prompt = stringc(prompt, color)
|
||||
|
||||
def list_modules(self):
|
||||
modules = set()
|
||||
if self.options.module_path:
|
||||
for path in self.options.module_path:
|
||||
if path:
|
||||
module_loader.add_directory(path)
|
||||
|
||||
module_paths = module_loader._get_paths()
|
||||
for path in module_paths:
|
||||
if path is not None:
|
||||
modules.update(self._find_modules_in_path(path))
|
||||
return modules
|
||||
|
||||
def _find_modules_in_path(self, path):
|
||||
|
||||
if os.path.isdir(path):
|
||||
for module in os.listdir(path):
|
||||
if module.startswith('.'):
|
||||
continue
|
||||
elif os.path.isdir(module):
|
||||
self._find_modules_in_path(module)
|
||||
elif module.startswith('__'):
|
||||
continue
|
||||
elif any(module.endswith(x) for x in C.BLACKLIST_EXTS):
|
||||
continue
|
||||
elif module in C.IGNORE_FILES:
|
||||
continue
|
||||
elif module.startswith('_'):
|
||||
fullpath = '/'.join([path, module])
|
||||
if os.path.islink(fullpath): # avoids aliases
|
||||
continue
|
||||
module = module.replace('_', '', 1)
|
||||
|
||||
module = os.path.splitext(module)[0] # removes the extension
|
||||
yield module
|
||||
|
||||
def default(self, arg, forceshell=False):
|
||||
""" actually runs modules """
|
||||
if arg.startswith("#"):
|
||||
return False
|
||||
|
||||
if not self.options.cwd:
|
||||
display.error("No host found")
|
||||
return False
|
||||
|
||||
if arg.split()[0] in self.modules:
|
||||
module = arg.split()[0]
|
||||
module_args = ' '.join(arg.split()[1:])
|
||||
else:
|
||||
module = 'shell'
|
||||
module_args = arg
|
||||
|
||||
if forceshell is True:
|
||||
module = 'shell'
|
||||
module_args = arg
|
||||
|
||||
self.options.module_name = module
|
||||
|
||||
result = None
|
||||
try:
|
||||
check_raw = self.options.module_name in ('command', 'shell', 'script', 'raw')
|
||||
play_ds = dict(
|
||||
name="Ansible Shell",
|
||||
hosts=self.options.cwd,
|
||||
gather_facts='no',
|
||||
tasks=[dict(action=dict(module=module, args=parse_kv(module_args, check_raw=check_raw)))]
|
||||
)
|
||||
play = Play().load(play_ds, variable_manager=self.variable_manager, loader=self.loader)
|
||||
except Exception as e:
|
||||
display.error(u"Unable to build command: %s" % to_text(e))
|
||||
return False
|
||||
|
||||
try:
|
||||
cb = 'minimal' # FIXME: make callbacks configurable
|
||||
# now create a task queue manager to execute the play
|
||||
self._tqm = None
|
||||
try:
|
||||
self._tqm = TaskQueueManager(
|
||||
inventory=self.inventory,
|
||||
variable_manager=self.variable_manager,
|
||||
loader=self.loader,
|
||||
options=self.options,
|
||||
passwords=self.passwords,
|
||||
stdout_callback=cb,
|
||||
run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS,
|
||||
run_tree=False,
|
||||
)
|
||||
|
||||
result = self._tqm.run(play)
|
||||
finally:
|
||||
if self._tqm:
|
||||
self._tqm.cleanup()
|
||||
if self.loader:
|
||||
self.loader.cleanup_all_tmp_files()
|
||||
|
||||
if result is None:
|
||||
display.error("No hosts found")
|
||||
return False
|
||||
except KeyboardInterrupt:
|
||||
display.error('User interrupted execution')
|
||||
return False
|
||||
except Exception as e:
|
||||
display.error(to_text(e))
|
||||
# FIXME: add traceback in very very verbose mode
|
||||
return False
|
||||
|
||||
def emptyline(self):
|
||||
return
|
||||
|
||||
def do_shell(self, arg):
|
||||
"""
|
||||
You can run shell commands through the shell module.
|
||||
|
||||
eg.:
|
||||
shell ps uax | grep java | wc -l
|
||||
shell killall python
|
||||
shell halt -n
|
||||
|
||||
You can use the ! to force the shell module. eg.:
|
||||
!ps aux | grep java | wc -l
|
||||
"""
|
||||
self.default(arg, True)
|
||||
|
||||
def do_forks(self, arg):
|
||||
"""Set the number of forks"""
|
||||
if not arg:
|
||||
display.display('Usage: forks <number>')
|
||||
return
|
||||
self.options.forks = int(arg)
|
||||
self.set_prompt()
|
||||
|
||||
do_serial = do_forks
|
||||
|
||||
def do_verbosity(self, arg):
|
||||
"""Set verbosity level"""
|
||||
if not arg:
|
||||
display.display('Usage: verbosity <number>')
|
||||
else:
|
||||
display.verbosity = int(arg)
|
||||
display.v('verbosity level set to %s' % arg)
|
||||
|
||||
def do_cd(self, arg):
|
||||
"""
|
||||
Change active host/group. You can use hosts patterns as well eg.:
|
||||
cd webservers
|
||||
cd webservers:dbservers
|
||||
cd webservers:!phoenix
|
||||
cd webservers:&staging
|
||||
cd webservers:dbservers:&staging:!phoenix
|
||||
"""
|
||||
if not arg:
|
||||
self.options.cwd = '*'
|
||||
elif arg in '/*':
|
||||
self.options.cwd = 'all'
|
||||
elif self.inventory.get_hosts(arg):
|
||||
self.options.cwd = arg
|
||||
else:
|
||||
display.display("no host matched")
|
||||
|
||||
self.set_prompt()
|
||||
|
||||
def do_list(self, arg):
|
||||
"""List the hosts in the current group"""
|
||||
if arg == 'groups':
|
||||
for group in self.groups:
|
||||
display.display(group)
|
||||
else:
|
||||
for host in self.selected:
|
||||
display.display(host.name)
|
||||
|
||||
def do_become(self, arg):
|
||||
"""Toggle whether plays run with become"""
|
||||
if arg:
|
||||
self.options.become = boolean(arg, strict=False)
|
||||
display.v("become changed to %s" % self.options.become)
|
||||
self.set_prompt()
|
||||
else:
|
||||
display.display("Please specify become value, e.g. `become yes`")
|
||||
|
||||
def do_remote_user(self, arg):
|
||||
"""Given a username, set the remote user plays are run by"""
|
||||
if arg:
|
||||
self.options.remote_user = arg
|
||||
self.set_prompt()
|
||||
else:
|
||||
display.display("Please specify a remote user, e.g. `remote_user root`")
|
||||
|
||||
def do_become_user(self, arg):
|
||||
"""Given a username, set the user that plays are run by when using become"""
|
||||
if arg:
|
||||
self.options.become_user = arg
|
||||
else:
|
||||
display.display("Please specify a user, e.g. `become_user jenkins`")
|
||||
display.v("Current user is %s" % self.options.become_user)
|
||||
self.set_prompt()
|
||||
|
||||
def do_become_method(self, arg):
|
||||
"""Given a become_method, set the privilege escalation method when using become"""
|
||||
if arg:
|
||||
self.options.become_method = arg
|
||||
display.v("become_method changed to %s" % self.options.become_method)
|
||||
else:
|
||||
display.display("Please specify a become_method, e.g. `become_method su`")
|
||||
|
||||
def do_check(self, arg):
|
||||
"""Toggle whether plays run with check mode"""
|
||||
if arg:
|
||||
self.options.check = boolean(arg, strict=False)
|
||||
display.v("check mode changed to %s" % self.options.check)
|
||||
else:
|
||||
display.display("Please specify check mode value, e.g. `check yes`")
|
||||
|
||||
def do_diff(self, arg):
|
||||
"""Toggle whether plays run with diff"""
|
||||
if arg:
|
||||
self.options.diff = boolean(arg, strict=False)
|
||||
display.v("diff mode changed to %s" % self.options.diff)
|
||||
else:
|
||||
display.display("Please specify a diff value , e.g. `diff yes`")
|
||||
|
||||
def do_exit(self, args):
|
||||
"""Exits from the console"""
|
||||
sys.stdout.write('\n')
|
||||
return -1
|
||||
|
||||
do_EOF = do_exit
|
||||
|
||||
def helpdefault(self, module_name):
|
||||
if module_name in self.modules:
|
||||
in_path = module_loader.find_plugin(module_name)
|
||||
if in_path:
|
||||
oc, a, _, _ = plugin_docs.get_docstring(in_path, fragment_loader)
|
||||
if oc:
|
||||
display.display(oc['short_description'])
|
||||
display.display('Parameters:')
|
||||
for opt in oc['options'].keys():
|
||||
display.display(' ' + stringc(opt, self.NORMAL_PROMPT) + ' ' + oc['options'][opt]['description'][0])
|
||||
else:
|
||||
display.error('No documentation found for %s.' % module_name)
|
||||
else:
|
||||
display.error('%s is not a valid command, use ? to list all valid commands.' % module_name)
|
||||
|
||||
def complete_cd(self, text, line, begidx, endidx):
|
||||
mline = line.partition(' ')[2]
|
||||
offs = len(mline) - len(text)
|
||||
|
||||
if self.options.cwd in ('all', '*', '\\'):
|
||||
completions = self.hosts + self.groups
|
||||
else:
|
||||
completions = [x.name for x in self.inventory.list_hosts(self.options.cwd)]
|
||||
|
||||
return [to_native(s)[offs:] for s in completions if to_native(s).startswith(to_native(mline))]
|
||||
|
||||
def completedefault(self, text, line, begidx, endidx):
|
||||
if line.split()[0] in self.modules:
|
||||
mline = line.split(' ')[-1]
|
||||
offs = len(mline) - len(text)
|
||||
completions = self.module_args(line.split()[0])
|
||||
|
||||
return [s[offs:] + '=' for s in completions if s.startswith(mline)]
|
||||
|
||||
def module_args(self, module_name):
|
||||
in_path = module_loader.find_plugin(module_name)
|
||||
oc, a, _, _ = plugin_docs.get_docstring(in_path, fragment_loader)
|
||||
return list(oc['options'].keys())
|
||||
|
||||
def run(self):
|
||||
|
||||
super(ConsoleCLI, self).run()
|
||||
|
||||
sshpass = None
|
||||
becomepass = None
|
||||
|
||||
# hosts
|
||||
if len(self.args) != 1:
|
||||
self.pattern = 'all'
|
||||
else:
|
||||
self.pattern = self.args[0]
|
||||
self.options.cwd = self.pattern
|
||||
|
||||
# dynamically add modules as commands
|
||||
self.modules = self.list_modules()
|
||||
for module in self.modules:
|
||||
setattr(self, 'do_' + module, lambda arg, module=module: self.default(module + ' ' + arg))
|
||||
setattr(self, 'help_' + module, lambda module=module: self.helpdefault(module))
|
||||
|
||||
self.normalize_become_options()
|
||||
(sshpass, becomepass) = self.ask_passwords()
|
||||
self.passwords = {'conn_pass': sshpass, 'become_pass': becomepass}
|
||||
|
||||
self.loader, self.inventory, self.variable_manager = self._play_prereqs(self.options)
|
||||
|
||||
hosts = CLI.get_host_list(self.inventory, self.options.subset, self.pattern)
|
||||
|
||||
self.groups = self.inventory.list_groups()
|
||||
self.hosts = [x.name for x in hosts]
|
||||
|
||||
# This hack is to work around readline issues on a mac:
|
||||
# http://stackoverflow.com/a/7116997/541202
|
||||
if 'libedit' in readline.__doc__:
|
||||
readline.parse_and_bind("bind ^I rl_complete")
|
||||
else:
|
||||
readline.parse_and_bind("tab: complete")
|
||||
|
||||
histfile = os.path.join(os.path.expanduser("~"), ".ansible-console_history")
|
||||
try:
|
||||
readline.read_history_file(histfile)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
atexit.register(readline.write_history_file, histfile)
|
||||
self.set_prompt()
|
||||
self.cmdloop()
|
653
env_27/lib/python2.7/site-packages/ansible/cli/doc.py
Normal file
653
env_27/lib/python2.7/site-packages/ansible/cli/doc.py
Normal file
@ -0,0 +1,653 @@
|
||||
# Copyright: (c) 2014, James Tanner <tanner.jc@gmail.com>
|
||||
# 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
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import textwrap
|
||||
import traceback
|
||||
import yaml
|
||||
|
||||
from collections import Sequence
|
||||
import ansible.plugins.loader as plugin_loader
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.cli import CLI
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.parsing.metadata import extract_metadata
|
||||
from ansible.parsing.plugin_docs import read_docstub
|
||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
||||
from ansible.plugins.loader import action_loader, fragment_loader
|
||||
from ansible.utils.plugin_docs import BLACKLIST, get_docstring
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class DocCLI(CLI):
|
||||
''' displays information on modules installed in Ansible libraries.
|
||||
It displays a terse listing of plugins and their short descriptions,
|
||||
provides a printout of their DOCUMENTATION strings,
|
||||
and it can create a short "snippet" which can be pasted into a playbook. '''
|
||||
|
||||
# default ignore list for detailed views
|
||||
IGNORE = ('module', 'docuri', 'version_added', 'short_description', 'now_date', 'plainexamples', 'returndocs')
|
||||
|
||||
def __init__(self, args):
|
||||
|
||||
super(DocCLI, self).__init__(args)
|
||||
self.plugin_list = set()
|
||||
|
||||
def parse(self):
|
||||
|
||||
self.parser = CLI.base_parser(
|
||||
usage='usage: %prog [-l|-F|-s] [options] [-t <plugin type> ] [plugin]',
|
||||
module_opts=True,
|
||||
desc="plugin documentation tool",
|
||||
epilog="See man pages for Ansible CLI options or website for tutorials https://docs.ansible.com"
|
||||
)
|
||||
|
||||
self.parser.add_option("-F", "--list_files", action="store_true", default=False, dest="list_files",
|
||||
help='Show plugin names and their source files without summaries (implies --list)')
|
||||
self.parser.add_option("-l", "--list", action="store_true", default=False, dest='list_dir',
|
||||
help='List available plugins')
|
||||
self.parser.add_option("-s", "--snippet", action="store_true", default=False, dest='show_snippet',
|
||||
help='Show playbook snippet for specified plugin(s)')
|
||||
self.parser.add_option("-a", "--all", action="store_true", default=False, dest='all_plugins',
|
||||
help='**For internal testing only** Show documentation for all plugins.')
|
||||
self.parser.add_option("-j", "--json", action="store_true", default=False, dest='json_dump',
|
||||
help='**For internal testing only** Dump json metadata for all plugins.')
|
||||
self.parser.add_option("-t", "--type", action="store", default='module', dest='type', type='choice',
|
||||
help='Choose which plugin type (defaults to "module")',
|
||||
choices=C.DOCUMENTABLE_PLUGINS)
|
||||
super(DocCLI, self).parse()
|
||||
|
||||
if [self.options.all_plugins, self.options.json_dump, self.options.list_dir, self.options.list_files, self.options.show_snippet].count(True) > 1:
|
||||
raise AnsibleOptionsError("Only one of -l, -F, -s, -j or -a can be used at the same time.")
|
||||
|
||||
display.verbosity = self.options.verbosity
|
||||
|
||||
def run(self):
|
||||
|
||||
super(DocCLI, self).run()
|
||||
|
||||
plugin_type = self.options.type
|
||||
|
||||
if plugin_type in C.DOCUMENTABLE_PLUGINS:
|
||||
loader = getattr(plugin_loader, '%s_loader' % plugin_type)
|
||||
else:
|
||||
raise AnsibleOptionsError("Unknown or undocumentable plugin type: %s" % plugin_type)
|
||||
|
||||
# add to plugin path from command line
|
||||
if self.options.module_path:
|
||||
for path in self.options.module_path:
|
||||
if path:
|
||||
loader.add_directory(path)
|
||||
|
||||
# save only top level paths for errors
|
||||
search_paths = DocCLI.print_paths(loader)
|
||||
loader._paths = None # reset so we can use subdirs below
|
||||
|
||||
# list plugins names and filepath for type
|
||||
if self.options.list_files:
|
||||
paths = loader._get_paths()
|
||||
for path in paths:
|
||||
self.plugin_list.update(self.find_plugins(path, plugin_type))
|
||||
|
||||
list_text = self.get_plugin_list_filenames(loader)
|
||||
self.pager(list_text)
|
||||
return 0
|
||||
|
||||
# list plugins for type
|
||||
if self.options.list_dir:
|
||||
paths = loader._get_paths()
|
||||
for path in paths:
|
||||
self.plugin_list.update(self.find_plugins(path, plugin_type))
|
||||
|
||||
self.pager(self.get_plugin_list_text(loader))
|
||||
return 0
|
||||
|
||||
# process all plugins of type
|
||||
if self.options.all_plugins:
|
||||
self.args = self.get_all_plugins_of_type(plugin_type)
|
||||
|
||||
# dump plugin metadata as JSON
|
||||
if self.options.json_dump:
|
||||
plugin_data = {}
|
||||
for plugin_type in C.DOCUMENTABLE_PLUGINS:
|
||||
plugin_data[plugin_type] = dict()
|
||||
plugin_names = self.get_all_plugins_of_type(plugin_type)
|
||||
for plugin_name in plugin_names:
|
||||
plugin_info = self.get_plugin_metadata(plugin_type, plugin_name)
|
||||
if plugin_info is not None:
|
||||
plugin_data[plugin_type][plugin_name] = plugin_info
|
||||
|
||||
self.pager(json.dumps(plugin_data, sort_keys=True, indent=4))
|
||||
|
||||
return 0
|
||||
|
||||
if len(self.args) == 0:
|
||||
raise AnsibleOptionsError("Incorrect options passed")
|
||||
|
||||
# process command line list
|
||||
text = ''
|
||||
for plugin in self.args:
|
||||
textret = self.format_plugin_doc(plugin, loader, plugin_type, search_paths)
|
||||
|
||||
if textret:
|
||||
text += textret
|
||||
|
||||
if text:
|
||||
self.pager(text)
|
||||
|
||||
return 0
|
||||
|
||||
def get_all_plugins_of_type(self, plugin_type):
|
||||
loader = getattr(plugin_loader, '%s_loader' % plugin_type)
|
||||
plugin_list = set()
|
||||
paths = loader._get_paths()
|
||||
for path in paths:
|
||||
plugins_to_add = self.find_plugins(path, plugin_type)
|
||||
plugin_list.update(plugins_to_add)
|
||||
return sorted(set(plugin_list))
|
||||
|
||||
def get_plugin_metadata(self, plugin_type, plugin_name):
|
||||
# if the plugin lives in a non-python file (eg, win_X.ps1), require the corresponding python file for docs
|
||||
loader = getattr(plugin_loader, '%s_loader' % plugin_type)
|
||||
filename = loader.find_plugin(plugin_name, mod_type='.py', ignore_deprecated=True, check_aliases=True)
|
||||
if filename is None:
|
||||
raise AnsibleError("unable to load {0} plugin named {1} ".format(plugin_type, plugin_name))
|
||||
|
||||
try:
|
||||
doc, __, __, metadata = get_docstring(filename, fragment_loader, verbose=(self.options.verbosity > 0))
|
||||
except Exception:
|
||||
display.vvv(traceback.format_exc())
|
||||
raise AnsibleError(
|
||||
"%s %s at %s has a documentation error formatting or is missing documentation." %
|
||||
(plugin_type, plugin_name, filename))
|
||||
|
||||
if doc is None:
|
||||
if 'removed' not in metadata.get('status', []):
|
||||
raise AnsibleError(
|
||||
"%s %s at %s has a documentation error formatting or is missing documentation." %
|
||||
(plugin_type, plugin_name, filename))
|
||||
|
||||
# Removed plugins don't have any documentation
|
||||
return None
|
||||
|
||||
return dict(
|
||||
name=plugin_name,
|
||||
namespace=self.namespace_from_plugin_filepath(filename, plugin_name, loader.package_path),
|
||||
description=doc.get('short_description', "UNKNOWN"),
|
||||
version_added=doc.get('version_added', "UNKNOWN")
|
||||
)
|
||||
|
||||
def namespace_from_plugin_filepath(self, filepath, plugin_name, basedir):
|
||||
if not basedir.endswith('/'):
|
||||
basedir += '/'
|
||||
rel_path = filepath.replace(basedir, '')
|
||||
extension_free = os.path.splitext(rel_path)[0]
|
||||
namespace_only = extension_free.rsplit(plugin_name, 1)[0].strip('/_')
|
||||
clean_ns = namespace_only.replace('/', '.')
|
||||
if clean_ns == '':
|
||||
clean_ns = None
|
||||
|
||||
return clean_ns
|
||||
|
||||
def format_plugin_doc(self, plugin, loader, plugin_type, search_paths):
|
||||
text = ''
|
||||
|
||||
try:
|
||||
# if the plugin lives in a non-python file (eg, win_X.ps1), require the corresponding python file for docs
|
||||
filename = loader.find_plugin(plugin, mod_type='.py', ignore_deprecated=True, check_aliases=True)
|
||||
if filename is None:
|
||||
display.warning("%s %s not found in:\n%s\n" % (plugin_type, plugin, search_paths))
|
||||
return
|
||||
|
||||
if any(filename.endswith(x) for x in C.BLACKLIST_EXTS):
|
||||
return
|
||||
|
||||
try:
|
||||
doc, plainexamples, returndocs, metadata = get_docstring(filename, fragment_loader,
|
||||
verbose=(self.options.verbosity > 0))
|
||||
except Exception:
|
||||
display.vvv(traceback.format_exc())
|
||||
display.error(
|
||||
"%s %s has a documentation error formatting or is missing documentation." % (plugin_type, plugin),
|
||||
wrap_text=False)
|
||||
return
|
||||
|
||||
if doc is not None:
|
||||
|
||||
# assign from other sections
|
||||
doc['plainexamples'] = plainexamples
|
||||
doc['returndocs'] = returndocs
|
||||
doc['metadata'] = metadata
|
||||
|
||||
# generate extra data
|
||||
if plugin_type == 'module':
|
||||
# is there corresponding action plugin?
|
||||
if plugin in action_loader:
|
||||
doc['action'] = True
|
||||
else:
|
||||
doc['action'] = False
|
||||
doc['filename'] = filename
|
||||
doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
|
||||
if 'docuri' in doc:
|
||||
doc['docuri'] = doc[plugin_type].replace('_', '-')
|
||||
|
||||
if self.options.show_snippet and plugin_type == 'module':
|
||||
text += self.get_snippet_text(doc)
|
||||
else:
|
||||
text += self.get_man_text(doc)
|
||||
|
||||
return text
|
||||
else:
|
||||
if 'removed' in metadata.get('status', []):
|
||||
display.warning("%s %s has been removed\n" % (plugin_type, plugin))
|
||||
return
|
||||
|
||||
# this typically means we couldn't even parse the docstring, not just that the YAML is busted,
|
||||
# probably a quoting issue.
|
||||
raise AnsibleError("Parsing produced an empty object.")
|
||||
except Exception as e:
|
||||
display.vvv(traceback.format_exc())
|
||||
raise AnsibleError(
|
||||
"%s %s missing documentation (or could not parse documentation): %s\n" % (plugin_type, plugin, str(e)))
|
||||
|
||||
def find_plugins(self, path, ptype):
|
||||
|
||||
display.vvvv("Searching %s for plugins" % path)
|
||||
|
||||
plugin_list = set()
|
||||
|
||||
if not os.path.exists(path):
|
||||
display.vvvv("%s does not exist" % path)
|
||||
return plugin_list
|
||||
|
||||
bkey = ptype.upper()
|
||||
for plugin in os.listdir(path):
|
||||
display.vvvv("Found %s" % plugin)
|
||||
full_path = '/'.join([path, plugin])
|
||||
|
||||
if plugin.startswith('.'):
|
||||
continue
|
||||
elif os.path.isdir(full_path):
|
||||
continue
|
||||
elif any(plugin.endswith(x) for x in C.BLACKLIST_EXTS):
|
||||
continue
|
||||
elif plugin.startswith('__'):
|
||||
continue
|
||||
elif plugin in C.IGNORE_FILES:
|
||||
continue
|
||||
elif plugin .startswith('_'):
|
||||
if os.path.islink(full_path): # avoids aliases
|
||||
continue
|
||||
|
||||
plugin = os.path.splitext(plugin)[0] # removes the extension
|
||||
plugin = plugin.lstrip('_') # remove underscore from deprecated plugins
|
||||
|
||||
if plugin not in BLACKLIST.get(bkey, ()):
|
||||
plugin_list.add(plugin)
|
||||
display.vvvv("Added %s" % plugin)
|
||||
|
||||
return plugin_list
|
||||
|
||||
def get_plugin_list_text(self, loader):
|
||||
columns = display.columns
|
||||
displace = max(len(x) for x in self.plugin_list)
|
||||
linelimit = columns - displace - 5
|
||||
text = []
|
||||
deprecated = []
|
||||
for plugin in sorted(self.plugin_list):
|
||||
|
||||
try:
|
||||
# if the module lives in a non-python file (eg, win_X.ps1), require the corresponding python file for docs
|
||||
filename = loader.find_plugin(plugin, mod_type='.py', ignore_deprecated=True, check_aliases=True)
|
||||
|
||||
if filename is None:
|
||||
continue
|
||||
if filename.endswith(".ps1"):
|
||||
continue
|
||||
if os.path.isdir(filename):
|
||||
continue
|
||||
|
||||
doc = None
|
||||
try:
|
||||
doc = read_docstub(filename)
|
||||
except Exception:
|
||||
display.warning("%s has a documentation formatting error" % plugin)
|
||||
continue
|
||||
|
||||
if not doc or not isinstance(doc, dict):
|
||||
with open(filename) as f:
|
||||
metadata = extract_metadata(module_data=f.read())
|
||||
if metadata[0]:
|
||||
if 'removed' not in metadata[0].get('status', []):
|
||||
display.warning("%s parsing did not produce documentation." % plugin)
|
||||
else:
|
||||
continue
|
||||
desc = 'UNDOCUMENTED'
|
||||
else:
|
||||
desc = self.tty_ify(doc.get('short_description', 'INVALID SHORT DESCRIPTION').strip())
|
||||
|
||||
if len(desc) > linelimit:
|
||||
desc = desc[:linelimit] + '...'
|
||||
|
||||
if plugin.startswith('_'): # Handle deprecated
|
||||
deprecated.append("%-*s %-*.*s" % (displace, plugin[1:], linelimit, len(desc), desc))
|
||||
else:
|
||||
text.append("%-*s %-*.*s" % (displace, plugin, linelimit, len(desc), desc))
|
||||
except Exception as e:
|
||||
raise AnsibleError("Failed reading docs at %s: %s" % (plugin, to_native(e)), orig_exc=e)
|
||||
|
||||
if len(deprecated) > 0:
|
||||
text.append("\nDEPRECATED:")
|
||||
text.extend(deprecated)
|
||||
return "\n".join(text)
|
||||
|
||||
def get_plugin_list_filenames(self, loader):
|
||||
columns = display.columns
|
||||
displace = max(len(x) for x in self.plugin_list)
|
||||
linelimit = columns - displace - 5
|
||||
text = []
|
||||
|
||||
for plugin in sorted(self.plugin_list):
|
||||
|
||||
try:
|
||||
# if the module lives in a non-python file (eg, win_X.ps1), require the corresponding python file for docs
|
||||
filename = loader.find_plugin(plugin, mod_type='.py', ignore_deprecated=True, check_aliases=True)
|
||||
|
||||
if filename is None:
|
||||
continue
|
||||
if filename.endswith(".ps1"):
|
||||
continue
|
||||
if os.path.isdir(filename):
|
||||
continue
|
||||
|
||||
text.append("%-*s %-*.*s" % (displace, plugin, linelimit, len(filename), filename))
|
||||
|
||||
except Exception as e:
|
||||
raise AnsibleError("Failed reading docs at %s: %s" % (plugin, to_native(e)), orig_exc=e)
|
||||
|
||||
return "\n".join(text)
|
||||
|
||||
@staticmethod
|
||||
def print_paths(finder):
|
||||
''' Returns a string suitable for printing of the search path '''
|
||||
|
||||
# Uses a list to get the order right
|
||||
ret = []
|
||||
for i in finder._get_paths(subdirs=False):
|
||||
if i not in ret:
|
||||
ret.append(i)
|
||||
return os.pathsep.join(ret)
|
||||
|
||||
def get_snippet_text(self, doc):
|
||||
|
||||
text = []
|
||||
desc = CLI.tty_ify(doc['short_description'])
|
||||
text.append("- name: %s" % (desc))
|
||||
text.append(" %s:" % (doc['module']))
|
||||
pad = 31
|
||||
subdent = " " * pad
|
||||
limit = display.columns - pad
|
||||
|
||||
for o in sorted(doc['options'].keys()):
|
||||
opt = doc['options'][o]
|
||||
if isinstance(opt['description'], string_types):
|
||||
desc = CLI.tty_ify(opt['description'])
|
||||
else:
|
||||
desc = CLI.tty_ify(" ".join(opt['description']))
|
||||
|
||||
required = opt.get('required', False)
|
||||
if not isinstance(required, bool):
|
||||
raise("Incorrect value for 'Required', a boolean is needed.: %s" % required)
|
||||
if required:
|
||||
desc = "(required) %s" % desc
|
||||
o = '%s:' % o
|
||||
text.append(" %-20s # %s" % (o, textwrap.fill(desc, limit, subsequent_indent=subdent)))
|
||||
text.append('')
|
||||
|
||||
return "\n".join(text)
|
||||
|
||||
def _dump_yaml(self, struct, indent):
|
||||
return CLI.tty_ify('\n'.join([indent + line for line in yaml.dump(struct, default_flow_style=False, Dumper=AnsibleDumper).split('\n')]))
|
||||
|
||||
def add_fields(self, text, fields, limit, opt_indent):
|
||||
|
||||
for o in sorted(fields):
|
||||
opt = fields[o]
|
||||
|
||||
required = opt.pop('required', False)
|
||||
if not isinstance(required, bool):
|
||||
raise AnsibleError("Incorrect value for 'Required', a boolean is needed.: %s" % required)
|
||||
if required:
|
||||
opt_leadin = "="
|
||||
else:
|
||||
opt_leadin = "-"
|
||||
|
||||
text.append("%s %s" % (opt_leadin, o))
|
||||
|
||||
if isinstance(opt['description'], list):
|
||||
for entry in opt['description']:
|
||||
text.append(textwrap.fill(CLI.tty_ify(entry), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
|
||||
else:
|
||||
text.append(textwrap.fill(CLI.tty_ify(opt['description']), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
|
||||
del opt['description']
|
||||
|
||||
aliases = ''
|
||||
if 'aliases' in opt:
|
||||
if len(opt['aliases']) > 0:
|
||||
aliases = "(Aliases: " + ", ".join(str(i) for i in opt['aliases']) + ")"
|
||||
del opt['aliases']
|
||||
choices = ''
|
||||
if 'choices' in opt:
|
||||
if len(opt['choices']) > 0:
|
||||
choices = "(Choices: " + ", ".join(str(i) for i in opt['choices']) + ")"
|
||||
del opt['choices']
|
||||
default = ''
|
||||
if 'default' in opt or not required:
|
||||
default = "[Default: %s" % str(opt.pop('default', '(null)')) + "]"
|
||||
|
||||
text.append(textwrap.fill(CLI.tty_ify(aliases + choices + default), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
|
||||
|
||||
if 'options' in opt:
|
||||
text.append("%soptions:\n" % opt_indent)
|
||||
self.add_fields(text, opt.pop('options'), limit, opt_indent + opt_indent)
|
||||
|
||||
if 'spec' in opt:
|
||||
text.append("%sspec:\n" % opt_indent)
|
||||
self.add_fields(text, opt.pop('spec'), limit, opt_indent + opt_indent)
|
||||
|
||||
conf = {}
|
||||
for config in ('env', 'ini', 'yaml', 'vars', 'keywords'):
|
||||
if config in opt and opt[config]:
|
||||
conf[config] = opt.pop(config)
|
||||
for ignore in self.IGNORE:
|
||||
for item in conf[config]:
|
||||
if ignore in item:
|
||||
del item[ignore]
|
||||
|
||||
if conf:
|
||||
text.append(self._dump_yaml({'set_via': conf}, opt_indent))
|
||||
|
||||
for k in sorted(opt):
|
||||
if k.startswith('_'):
|
||||
continue
|
||||
if isinstance(opt[k], string_types):
|
||||
text.append('%s%s: %s' % (opt_indent, k, textwrap.fill(CLI.tty_ify(opt[k]), limit - (len(k) + 2), subsequent_indent=opt_indent)))
|
||||
elif isinstance(opt[k], (Sequence)) and all(isinstance(x, string_types) for x in opt[k]):
|
||||
text.append(CLI.tty_ify('%s%s: %s' % (opt_indent, k, ', '.join(opt[k]))))
|
||||
else:
|
||||
text.append(self._dump_yaml({k: opt[k]}, opt_indent))
|
||||
text.append('')
|
||||
|
||||
@staticmethod
|
||||
def get_support_block(doc):
|
||||
# Note: 'curated' is deprecated and not used in any of the modules we ship
|
||||
support_level_msg = {'core': 'The Ansible Core Team',
|
||||
'network': 'The Ansible Network Team',
|
||||
'certified': 'an Ansible Partner',
|
||||
'community': 'The Ansible Community',
|
||||
'curated': 'A Third Party',
|
||||
}
|
||||
if doc['metadata'].get('metadata_version') in ('1.0', '1.1'):
|
||||
return [" * This module is maintained by %s" % support_level_msg[doc['metadata']['supported_by']]]
|
||||
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_metadata_block(doc):
|
||||
text = []
|
||||
if doc['metadata'].get('metadata_version') in ('1.0', '1.1'):
|
||||
text.append("METADATA:")
|
||||
text.append('\tSUPPORT LEVEL: %s' % doc['metadata']['supported_by'])
|
||||
|
||||
for k in (m for m in doc['metadata'] if m not in ('version', 'metadata_version', 'supported_by')):
|
||||
if isinstance(k, list):
|
||||
text.append("\t%s: %s" % (k.capitalize(), ", ".join(doc['metadata'][k])))
|
||||
else:
|
||||
text.append("\t%s: %s" % (k.capitalize(), doc['metadata'][k]))
|
||||
return text
|
||||
|
||||
return []
|
||||
|
||||
def get_man_text(self, doc):
|
||||
|
||||
self.IGNORE = self.IGNORE + (self.options.type,)
|
||||
opt_indent = " "
|
||||
text = []
|
||||
pad = display.columns * 0.20
|
||||
limit = max(display.columns - int(pad), 70)
|
||||
|
||||
text.append("> %s (%s)\n" % (doc.get(self.options.type, doc.get('plugin_type')).upper(), doc.pop('filename')))
|
||||
|
||||
if isinstance(doc['description'], list):
|
||||
desc = " ".join(doc.pop('description'))
|
||||
else:
|
||||
desc = doc.pop('description')
|
||||
|
||||
text.append("%s\n" % textwrap.fill(CLI.tty_ify(desc), limit, initial_indent=opt_indent, subsequent_indent=opt_indent))
|
||||
|
||||
if 'deprecated' in doc and doc['deprecated'] is not None and len(doc['deprecated']) > 0:
|
||||
text.append("DEPRECATED: \n")
|
||||
if isinstance(doc['deprecated'], dict):
|
||||
if 'version' in doc['deprecated'] and 'removed_in' not in doc['deprecated']:
|
||||
doc['deprecated']['removed_in'] = doc['deprecated']['version']
|
||||
text.append("\tReason: %(why)s\n\tWill be removed in: Ansible %(removed_in)s\n\tAlternatives: %(alternative)s" % doc.pop('deprecated'))
|
||||
else:
|
||||
text.append("%s" % doc.pop('deprecated'))
|
||||
text.append("\n")
|
||||
|
||||
try:
|
||||
support_block = self.get_support_block(doc)
|
||||
if support_block:
|
||||
text.extend(support_block)
|
||||
except Exception:
|
||||
pass # FIXME: not suported by plugins
|
||||
|
||||
if doc.pop('action', False):
|
||||
text.append(" * note: %s\n" % "This module has a corresponding action plugin.")
|
||||
|
||||
if 'options' in doc and doc['options']:
|
||||
text.append("OPTIONS (= is mandatory):\n")
|
||||
self.add_fields(text, doc.pop('options'), limit, opt_indent)
|
||||
text.append('')
|
||||
|
||||
if 'notes' in doc and doc['notes'] and len(doc['notes']) > 0:
|
||||
text.append("NOTES:")
|
||||
for note in doc['notes']:
|
||||
text.append(textwrap.fill(CLI.tty_ify(note), limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent))
|
||||
text.append('')
|
||||
text.append('')
|
||||
del doc['notes']
|
||||
|
||||
if 'seealso' in doc and doc['seealso']:
|
||||
text.append("SEE ALSO:")
|
||||
for item in doc['seealso']:
|
||||
if 'module' in item and 'description' in item:
|
||||
text.append(textwrap.fill(CLI.tty_ify('Module %s' % item['module']),
|
||||
limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent))
|
||||
text.append(textwrap.fill(CLI.tty_ify(item['description']),
|
||||
limit - 6, initial_indent=opt_indent, subsequent_indent=opt_indent))
|
||||
text.append(textwrap.fill(CLI.tty_ify('https://docs.ansible.com/ansible/latest/modules/%s_module.html' % item['module']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent))
|
||||
elif 'module' in item:
|
||||
text.append(textwrap.fill(CLI.tty_ify('Module %s' % item['module']),
|
||||
limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent))
|
||||
text.append(textwrap.fill(CLI.tty_ify('The official documentation on the %s module.' % item['module']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' '))
|
||||
text.append(textwrap.fill(CLI.tty_ify('https://docs.ansible.com/ansible/latest/modules/%s_module.html' % item['module']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent))
|
||||
elif 'name' in item and 'link' in item and 'description' in item:
|
||||
text.append(textwrap.fill(CLI.tty_ify(item['name']),
|
||||
limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent))
|
||||
text.append(textwrap.fill(CLI.tty_ify(item['description']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' '))
|
||||
text.append(textwrap.fill(CLI.tty_ify(item['link']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' '))
|
||||
elif 'ref' in item and 'description' in item:
|
||||
text.append(textwrap.fill(CLI.tty_ify('Ansible documentation [%s]' % item['ref']),
|
||||
limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent))
|
||||
text.append(textwrap.fill(CLI.tty_ify(item['description']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' '))
|
||||
text.append(textwrap.fill(CLI.tty_ify('https://docs.ansible.com/ansible/latest/#stq=%s&stp=1' % item['ref']),
|
||||
limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' '))
|
||||
|
||||
text.append('')
|
||||
text.append('')
|
||||
del doc['seealso']
|
||||
|
||||
if 'requirements' in doc and doc['requirements'] is not None and len(doc['requirements']) > 0:
|
||||
req = ", ".join(doc.pop('requirements'))
|
||||
text.append("REQUIREMENTS:%s\n" % textwrap.fill(CLI.tty_ify(req), limit - 16, initial_indent=" ", subsequent_indent=opt_indent))
|
||||
|
||||
# Generic handler
|
||||
for k in sorted(doc):
|
||||
if k in self.IGNORE or not doc[k]:
|
||||
continue
|
||||
if isinstance(doc[k], string_types):
|
||||
text.append('%s: %s' % (k.upper(), textwrap.fill(CLI.tty_ify(doc[k]), limit - (len(k) + 2), subsequent_indent=opt_indent)))
|
||||
elif isinstance(doc[k], (list, tuple)):
|
||||
text.append('%s: %s' % (k.upper(), ', '.join(doc[k])))
|
||||
else:
|
||||
text.append(self._dump_yaml({k.upper(): doc[k]}, opt_indent))
|
||||
del doc[k]
|
||||
text.append('')
|
||||
|
||||
if 'plainexamples' in doc and doc['plainexamples'] is not None:
|
||||
text.append("EXAMPLES:")
|
||||
text.append('')
|
||||
if isinstance(doc['plainexamples'], string_types):
|
||||
text.append(doc.pop('plainexamples').strip())
|
||||
else:
|
||||
text.append(yaml.dump(doc.pop('plainexamples'), indent=2, default_flow_style=False))
|
||||
text.append('')
|
||||
text.append('')
|
||||
|
||||
if 'returndocs' in doc and doc['returndocs'] is not None:
|
||||
text.append("RETURN VALUES:")
|
||||
if isinstance(doc['returndocs'], string_types):
|
||||
text.append(doc.pop('returndocs'))
|
||||
else:
|
||||
text.append(yaml.dump(doc.pop('returndocs'), indent=2, default_flow_style=False))
|
||||
text.append('')
|
||||
|
||||
try:
|
||||
metadata_block = self.get_metadata_block(doc)
|
||||
if metadata_block:
|
||||
text.extend(metadata_block)
|
||||
text.append('')
|
||||
except Exception:
|
||||
pass # metadata is optional
|
||||
|
||||
return "\n".join(text)
|
691
env_27/lib/python2.7/site-packages/ansible/cli/galaxy.py
Normal file
691
env_27/lib/python2.7/site-packages/ansible/cli/galaxy.py
Normal file
@ -0,0 +1,691 @@
|
||||
########################################################################
|
||||
#
|
||||
# (C) 2013, James Cammarata <jcammarata@ansible.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
|
||||
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import yaml
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
import ansible.constants as C
|
||||
from ansible.cli import CLI
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.galaxy import Galaxy
|
||||
from ansible.galaxy.api import GalaxyAPI
|
||||
from ansible.galaxy.login import GalaxyLogin
|
||||
from ansible.galaxy.role import GalaxyRole
|
||||
from ansible.galaxy.token import GalaxyToken
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.playbook.role.requirement import RoleRequirement
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
class GalaxyCLI(CLI):
|
||||
'''command to manage Ansible roles in shared repositories, the default of which is Ansible Galaxy *https://galaxy.ansible.com*.'''
|
||||
|
||||
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url")
|
||||
VALID_ACTIONS = ("delete", "import", "info", "init", "install", "list", "login", "remove", "search", "setup")
|
||||
|
||||
def __init__(self, args):
|
||||
self.api = None
|
||||
self.galaxy = None
|
||||
super(GalaxyCLI, self).__init__(args)
|
||||
|
||||
def set_action(self):
|
||||
|
||||
super(GalaxyCLI, self).set_action()
|
||||
|
||||
# specific to actions
|
||||
if self.action == "delete":
|
||||
self.parser.set_usage("usage: %prog delete [options] github_user github_repo")
|
||||
self.parser.set_description("Removes the role from Galaxy. It does not remove or alter the actual GitHub repository.")
|
||||
elif self.action == "import":
|
||||
self.parser.set_usage("usage: %prog import [options] github_user github_repo")
|
||||
self.parser.set_description("Import a role.")
|
||||
self.parser.add_option('--no-wait', dest='wait', action='store_false', default=True, help='Don\'t wait for import results.')
|
||||
self.parser.add_option('--branch', dest='reference',
|
||||
help='The name of a branch to import. Defaults to the repository\'s default branch (usually master)')
|
||||
self.parser.add_option('--role-name', dest='role_name', help='The name the role should have, if different than the repo name')
|
||||
self.parser.add_option('--status', dest='check_status', action='store_true', default=False,
|
||||
help='Check the status of the most recent import request for given github_user/github_repo.')
|
||||
elif self.action == "info":
|
||||
self.parser.set_usage("usage: %prog info [options] role_name[,version]")
|
||||
self.parser.set_description("View more details about a specific role.")
|
||||
elif self.action == "init":
|
||||
self.parser.set_usage("usage: %prog init [options] role_name")
|
||||
self.parser.set_description("Initialize new role with the base structure of a role.")
|
||||
self.parser.add_option('--init-path', dest='init_path', default="./",
|
||||
help='The path in which the skeleton role will be created. The default is the current working directory.')
|
||||
self.parser.add_option('--type', dest='role_type', action='store', default='default',
|
||||
help="Initialize using an alternate role type. Valid types include: 'container', 'apb' and 'network'.")
|
||||
self.parser.add_option('--role-skeleton', dest='role_skeleton', default=C.GALAXY_ROLE_SKELETON,
|
||||
help='The path to a role skeleton that the new role should be based upon.')
|
||||
elif self.action == "install":
|
||||
self.parser.set_usage("usage: %prog install [options] [-r FILE | role_name(s)[,version] | scm+role_repo_url[,version] | tar_file(s)]")
|
||||
self.parser.set_description("Install Roles from file(s), URL(s) or tar file(s)")
|
||||
self.parser.add_option('-i', '--ignore-errors', dest='ignore_errors', action='store_true', default=False,
|
||||
help='Ignore errors and continue with the next specified role.')
|
||||
self.parser.add_option('-n', '--no-deps', dest='no_deps', action='store_true', default=False, help='Don\'t download roles listed as dependencies')
|
||||
self.parser.add_option('-r', '--role-file', dest='role_file', help='A file containing a list of roles to be imported')
|
||||
self.parser.add_option('-g', '--keep-scm-meta', dest='keep_scm_meta', action='store_true',
|
||||
default=False, help='Use tar instead of the scm archive option when packaging the role')
|
||||
elif self.action == "remove":
|
||||
self.parser.set_usage("usage: %prog remove role1 role2 ...")
|
||||
self.parser.set_description("Delete a role from roles_path.")
|
||||
elif self.action == "list":
|
||||
self.parser.set_usage("usage: %prog list [role_name]")
|
||||
self.parser.set_description("Show the name and version of each role installed in the roles_path.")
|
||||
elif self.action == "login":
|
||||
self.parser.set_usage("usage: %prog login [options]")
|
||||
self.parser.set_description("Login to api.github.com server in order to use ansible-galaxy sub command such as 'import', 'delete' and 'setup'.")
|
||||
self.parser.add_option('--github-token', dest='token', default=None, help='Identify with github token rather than username and password.')
|
||||
elif self.action == "search":
|
||||
self.parser.set_usage("usage: %prog search [searchterm1 searchterm2] [--galaxy-tags galaxy_tag1,galaxy_tag2] [--platforms platform1,platform2] "
|
||||
"[--author username]")
|
||||
self.parser.add_option('--platforms', dest='platforms', help='list of OS platforms to filter by')
|
||||
self.parser.add_option('--galaxy-tags', dest='galaxy_tags', help='list of galaxy tags to filter by')
|
||||
self.parser.add_option('--author', dest='author', help='GitHub username')
|
||||
self.parser.set_description("Search the Galaxy database by tags, platforms, author and multiple keywords.")
|
||||
elif self.action == "setup":
|
||||
self.parser.set_usage("usage: %prog setup [options] source github_user github_repo secret")
|
||||
self.parser.add_option('--remove', dest='remove_id', default=None,
|
||||
help='Remove the integration matching the provided ID value. Use --list to see ID values.')
|
||||
self.parser.add_option('--list', dest="setup_list", action='store_true', default=False, help='List all of your integrations.')
|
||||
self.parser.set_description("Manage the integration between Galaxy and the given source.")
|
||||
# options that apply to more than one action
|
||||
if self.action in ['init', 'info']:
|
||||
self.parser.add_option('--offline', dest='offline', default=False, action='store_true', help="Don't query the galaxy API when creating roles")
|
||||
|
||||
if self.action not in ("delete", "import", "init", "login", "setup"):
|
||||
# NOTE: while the option type=str, the default is a list, and the
|
||||
# callback will set the value to a list.
|
||||
self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.unfrack_paths, default=C.DEFAULT_ROLES_PATH,
|
||||
help='The path to the directory containing your roles. The default is the roles_path configured in your ansible.cfg'
|
||||
' file (/etc/ansible/roles if not configured)', type='str')
|
||||
if self.action in ("init", "install"):
|
||||
self.parser.add_option('-f', '--force', dest='force', action='store_true', default=False, help='Force overwriting an existing role')
|
||||
|
||||
def parse(self):
|
||||
''' create an options parser for bin/ansible '''
|
||||
|
||||
self.parser = CLI.base_parser(
|
||||
usage="usage: %%prog [%s] [--help] [options] ..." % "|".join(self.VALID_ACTIONS),
|
||||
epilog="\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]),
|
||||
desc="Perform various Role related operations.",
|
||||
)
|
||||
|
||||
# common
|
||||
self.parser.add_option('-s', '--server', dest='api_server', default=C.GALAXY_SERVER, help='The API server destination')
|
||||
self.parser.add_option('-c', '--ignore-certs', action='store_true', dest='ignore_certs', default=C.GALAXY_IGNORE_CERTS,
|
||||
help='Ignore SSL certificate validation errors.')
|
||||
self.set_action()
|
||||
|
||||
super(GalaxyCLI, self).parse()
|
||||
|
||||
display.verbosity = self.options.verbosity
|
||||
self.galaxy = Galaxy(self.options)
|
||||
|
||||
def run(self):
|
||||
|
||||
super(GalaxyCLI, self).run()
|
||||
|
||||
self.api = GalaxyAPI(self.galaxy)
|
||||
self.execute()
|
||||
|
||||
def exit_without_ignore(self, rc=1):
|
||||
"""
|
||||
Exits with the specified return code unless the
|
||||
option --ignore-errors was specified
|
||||
"""
|
||||
if not self.options.ignore_errors:
|
||||
raise AnsibleError('- you can use --ignore-errors to skip failed roles and finish processing the list.')
|
||||
|
||||
def _display_role_info(self, role_info):
|
||||
|
||||
text = [u"", u"Role: %s" % to_text(role_info['name'])]
|
||||
text.append(u"\tdescription: %s" % role_info.get('description', ''))
|
||||
|
||||
for k in sorted(role_info.keys()):
|
||||
|
||||
if k in self.SKIP_INFO_KEYS:
|
||||
continue
|
||||
|
||||
if isinstance(role_info[k], dict):
|
||||
text.append(u"\t%s:" % (k))
|
||||
for key in sorted(role_info[k].keys()):
|
||||
if key in self.SKIP_INFO_KEYS:
|
||||
continue
|
||||
text.append(u"\t\t%s: %s" % (key, role_info[k][key]))
|
||||
else:
|
||||
text.append(u"\t%s: %s" % (k, role_info[k]))
|
||||
|
||||
return u'\n'.join(text)
|
||||
|
||||
############################
|
||||
# execute actions
|
||||
############################
|
||||
|
||||
def execute_init(self):
|
||||
"""
|
||||
creates the skeleton framework of a role that complies with the galaxy metadata format.
|
||||
"""
|
||||
|
||||
init_path = self.options.init_path
|
||||
force = self.options.force
|
||||
role_skeleton = self.options.role_skeleton
|
||||
|
||||
role_name = self.args.pop(0).strip() if self.args else None
|
||||
if not role_name:
|
||||
raise AnsibleOptionsError("- no role name specified for init")
|
||||
role_path = os.path.join(init_path, role_name)
|
||||
if os.path.exists(role_path):
|
||||
if os.path.isfile(role_path):
|
||||
raise AnsibleError("- the path %s already exists, but is a file - aborting" % role_path)
|
||||
elif not force:
|
||||
raise AnsibleError("- the directory %s already exists."
|
||||
"you can use --force to re-initialize this directory,\n"
|
||||
"however it will reset any main.yml files that may have\n"
|
||||
"been modified there already." % role_path)
|
||||
|
||||
inject_data = dict(
|
||||
role_name=role_name,
|
||||
author='your name',
|
||||
description='your description',
|
||||
company='your company (optional)',
|
||||
license='license (GPLv2, CC-BY, etc)',
|
||||
issue_tracker_url='http://example.com/issue/tracker',
|
||||
min_ansible_version='2.4',
|
||||
role_type=self.options.role_type
|
||||
)
|
||||
|
||||
# create role directory
|
||||
if not os.path.exists(role_path):
|
||||
os.makedirs(role_path)
|
||||
|
||||
if role_skeleton is not None:
|
||||
skeleton_ignore_expressions = C.GALAXY_ROLE_SKELETON_IGNORE
|
||||
else:
|
||||
role_skeleton = self.galaxy.default_role_skeleton_path
|
||||
skeleton_ignore_expressions = ['^.*/.git_keep$']
|
||||
|
||||
role_skeleton = os.path.expanduser(role_skeleton)
|
||||
skeleton_ignore_re = [re.compile(x) for x in skeleton_ignore_expressions]
|
||||
|
||||
template_env = Environment(loader=FileSystemLoader(role_skeleton))
|
||||
|
||||
for root, dirs, files in os.walk(role_skeleton, topdown=True):
|
||||
rel_root = os.path.relpath(root, role_skeleton)
|
||||
in_templates_dir = rel_root.split(os.sep, 1)[0] == 'templates'
|
||||
dirs[:] = [d for d in dirs if not any(r.match(d) for r in skeleton_ignore_re)]
|
||||
|
||||
for f in files:
|
||||
filename, ext = os.path.splitext(f)
|
||||
if any(r.match(os.path.join(rel_root, f)) for r in skeleton_ignore_re):
|
||||
continue
|
||||
elif ext == ".j2" and not in_templates_dir:
|
||||
src_template = os.path.join(rel_root, f)
|
||||
dest_file = os.path.join(role_path, rel_root, filename)
|
||||
template_env.get_template(src_template).stream(inject_data).dump(dest_file)
|
||||
else:
|
||||
f_rel_path = os.path.relpath(os.path.join(root, f), role_skeleton)
|
||||
shutil.copyfile(os.path.join(root, f), os.path.join(role_path, f_rel_path))
|
||||
|
||||
for d in dirs:
|
||||
dir_path = os.path.join(role_path, rel_root, d)
|
||||
if not os.path.exists(dir_path):
|
||||
os.makedirs(dir_path)
|
||||
|
||||
display.display("- %s was created successfully" % role_name)
|
||||
|
||||
def execute_info(self):
|
||||
"""
|
||||
prints out detailed information about an installed role as well as info available from the galaxy API.
|
||||
"""
|
||||
|
||||
if len(self.args) == 0:
|
||||
# the user needs to specify a role
|
||||
raise AnsibleOptionsError("- you must specify a user/role name")
|
||||
|
||||
roles_path = self.options.roles_path
|
||||
|
||||
data = ''
|
||||
for role in self.args:
|
||||
|
||||
role_info = {'path': roles_path}
|
||||
gr = GalaxyRole(self.galaxy, role)
|
||||
|
||||
install_info = gr.install_info
|
||||
if install_info:
|
||||
if 'version' in install_info:
|
||||
install_info['installed_version'] = install_info['version']
|
||||
del install_info['version']
|
||||
role_info.update(install_info)
|
||||
|
||||
remote_data = False
|
||||
if not self.options.offline:
|
||||
remote_data = self.api.lookup_role_by_name(role, False)
|
||||
|
||||
if remote_data:
|
||||
role_info.update(remote_data)
|
||||
|
||||
if gr.metadata:
|
||||
role_info.update(gr.metadata)
|
||||
|
||||
req = RoleRequirement()
|
||||
role_spec = req.role_yaml_parse({'role': role})
|
||||
if role_spec:
|
||||
role_info.update(role_spec)
|
||||
|
||||
data = self._display_role_info(role_info)
|
||||
# FIXME: This is broken in both 1.9 and 2.0 as
|
||||
# _display_role_info() always returns something
|
||||
if not data:
|
||||
data = u"\n- the role %s was not found" % role
|
||||
|
||||
self.pager(data)
|
||||
|
||||
def execute_install(self):
|
||||
"""
|
||||
uses the args list of roles to be installed, unless -f was specified. The list of roles
|
||||
can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file.
|
||||
"""
|
||||
role_file = self.options.role_file
|
||||
|
||||
if len(self.args) == 0 and role_file is None:
|
||||
# the user needs to specify one of either --role-file or specify a single user/role name
|
||||
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
||||
|
||||
no_deps = self.options.no_deps
|
||||
force = self.options.force
|
||||
|
||||
roles_left = []
|
||||
if role_file:
|
||||
try:
|
||||
f = open(role_file, 'r')
|
||||
if role_file.endswith('.yaml') or role_file.endswith('.yml'):
|
||||
try:
|
||||
required_roles = yaml.safe_load(f.read())
|
||||
except Exception as e:
|
||||
raise AnsibleError("Unable to load data from the requirements file: %s" % role_file)
|
||||
|
||||
if required_roles is None:
|
||||
raise AnsibleError("No roles found in file: %s" % role_file)
|
||||
|
||||
for role in required_roles:
|
||||
if "include" not in role:
|
||||
role = RoleRequirement.role_yaml_parse(role)
|
||||
display.vvv("found role %s in yaml file" % str(role))
|
||||
if "name" not in role and "scm" not in role:
|
||||
raise AnsibleError("Must specify name or src for role")
|
||||
roles_left.append(GalaxyRole(self.galaxy, **role))
|
||||
else:
|
||||
with open(role["include"]) as f_include:
|
||||
try:
|
||||
roles_left += [
|
||||
GalaxyRole(self.galaxy, **r) for r in
|
||||
(RoleRequirement.role_yaml_parse(i) for i in yaml.safe_load(f_include))
|
||||
]
|
||||
except Exception as e:
|
||||
msg = "Unable to load data from the include requirements file: %s %s"
|
||||
raise AnsibleError(msg % (role_file, e))
|
||||
else:
|
||||
raise AnsibleError("Invalid role requirements file")
|
||||
f.close()
|
||||
except (IOError, OSError) as e:
|
||||
raise AnsibleError('Unable to open %s: %s' % (role_file, str(e)))
|
||||
else:
|
||||
# roles were specified directly, so we'll just go out grab them
|
||||
# (and their dependencies, unless the user doesn't want us to).
|
||||
for rname in self.args:
|
||||
role = RoleRequirement.role_yaml_parse(rname.strip())
|
||||
roles_left.append(GalaxyRole(self.galaxy, **role))
|
||||
|
||||
for role in roles_left:
|
||||
# only process roles in roles files when names matches if given
|
||||
if role_file and self.args and role.name not in self.args:
|
||||
display.vvv('Skipping role %s' % role.name)
|
||||
continue
|
||||
|
||||
display.vvv('Processing role %s ' % role.name)
|
||||
|
||||
# query the galaxy API for the role data
|
||||
|
||||
if role.install_info is not None:
|
||||
if role.install_info['version'] != role.version or force:
|
||||
if force:
|
||||
display.display('- changing role %s from %s to %s' %
|
||||
(role.name, role.install_info['version'], role.version or "unspecified"))
|
||||
role.remove()
|
||||
else:
|
||||
display.warning('- %s (%s) is already installed - use --force to change version to %s' %
|
||||
(role.name, role.install_info['version'], role.version or "unspecified"))
|
||||
continue
|
||||
else:
|
||||
if not force:
|
||||
display.display('- %s is already installed, skipping.' % str(role))
|
||||
continue
|
||||
|
||||
try:
|
||||
installed = role.install()
|
||||
except AnsibleError as e:
|
||||
display.warning("- %s was NOT installed successfully: %s " % (role.name, str(e)))
|
||||
self.exit_without_ignore()
|
||||
continue
|
||||
|
||||
# install dependencies, if we want them
|
||||
if not no_deps and installed:
|
||||
if not role.metadata:
|
||||
display.warning("Meta file %s is empty. Skipping dependencies." % role.path)
|
||||
else:
|
||||
role_dependencies = role.metadata.get('dependencies') or []
|
||||
for dep in role_dependencies:
|
||||
display.debug('Installing dep %s' % dep)
|
||||
dep_req = RoleRequirement()
|
||||
dep_info = dep_req.role_yaml_parse(dep)
|
||||
dep_role = GalaxyRole(self.galaxy, **dep_info)
|
||||
if '.' not in dep_role.name and '.' not in dep_role.src and dep_role.scm is None:
|
||||
# we know we can skip this, as it's not going to
|
||||
# be found on galaxy.ansible.com
|
||||
continue
|
||||
if dep_role.install_info is None:
|
||||
if dep_role not in roles_left:
|
||||
display.display('- adding dependency: %s' % str(dep_role))
|
||||
roles_left.append(dep_role)
|
||||
else:
|
||||
display.display('- dependency %s already pending installation.' % dep_role.name)
|
||||
else:
|
||||
if dep_role.install_info['version'] != dep_role.version:
|
||||
display.warning('- dependency %s from role %s differs from already installed version (%s), skipping' %
|
||||
(str(dep_role), role.name, dep_role.install_info['version']))
|
||||
else:
|
||||
display.display('- dependency %s is already installed, skipping.' % dep_role.name)
|
||||
|
||||
if not installed:
|
||||
display.warning("- %s was NOT installed successfully." % role.name)
|
||||
self.exit_without_ignore()
|
||||
|
||||
return 0
|
||||
|
||||
def execute_remove(self):
|
||||
"""
|
||||
removes the list of roles passed as arguments from the local system.
|
||||
"""
|
||||
|
||||
if len(self.args) == 0:
|
||||
raise AnsibleOptionsError('- you must specify at least one role to remove.')
|
||||
|
||||
for role_name in self.args:
|
||||
role = GalaxyRole(self.galaxy, role_name)
|
||||
try:
|
||||
if role.remove():
|
||||
display.display('- successfully removed %s' % role_name)
|
||||
else:
|
||||
display.display('- %s is not installed, skipping.' % role_name)
|
||||
except Exception as e:
|
||||
raise AnsibleError("Failed to remove role %s: %s" % (role_name, str(e)))
|
||||
|
||||
return 0
|
||||
|
||||
def execute_list(self):
|
||||
"""
|
||||
lists the roles installed on the local system or matches a single role passed as an argument.
|
||||
"""
|
||||
|
||||
if len(self.args) > 1:
|
||||
raise AnsibleOptionsError("- please specify only one role to list, or specify no roles to see a full list")
|
||||
|
||||
if len(self.args) == 1:
|
||||
# show only the request role, if it exists
|
||||
name = self.args.pop()
|
||||
gr = GalaxyRole(self.galaxy, name)
|
||||
if gr.metadata:
|
||||
install_info = gr.install_info
|
||||
version = None
|
||||
if install_info:
|
||||
version = install_info.get("version", None)
|
||||
if not version:
|
||||
version = "(unknown version)"
|
||||
# show some more info about single roles here
|
||||
display.display("- %s, %s" % (name, version))
|
||||
else:
|
||||
display.display("- the role %s was not found" % name)
|
||||
else:
|
||||
# show all valid roles in the roles_path directory
|
||||
roles_path = self.options.roles_path
|
||||
path_found = False
|
||||
for path in roles_path:
|
||||
role_path = os.path.expanduser(path)
|
||||
if not os.path.exists(role_path):
|
||||
display.warning("- the configured path %s does not exist." % role_path)
|
||||
continue
|
||||
elif not os.path.isdir(role_path):
|
||||
display.warning("- the configured path %s, exists, but it is not a directory." % role_path)
|
||||
continue
|
||||
path_files = os.listdir(role_path)
|
||||
path_found = True
|
||||
for path_file in path_files:
|
||||
gr = GalaxyRole(self.galaxy, path_file, path=path)
|
||||
if gr.metadata:
|
||||
install_info = gr.install_info
|
||||
version = None
|
||||
if install_info:
|
||||
version = install_info.get("version", None)
|
||||
if not version:
|
||||
version = "(unknown version)"
|
||||
display.display("- %s, %s" % (path_file, version))
|
||||
if not path_found:
|
||||
raise AnsibleOptionsError("- None of the provided paths was usable. Please specify a valid path with --roles-path")
|
||||
return 0
|
||||
|
||||
def execute_search(self):
|
||||
''' searches for roles on the Ansible Galaxy server'''
|
||||
page_size = 1000
|
||||
search = None
|
||||
|
||||
if len(self.args):
|
||||
terms = []
|
||||
for i in range(len(self.args)):
|
||||
terms.append(self.args.pop())
|
||||
search = '+'.join(terms[::-1])
|
||||
|
||||
if not search and not self.options.platforms and not self.options.galaxy_tags and not self.options.author:
|
||||
raise AnsibleError("Invalid query. At least one search term, platform, galaxy tag or author must be provided.")
|
||||
|
||||
response = self.api.search_roles(search, platforms=self.options.platforms,
|
||||
tags=self.options.galaxy_tags, author=self.options.author, page_size=page_size)
|
||||
|
||||
if response['count'] == 0:
|
||||
display.display("No roles match your search.", color=C.COLOR_ERROR)
|
||||
return True
|
||||
|
||||
data = [u'']
|
||||
|
||||
if response['count'] > page_size:
|
||||
data.append(u"Found %d roles matching your search. Showing first %s." % (response['count'], page_size))
|
||||
else:
|
||||
data.append(u"Found %d roles matching your search:" % response['count'])
|
||||
|
||||
max_len = []
|
||||
for role in response['results']:
|
||||
max_len.append(len(role['username'] + '.' + role['name']))
|
||||
name_len = max(max_len)
|
||||
format_str = u" %%-%ds %%s" % name_len
|
||||
data.append(u'')
|
||||
data.append(format_str % (u"Name", u"Description"))
|
||||
data.append(format_str % (u"----", u"-----------"))
|
||||
for role in response['results']:
|
||||
data.append(format_str % (u'%s.%s' % (role['username'], role['name']), role['description']))
|
||||
|
||||
data = u'\n'.join(data)
|
||||
self.pager(data)
|
||||
|
||||
return True
|
||||
|
||||
def execute_login(self):
|
||||
"""
|
||||
verify user's identify via Github and retrieve an auth token from Ansible Galaxy.
|
||||
"""
|
||||
# Authenticate with github and retrieve a token
|
||||
if self.options.token is None:
|
||||
if C.GALAXY_TOKEN:
|
||||
github_token = C.GALAXY_TOKEN
|
||||
else:
|
||||
login = GalaxyLogin(self.galaxy)
|
||||
github_token = login.create_github_token()
|
||||
else:
|
||||
github_token = self.options.token
|
||||
|
||||
galaxy_response = self.api.authenticate(github_token)
|
||||
|
||||
if self.options.token is None and C.GALAXY_TOKEN is None:
|
||||
# Remove the token we created
|
||||
login.remove_github_token()
|
||||
|
||||
# Store the Galaxy token
|
||||
token = GalaxyToken()
|
||||
token.set(galaxy_response['token'])
|
||||
|
||||
display.display("Successfully logged into Galaxy as %s" % galaxy_response['username'])
|
||||
return 0
|
||||
|
||||
def execute_import(self):
|
||||
""" used to import a role into Ansible Galaxy """
|
||||
|
||||
colors = {
|
||||
'INFO': 'normal',
|
||||
'WARNING': C.COLOR_WARN,
|
||||
'ERROR': C.COLOR_ERROR,
|
||||
'SUCCESS': C.COLOR_OK,
|
||||
'FAILED': C.COLOR_ERROR,
|
||||
}
|
||||
|
||||
if len(self.args) < 2:
|
||||
raise AnsibleError("Expected a github_username and github_repository. Use --help.")
|
||||
|
||||
github_repo = to_text(self.args.pop(), errors='surrogate_or_strict')
|
||||
github_user = to_text(self.args.pop(), errors='surrogate_or_strict')
|
||||
|
||||
if self.options.check_status:
|
||||
task = self.api.get_import_task(github_user=github_user, github_repo=github_repo)
|
||||
else:
|
||||
# Submit an import request
|
||||
task = self.api.create_import_task(github_user, github_repo, reference=self.options.reference, role_name=self.options.role_name)
|
||||
|
||||
if len(task) > 1:
|
||||
# found multiple roles associated with github_user/github_repo
|
||||
display.display("WARNING: More than one Galaxy role associated with Github repo %s/%s." % (github_user, github_repo),
|
||||
color='yellow')
|
||||
display.display("The following Galaxy roles are being updated:" + u'\n', color=C.COLOR_CHANGED)
|
||||
for t in task:
|
||||
display.display('%s.%s' % (t['summary_fields']['role']['namespace'], t['summary_fields']['role']['name']), color=C.COLOR_CHANGED)
|
||||
display.display(u'\nTo properly namespace this role, remove each of the above and re-import %s/%s from scratch' % (github_user, github_repo),
|
||||
color=C.COLOR_CHANGED)
|
||||
return 0
|
||||
# found a single role as expected
|
||||
display.display("Successfully submitted import request %d" % task[0]['id'])
|
||||
if not self.options.wait:
|
||||
display.display("Role name: %s" % task[0]['summary_fields']['role']['name'])
|
||||
display.display("Repo: %s/%s" % (task[0]['github_user'], task[0]['github_repo']))
|
||||
|
||||
if self.options.check_status or self.options.wait:
|
||||
# Get the status of the import
|
||||
msg_list = []
|
||||
finished = False
|
||||
while not finished:
|
||||
task = self.api.get_import_task(task_id=task[0]['id'])
|
||||
for msg in task[0]['summary_fields']['task_messages']:
|
||||
if msg['id'] not in msg_list:
|
||||
display.display(msg['message_text'], color=colors[msg['message_type']])
|
||||
msg_list.append(msg['id'])
|
||||
if task[0]['state'] in ['SUCCESS', 'FAILED']:
|
||||
finished = True
|
||||
else:
|
||||
time.sleep(10)
|
||||
|
||||
return 0
|
||||
|
||||
def execute_setup(self):
|
||||
""" Setup an integration from Github or Travis for Ansible Galaxy roles"""
|
||||
|
||||
if self.options.setup_list:
|
||||
# List existing integration secrets
|
||||
secrets = self.api.list_secrets()
|
||||
if len(secrets) == 0:
|
||||
# None found
|
||||
display.display("No integrations found.")
|
||||
return 0
|
||||
display.display(u'\n' + "ID Source Repo", color=C.COLOR_OK)
|
||||
display.display("---------- ---------- ----------", color=C.COLOR_OK)
|
||||
for secret in secrets:
|
||||
display.display("%-10s %-10s %s/%s" % (secret['id'], secret['source'], secret['github_user'],
|
||||
secret['github_repo']), color=C.COLOR_OK)
|
||||
return 0
|
||||
|
||||
if self.options.remove_id:
|
||||
# Remove a secret
|
||||
self.api.remove_secret(self.options.remove_id)
|
||||
display.display("Secret removed. Integrations using this secret will not longer work.", color=C.COLOR_OK)
|
||||
return 0
|
||||
|
||||
if len(self.args) < 4:
|
||||
raise AnsibleError("Missing one or more arguments. Expecting: source github_user github_repo secret")
|
||||
|
||||
secret = self.args.pop()
|
||||
github_repo = self.args.pop()
|
||||
github_user = self.args.pop()
|
||||
source = self.args.pop()
|
||||
|
||||
resp = self.api.add_secret(source, github_user, github_repo, secret)
|
||||
display.display("Added integration for %s %s/%s" % (resp['source'], resp['github_user'], resp['github_repo']))
|
||||
|
||||
return 0
|
||||
|
||||
def execute_delete(self):
|
||||
""" Delete a role from Ansible Galaxy. """
|
||||
|
||||
if len(self.args) < 2:
|
||||
raise AnsibleError("Missing one or more arguments. Expected: github_user github_repo")
|
||||
|
||||
github_repo = self.args.pop()
|
||||
github_user = self.args.pop()
|
||||
resp = self.api.delete_role(github_user, github_repo)
|
||||
|
||||
if len(resp['deleted_roles']) > 1:
|
||||
display.display("Deleted the following roles:")
|
||||
display.display("ID User Name")
|
||||
display.display("------ --------------- ----------")
|
||||
for role in resp['deleted_roles']:
|
||||
display.display("%-8s %-15s %s" % (role.id, role.namespace, role.name))
|
||||
|
||||
display.display(resp['status'])
|
||||
|
||||
return True
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user