From ce8f4b69bb6816bbb5c7c28bf68c7d2331ed2d00 Mon Sep 17 00:00:00 2001 From: Zachary Seguin Date: Tue, 8 Dec 2015 00:16:07 -0500 Subject: [PATCH] Initial commit --- .gitignore | 3 + README | 14 ++++ ansible.cfg | 19 +++++ hosts | 14 ++++ install-etckeeper.yml | 30 ++++++++ plugins/callback/log_plays/log_plays.py | 97 +++++++++++++++++++++++++ test-playbook.yml | 6 ++ upgrade-office.yml | 6 ++ 8 files changed, 189 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 ansible.cfg create mode 100644 hosts create mode 100644 install-etckeeper.yml create mode 100644 plugins/callback/log_plays/log_plays.py create mode 100644 test-playbook.yml create mode 100644 upgrade-office.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63a7abd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +logs/ +*.log +*.pyc diff --git a/README b/README new file mode 100644 index 0000000..db07f85 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ + ____ ____ ____ _ _ _ _ + / ___/ ___| / ___| / \ _ __ ___(_) |__ | | ___ + | | \___ \| | / _ \ | '_ \/ __| | '_ \| |/ _ \ + | |___ ___) | |___ / ___ \| | | \__ \ | |_) | | __/ + \____|____/ \____| /_/ \_\_| |_|___/_|_.__/|_|\___| + +Ansible playbooks of the University of Waterloo Computer Science Club. + +** Usage ** + +To run playbooks which require authentication as 'root': + + 1. kadmin -p sysadmin/admin + 2. execute the ansible playbook diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..afca5ff --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,19 @@ +[defaults] +# Settings +ask_sudo_pass = False +remote_tmp = /tmp/${USER}/ansible +nocows = 1 + +# Inventory +inventory = hosts + +# Logging +log_path = ansible.log + +# Plugins + +callback_plugins = plugins/callback/log_plays/ + +[ssh_connection] +ssh_args = -o ServerAliveInterval=30 -o ControlMaster=no + diff --git a/hosts b/hosts new file mode 100644 index 0000000..9dc79f0 --- /dev/null +++ b/hosts @@ -0,0 +1,14 @@ +[general-use] +caffeine.csclub.uwaterloo.ca +corn-syrup.csclub.uwaterloo.ca +high-fructose-corn-syrup.csclub.uwaterloo.ca +sucrose.csclub.uwaterloo.ca +taurine.csclub.uwaterloo.ca + +[office] +bit-shifter.csclub.uwaterloo.ca +gwem.csclub.uwaterloo.ca +maltodextrin.csclub.uwaterloo.ca +natural-flavours.csclub.uwaterloo.ca +nullsleep.csclub.uwaterloo.ca +strombola.csclub.uwaterloo.ca diff --git a/install-etckeeper.yml b/install-etckeeper.yml new file mode 100644 index 0000000..58bb6ec --- /dev/null +++ b/install-etckeeper.yml @@ -0,0 +1,30 @@ +--- + - hosts: all + remote_user: root + tasks: + - name: update apt cache + apt: update_cache=yes + - name: install git + apt: name=git state=present + - name: install etckeeper + apt: name=etckeeper state=present + register: etckeeper + - name: update etckeeper VCS + lineinfile: dest=/etc/etckeeper/etckeeper.conf + state=present + backrefs=yes + regexp={{ item.regex }} + line={{ item.line }} + with_items: + - { regex: '^(VCS=.*)$', line: '#\\1' } + - { regex: '^#(VCS=\"git\")$', line: '\\1' } + when: etckeeper.changed == true + - name: re-initialize etckeeper with git + command: "{{ item }}" + with_items: + - 'etckeeper uninit -f' + - 'etckeeper init' + - 'git commit -m "Initial commit"' + args: + chdir: /etc + when: etckeeper.changed == true diff --git a/plugins/callback/log_plays/log_plays.py b/plugins/callback/log_plays/log_plays.py new file mode 100644 index 0000000..dea0cf8 --- /dev/null +++ b/plugins/callback/log_plays/log_plays.py @@ -0,0 +1,97 @@ +# (C) 2012, Michael DeHaan, + +# 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 . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import time +import json + +from ansible.utils.unicode import to_bytes + +# NOTE: in Ansible 1.2 or later general logging is available without +# this plugin, just set ANSIBLE_LOG_PATH as an environment variable +# or log_path in the DEFAULTS section of your ansible configuration +# file. This callback is an example of per hosts logging for those +# that want it. + + +class CallbackModule(object): + """ + logs playbook results, per host, in /var/log/ansible/hosts + """ + CALLBACK_VERSION = 2.0 + CALLBACK_TYPE = 'notification' + CALLBACK_NAME = 'log_plays' + CALLBACK_NEEDS_WHITELIST = True + + TIME_FORMAT="%b %d %Y %H:%M:%S" + MSG_FORMAT="%(now)s - %(category)s - %(data)s\n\n" + + def __init__(self): + + super(CallbackModule, self).__init__() + + if not os.path.exists("./logs"): + os.makedirs("./logs") + + def log(self, host, category, data): + if type(data) == dict: + if '_ansible_verbose_override' in data: + # avoid logging extraneous data + data = 'omitted' + else: + data = data.copy() + invocation = data.pop('invocation', None) + + if invocation['module_name'] == 'setup': + data = json.dumps(data) + else: + data = json.dumps(data, indent=3, sort_keys=True, separators=(',', ': ')) + + if invocation is not None: + data = json.dumps(invocation, indent=3, sort_keys=True, separators=(',', ': ')) + " => %s " % data + + path = os.path.join("./logs/", host) + now = time.strftime(self.TIME_FORMAT, time.localtime()) + + msg = to_bytes(self.MSG_FORMAT % dict(now=now, category=category, data=data)) + with open(path, "ab") as fd: + fd.write(msg) + + def runner_on_failed(self, host, res, ignore_errors=False): + self.log(host, 'FAILED', res) + + def runner_on_ok(self, host, res): + self.log(host, 'OK', res) + + def runner_on_skipped(self, host, item=None): + self.log(host, 'SKIPPED', '...') + + def runner_on_unreachable(self, host, res): + self.log(host, 'UNREACHABLE', res) + + def runner_on_async_failed(self, host, res, jid): + self.log(host, 'ASYNC_FAILED', res) + + def playbook_on_import_for_host(self, host, imported_file): + self.log(host, 'IMPORTED', imported_file) + + def playbook_on_not_import_for_host(self, host, missing_file): + self.log(host, 'NOTIMPORTED', missing_file) diff --git a/test-playbook.yml b/test-playbook.yml new file mode 100644 index 0000000..1e36deb --- /dev/null +++ b/test-playbook.yml @@ -0,0 +1,6 @@ +--- + - hosts: office + remote_user: root + tasks: + - name: whoami + command: whoami diff --git a/upgrade-office.yml b/upgrade-office.yml new file mode 100644 index 0000000..2cfddb0 --- /dev/null +++ b/upgrade-office.yml @@ -0,0 +1,6 @@ +--- + - hosts: office + remote_user: root + tasks: + - name: upgrade software packages (safe) + apt: update_cache=yes upgrade=safe