Setup module no longer saves to disk, as templates are mostly useful in playbooks and this allows lots of simplifications

around file pathing and removes occasional permissions conflicts depending on how things are used.
This commit is contained in:
Michael DeHaan 2012-07-14 11:59:12 -04:00
parent 2a2017f295
commit 931f9f1a61
9 changed files with 10 additions and 196 deletions

View file

@ -19,6 +19,7 @@ Ansible Changes By Release
* fetch module fixes for SSH connection type * fetch module fixes for SSH connection type
* modules now consistently all take yes/no for boolean parameters (some accepted true/false) * modules now consistently all take yes/no for boolean parameters (some accepted true/false)
* in YAML inventory, hosts can list their groups in inverted order now also (see tests/yaml_hosts) * in YAML inventory, hosts can list their groups in inverted order now also (see tests/yaml_hosts)
* setup module no longer saves to disk, template module now only used in playbooks
0.5 "Amsterdam" ------- July 04, 2012 0.5 "Amsterdam" ------- July 04, 2012

View file

@ -545,6 +545,9 @@ class Runner(object):
def _execute_template(self, conn, tmp): def _execute_template(self, conn, tmp):
''' handler for template operations ''' ''' handler for template operations '''
if not self.is_playbook:
raise errors.AnsibleError("in current versions of ansible, templates are only usable in playbooks")
# load up options # load up options
options = utils.parse_kv(self.module_args) options = utils.parse_kv(self.module_args)
source = options.get('src', None) source = options.get('src', None)
@ -571,38 +574,11 @@ class Runner(object):
result = dict(failed=True, msg="could not find src in first_available_file list") result = dict(failed=True, msg="could not find src in first_available_file list")
return ReturnData(host=conn.host, comm_ok=False, result=result) return ReturnData(host=conn.host, comm_ok=False, result=result)
if self.module_vars is not None: if self.module_vars is not None:
inject.update(self.module_vars) inject.update(self.module_vars)
source = utils.template(source, inject, self.setup_cache) source = utils.template(source, inject, self.setup_cache)
#(host, ok, data, err) = (None, None, None, None)
if not self.is_playbook:
# not running from a playbook so we have to fetch the remote
# setup file contents before proceeding...
if metadata is None:
if self.remote_user == 'root':
metadata = '/etc/ansible/setup'
else:
# path is expanded on remote side
metadata = "~/.ansible/tmp/setup"
# install the template module
slurp_module = self._transfer_module(conn, tmp, 'slurp')
# run the slurp module to get the metadata file
args = "src=%s" % metadata
result1 = self._execute_module(conn, tmp, slurp_module, args)
if not 'content' in result1.result or result1.result.get('encoding','base64') != 'base64':
result1.result['failed'] = True
return result1
content = base64.b64decode(result1.result['content'])
inject = utils.json_loads(content)
# install the template module # install the template module
copy_module = self._transfer_module(conn, tmp, 'copy') copy_module = self._transfer_module(conn, tmp, 'copy')

View file

@ -1,24 +1 @@
#!/usr/bin/python # this is a virtual module that is entirely implemented server side
# (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/>.
#
### THIS FILE IS FOR REFERENCE OR FUTURE USE ###
# See lib/ansible/runner.py for implementation of the fetch functionality #

View file

@ -1,23 +1 @@
#!/usr/bin/python # this is a virtual module that is entirely implemented server side
# (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/>.
# hey the Ansible raw module isn't really a remote transferred
# module. All the magic happens in Runner.py, see the web docs
# for more details.

View file

