From fa84c9c87d9c1195406919d51a8091808abe5d06 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Wed, 15 Feb 2017 15:47:16 +0100 Subject: [PATCH] Changing request for clearing cache to a curl execution --- lib/webhooks/__init__.py | 2 +- lib/webhooks/base_app.py | 79 ++++++++++++++++++++++++++ lib/webhooks/r10k.py | 120 +++++++++++++-------------------------- 3 files changed, 118 insertions(+), 83 deletions(-) diff --git a/lib/webhooks/__init__.py b/lib/webhooks/__init__.py index cfb1f3f..cd141fc 100644 --- a/lib/webhooks/__init__.py +++ b/lib/webhooks/__init__.py @@ -1,6 +1,6 @@ #!/bin/env python3 # -*- coding: utf-8 -*- -__version__ = '0.4.5' +__version__ = '0.4.6' # vim: ts=4 et list diff --git a/lib/webhooks/base_app.py b/lib/webhooks/base_app.py index 1ca90cf..074088d 100644 --- a/lib/webhooks/base_app.py +++ b/lib/webhooks/base_app.py @@ -89,6 +89,8 @@ class BaseHookApp(object): self.cmdline_args = None + self.curl_bin = None + self.error_data = [] self.smtp_server = 'smtp.pixelpark.com' self.smtp_port = 25 @@ -109,6 +111,8 @@ class BaseHookApp(object): self.read_config() self.init_logging() + self.search_curl_bin() + # ----------------------------------------------------------- @property def appname(self): @@ -257,6 +261,81 @@ class BaseHookApp(object): if not os.environ.get('REQUEST_METHOD', None): os.environ['REQUEST_METHOD'] = 'GET' + # ------------------------------------------------------------------------- + def get_cmd(self, cmd): + + if os.path.isabs(cmd): + if not os.path.exists(cmd): + LOG.error("Command {!r} does not exists.".format(cmd)) + return None + if not os.access(cmd, os.X_OK): + LOG.error("Command {!r} is not executable.".format(cmd)) + return None + return os.path.normpath(cmd) + + path_list = [] + cmd_abs = None + + search_path = os.environ.get('PATH', None) + if not search_path: + search_path = os.defpath + + search_path_list = [ + '/opt/pixelpark/bin', + '/www/bin', + ] + + search_path_list += search_path.split(os.pathsep) + + default_path = [ + '/usr/local/sbin', + '/usr/local/bin', + '/usr/sbin', + '/usr/bin', + '/sbin', + '/bin', + ] + search_path_list += default_path + + for d in search_path_list: + if not os.path.exists(d): + continue + if not os.path.isdir(d): + continue + d_abs = os.path.realpath(d) + if d_abs not in path_list: + path_list.append(d_abs) + + if self.verbose > 1: + LOG.debug("Searching for command {c!r} in:\n{p}".format( + c=cmd, p=pp(path_list))) + + for d in path_list: + p = os.path.join(d, cmd) + if os.path.exists(p): + if self.verbose > 2: + LOG.debug("Found {!r} ...".format(p)) + if os.access(p, os.X_OK): + cmd_abs = p + break + else: + LOG.debug("Command {!r} is not executable.".format(p)) + + if cmd_abs: + LOG.debug("Found {c!r} in {p!r}.".format(c=cmd, p=self.r10k_bin)) + else: + LOG.error("Command {!r} not found.".format(cmd)) + + return cmd_abs + + # ------------------------------------------------------------------------- + def search_curl_bin(self): + + cmd = self.get_cmd('curl') + if not cmd: + sys.exit(9) + self.curl_bin = cmd + # ------------------------------------------------------------------------- def read_config(self): """Reading configuration from different YAML files.""" diff --git a/lib/webhooks/r10k.py b/lib/webhooks/r10k.py index 976b707..583cfdd 100644 --- a/lib/webhooks/r10k.py +++ b/lib/webhooks/r10k.py @@ -15,13 +15,9 @@ import re import textwrap import datetime import locale -import ssl import pipes import subprocess import urllib.parse -import traceback - -from http.client import HTTPSConnection # Third party modules import yaml @@ -85,59 +81,10 @@ class R10kHookApp(BaseHookApp): # ------------------------------------------------------------------------- def search_r10k_bin(self): - path_list = [] - cmd = 'r10k' - - search_path = os.environ.get('PATH', None) - if not search_path: - search_path = os.defpath - - search_path_list = [ - '/opt/pixelpark/bin', - '/www/bin', - ] - - search_path_list += search_path.split(os.pathsep) - - default_path = [ - '/usr/local/sbin', - '/usr/local/bin', - '/usr/sbin', - '/usr/bin', - '/sbin', - '/bin', - ] - search_path_list += default_path - - for d in search_path_list: - if not os.path.exists(d): - continue - if not os.path.isdir(d): - continue - d_abs = os.path.realpath(d) - if d_abs not in path_list: - path_list.append(d_abs) - - if self.verbose > 1: - LOG.debug("Searching for command {c!r} in:\n{p}".format( - c=cmd, p=pp(path_list))) - - for d in path_list: - p = os.path.join(d, cmd) - if os.path.exists(p): - if self.verbose > 2: - LOG.debug("Found {!r} ...".format(p)) - if os.access(p, os.X_OK): - self.r10k_bin = p - break - else: - LOG.debug("Command {!r} is not executable.".format(p)) - - if self.r10k_bin: - LOG.debug("Found {c!r} in {p!r}.".format(c=cmd, p=self.r10k_bin)) - else: - LOG.error("Command {!r} not found.".format(cmd)) + cmd = self.get_cmd('r10k') + if not cmd: sys.exit(9) + self.r10k_bin = cmd # ------------------------------------------------------------------------- def check_cert_files(self): @@ -231,29 +178,11 @@ class R10kHookApp(BaseHookApp): LOG.warn("Executing {!r} was not successful.".format(self.r10k_bin)) return - ssl_context = None - try: - ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) - except Exception as e: - LOG.error("Got a {c}: {e}".format(c=e.__class__.__name__, e=e)) - else: - ssl_context.verify_mode = ssl.CERT_NONE - ssl_context.check_hostname = False - key_file = os.path.join( self.puppetmaster_ssl_dir, 'private_keys', self.puppetmaster_host + '.pem') cert_file = os.path.join( self.puppetmaster_ssl_dir, 'certs', self.puppetmaster_host + '.pem') - LOG.debug("Creating connection to https://{h}:{p} ...".format( - h=self.puppetmaster_host, p=self.puppetmaster_api_port)) - conn = HTTPSConnection( - self.puppetmaster_host, self.puppetmaster_api_port, - key_file=key_file, cert_file=cert_file, timeout=self.http_timeout, - context=ssl_context) - if self.verbose > 1: - LOG.debug("HTTPS connection object: {!r}".format(conn)) - path = ( self.puppetmaster_api_path + '/environment-cache?environment=' + urllib.parse.quote(self.ref)) @@ -261,18 +190,45 @@ class R10kHookApp(BaseHookApp): h=self.puppetmaster_host, po=self.puppetmaster_api_port, pa=path) LOG.info("Requesting DELETE from {} ...".format(url)) + cmd = [] + if self.do_sudo: + cmd = ['sudo', '-n'] + + cmd += [ + self.curl_bin, '-i', + '--cert', cert_file, + '--key', key_file, + '-X', 'DELETE', + url, + ] + cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd)) + if self.verbose > 2: + LOG.debug("Cmd: {}".format(pp(cmd))) + LOG.debug("Executing: {}".format(cmd_str)) + if self.simulate: - LOG.info("Simulation mode, don't requesting {}.".format(url)) + LOG.info("Simulation mode, don't executing {}.".format(self.curl_bin)) return - conn.request('DELETE', path) - response = conn.getresponse() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdoutdata, stderrdata) = proc.communicate() + ret_val = proc.wait() - LOG.info("Response: {s} {r}".format(s=response.status, r=response.reason)) - if response.status != 200: - msg = 'Error on clearing Puppet cache:' - self.error_data.append(msg) - LOG.error(msg) + LOG.debug("Return value: {}".format(ret_val)) + if stdoutdata: + msg = "Output:\n{}".format(to_str(stdoutdata)) + LOG.debug(msg) + self.print_out(msg) + else: + LOG.debug("No output.") + if stderrdata: + msg = "Error messages on '{c}':\n{e}".format(c=cmd_str, e=to_str(stderrdata)) + if ret_val: + LOG.warn(msg) + self.error_data.append(msg) + else: + LOG.debug(msg) + self.print_out(msg) return -- 2.39.5