From a192814194dd26978f78a38eb52eefc60bf1254d Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 13 Sep 2016 11:56:05 -0500 Subject: [PATCH] Put script string in directly instead of in files Now that we're using the command module, just do inline script content to make debugging/reading easier. Change-Id: Ia63f77fd41a03b4662c26f9d0f3b70d1e6a8b5d3 --- zuul/launcher/ansiblelaunchserver.py | 65 +++++++++++++++++++--------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/zuul/launcher/ansiblelaunchserver.py b/zuul/launcher/ansiblelaunchserver.py index 5c6b06cdab..4f02938e68 100644 --- a/zuul/launcher/ansiblelaunchserver.py +++ b/zuul/launcher/ansiblelaunchserver.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import getopt import json import logging import os @@ -25,7 +26,6 @@ import threading import time import traceback import Queue -import uuid import gear import yaml @@ -52,6 +52,45 @@ def boolify(x): return bool(x) +def deal_with_shebang(data): + # Ansible shell blocks do not honor shebang lines. That's fine - but + # we do have a bunch of scripts that have either nothing, -x, -xe, + # -ex or -eux. Transform those into leading set commands + if not data.startswith('#!'): + return (None, data) + data_lines = data.split('\n') + data_lines.reverse() + shebang = data_lines.pop() + split_line = shebang.split() + # Strip the # and the ! + executable = split_line[0][2:] + if executable == '/bin/sh': + # Ansible default + executable = None + if len(split_line) > 1: + flag_x = False + flag_e = False + flag_u = False + optlist, args = getopt.getopt(split_line[1:], 'uex') + for opt, _ in optlist: + if opt == '-x': + flag_x = True + elif opt == '-e': + flag_e = True + elif opt == '-u': + flag_u = True + + if flag_x: + data_lines.append('set -x') + if flag_e: + data_lines.append('set -e') + if flag_u: + data_lines.append('set -u') + data_lines.reverse() + data = '\n'.join(data_lines) + return (executable, data) + + class LaunchGearWorker(gear.Worker): def __init__(self, *args, **kw): self.__launch_server = kw.pop('launch_server') @@ -116,9 +155,7 @@ class JobDir(object): self.playbook = os.path.join(self.ansible_root, 'playbook') self.post_playbook = os.path.join(self.ansible_root, 'post_playbook') self.config = os.path.join(self.ansible_root, 'ansible.cfg') - self.script_root = os.path.join(self.ansible_root, 'scripts') self.ansible_log = os.path.join(self.ansible_root, 'ansible_log.txt') - os.makedirs(self.script_root) self.staging_root = os.path.join(self.root, 'staging') os.makedirs(self.staging_root) @@ -1272,22 +1309,10 @@ class NodeWorker(object): def _makeBuilderTask(self, jobdir, builder, parameters): tasks = [] - script_fn = '%s.sh' % str(uuid.uuid4().hex) - script_path = os.path.join(jobdir.script_root, script_fn) - with open(script_path, 'w') as script: - data = builder['shell'] - if not data.startswith('#!'): - data = '#!/bin/bash -x\n %s' % (data,) - script.write(data) - remote_path = os.path.join('/tmp', script_fn) - copy = dict(src=script_path, - dest=remote_path, - mode=0o555) - task = dict(copy=copy) - tasks.append(task) + (executable, shell) = deal_with_shebang(builder['shell']) - task = dict(command=remote_path) + task = dict(shell=shell) task['name'] = ('command with {{ timeout | int - elapsed_time }} ' 'second timeout') task['when'] = '{{ elapsed_time < timeout | int }}' @@ -1295,11 +1320,9 @@ class NodeWorker(object): task['poll'] = 5 task['environment'] = parameters task['args'] = dict(chdir=parameters['WORKSPACE']) - tasks.append(task) + if executable: + task['args']['executable'] = executable - filetask = dict(path=remote_path, - state='absent') - task = dict(file=filetask) tasks.append(task) return tasks