@ -17,8 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DEFAULT_ANSIBLE_SETUP = "/etc/ansible/setup"
import array import array
import fcntl import fcntl
import glob import glob
@ -33,11 +31,6 @@ import subprocess
import traceback import traceback
import syslog import syslog
try:
from hashlib import md5 as _md5
except ImportError:
from md5 import md5 as _md5
try: try:
import selinux import selinux
HAVE_SELINUX=True HAVE_SELINUX=True
@ -316,20 +309,6 @@ def ansible_facts():
get_service_facts(facts) get_service_facts(facts)
return facts return facts
def md5(filename):
''' Return MD5 hex digest of local file, or None if file is not present. '''
if not os.path.exists(filename):
return None
digest = _md5()
blocksize = 64 * 1024
infile = open(filename, 'rb')
block = infile.read(blocksize)
while block:
digest.update(block)
block = infile.read(blocksize)
infile.close()
return digest.hexdigest()
# =========================================== # ===========================================
# load config & template variables # load config & template variables
@ -355,21 +334,6 @@ except:
syslog.openlog('ansible-%s' % os.path.basename(__file__)) syslog.openlog('ansible-%s' % os.path.basename(__file__))
syslog.syslog(syslog.LOG_NOTICE, 'Invoked with %s' % setup_options) syslog.syslog(syslog.LOG_NOTICE, 'Invoked with %s' % setup_options)
ansible_file = os.path.expandvars(setup_options.get('metadata', DEFAULT_ANSIBLE_SETUP))
ansible_dir = os.path.dirname(ansible_file)
# create the config dir if it doesn't exist
if not os.path.exists(ansible_dir):
os.makedirs(ansible_dir)
changed = False
md5sum = None
if not os.path.exists(ansible_file):
changed = True
else:
md5sum = md5(ansible_file)
# Get some basic facts in case facter or ohai are not installed # Get some basic facts in case facter or ohai are not installed
for (k, v) in ansible_facts().items(): for (k, v) in ansible_facts().items():
setup_options["ansible_%s" % k] = v setup_options["ansible_%s" % k] = v
@ -409,23 +373,7 @@ if os.path.exists("/usr/bin/ohai"):
k2 = "ohai_%s" % k k2 = "ohai_%s" % k
setup_options[k2] = v setup_options[k2] = v
# write the template/settings file using
# instructions from server
f = open(ansible_file, "w+")
reformat = json.dumps(setup_options, sort_keys=True, indent=4)
f.write(reformat)
f.close()
md5sum2 = md5(ansible_file)
if md5sum != md5sum2:
changed = True
setup_result = {} setup_result = {}
setup_result['written'] = ansible_file
setup_result['changed'] = changed
setup_result['md5sum'] = md5sum2
setup_result['ansible_facts'] = setup_options setup_result['ansible_facts'] = setup_options
# hack to keep --verbose from showing all the setup module results # hack to keep --verbose from showing all the setup module results

View file

@ -1,6 +1,3 @@
# VIRTUAL # There is actually no actual shell module source, when you use 'shell' in ansible,
# it runs the 'command' module with special arguments and it behaves differently.
There is actually no actual shell module source, when you use 'shell' in ansible, # See the command source and the comment "#USE_SHELL".
it runs the 'command' module with special arguments and it behaves differently.
See the command source and the comment "#USE_SHELL".

View file

@ -1,24 +1 @@
#!/usr/bin/python # this is a virtual module that is entirely implemented server side
# (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/>.
# hey the Ansible template module isn't really a remote transferred
# module. All the magic happens in Runner.py making use of the
# copy module, and if not running from a playbook, also the 'slurp'
# module.

View file

@ -119,28 +119,6 @@ class TestRunner(unittest.TestCase):
]) ])
assert result['changed'] == False assert result['changed'] == False
def test_template(self):
input_ = self._get_test_file('sample.j2')
metadata = self._get_test_file('metadata.json')
output = self._get_stage_file('sample.out')
result = self._run('template', [
"src=%s" % input_,
"dest=%s" % output,
"metadata=%s" % metadata
])
assert os.path.exists(output)
out = file(output).read()
assert out.find("duck") != -1
assert result['changed'] == True
assert 'md5sum' in result
assert 'failed' not in result
result = self._run('template', [
"src=%s" % input_,
"dest=%s" % output,
"metadata=%s" % metadata
])
assert result['changed'] == False
def test_command(self): def test_command(self):
# test command module, change trigger, etc # test command module, change trigger, etc
result = self._run('command', [ "/bin/echo", "hi" ]) result = self._run('command', [ "/bin/echo", "hi" ])
@ -177,21 +155,6 @@ class TestRunner(unittest.TestCase):
assert len(result['stdout']) > 100000 assert len(result['stdout']) > 100000
assert result['stderr'] == '' assert result['stderr'] == ''
def test_setup(self):
output = self._get_stage_file('output.json')
result = self._run('setup', [ "metadata=%s" % output, "a=2", "b=3", "c=4" ])
assert 'failed' not in result
assert 'md5sum' in result
assert result['changed'] == True
outds = json.loads(file(output).read())
assert outds['c'] == '4'
# not bothering to test change hooks here since ohai/facter results change
# almost every time so changed is always true, this just tests that
# rewriting the file is ok
result = self._run('setup', [ "metadata=%s" % output, "a=2", "b=3", "c=4" ])
print "RAW RESULT=%s" % result
assert 'md5sum' in result
def test_async(self): def test_async(self):
# test async launch and job status # test async launch and job status
# of any particular module # of any particular module

View file

@ -1,3 +0,0 @@
{
"answer" : "Where will we find a duck and a hose at this hour?"
}