Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
070c7c31
Commit
070c7c31
authored
Mar 13, 2015
by
James Cammarata
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Started implementing become in v2
parent
f451974e
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
238 additions
and
95 deletions
+238
-95
v2/ansible/constants.py
+18
-2
v2/ansible/executor/connection_info.py
+63
-39
v2/ansible/executor/play_iterator.py
+1
-1
v2/ansible/executor/task_executor.py
+1
-0
v2/ansible/playbook/base.py
+5
-0
v2/ansible/playbook/become.py
+88
-0
v2/ansible/playbook/block.py
+3
-1
v2/ansible/playbook/play.py
+10
-10
v2/ansible/playbook/playbook_include.py
+1
-1
v2/ansible/playbook/role/definition.py
+1
-1
v2/ansible/playbook/task.py
+4
-8
v2/ansible/plugins/action/__init__.py
+9
-16
v2/ansible/plugins/connections/local.py
+3
-3
v2/ansible/plugins/connections/ssh.py
+15
-13
v2/ansible/utils/cli.py
+9
-0
v2/samples/test_become.yml
+7
-0
No files found.
v2/ansible/constants.py
View file @
070c7c31
...
...
@@ -24,7 +24,6 @@ import pwd
import
sys
from
.
compat
import
configparser
from
string
import
ascii_letters
,
digits
# copied from utils, avoid circular reference fun :)
...
...
@@ -143,6 +142,19 @@ DEFAULT_ASK_SU_PASS = get_config(p, DEFAULTS, 'ask_su_pass', 'ANSIBLE_ASK_
DEFAULT_GATHERING
=
get_config
(
p
,
DEFAULTS
,
'gathering'
,
'ANSIBLE_GATHERING'
,
'implicit'
)
.
lower
()
DEFAULT_LOG_PATH
=
shell_expand_path
(
get_config
(
p
,
DEFAULTS
,
'log_path'
,
'ANSIBLE_LOG_PATH'
,
''
))
#TODO: get rid of ternary chain mess
BECOME_METHODS
=
[
'sudo'
,
'su'
,
'pbrun'
,
'pfexec'
,
'runas'
]
BECOME_ERROR_STRINGS
=
{
'sudo'
:
'Sorry, try again.'
,
'su'
:
'Authentication failure'
,
'pbrun'
:
''
,
'pfexec'
:
''
,
'runas'
:
''
}
DEFAULT_BECOME
=
get_config
(
p
,
'privilege_escalation'
,
'become'
,
'ANSIBLE_BECOME'
,
True
if
DEFAULT_SUDO
or
DEFAULT_SU
else
False
,
boolean
=
True
)
DEFAULT_BECOME_METHOD
=
get_config
(
p
,
'privilege_escalation'
,
'become_method'
,
'ANSIBLE_BECOME_METHOD'
,
'sudo'
if
DEFAULT_SUDO
else
'su'
if
DEFAULT_SU
else
'sudo'
)
.
lower
()
DEFAULT_BECOME_USER
=
get_config
(
p
,
'privilege_escalation'
,
'become_user'
,
'ANSIBLE_BECOME_USER'
,
DEFAULT_SUDO_USER
if
DEFAULT_SUDO
else
DEFAULT_SU_USER
if
DEFAULT_SU
else
'root'
)
DEFAULT_BECOME_ASK_PASS
=
get_config
(
p
,
'privilege_escalation'
,
'become_ask_pass'
,
'ANSIBLE_BECOME_ASK_PASS'
,
True
if
DEFAULT_ASK_SUDO_PASS
else
False
,
boolean
=
True
)
# need to rethink impementing these 2
DEFAULT_BECOME_EXE
=
None
#DEFAULT_BECOME_EXE = get_config(p, DEFAULTS, 'become_exe', 'ANSIBLE_BECOME_EXE','sudo' if DEFAULT_SUDO else 'su' if DEFAULT_SU else 'sudo')
#DEFAULT_BECOME_FLAGS = get_config(p, DEFAULTS, 'become_flags', 'ANSIBLE_BECOME_FLAGS',DEFAULT_SUDO_FLAGS if DEFAULT_SUDO else DEFAULT_SU_FLAGS if DEFAULT_SU else '-H')
DEFAULT_ACTION_PLUGIN_PATH
=
get_config
(
p
,
DEFAULTS
,
'action_plugins'
,
'ANSIBLE_ACTION_PLUGINS'
,
'~/.ansible/plugins/action_plugins:/usr/share/ansible_plugins/action_plugins'
)
DEFAULT_CACHE_PLUGIN_PATH
=
get_config
(
p
,
DEFAULTS
,
'cache_plugins'
,
'ANSIBLE_CACHE_PLUGINS'
,
'~/.ansible/plugins/cache_plugins:/usr/share/ansible_plugins/cache_plugins'
)
DEFAULT_CALLBACK_PLUGIN_PATH
=
get_config
(
p
,
DEFAULTS
,
'callback_plugins'
,
'ANSIBLE_CALLBACK_PLUGINS'
,
'~/.ansible/plugins/callback_plugins:/usr/share/ansible_plugins/callback_plugins'
)
...
...
@@ -168,12 +180,15 @@ DEFAULT_CALLABLE_WHITELIST = get_config(p, DEFAULTS, 'callable_whitelist', '
COMMAND_WARNINGS
=
get_config
(
p
,
DEFAULTS
,
'command_warnings'
,
'ANSIBLE_COMMAND_WARNINGS'
,
False
,
boolean
=
True
)
DEFAULT_LOAD_CALLBACK_PLUGINS
=
get_config
(
p
,
DEFAULTS
,
'bin_ansible_callbacks'
,
'ANSIBLE_LOAD_CALLBACK_PLUGINS'
,
False
,
boolean
=
True
)
RETRY_FILES_ENABLED
=
get_config
(
p
,
DEFAULTS
,
'retry_files_enabled'
,
'ANSIBLE_RETRY_FILES_ENABLED'
,
True
,
boolean
=
True
)
RETRY_FILES_SAVE_PATH
=
get_config
(
p
,
DEFAULTS
,
'retry_files_save_path'
,
'ANSIBLE_RETRY_FILES_SAVE_PATH'
,
'~/'
)
# CONNECTION RELATED
ANSIBLE_SSH_ARGS
=
get_config
(
p
,
'ssh_connection'
,
'ssh_args'
,
'ANSIBLE_SSH_ARGS'
,
None
)
ANSIBLE_SSH_CONTROL_PATH
=
get_config
(
p
,
'ssh_connection'
,
'control_path'
,
'ANSIBLE_SSH_CONTROL_PATH'
,
"
%(directory)
s/ansible-ssh-
%%
h-
%%
p-
%%
r"
)
ANSIBLE_SSH_PIPELINING
=
get_config
(
p
,
'ssh_connection'
,
'pipelining'
,
'ANSIBLE_SSH_PIPELINING'
,
False
,
boolean
=
True
)
PARAMIKO_RECORD_HOST_KEYS
=
get_config
(
p
,
'paramiko_connection'
,
'record_host_keys'
,
'ANSIBLE_PARAMIKO_RECORD_HOST_KEYS'
,
True
,
boolean
=
True
)
# obsolete -- will be formally removed
in 1.6
# obsolete -- will be formally removed
ZEROMQ_PORT
=
get_config
(
p
,
'fireball_connection'
,
'zeromq_port'
,
'ANSIBLE_ZEROMQ_PORT'
,
5099
,
integer
=
True
)
ACCELERATE_PORT
=
get_config
(
p
,
'accelerate'
,
'accelerate_port'
,
'ACCELERATE_PORT'
,
5099
,
integer
=
True
)
ACCELERATE_TIMEOUT
=
get_config
(
p
,
'accelerate'
,
'accelerate_timeout'
,
'ACCELERATE_TIMEOUT'
,
30
,
integer
=
True
)
...
...
@@ -189,6 +204,7 @@ PARAMIKO_PTY = get_config(p, 'paramiko_connection', 'pty', 'AN
DEFAULT_PASSWORD_CHARS
=
ascii_letters
+
digits
+
".,:-_"
# non-configurable things
DEFAULT_BECOME_PASS
=
None
DEFAULT_SUDO_PASS
=
None
DEFAULT_REMOTE_PASS
=
None
DEFAULT_SUBSET
=
None
...
...
v2/ansible/executor/connection_info.py
View file @
070c7c31
...
...
@@ -48,16 +48,16 @@ class ConnectionInformation:
self
.
password
=
''
self
.
port
=
22
self
.
private_key_file
=
None
self
.
su
=
False
self
.
su_user
=
''
self
.
su_pass
=
''
self
.
sudo
=
False
self
.
sudo_user
=
''
self
.
sudo_pass
=
''
self
.
verbosity
=
0
self
.
only_tags
=
set
()
self
.
skip_tags
=
set
()
# privilege escalation
self
.
become
=
False
self
.
become_method
=
C
.
DEFAULT_BECOME_METHOD
self
.
become_user
=
''
self
.
become_pass
=
''
self
.
no_log
=
False
self
.
check_mode
=
False
...
...
@@ -84,15 +84,13 @@ class ConnectionInformation:
if
play
.
connection
:
self
.
connection
=
play
.
connection
self
.
remote_user
=
play
.
remote_user
self
.
password
=
''
self
.
port
=
int
(
play
.
port
)
if
play
.
port
else
22
self
.
su
=
play
.
su
self
.
su_user
=
play
.
su_user
self
.
su_pass
=
play
.
su_pass
self
.
sudo
=
play
.
sudo
self
.
sudo_user
=
play
.
sudo_user
self
.
sudo_pass
=
play
.
sudo_pass
self
.
remote_user
=
play
.
remote_user
self
.
password
=
''
self
.
port
=
int
(
play
.
port
)
if
play
.
port
else
22
self
.
become
=
play
.
become
self
.
become_method
=
play
.
become_method
self
.
become_user
=
play
.
become_user
self
.
become_pass
=
play
.
become_pass
# non connection related
self
.
no_log
=
play
.
no_log
...
...
@@ -158,7 +156,7 @@ class ConnectionInformation:
new_info
=
ConnectionInformation
()
new_info
.
copy
(
self
)
for
attr
in
(
'connection'
,
'remote_user'
,
'
su'
,
'su_user'
,
'su_pass'
,
'sudo'
,
'sudo_user'
,
'sudo_pass
'
,
'environment'
,
'no_log'
):
for
attr
in
(
'connection'
,
'remote_user'
,
'
become'
,
'become_user'
,
'become_pass'
,
'become_method
'
,
'environment'
,
'no_log'
):
if
hasattr
(
task
,
attr
):
attr_val
=
getattr
(
task
,
attr
)
if
attr_val
:
...
...
@@ -166,31 +164,58 @@ class ConnectionInformation:
return
new_info
def
make_sudo_cmd
(
self
,
sudo_exe
,
executable
,
cmd
):
def
make_become_cmd
(
self
,
cmd
,
shell
,
become_settings
=
None
):
"""
Helper function for wrapping commands with sudo.
Rather than detect if sudo wants a password this time, -k makes
sudo always ask for a password if one is required. Passing a quoted
compound command to sudo (or sudo -s) directly doesn't work, so we
shellquote it with pipes.quote() and pass the quoted string to the
user's shell. We loop reading output until we see the randomly-
generated sudo prompt set with the -p option.
helper function to create privilege escalation commands
"""
randbits
=
''
.
join
(
chr
(
random
.
randint
(
ord
(
'a'
),
ord
(
'z'
)))
for
x
in
xrange
(
32
))
prompt
=
'[sudo via ansible, key=
%
s] password: '
%
randbits
success_key
=
'SUDO-SUCCESS-
%
s'
%
randbits
sudocmd
=
'
%
s -k &&
%
s
%
s -S -p "
%
s" -u
%
s
%
s -c
%
s'
%
(
sudo_exe
,
sudo_exe
,
C
.
DEFAULT_SUDO_FLAGS
,
prompt
,
self
.
sudo_user
,
executable
or
'$SHELL'
,
pipes
.
quote
(
'echo
%
s;
%
s'
%
(
success_key
,
cmd
))
)
# FIXME: old code, can probably be removed as it's been commented out for a while
#return ('/bin/sh -c ' + pipes.quote(sudocmd), prompt, success_key)
return
(
sudocmd
,
prompt
,
success_key
)
# FIXME: become settings should probably be stored in the connection info itself
if
become_settings
is
None
:
become_settings
=
{}
randbits
=
''
.
join
(
chr
(
random
.
randint
(
ord
(
'a'
),
ord
(
'z'
)))
for
x
in
xrange
(
32
))
success_key
=
'BECOME-SUCCESS-
%
s'
%
randbits
prompt
=
None
becomecmd
=
None
shell
=
shell
or
'$SHELL'
if
self
.
become_method
==
'sudo'
:
# Rather than detect if sudo wants a password this time, -k makes sudo always ask for
# a password if one is required. Passing a quoted compound command to sudo (or sudo -s)
# directly doesn't work, so we shellquote it with pipes.quote() and pass the quoted
# string to the user's shell. We loop reading output until we see the randomly-generated
# sudo prompt set with the -p option.
prompt
=
'[sudo via ansible, key=
%
s] password: '
%
randbits
exe
=
become_settings
.
get
(
'sudo_exe'
,
C
.
DEFAULT_SUDO_EXE
)
flags
=
become_settings
.
get
(
'sudo_flags'
,
C
.
DEFAULT_SUDO_FLAGS
)
becomecmd
=
'
%
s -k &&
%
s
%
s -S -p "
%
s" -u
%
s
%
s -c "
%
s"'
%
\
(
exe
,
exe
,
flags
or
C
.
DEFAULT_SUDO_FLAGS
,
prompt
,
self
.
become_user
,
shell
,
'echo
%
s;
%
s'
%
(
success_key
,
cmd
))
elif
self
.
become_method
==
'su'
:
exe
=
become_settings
.
get
(
'su_exe'
,
C
.
DEFAULT_SU_EXE
)
flags
=
become_settings
.
get
(
'su_flags'
,
C
.
DEFAULT_SU_FLAGS
)
becomecmd
=
'
%
s
%
s
%
s -c "
%
s -c
%
s"'
%
(
exe
,
flags
,
self
.
become_user
,
shell
,
pipes
.
quote
(
'echo
%
s;
%
s'
%
(
success_key
,
cmd
)))
elif
self
.
become_method
==
'pbrun'
:
exe
=
become_settings
.
get
(
'pbrun_exe'
,
'pbrun'
)
flags
=
become_settings
.
get
(
'pbrun_flags'
,
''
)
becomecmd
=
'
%
s -b -l
%
s -u
%
s "
%
s"'
%
(
exe
,
flags
,
self
.
become_user
,
'echo
%
s;
%
s'
%
(
success_key
,
cmd
))
elif
self
.
become_method
==
'pfexec'
:
exe
=
become_settings
.
get
(
'pfexec_exe'
,
'pbrun'
)
flags
=
become_settings
.
get
(
'pfexec_flags'
,
''
)
# No user as it uses it's own exec_attr to figure it out
becomecmd
=
'
%
s
%
s "
%
s"'
%
(
exe
,
flags
,
'echo
%
s;
%
s'
%
(
success_key
,
cmd
))
elif
self
.
become
:
raise
errors
.
AnsibleError
(
"Privilege escalation method not found:
%
s"
%
method
)
return
((
'
%
s -c '
%
shell
)
+
pipes
.
quote
(
becomecmd
),
prompt
,
success_key
)
def
check_become_success
(
self
,
output
,
become_settings
):
#TODO: implement
pass
def
_get_fields
(
self
):
return
[
i
for
i
in
self
.
__dict__
.
keys
()
if
i
[:
1
]
!=
'_'
]
...
...
@@ -204,4 +229,3 @@ class ConnectionInformation:
for
field
in
self
.
_get_fields
():
value
=
templar
.
template
(
getattr
(
self
,
field
))
setattr
(
self
,
field
,
value
)
v2/ansible/executor/play_iterator.py
View file @
070c7c31
...
...
@@ -197,7 +197,7 @@ class PlayIterator:
self
.
_host_states
[
host
.
name
]
=
s
def
get_failed_hosts
(
self
):
return
dict
((
host
,
True
)
for
(
host
,
state
)
in
self
.
_host_states
.
iteritems
()
if
state
.
run_state
==
self
.
ITERATING_COMPLETE
and
state
.
fail
ed
_state
!=
self
.
FAILED_NONE
)
return
dict
((
host
,
True
)
for
(
host
,
state
)
in
self
.
_host_states
.
iteritems
()
if
state
.
run_state
==
self
.
ITERATING_COMPLETE
and
state
.
fail_state
!=
self
.
FAILED_NONE
)
def
get_original_task
(
self
,
host
,
task
):
'''
...
...
v2/ansible/executor/task_executor.py
View file @
070c7c31
...
...
@@ -33,6 +33,7 @@ __all__ = ['TaskExecutor']
import
json
import
time
import
pipes
class
TaskExecutor
:
...
...
v2/ansible/playbook/base.py
View file @
070c7c31
...
...
@@ -72,6 +72,11 @@ class Base:
def
munge
(
self
,
ds
):
''' infrequently used method to do some pre-processing of legacy terms '''
for
base_class
in
self
.
__class__
.
__bases__
:
method
=
getattr
(
self
,
(
"_munge_
%
s"
%
base_class
.
__name__
)
.
lower
(),
None
)
if
method
:
ds
=
method
(
ds
)
return
ds
def
load_data
(
self
,
ds
,
variable_manager
=
None
,
loader
=
None
):
...
...
v2/ansible/playbook/become.py
0 → 100644
View file @
070c7c31
# (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
from
ansible.errors
import
AnsibleError
,
AnsibleParserError
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
#from ansible.utils.display import deprecated
class
Become
:
# Privlege escalation
_become
=
FieldAttribute
(
isa
=
'bool'
,
default
=
False
)
_become_method
=
FieldAttribute
(
isa
=
'string'
)
_become_user
=
FieldAttribute
(
isa
=
'string'
)
_become_pass
=
FieldAttribute
(
isa
=
'string'
)
def
__init__
(
self
):
return
super
(
Become
,
self
)
.
__init__
()
def
_detect_privilege_escalation_conflict
(
self
,
ds
):
# Fail out if user specifies conflicting privelege escalations
has_become
=
'become'
in
ds
or
'become_user'
in
ds
has_sudo
=
'sudo'
in
ds
or
'sudo_user'
in
ds
has_su
=
'su'
in
ds
or
'su_user'
in
ds
if
has_become
:
msg
=
'The become params ("become", "become_user") and'
if
has_sudo
:
raise
errors
.
AnsibleParserError
(
'
%
s sudo params ("sudo", "sudo_user") cannot be used together'
%
msg
)
elif
has_su
:
raise
errors
.
AnsibleParserError
(
'
%
s su params ("su", "su_user") cannot be used together'
%
msg
)
elif
has_sudo
and
has_su
:
raise
errors
.
AnsibleParserError
(
'sudo params ("sudo", "sudo_user") and su params ("su", "su_user") cannot be used together'
)
def
_munge_become
(
self
,
ds
):
self
.
_detect_privilege_escalation_conflict
(
ds
)
# Setting user implies setting become/sudo/su to true
if
'become_user'
in
ds
and
not
ds
.
get
(
'become'
,
False
):
ds
[
'become'
]
=
True
# Privilege escalation, backwards compatibility for sudo/su
if
'sudo'
in
ds
or
'sudo_user'
in
ds
:
ds
[
'become_method'
]
=
'sudo'
if
'sudo'
in
ds
:
ds
[
'become'
]
=
ds
[
'sudo'
]
del
ds
[
'sudo'
]
else
:
ds
[
'become'
]
=
True
if
'sudo_user'
in
ds
:
ds
[
'become_user'
]
=
ds
[
'sudo_user'
]
del
ds
[
'sudo_user'
]
#deprecated("Instead of sudo/sudo_user, use become/become_user and set become_method to 'sudo' (default)")
elif
'su'
in
ds
or
'su_user'
in
ds
:
ds
[
'become_method'
]
=
'su'
if
'su'
in
ds
:
ds
[
'become'
]
=
ds
[
'su'
]
del
ds
[
'su'
]
else
:
ds
[
'become'
]
=
True
if
'su_user'
in
ds
:
ds
[
'become_user'
]
=
ds
[
'su_user'
]
del
ds
[
'su_user'
]
#deprecated("Instead of su/su_user, use become/become_user and set become_method to 'su' (default is sudo)")
return
ds
v2/ansible/playbook/block.py
View file @
070c7c31
...
...
@@ -21,6 +21,7 @@ __metaclass__ = type
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
from
ansible.playbook.base
import
Base
#from ansible.playbook.become import Become
from
ansible.playbook.conditional
import
Conditional
from
ansible.playbook.helpers
import
load_list_of_tasks
from
ansible.playbook.role
import
Role
...
...
@@ -80,7 +81,8 @@ class Block(Base, Conditional, Taggable):
return
dict
(
block
=
ds
)
else
:
return
dict
(
block
=
[
ds
])
return
ds
return
super
(
Block
,
self
)
.
munge
(
ds
)
def
_load_block
(
self
,
attr
,
ds
):
return
load_list_of_tasks
(
...
...
v2/ansible/playbook/play.py
View file @
070c7c31
...
...
@@ -23,6 +23,7 @@ from ansible.errors import AnsibleError, AnsibleParserError
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
from
ansible.playbook.base
import
Base
from
ansible.playbook.become
import
Become
from
ansible.playbook.helpers
import
load_list_of_blocks
,
load_list_of_roles
,
compile_block_list
from
ansible.playbook.role
import
Role
from
ansible.playbook.taggable
import
Taggable
...
...
@@ -33,7 +34,7 @@ from ansible.utils.vars import combine_vars
__all__
=
[
'Play'
]
class
Play
(
Base
,
Taggable
):
class
Play
(
Base
,
Taggable
,
Become
):
"""
A play is a language feature that represents a list of roles and/or
...
...
@@ -47,21 +48,19 @@ class Play(Base, Taggable):
# =================================================================================
# Connection-Related Attributes
# TODO: generalize connection
_accelerate
=
FieldAttribute
(
isa
=
'bool'
,
default
=
False
)
_accelerate_ipv6
=
FieldAttribute
(
isa
=
'bool'
,
default
=
False
)
_accelerate_port
=
FieldAttribute
(
isa
=
'int'
,
default
=
5099
)
_accelerate_port
=
FieldAttribute
(
isa
=
'int'
,
default
=
5099
)
# should be alias of port
# Connection
_connection
=
FieldAttribute
(
isa
=
'string'
,
default
=
'smart'
)
_gather_facts
=
FieldAttribute
(
isa
=
'string'
,
default
=
'smart'
)
_hosts
=
FieldAttribute
(
isa
=
'list'
,
default
=
[],
required
=
True
)
_name
=
FieldAttribute
(
isa
=
'string'
,
default
=
'<no name specified>'
)
_port
=
FieldAttribute
(
isa
=
'int'
,
default
=
22
)
_remote_user
=
FieldAttribute
(
isa
=
'string'
,
default
=
'root'
)
_su
=
FieldAttribute
(
isa
=
'bool'
,
default
=
False
)
_su_user
=
FieldAttribute
(
isa
=
'string'
,
default
=
'root'
)
_su_pass
=
FieldAttribute
(
isa
=
'string'
)
_sudo
=
FieldAttribute
(
isa
=
'bool'
,
default
=
False
)
_sudo_user
=
FieldAttribute
(
isa
=
'string'
,
default
=
'root'
)
_sudo_pass
=
FieldAttribute
(
isa
=
'string'
)
# Variable Attributes
_vars
=
FieldAttribute
(
isa
=
'dict'
,
default
=
dict
())
...
...
@@ -101,6 +100,7 @@ class Play(Base, Taggable):
@staticmethod
def
load
(
data
,
variable_manager
=
None
,
loader
=
None
):
p
=
Play
()
print
(
"in play load, become is:
%
s"
%
getattr
(
p
,
'become'
))
return
p
.
load_data
(
data
,
variable_manager
=
variable_manager
,
loader
=
loader
)
def
munge
(
self
,
ds
):
...
...
@@ -122,7 +122,7 @@ class Play(Base, Taggable):
ds
[
'remote_user'
]
=
ds
[
'user'
]
del
ds
[
'user'
]
return
ds
return
super
(
Play
,
self
)
.
munge
(
ds
)
def
_load_vars
(
self
,
attr
,
ds
):
'''
...
...
@@ -187,7 +187,7 @@ class Play(Base, Taggable):
roles
.
append
(
Role
.
load
(
ri
))
return
roles
# FIXME: post_validation needs to ensure that
su/sudo are not both
set
# FIXME: post_validation needs to ensure that
become/su/sudo have only 1
set
def
_compile_roles
(
self
):
'''
...
...
v2/ansible/playbook/playbook_include.py
View file @
070c7c31
...
...
@@ -98,7 +98,7 @@ class PlaybookInclude(Base):
raise
AnsibleParserError
(
"vars for include statements must be specified as a dictionary"
,
obj
=
ds
)
new_ds
[
k
]
=
v
return
new_ds
return
super
(
PlaybookInclude
,
self
)
.
munge
(
new_ds
)
def
_munge_include
(
self
,
ds
,
new_ds
,
k
,
v
):
'''
...
...
v2/ansible/playbook/role/definition.py
View file @
070c7c31
...
...
@@ -88,7 +88,7 @@ class RoleDefinition(Base, Conditional, Taggable):
self
.
_ds
=
ds
# and return the cleaned-up data structure
return
new_ds
return
super
(
RoleDefinition
,
self
)
.
munge
(
new_ds
)
def
_load_role_name
(
self
,
ds
):
'''
...
...
v2/ansible/playbook/task.py
View file @
070c7c31
...
...
@@ -29,6 +29,7 @@ from ansible.plugins import module_loader, lookup_loader
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
from
ansible.playbook.base
import
Base
from
ansible.playbook.become
import
Become
from
ansible.playbook.block
import
Block
from
ansible.playbook.conditional
import
Conditional
from
ansible.playbook.role
import
Role
...
...
@@ -36,7 +37,7 @@ from ansible.playbook.taggable import Taggable
__all__
=
[
'Task'
]
class
Task
(
Base
,
Conditional
,
Taggable
):
class
Task
(
Base
,
Conditional
,
Taggable
,
Become
):
"""
A task is a language feature that represents a call to a module, with given arguments and other parameters.
...
...
@@ -86,12 +87,6 @@ class Task(Base, Conditional, Taggable):
_remote_user
=
FieldAttribute
(
isa
=
'string'
)
_retries
=
FieldAttribute
(
isa
=
'int'
,
default
=
1
)
_run_once
=
FieldAttribute
(
isa
=
'bool'
)
_su
=
FieldAttribute
(
isa
=
'bool'
)
_su_pass
=
FieldAttribute
(
isa
=
'string'
)
_su_user
=
FieldAttribute
(
isa
=
'string'
)
_sudo
=
FieldAttribute
(
isa
=
'bool'
)
_sudo_user
=
FieldAttribute
(
isa
=
'string'
)
_sudo_pass
=
FieldAttribute
(
isa
=
'string'
)
_transport
=
FieldAttribute
(
isa
=
'string'
)
_until
=
FieldAttribute
(
isa
=
'list'
)
# ?
_vars
=
FieldAttribute
(
isa
=
'dict'
,
default
=
dict
())
...
...
@@ -172,6 +167,7 @@ class Task(Base, Conditional, Taggable):
args_parser
=
ModuleArgsParser
(
task_ds
=
ds
)
(
action
,
args
,
delegate_to
)
=
args_parser
.
parse
()
new_ds
[
'action'
]
=
action
new_ds
[
'args'
]
=
args
new_ds
[
'delegate_to'
]
=
delegate_to
...
...
@@ -186,7 +182,7 @@ class Task(Base, Conditional, Taggable):
else
:
new_ds
[
k
]
=
v
return
new_ds
return
super
(
Task
,
self
)
.
munge
(
new_ds
)
def
post_validate
(
self
,
all_vars
=
dict
(),
fail_on_undefined
=
True
):
'''
...
...
v2/ansible/plugins/action/__init__.py
View file @
070c7c31
...
...
@@ -130,7 +130,7 @@ class ActionBase:
if
tmp
and
"tmp"
in
tmp
:
# tmp has already been created
return
False
if
not
self
.
_connection
.
_has_pipelining
or
not
C
.
ANSIBLE_SSH_PIPELINING
or
C
.
DEFAULT_KEEP_REMOTE_FILES
or
self
.
_connection_info
.
su
:
if
not
self
.
_connection
.
_has_pipelining
or
not
C
.
ANSIBLE_SSH_PIPELINING
or
C
.
DEFAULT_KEEP_REMOTE_FILES
or
self
.
_connection_info
.
become
:
# tmp is necessary to store module source code
return
True
if
not
self
.
_connection
.
_has_pipelining
:
...
...
@@ -152,12 +152,11 @@ class ActionBase:
basefile
=
'ansible-tmp-
%
s-
%
s'
%
(
time
.
time
(),
random
.
randint
(
0
,
2
**
48
))
use_system_tmp
=
False
if
(
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
!=
'root'
)
or
(
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
!=
'root'
)
:
if
self
.
_connection_info
.
become
and
self
.
_connection_info
.
become_user
!=
'root'
:
use_system_tmp
=
True
tmp_mode
=
None
if
self
.
_connection_info
.
remote_user
!=
'root'
or
\
((
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
!=
'root'
)
or
(
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
!=
'root'
)):
if
self
.
_connection_info
.
remote_user
!=
'root'
or
self
.
_connection_info
.
become
and
self
.
_connection_info
.
become_user
!=
'root'
:
tmp_mode
=
'a+rx'
cmd
=
self
.
_shell
.
mkdtemp
(
basefile
,
use_system_tmp
,
tmp_mode
)
...
...
@@ -291,10 +290,8 @@ class ActionBase:
split_path
=
path
.
split
(
os
.
path
.
sep
,
1
)
expand_path
=
split_path
[
0
]
if
expand_path
==
'~'
:
if
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
:
expand_path
=
'~
%
s'
%
self
.
_connection_info
.
sudo_user
elif
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
:
expand_path
=
'~
%
s'
%
self
.
_connection_info
.
su_user
if
self
.
_connection_info
.
become
and
self
.
_connection_info
.
become_user
:
expand_path
=
'~
%
s'
%
self
.
_connection_info
.
become_user
cmd
=
self
.
_shell
.
expand_user
(
expand_path
)
debug
(
"calling _low_level_execute_command to expand the remote user path"
)
...
...
@@ -373,7 +370,7 @@ class ActionBase:
environment_string
=
self
.
_compute_environment_string
()
if
tmp
and
"tmp"
in
tmp
and
((
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
!=
'root'
)
or
(
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
!=
'root'
))
:
if
tmp
and
"tmp"
in
tmp
and
self
.
_connection_info
.
become
and
self
.
_connection_info
.
become_user
!=
'root'
:
# deal with possible umask issues once sudo'ed to other user
self
.
_remote_chmod
(
tmp
,
'a+r'
,
remote_module_path
)
...
...
@@ -391,7 +388,7 @@ class ActionBase:
rm_tmp
=
None
if
tmp
and
"tmp"
in
tmp
and
not
C
.
DEFAULT_KEEP_REMOTE_FILES
and
not
persist_files
and
delete_remote_tmp
:
if
not
self
.
_connection_info
.
sudo
or
self
.
_connection_info
.
su
or
self
.
_connection_info
.
sudo_user
==
'root'
or
self
.
_connection_info
.
su
_user
==
'root'
:
if
not
self
.
_connection_info
.
become
or
self
.
_connection_info
.
become
_user
==
'root'
:
# not sudoing or sudoing to root, so can cleanup files in the same step
rm_tmp
=
tmp
...
...
@@ -409,7 +406,7 @@ class ActionBase:
debug
(
"_low_level_execute_command returned ok"
)
if
tmp
and
"tmp"
in
tmp
and
not
C
.
DEFAULT_KEEP_REMOTE_FILES
and
not
persist_files
and
delete_remote_tmp
:
if
(
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
!=
'root'
)
or
(
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
!=
'root'
)
:
if
self
.
_connection_info
.
become
and
self
.
_connection_info
.
become_user
!=
'root'
:
# not sudoing to root, so maybe can't delete files as that other user
# have to clean up temp files as original user in a second step
cmd2
=
self
.
_shell
.
remove
(
tmp
,
recurse
=
True
)
...
...
@@ -457,11 +454,7 @@ class ActionBase:
success_key
=
None
if
sudoable
:
if
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
:
cmd
,
prompt
,
success_key
=
self
.
_connection_info
.
make_su_cmd
(
executable
,
cmd
)
elif
self
.
_connection_info
.
sudo
and
self
.
_connection_info
.
sudo_user
:
# FIXME: hard-coded sudo_exe here
cmd
,
prompt
,
success_key
=
self
.
_connection_info
.
make_sudo_cmd
(
'/usr/bin/sudo'
,
executable
,
cmd
)
cmd
,
prompt
,
success_key
=
self
.
_connection_info
.
make_become_cmd
(
executable
,
cmd
)
debug
(
"executing the command
%
s through the connection"
%
cmd
)
rc
,
stdin
,
stdout
,
stderr
=
self
.
_connection
.
exec_command
(
cmd
,
tmp
,
executable
=
executable
,
in_data
=
in_data
)
...
...
v2/ansible/plugins/connections/local.py
View file @
070c7c31
...
...
@@ -44,8 +44,8 @@ class Connection(ConnectionBase):
debug
(
"in local.exec_command()"
)
# su requires to be run from a terminal, and therefore isn't supported here (yet?)
if
self
.
_connection_info
.
su
:
raise
AnsibleError
(
"Internal Error: this module does not support running commands via su"
)
#
if self._connection_info.su:
#
raise AnsibleError("Internal Error: this module does not support running commands via su")
if
in_data
:
raise
AnsibleError
(
"Internal Error: this module does not support optimized module pipelining"
)
...
...
@@ -57,7 +57,7 @@ class Connection(ConnectionBase):
# else:
# local_cmd = cmd
#else:
# local_cmd, prompt, success_key = utils.make_
sudo
_cmd(self.runner.sudo_exe, sudo_user, executable, cmd)
# local_cmd, prompt, success_key = utils.make_
become
_cmd(self.runner.sudo_exe, sudo_user, executable, cmd)
if
executable
:
local_cmd
=
executable
.
split
()
+
[
'-c'
,
cmd
]
else
:
...
...
v2/ansible/plugins/connections/ssh.py
View file @
070c7c31
...
...
@@ -281,19 +281,19 @@ class Connection(ConnectionBase):
# ssh_cmd += ['-6']
ssh_cmd
+=
[
self
.
_connection_info
.
remote_addr
]
if
not
(
self
.
_connection_info
.
sudo
or
self
.
_connection_info
.
su
):
prompt
=
None
if
executable
:
ssh_cmd
.
append
(
executable
+
' -c '
+
pipes
.
quote
(
cmd
))
else
:
ssh_cmd
.
append
(
cmd
)
elif
self
.
_connection_info
.
su
and
self
.
_connection_info
.
su_user
:
su_cmd
,
prompt
,
success_key
=
self
.
_connection_info
.
make_su_cmd
(
executable
,
cmd
)
ssh_cmd
.
append
(
su_cmd
)
else
:
# FIXME: hard-coded sudo_exe here
sudo_cmd
,
prompt
,
success_key
=
self
.
_connection_info
.
make_sudo
_cmd
(
'/usr/bin/sudo'
,
executable
,
cmd
)
ssh_cmd
.
append
(
sudo_cmd
)
#
if not (self._connection_info.sudo or self._connection_info.su):
#
prompt = None
#
if executable:
#
ssh_cmd.append(executable + ' -c ' + pipes.quote(cmd))
#
else:
#
ssh_cmd.append(cmd)
#
elif self._connection_info.su and self._connection_info.su_user:
#
su_cmd, prompt, success_key = self._connection_info.make_su_cmd(executable, cmd)
#
ssh_cmd.append(su_cmd)
#
else:
#
# FIXME: hard-coded sudo_exe here
# sudo_cmd, prompt, success_key = self._connection_info.make_become
_cmd('/usr/bin/sudo', executable, cmd)
#
ssh_cmd.append(sudo_cmd)
self
.
_display
.
vvv
(
"EXEC
%
s"
%
' '
.
join
(
ssh_cmd
),
host
=
self
.
_connection_info
.
remote_addr
)
...
...
@@ -369,6 +369,8 @@ class Connection(ConnectionBase):
# no_prompt_err += sudo_errput
#(returncode, stdout, stderr) = self._communicate(p, stdin, in_data, su=su, sudoable=sudoable, prompt=prompt)
# FIXME: the prompt won't be here anymore
prompt
=
""
(
returncode
,
stdout
,
stderr
)
=
self
.
_communicate
(
p
,
stdin
,
in_data
,
prompt
=
prompt
)
#if C.HOST_KEY_CHECKING and not_in_host_file:
...
...
v2/ansible/utils/cli.py
View file @
070c7c31
...
...
@@ -59,6 +59,8 @@ def base_parser(usage="", output_opts=False, runas_opts=False,
help
=
'ask for sudo password'
)
parser
.
add_option
(
'--ask-su-pass'
,
default
=
False
,
dest
=
'ask_su_pass'
,
action
=
'store_true'
,
help
=
'ask for su password'
)
parser
.
add_option
(
'--ask-become-pass'
,
default
=
False
,
dest
=
'ask_become_pass'
,
action
=
'store_true'
,
help
=
'ask for privlege escalation password'
)
parser
.
add_option
(
'--ask-vault-pass'
,
default
=
False
,
dest
=
'ask_vault_pass'
,
action
=
'store_true'
,
help
=
'ask for vault password'
)
parser
.
add_option
(
'--vault-password-file'
,
default
=
C
.
DEFAULT_VAULT_PASSWORD_FILE
,
...
...
@@ -84,6 +86,10 @@ def base_parser(usage="", output_opts=False, runas_opts=False,
help
=
'log output to this directory'
)
if
runas_opts
:
parser
.
add_option
(
"-b"
,
"--become"
,
default
=
C
.
DEFAULT_BECOME
,
action
=
"store_true"
,
dest
=
'become'
,
help
=
"run operations with become (nopasswd implied)"
)
parser
.
add_option
(
'-B'
,
'--become-user'
,
help
=
'run operations with as this '
'user (default=
%
s)'
%
C
.
DEFAULT_BECOME_USER
)
parser
.
add_option
(
"-s"
,
"--sudo"
,
default
=
C
.
DEFAULT_SUDO
,
action
=
"store_true"
,
dest
=
'sudo'
,
help
=
"run operations with sudo (nopasswd)"
)
parser
.
add_option
(
'-U'
,
'--sudo-user'
,
dest
=
'sudo_user'
,
default
=
None
,
...
...
@@ -100,6 +106,9 @@ def base_parser(usage="", output_opts=False, runas_opts=False,
parser
.
add_option
(
'-c'
,
'--connection'
,
dest
=
'connection'
,
default
=
C
.
DEFAULT_TRANSPORT
,
help
=
"connection type to use (default=
%
s)"
%
C
.
DEFAULT_TRANSPORT
)
parser
.
add_option
(
'--become-method'
,
dest
=
'become_method'
,
default
=
C
.
DEFAULT_BECOME_METHOD
,
help
=
"privlege escalation method to use (default=
%
s)"
%
C
.
DEFAULT_BECOME_METHOD
)
if
async_opts
:
parser
.
add_option
(
'-P'
,
'--poll'
,
default
=
C
.
DEFAULT_POLL_INTERVAL
,
type
=
'int'
,
...
...
v2/samples/test_become.yml
0 → 100644
View file @
070c7c31
-
hosts
:
all
gather_facts
:
no
tasks
:
-
command
:
whoami
become
:
yes
become_user
:
jamesc
become_method
:
su
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment