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
87f75a50
Commit
87f75a50
authored
Sep 03, 2015
by
James Cammarata
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use proxy class to mark variables unsafe for templating
Fixes #12191
parent
2d251cba
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
142 additions
and
3 deletions
+142
-3
lib/ansible/template/__init__.py
+5
-2
lib/ansible/vars/__init__.py
+5
-1
lib/ansible/vars/unsafe_proxy.py
+132
-0
No files found.
lib/ansible/template/__init__.py
View file @
87f75a50
...
@@ -213,6 +213,9 @@ class Templar:
...
@@ -213,6 +213,9 @@ class Templar:
before being sent through the template engine.
before being sent through the template engine.
'''
'''
if
hasattr
(
variable
,
'__UNSAFE__'
):
return
variable
try
:
try
:
if
convert_bare
:
if
convert_bare
:
variable
=
self
.
_convert_bare_variable
(
variable
)
variable
=
self
.
_convert_bare_variable
(
variable
)
...
@@ -250,13 +253,13 @@ class Templar:
...
@@ -250,13 +253,13 @@ class Templar:
return
result
return
result
elif
isinstance
(
variable
,
(
list
,
tuple
)):
elif
isinstance
(
variable
,
(
list
,
tuple
)):
return
[
self
.
template
(
v
,
convert_bare
=
convert_bare
,
preserve_trailing_newlines
=
preserve_trailing_newlines
,
fail_on_undefined
=
fail_on_undefined
,
overrides
=
overrides
)
for
v
in
variable
]
return
[
self
.
template
(
v
,
preserve_trailing_newlines
=
preserve_trailing_newlines
,
fail_on_undefined
=
fail_on_undefined
,
overrides
=
overrides
)
for
v
in
variable
]
elif
isinstance
(
variable
,
dict
):
elif
isinstance
(
variable
,
dict
):
d
=
{}
d
=
{}
# we don't use iteritems() here to avoid problems if the underlying dict
# we don't use iteritems() here to avoid problems if the underlying dict
# changes sizes due to the templating, which can happen with hostvars
# changes sizes due to the templating, which can happen with hostvars
for
k
in
variable
.
keys
():
for
k
in
variable
.
keys
():
d
[
k
]
=
self
.
template
(
variable
[
k
],
convert_bare
=
convert_bare
,
preserve_trailing_newlines
=
preserve_trailing_newlines
,
fail_on_undefined
=
fail_on_undefined
,
overrides
=
overrides
)
d
[
k
]
=
self
.
template
(
variable
[
k
],
preserve_trailing_newlines
=
preserve_trailing_newlines
,
fail_on_undefined
=
fail_on_undefined
,
overrides
=
overrides
)
return
d
return
d
else
:
else
:
return
variable
return
variable
...
...
lib/ansible/vars/__init__.py
View file @
87f75a50
...
@@ -40,6 +40,7 @@ from ansible.template import Templar
...
@@ -40,6 +40,7 @@ from ansible.template import Templar
from
ansible.utils.debug
import
debug
from
ansible.utils.debug
import
debug
from
ansible.utils.vars
import
combine_vars
from
ansible.utils.vars
import
combine_vars
from
ansible.vars.hostvars
import
HostVars
from
ansible.vars.hostvars
import
HostVars
from
ansible.vars.unsafe_proxy
import
UnsafeProxy
CACHED_VARS
=
dict
()
CACHED_VARS
=
dict
()
...
@@ -175,7 +176,10 @@ class VariableManager:
...
@@ -175,7 +176,10 @@ class VariableManager:
# next comes the facts cache and the vars cache, respectively
# next comes the facts cache and the vars cache, respectively
try
:
try
:
all_vars
=
combine_vars
(
all_vars
,
self
.
_fact_cache
.
get
(
host
.
name
,
dict
()))
host_facts
=
self
.
_fact_cache
.
get
(
host
.
name
,
dict
())
for
k
in
host_facts
.
keys
():
host_facts
[
k
]
=
UnsafeProxy
(
host_facts
[
k
])
all_vars
=
combine_vars
(
all_vars
,
host_facts
)
except
KeyError
:
except
KeyError
:
pass
pass
...
...
lib/ansible/vars/unsafe_proxy.py
0 → 100644
View file @
87f75a50
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
# --------------------------------------------
#
# 1. This LICENSE AGREEMENT is between the Python Software Foundation
# ("PSF"), and the Individual or Organization ("Licensee") accessing and
# otherwise using this software ("Python") in source or binary form and
# its associated documentation.
#
# 2. Subject to the terms and conditions of this License Agreement, PSF hereby
# grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
# analyze, test, perform and/or display publicly, prepare derivative works,
# distribute, and otherwise use Python alone or in any derivative version,
# provided, however, that PSF's License Agreement and PSF's notice of copyright,
# i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014 Python Software Foundation; All Rights Reserved" are
# retained in Python alone or in any derivative version prepared by Licensee.
#
# 3. In the event Licensee prepares a derivative work that is based on
# or incorporates Python or any part thereof, and wants to make
# the derivative work available to others as provided herein, then
# Licensee hereby agrees to include in any such work a brief summary of
# the changes made to Python.
#
# 4. PSF is making Python available to Licensee on an "AS IS"
# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
# INFRINGE ANY THIRD PARTY RIGHTS.
#
# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
# FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
#
# 6. This License Agreement will automatically terminate upon a material
# breach of its terms and conditions.
#
# 7. Nothing in this License Agreement shall be deemed to create any
# relationship of agency, partnership, or joint venture between PSF and
# Licensee. This License Agreement does not grant permission to use PSF
# trademarks or trade name in a trademark sense to endorse or promote
# products or services of Licensee, or any third party.
#
# 8. By copying, installing or otherwise using Python, Licensee
# agrees to be bound by the terms and conditions of this License
# Agreement.
#
# Original Python Recipe for Proxy:
# http://code.activestate.com/recipes/496741-object-proxying/
# Author: Tomer Filiba
class
UnsafeProxy
(
object
):
__slots__
=
[
"_obj"
,
"__weakref__"
]
def
__init__
(
self
,
obj
):
object
.
__setattr__
(
self
,
"_obj"
,
obj
)
#
# proxying (special cases)
#
def
__getattribute__
(
self
,
name
):
if
name
==
'__UNSAFE__'
:
return
True
else
:
return
getattr
(
object
.
__getattribute__
(
self
,
"_obj"
),
name
)
def
__delattr__
(
self
,
name
):
delattr
(
object
.
__getattribute__
(
self
,
"_obj"
),
name
)
def
__setattr__
(
self
,
name
,
value
):
setattr
(
object
.
__getattribute__
(
self
,
"_obj"
),
name
,
value
)
def
__nonzero__
(
self
):
return
bool
(
object
.
__getattribute__
(
self
,
"_obj"
))
def
__str__
(
self
):
return
str
(
object
.
__getattribute__
(
self
,
"_obj"
))
def
__repr__
(
self
):
return
repr
(
object
.
__getattribute__
(
self
,
"_obj"
))
#
# factories
#
_special_names
=
[
'__abs__'
,
'__add__'
,
'__and__'
,
'__call__'
,
'__cmp__'
,
'__coerce__'
,
'__contains__'
,
'__delitem__'
,
'__delslice__'
,
'__div__'
,
'__divmod__'
,
'__eq__'
,
'__float__'
,
'__floordiv__'
,
'__ge__'
,
'__getitem__'
,
'__getslice__'
,
'__gt__'
,
'__hash__'
,
'__hex__'
,
'__iadd__'
,
'__iand__'
,
'__idiv__'
,
'__idivmod__'
,
'__ifloordiv__'
,
'__ilshift__'
,
'__imod__'
,
'__imul__'
,
'__int__'
,
'__invert__'
,
'__ior__'
,
'__ipow__'
,
'__irshift__'
,
'__isub__'
,
'__iter__'
,
'__itruediv__'
,
'__ixor__'
,
'__le__'
,
'__len__'
,
'__long__'
,
'__lshift__'
,
'__lt__'
,
'__mod__'
,
'__mul__'
,
'__ne__'
,
'__neg__'
,
'__oct__'
,
'__or__'
,
'__pos__'
,
'__pow__'
,
'__radd__'
,
'__rand__'
,
'__rdiv__'
,
'__rdivmod__'
,
'__reduce__'
,
'__reduce_ex__'
,
'__repr__'
,
'__reversed__'
,
'__rfloorfiv__'
,
'__rlshift__'
,
'__rmod__'
,
'__rmul__'
,
'__ror__'
,
'__rpow__'
,
'__rrshift__'
,
'__rshift__'
,
'__rsub__'
,
'__rtruediv__'
,
'__rxor__'
,
'__setitem__'
,
'__setslice__'
,
'__sub__'
,
'__truediv__'
,
'__xor__'
,
'next'
,
]
@classmethod
def
_create_class_proxy
(
cls
,
theclass
):
"""creates a proxy for the given class"""
def
make_method
(
name
):
def
method
(
self
,
*
args
,
**
kw
):
return
getattr
(
object
.
__getattribute__
(
self
,
"_obj"
),
name
)(
*
args
,
**
kw
)
return
method
namespace
=
{}
for
name
in
cls
.
_special_names
:
if
hasattr
(
theclass
,
name
):
namespace
[
name
]
=
make_method
(
name
)
return
type
(
"
%
s(
%
s)"
%
(
cls
.
__name__
,
theclass
.
__name__
),
(
cls
,),
namespace
)
def
__new__
(
cls
,
obj
,
*
args
,
**
kwargs
):
"""
creates an proxy instance referencing `obj`. (obj, *args, **kwargs) are
passed to this class' __init__, so deriving classes can define an
__init__ method of their own.
note: _class_proxy_cache is unique per deriving class (each deriving
class must hold its own cache)
"""
try
:
cache
=
cls
.
__dict__
[
"_class_proxy_cache"
]
except
KeyError
:
cls
.
_class_proxy_cache
=
cache
=
{}
try
:
theclass
=
cache
[
obj
.
__class__
]
except
KeyError
:
cache
[
obj
.
__class__
]
=
theclass
=
cls
.
_create_class_proxy
(
obj
.
__class__
)
ins
=
object
.
__new__
(
theclass
)
theclass
.
__init__
(
ins
,
obj
,
*
args
,
**
kwargs
)
return
ins
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