Remove debops* bin…
This commit is contained in:
parent
b0d36ad389
commit
2eafc4907e
180
debops
180
debops
|
@ -1,180 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
debops: run ansible-playbook with some customization
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import ConfigParser
|
|
||||||
|
|
||||||
import ansible
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
|
|
||||||
PATHSEP = ':'
|
|
||||||
|
|
||||||
ConfigFileHeader = """\
|
|
||||||
# Ansible configuration file generated by DebOps, all changes will be lost.
|
|
||||||
# You can manipulate the contents of this file via `.debops.cfg`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def write_config(filename, config):
|
|
||||||
cfgparser = ConfigParser.ConfigParser()
|
|
||||||
for section, pairs in config.items():
|
|
||||||
cfgparser.add_section(section)
|
|
||||||
for option, value in pairs.items():
|
|
||||||
cfgparser.set(section, option, value)
|
|
||||||
|
|
||||||
with open(filename, "w") as fh:
|
|
||||||
print(ConfigFileHeader, file=fh)
|
|
||||||
cfgparser.write(fh)
|
|
||||||
|
|
||||||
|
|
||||||
def gen_ansible_cfg(filename, config, project_root, playbooks_path,
|
|
||||||
inventory_path):
|
|
||||||
# Generate Ansible configuration file
|
|
||||||
|
|
||||||
def custom_paths(type):
|
|
||||||
if type in defaults:
|
|
||||||
# prepend value from .debops.cfg
|
|
||||||
yield defaults[type]
|
|
||||||
yield os.path.join(project_root, "ansible", type)
|
|
||||||
yield os.path.join(playbooks_path, type)
|
|
||||||
yield os.path.join("/usr/share/ansible/", type)
|
|
||||||
|
|
||||||
# Add custom configuration options to ansible.cfg: Take values
|
|
||||||
# from [ansible ...] sections of the .debops.cfg file
|
|
||||||
# Note: To set debops default values, use debops.config.DEFAULTS
|
|
||||||
cfg = dict((sect.split(None, 1)[1], pairs)
|
|
||||||
for sect, pairs in config.items() if sect.startswith('ansible '))
|
|
||||||
|
|
||||||
defaults = cfg.setdefault('defaults', {})
|
|
||||||
defaults['inventory'] = inventory_path
|
|
||||||
defaults['roles_path'] = PATHSEP.join(filter(None, (
|
|
||||||
defaults.get('roles_path'), # value from .debops.cfg or None
|
|
||||||
os.path.join(project_root, "roles"),
|
|
||||||
os.path.join(project_root, "ansible", "roles"),
|
|
||||||
os.path.join(playbooks_path, "..", "roles"),
|
|
||||||
os.path.join(playbooks_path, "roles"),
|
|
||||||
"/etc/ansible/roles")))
|
|
||||||
for plugin_type in ('action', 'callback', 'connection',
|
|
||||||
'filter', 'lookup', 'vars'):
|
|
||||||
plugin_type = plugin_type+"_plugins"
|
|
||||||
defaults[plugin_type] = PATHSEP.join(custom_paths(plugin_type))
|
|
||||||
|
|
||||||
if ansible.__version__ >= "1.7":
|
|
||||||
# work around a bug obviously introduced in 1.7, see
|
|
||||||
# https://github.com/ansible/ansible/issues/8555
|
|
||||||
if ' ' in defaults[plugin_type]:
|
|
||||||
defaults[plugin_type] = PATHSEP.join(
|
|
||||||
'"%s"' % p for p in defaults[plugin_type].split(PATHSEP))
|
|
||||||
|
|
||||||
defaults['library'] = PATHSEP.join(custom_paths('library'))
|
|
||||||
|
|
||||||
write_config(filename, cfg)
|
|
||||||
|
|
||||||
|
|
||||||
def main(cmd_args):
|
|
||||||
project_root = find_debops_project(required=True)
|
|
||||||
config = read_config(project_root)
|
|
||||||
playbooks_path = find_playbookpath(config, project_root, required=True)
|
|
||||||
|
|
||||||
# Make sure required commands are present
|
|
||||||
require_commands('ansible-playbook')
|
|
||||||
|
|
||||||
def find_playbook(playbook):
|
|
||||||
tries = [
|
|
||||||
(project_root, "playbooks", playbook),
|
|
||||||
(project_root, "ansible", "playbooks", playbook),
|
|
||||||
(playbooks_path, playbook),
|
|
||||||
]
|
|
||||||
|
|
||||||
if 'playbooks_path' in config['paths']:
|
|
||||||
tries += [(custom_path, playbook) for custom_path in
|
|
||||||
config['paths']['playbooks_path'].split(PATHSEP)]
|
|
||||||
|
|
||||||
for parts in tries:
|
|
||||||
play = os.path.join(*parts)
|
|
||||||
if os.path.isfile(play):
|
|
||||||
return play
|
|
||||||
|
|
||||||
# Check if user specified a potential playbook name as the first
|
|
||||||
# argument. If yes, use it as the playbook name and remove it from
|
|
||||||
# the argument list
|
|
||||||
play = None
|
|
||||||
if len(cmd_args) > 0:
|
|
||||||
maybe_play = cmd_args[0]
|
|
||||||
if os.path.isfile(maybe_play):
|
|
||||||
play = maybe_play
|
|
||||||
else:
|
|
||||||
play = find_playbook(maybe_play + ".yml")
|
|
||||||
if play:
|
|
||||||
cmd_args.pop(0)
|
|
||||||
del maybe_play
|
|
||||||
if not play:
|
|
||||||
play = find_playbook("site.yml")
|
|
||||||
|
|
||||||
inventory_path = find_inventorypath(project_root)
|
|
||||||
os.environ['ANSIBLE_HOSTS'] = inventory_path
|
|
||||||
|
|
||||||
ansible_config_file = os.path.join(project_root, ANSIBLE_CONFIG_FILE)
|
|
||||||
os.environ['ANSIBLE_CONFIG'] = os.path.abspath(ansible_config_file)
|
|
||||||
gen_ansible_cfg(ansible_config_file, config, project_root, playbooks_path,
|
|
||||||
inventory_path)
|
|
||||||
|
|
||||||
# Allow insecure SSH connections if requested
|
|
||||||
if INSECURE:
|
|
||||||
os.environ['ANSIBLE_HOST_KEY_CHECKING'] = 'False'
|
|
||||||
|
|
||||||
# Create path to EncFS encrypted directory, based on inventory name
|
|
||||||
encfs_encrypted = os.path.join(os.path.dirname(inventory_path),
|
|
||||||
ENCFS_PREFIX + SECRET_NAME)
|
|
||||||
|
|
||||||
# Check if encrypted secret directory exists and use it
|
|
||||||
revert_unlock = padlock_unlock(encfs_encrypted)
|
|
||||||
try:
|
|
||||||
# Run ansible-playbook with custom environment
|
|
||||||
print("Running Ansible playbook from:")
|
|
||||||
print(play, "...")
|
|
||||||
return subprocess.call(['ansible-playbook', play] + cmd_args)
|
|
||||||
finally:
|
|
||||||
if revert_unlock:
|
|
||||||
padlock_lock(encfs_encrypted)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
sys.exit(main(sys.argv[1:]))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit('... aborted')
|
|
111
debops-defaults
111
debops-defaults
|
@ -1,111 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
debops-defaults: aggregate all defaults from Ansible roles into one stream
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import codecs
|
|
||||||
import subprocess
|
|
||||||
import glob
|
|
||||||
import argparse
|
|
||||||
import errno
|
|
||||||
|
|
||||||
reload(sys)
|
|
||||||
sys.setdefaultencoding('utf-8')
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
def cat(filename, outstream):
|
|
||||||
try:
|
|
||||||
fh = codecs.open(filename, encoding=sys.getdefaultencoding())
|
|
||||||
except IOError, e:
|
|
||||||
# This should only happen if the user listed a unknown role.
|
|
||||||
outstream.write('%s: %s\n' % (e.strerror, e.filename))
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
# Read input file as Unicode object and pass it to outstream.
|
|
||||||
outstream.write(fh.read())
|
|
||||||
finally:
|
|
||||||
fh.close()
|
|
||||||
|
|
||||||
def aggregate_defaults(playbooks_path, role_list, outstream):
|
|
||||||
# Aggregate role/defaults/main.yml files from all roles into one stream
|
|
||||||
roles_path = os.path.normpath(os.path.join(playbooks_path, '..', 'roles'))
|
|
||||||
if role_list:
|
|
||||||
for role in role_list:
|
|
||||||
if not '.' in role:
|
|
||||||
role = ROLE_PREFIX + '.' + role
|
|
||||||
fn = os.path.join(roles_path, role, 'defaults', 'main.yml')
|
|
||||||
cat(fn, outstream=outstream)
|
|
||||||
else:
|
|
||||||
for fn in glob.glob(os.path.join(roles_path,
|
|
||||||
'*', 'defaults', 'main.yml')):
|
|
||||||
cat(fn, outstream=outstream)
|
|
||||||
|
|
||||||
# ---- DebOps environment setup ----
|
|
||||||
|
|
||||||
def main(role_list):
|
|
||||||
project_root = find_debops_project(required=False)
|
|
||||||
config = read_config(project_root)
|
|
||||||
playbooks_path = find_playbookpath(config, project_root, required=True)
|
|
||||||
|
|
||||||
# Make sure required commands are present
|
|
||||||
require_commands('view')
|
|
||||||
|
|
||||||
if sys.stdout.isatty():
|
|
||||||
# if script is run as standalone, redirect to view
|
|
||||||
view = subprocess.Popen(['view', '+set ft=yaml', '-'],
|
|
||||||
stdin=subprocess.PIPE)
|
|
||||||
try:
|
|
||||||
aggregate_defaults(playbooks_path, role_list, view.stdin)
|
|
||||||
except IOError, e:
|
|
||||||
if e.errno not in (errno.EPIPE, errno.EINVAL):
|
|
||||||
# "Invalid pipe" or "Invalid argument"
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
view.communicate()
|
|
||||||
else:
|
|
||||||
# else, send everything to stdout
|
|
||||||
aggregate_defaults(playbooks_path, role_list, sys.stdout)
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('role', nargs='*')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
try:
|
|
||||||
main(args.role)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit('... aborted')
|
|
205
debops-init
205
debops-init
|
@ -1,205 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
debops-init: create a new DebOps project directory
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import codecs
|
|
||||||
import subprocess
|
|
||||||
import glob
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
SKEL_DIRS = (
|
|
||||||
os.path.join("ansible", INVENTORY, "group_vars", "all"),
|
|
||||||
os.path.join("ansible", INVENTORY, "host_vars"),
|
|
||||||
os.path.join("ansible", "playbooks"),
|
|
||||||
os.path.join("ansible", "roles"),
|
|
||||||
)
|
|
||||||
|
|
||||||
DEFAULT_DEBOPS_CONFIG = """
|
|
||||||
# -*- conf -*-
|
|
||||||
|
|
||||||
[paths]
|
|
||||||
;data-home: /opt/debops
|
|
||||||
|
|
||||||
[ansible defaults]
|
|
||||||
display_skipped_hosts = False
|
|
||||||
retry_files_enabled = False
|
|
||||||
;callback_plugins = /my/plugins/callback
|
|
||||||
;roles_path = /my/roles
|
|
||||||
|
|
||||||
[ansible paramiko]
|
|
||||||
;record_host_keys=True
|
|
||||||
|
|
||||||
[ansible ssh_connection]
|
|
||||||
;ssh_args = -o ControlMaster=auto -o ControlPersist=60s
|
|
||||||
"""
|
|
||||||
|
|
||||||
DEFAULT_GITIGNORE = """\
|
|
||||||
ansible/{SECRET_NAME}
|
|
||||||
{SECRET_NAME}
|
|
||||||
{ENCFS_PREFIX}{SECRET_NAME}
|
|
||||||
ansible.cfg
|
|
||||||
|
|
||||||
#-- python
|
|
||||||
*.py[co]
|
|
||||||
|
|
||||||
#-- vim
|
|
||||||
[._]*.s[a-w][a-z]
|
|
||||||
[._]s[a-w][a-z]
|
|
||||||
*.un~
|
|
||||||
Session.vim
|
|
||||||
.netrwhist
|
|
||||||
*~
|
|
||||||
|
|
||||||
#-- Emacs
|
|
||||||
\#*\#
|
|
||||||
/.emacs.desktop
|
|
||||||
/.emacs.desktop.lock
|
|
||||||
*.elc
|
|
||||||
auto-save-list
|
|
||||||
tramp
|
|
||||||
.\#*
|
|
||||||
|
|
||||||
#-- SublimeText
|
|
||||||
*.sublime-workspace
|
|
||||||
#*.sublime-project
|
|
||||||
|
|
||||||
#-- sftp configuration file
|
|
||||||
sftp-config.json
|
|
||||||
"""
|
|
||||||
|
|
||||||
HOSTS_FILE_HEADER = """\
|
|
||||||
# This is an Ansible inventory file in INI format. You can define a list of
|
|
||||||
# hosts and groups to be managed by this particular inventory.
|
|
||||||
|
|
||||||
# Hosts listed under [debops_all_hosts] will have common DebOps plays
|
|
||||||
# ran against them. It will include services such as iptables, DNS, Postfix,
|
|
||||||
# sshd configuration and more.
|
|
||||||
#
|
|
||||||
# View the list here:
|
|
||||||
# https://github.com/debops/debops-playbooks/blob/master/playbooks/common.yml
|
|
||||||
#
|
|
||||||
# You should check Getting Started guide for useful suggestions:
|
|
||||||
# https://docs.debops.org/en/latest/debops-playbooks/docs/guides/getting-started.html
|
|
||||||
"""
|
|
||||||
|
|
||||||
HOSTS_FILE_CONTENT_CONTROLER = """
|
|
||||||
# Your host is eligible to be managed by DebOps' common playbook. If you want
|
|
||||||
# that functionality and more, then uncomment your hostname below.
|
|
||||||
|
|
||||||
[debops_all_hosts]
|
|
||||||
#%s ansible_connection=local
|
|
||||||
""" % platform.node()
|
|
||||||
|
|
||||||
HOSTS_FILE_CONTENT_NO_CONTROLER = """
|
|
||||||
# Your host was not detected as compatible with DebOps playbooks, so you will
|
|
||||||
# not be able to leverage the above features on your current operating system.
|
|
||||||
# You can however use a virtual machine as the Ansible Controller.
|
|
||||||
|
|
||||||
[debops_all_hosts]
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def write_file(filename, *content):
|
|
||||||
"""
|
|
||||||
If file:`filename` does not exist, create it and write
|
|
||||||
var:`content` into it.
|
|
||||||
"""
|
|
||||||
if not os.path.exists(filename):
|
|
||||||
with open(filename, "w") as fh:
|
|
||||||
fh.writelines(content)
|
|
||||||
|
|
||||||
|
|
||||||
def write_config_files(project_root):
|
|
||||||
"""
|
|
||||||
Create the default debops-config files in the dir:`project_root`
|
|
||||||
directory.
|
|
||||||
"""
|
|
||||||
# Create .debops.cfg
|
|
||||||
write_file(os.path.join(project_root, DEBOPS_CONFIG), DEFAULT_DEBOPS_CONFIG)
|
|
||||||
# Create .gitignore
|
|
||||||
write_file(os.path.join(project_root, '.gitignore'),
|
|
||||||
DEFAULT_GITIGNORE.format(SECRET_NAME=SECRET_NAME, ENCFS_PREFIX=ENCFS_PREFIX))
|
|
||||||
|
|
||||||
hosts_filename = os.path.join(project_root, "ansible", INVENTORY, "hosts")
|
|
||||||
# Swap in different hosts file content depending on the host's OS/distro
|
|
||||||
if (platform.system() == "Linux" and
|
|
||||||
platform.linux_distribution()[0].lower() in ("debian", "ubuntu")):
|
|
||||||
write_file(hosts_filename,
|
|
||||||
HOSTS_FILE_HEADER, HOSTS_FILE_CONTENT_CONTROLER)
|
|
||||||
else:
|
|
||||||
write_file(hosts_filename,
|
|
||||||
HOSTS_FILE_HEADER, HOSTS_FILE_CONTENT_NO_CONTROLER)
|
|
||||||
|
|
||||||
|
|
||||||
def main(project_root):
|
|
||||||
orig_project_root = project_root
|
|
||||||
project_root = os.path.abspath(project_root)
|
|
||||||
|
|
||||||
#-- Check for existing debops project directory
|
|
||||||
debops_project_root = find_debops_project(project_root, required=False)
|
|
||||||
|
|
||||||
# Exit if DebOps configuration file has been found in project_dir
|
|
||||||
if os.path.exists(os.path.join(project_root, DEBOPS_CONFIG)):
|
|
||||||
error_msg("%s is already a DebOps project directory" % project_root)
|
|
||||||
|
|
||||||
# Exit if we are in a DebOps project dir and nested project would be created
|
|
||||||
if debops_project_root:
|
|
||||||
error_msg("You are inside %s project already" % debops_project_root)
|
|
||||||
|
|
||||||
#-- Main script
|
|
||||||
|
|
||||||
print("Creating new DebOps project directory in", orig_project_root, "...")
|
|
||||||
|
|
||||||
# Create base project directories
|
|
||||||
for skel_dir in SKEL_DIRS:
|
|
||||||
skel_dir = os.path.join(project_root, skel_dir)
|
|
||||||
if not os.path.isdir(skel_dir):
|
|
||||||
os.makedirs(skel_dir)
|
|
||||||
# Write default config files
|
|
||||||
write_config_files(project_root)
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('project_dir', default=os.curdir)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
try:
|
|
||||||
main(args.project_dir)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit('... aborted')
|
|
187
debops-padlock
187
debops-padlock
|
@ -1,187 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
debops-padlock: encrypt secret directory with EncFS and GPG
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import argparse
|
|
||||||
import itertools
|
|
||||||
import stat
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
from pkg_resources import resource_filename
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
def gen_pwd():
|
|
||||||
from string import ascii_letters, digits, punctuation
|
|
||||||
import random
|
|
||||||
ALLCHARS = digits + ascii_letters + punctuation
|
|
||||||
ALLCHARS = digits + ascii_letters + '-_!@#$%^&*()_+{}|:<>?='
|
|
||||||
pwd = ''.join(random.choice(ALLCHARS) for i in range(ENCFS_KEYFILE_LENGTH))
|
|
||||||
return pwd
|
|
||||||
|
|
||||||
|
|
||||||
# Randomness source for EncFS keyfile generation
|
|
||||||
devrandom = os.environ.get('DEVRANDOM', "/dev/urandom")
|
|
||||||
|
|
||||||
SCRIPT_FILENAME = 'padlock-script'
|
|
||||||
|
|
||||||
# ---- DebOps environment setup ----
|
|
||||||
|
|
||||||
def main(subcommand_func, **kwargs):
|
|
||||||
project_root = find_debops_project(required=True)
|
|
||||||
# :todo: Source DebOps configuration file
|
|
||||||
#[ -r ${debops_config} ] && source ${debops_config}
|
|
||||||
|
|
||||||
# ---- Main script ----
|
|
||||||
|
|
||||||
# Make sure required commands are present
|
|
||||||
require_commands('encfs', 'find', 'fusermount', 'gpg')
|
|
||||||
|
|
||||||
inventory_path = find_inventorypath(project_root, required=False)
|
|
||||||
# If inventory hasn't been found automatically, assume it's the default
|
|
||||||
if not inventory_path:
|
|
||||||
inventory_path = os.path.join(project_root, 'ansible', INVENTORY)
|
|
||||||
|
|
||||||
# Create names of EncFS encrypted and decrypted directories, based on
|
|
||||||
# inventory name (absolute paths are specified)
|
|
||||||
encfs_encrypted = os.path.join(os.path.dirname(inventory_path),
|
|
||||||
ENCFS_PREFIX + SECRET_NAME)
|
|
||||||
encfs_decrypted = os.path.join(os.path.dirname(inventory_path),
|
|
||||||
SECRET_NAME)
|
|
||||||
subcommand_func(encfs_decrypted, encfs_encrypted, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def init(encfs_decrypted, encfs_encrypted, recipients):
|
|
||||||
# EncFS cannot create encrypted directory if directory with
|
|
||||||
# decrypted data is not empty
|
|
||||||
if not os.path.exists(encfs_decrypted):
|
|
||||||
os.makedirs(encfs_decrypted)
|
|
||||||
elif os.listdir(encfs_decrypted):
|
|
||||||
error_msg("secret directory not empty")
|
|
||||||
|
|
||||||
# Quit if encrypted directory already exists.
|
|
||||||
if os.path.isdir(encfs_encrypted):
|
|
||||||
error_msg("EncFS directory already exists")
|
|
||||||
os.makedirs(encfs_encrypted)
|
|
||||||
|
|
||||||
encfs_keyfile = os.path.join(encfs_encrypted, ENCFS_KEYFILE)
|
|
||||||
encfs_configfile = os.path.join(encfs_encrypted, ENCFS_CONFIGFILE)
|
|
||||||
|
|
||||||
# put a `-r` in front of each recipient for passing as args to gpg
|
|
||||||
recipients = list(itertools.chain.from_iterable(['-r', r]
|
|
||||||
for r in recipients))
|
|
||||||
|
|
||||||
# Generate a random password and encrypt it with GPG keys of recipients.
|
|
||||||
print("Generating a random", ENCFS_KEYFILE_LENGTH, "char password")
|
|
||||||
pwd = gen_pwd()
|
|
||||||
gpg = subprocess.Popen(['gpg', '--encrypt', '--armor',
|
|
||||||
'--output', encfs_keyfile] + recipients,
|
|
||||||
stdin=subprocess.PIPE)
|
|
||||||
gpg.communicate(pwd)
|
|
||||||
|
|
||||||
# Mount the encfs to the config file will be written. Tell encfs
|
|
||||||
# it to ask gpg for the password.
|
|
||||||
# NB1: Alternativly we could use --stdinpass, but using --extpass makes
|
|
||||||
# the user check if she has the correct passphrase early.
|
|
||||||
# NB2: We can not use padlock_unlock here, because the config file
|
|
||||||
# does not yet exist.
|
|
||||||
encfs = subprocess.Popen([
|
|
||||||
'encfs', encfs_encrypted, encfs_decrypted,
|
|
||||||
'--extpass', 'gpg --no-mdc-warning --output - '+shquote(encfs_keyfile)],
|
|
||||||
stdin=subprocess.PIPE)
|
|
||||||
encfs.communicate('p\n'+pwd)
|
|
||||||
|
|
||||||
# Create padlock-script
|
|
||||||
padlock_script = os.path.join(encfs_encrypted, PADLOCK_CMD)
|
|
||||||
|
|
||||||
# :todo: use resource_stream
|
|
||||||
shutil.copy(resource_filename('debops', SCRIPT_FILENAME), padlock_script)
|
|
||||||
os.chmod(padlock_script,
|
|
||||||
os.stat(padlock_script).st_mode|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
|
|
||||||
|
|
||||||
# Lock the EncFS directory after creation
|
|
||||||
time.sleep(0.5) # :fixme: why sleeping here?
|
|
||||||
padlock_lock(encfs_encrypted)
|
|
||||||
|
|
||||||
# Protect the EncFS configuration file by also encrypting it with
|
|
||||||
# the GPG keys of recipients.
|
|
||||||
subprocess.call(['gpg', '--encrypt', '--armor',
|
|
||||||
'--output', encfs_configfile+'.asc']
|
|
||||||
+ recipients + [encfs_configfile])
|
|
||||||
os.remove(encfs_configfile)
|
|
||||||
|
|
||||||
|
|
||||||
def lock(encfs_decrypted, encfs_encrypted, verbose):
|
|
||||||
# Unmount the directory if it is mounted
|
|
||||||
if padlock_lock(encfs_encrypted):
|
|
||||||
if verbose: print("Locked!")
|
|
||||||
else:
|
|
||||||
if verbose: print("Is already locked.")
|
|
||||||
|
|
||||||
|
|
||||||
def unlock(encfs_decrypted, encfs_encrypted, verbose):
|
|
||||||
# Mount the directory it if it is unmounted
|
|
||||||
if padlock_unlock(encfs_encrypted):
|
|
||||||
if verbose: print("Unlocked!")
|
|
||||||
else:
|
|
||||||
if verbose: print("Is already unlocked.")
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
subparsers = parser.add_subparsers(
|
|
||||||
help='action to perform. Use `%(prog)s --help <action>` for further help.')
|
|
||||||
|
|
||||||
p = subparsers.add_parser('init')
|
|
||||||
p.add_argument('recipients', nargs='*',
|
|
||||||
help=("GPG recipients for which the secret key should be "
|
|
||||||
"encrypted for (name, e-mail or key-id)"))
|
|
||||||
p.set_defaults(subcommand_func=init)
|
|
||||||
|
|
||||||
p = subparsers.add_parser('unlock')
|
|
||||||
p.add_argument('-v', '--verbose', action='store_true', help="be verbose")
|
|
||||||
p.set_defaults(subcommand_func=unlock)
|
|
||||||
|
|
||||||
p = subparsers.add_parser('lock')
|
|
||||||
p.add_argument('-v', '--verbose', action='store_true', help="be verbose")
|
|
||||||
p.set_defaults(subcommand_func=lock)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
try:
|
|
||||||
main(**vars(args))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit('... aborted')
|
|
74
debops-task
74
debops-task
|
@ -1,74 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
debops-task: run ansible with some customization
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
|
|
||||||
DEBOPS_RESERVED_NAMES = ["task", "init", "update", "defaults", "padlock"]
|
|
||||||
|
|
||||||
# ---- DebOps environment setup ----
|
|
||||||
|
|
||||||
# Find DebOps configuration file
|
|
||||||
project_root = find_debops_project(required=True)
|
|
||||||
# Source DebOps configuration file
|
|
||||||
###----- todo: need to decide on semantics!
|
|
||||||
#config = read_config(project_root)
|
|
||||||
|
|
||||||
|
|
||||||
# ---- Main script ----
|
|
||||||
|
|
||||||
# Make sure required commands are present
|
|
||||||
require_commands('ansible')
|
|
||||||
|
|
||||||
ansible_inventory = find_inventorypath(project_root)
|
|
||||||
|
|
||||||
# Get module name from the script name if script is named 'debops-*'
|
|
||||||
module_name = SCRIPT_NAME.rsplit('-', 1)[-1]
|
|
||||||
if module_name not in DEBOPS_RESERVED_NAMES:
|
|
||||||
module = ["-m", module_name]
|
|
||||||
else:
|
|
||||||
module = []
|
|
||||||
|
|
||||||
os.environ['ANSIBLE_HOSTS'] = os.path.abspath(ansible_inventory)
|
|
||||||
|
|
||||||
# Allow insecure SSH connections if requested
|
|
||||||
if INSECURE:
|
|
||||||
os.environ['ANSIBLE_HOST_KEY_CHECKING'] = 'False'
|
|
||||||
|
|
||||||
# Run ansible with custom environment
|
|
||||||
cmd = ['ansible'] + module + sys.argv[1:]
|
|
||||||
subprocess.call(cmd)
|
|
247
debops-update
247
debops-update
|
@ -1,247 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
("""
|
|
||||||
debops-update: install or update DebOps playbooks and roles
|
|
||||||
"""
|
|
||||||
# Copyright (C) 2014-2015 Hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
||||||
# Part of the DebOps - https://debops.org/
|
|
||||||
|
|
||||||
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
# This program 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 this program; if not,
|
|
||||||
# write to the Free Software Foundation, Inc., 59
|
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# An on-line copy of the GNU General Public License can
|
|
||||||
# be downloaded from the FSF web page at:
|
|
||||||
# https://www.gnu.org/copyleft/gpl.html
|
|
||||||
|
|
||||||
"""
|
|
||||||
This script can be used to install or update installed DebOps playbooks and
|
|
||||||
roles to current or specified version. By default it works on the installed
|
|
||||||
playbook in users $HOME/.local/share/debops directory, but it can also be
|
|
||||||
used on locally installed playbooks and roles in current directory.
|
|
||||||
|
|
||||||
Short usage guide:
|
|
||||||
|
|
||||||
- 'debops-update' will check if we are in DebOps project directory
|
|
||||||
('.debops.cfg' exists)
|
|
||||||
* if yes, it will check if 'debops-playbooks/playbooks/site.yml' exists
|
|
||||||
* if yes, update playbooks and roles in $PWD
|
|
||||||
* if no, check if DebOps playbooks are installed in known places,
|
|
||||||
like ~/.local/share/debops
|
|
||||||
* if yes, update playbooks in a place that they are installed at
|
|
||||||
* if no, install DebOps playbooks in
|
|
||||||
~/.local/share/debops/debops-playbooks
|
|
||||||
|
|
||||||
- 'debops-update path/to/dir' will check if specified directory exists
|
|
||||||
* if no, create it
|
|
||||||
* if yes, check if DebOps playbooks are installed at $path/debops-playbooks
|
|
||||||
* if yes, update them
|
|
||||||
* if no, install DebOps playbooks at $path/debops-playbooks
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
from debops import *
|
|
||||||
from debops.cmds import *
|
|
||||||
|
|
||||||
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__copyright__ = "Copyright 2014-2015 by Hartmut Goebel <h.goebel@crazy-compilers.com>"
|
|
||||||
__licence__ = "GNU General Public License version 3 (GPL v3) or later"
|
|
||||||
|
|
||||||
|
|
||||||
# ---- Configuration variables ----
|
|
||||||
|
|
||||||
# Default URI of DebOps (user https for server authentication)
|
|
||||||
GIT_URI = "https://github.com/debops"
|
|
||||||
|
|
||||||
# Default git sources for debops-playbooks
|
|
||||||
PLAYBOOKS_GIT_URI = GIT_URI + "/debops-playbooks"
|
|
||||||
|
|
||||||
# Default slug prefix for roles
|
|
||||||
GIT_ROLE_PREFIX = "ansible-"
|
|
||||||
|
|
||||||
# Ansible Galaxy requirements file to use by default to download or update
|
|
||||||
GALAXY_REQUIREMENTS = "galaxy/requirements.txt"
|
|
||||||
|
|
||||||
# Default Ansible Galaxy user account name
|
|
||||||
GALAXY_ACCOUNT = "debops"
|
|
||||||
|
|
||||||
|
|
||||||
# ---- Functions ----
|
|
||||||
|
|
||||||
def fetch_or_clone_roles(roles_path, requirements_file, dry_run=False):
|
|
||||||
"""
|
|
||||||
Efficiently fetch or clone a role
|
|
||||||
"""
|
|
||||||
with open(requirements_file) as fh:
|
|
||||||
requirements = [r.strip().split() for r in fh.readlines()]
|
|
||||||
num_roles = len(requirements)
|
|
||||||
|
|
||||||
for cnt, role_name in enumerate(requirements, 1):
|
|
||||||
# Parse the requirements.txt file to extract the role name and version
|
|
||||||
try:
|
|
||||||
role_name, role_version = role_name[:2]
|
|
||||||
except:
|
|
||||||
role_name = role_name[0]
|
|
||||||
role_version = 'master'
|
|
||||||
|
|
||||||
# :todo: rethink if we really want this
|
|
||||||
if role_name.startswith(GALAXY_ACCOUNT + '.'):
|
|
||||||
galaxy_name = role_name
|
|
||||||
role_name = role_name.split('.', 1)[1]
|
|
||||||
else:
|
|
||||||
galaxy_name = GALAXY_ACCOUNT + '.' + role_name
|
|
||||||
|
|
||||||
remote_uri = GIT_URI + '/' + GIT_ROLE_PREFIX + role_name
|
|
||||||
destination_dir = os.path.join(roles_path, galaxy_name)
|
|
||||||
progress_label="[{role_version}] ({cnt}/{num_roles})".format(**locals())
|
|
||||||
|
|
||||||
# Either update or clone the role
|
|
||||||
if os.path.exists(destination_dir):
|
|
||||||
print("Updating", remote_uri, progress_label)
|
|
||||||
update_git_repository(destination_dir, dry_run, remote_uri)
|
|
||||||
else:
|
|
||||||
print()
|
|
||||||
print("Installing", remote_uri, progress_label)
|
|
||||||
clone_git_repository(remote_uri, role_version, destination_dir, dry_run)
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def clone_git_repository(repo_uri, branch, destination, dry_run=False):
|
|
||||||
if dry_run:
|
|
||||||
print("Cloning '%s' to %s..." % (repo_uri, destination))
|
|
||||||
else:
|
|
||||||
subprocess.call(['git', 'clone', '--quiet', '--branch', branch,
|
|
||||||
repo_uri, destination])
|
|
||||||
|
|
||||||
def update_git_repository(path, dry_run=False, remote_uri=False):
|
|
||||||
"""
|
|
||||||
Update an exiting git repository.
|
|
||||||
|
|
||||||
To get nice output, merge only of origin as updates.
|
|
||||||
"""
|
|
||||||
# Move into the role's directory
|
|
||||||
old_pwd = os.getcwd()
|
|
||||||
os.chdir(path)
|
|
||||||
|
|
||||||
if dry_run:
|
|
||||||
subprocess.call(['git', 'fetch'])
|
|
||||||
subprocess.call(['git', 'diff', 'HEAD', 'origin', '--stat'])
|
|
||||||
else:
|
|
||||||
# Get the current sha of the head branch
|
|
||||||
current_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
|
|
||||||
|
|
||||||
# Fetch it silently and store the new sha
|
|
||||||
subprocess.call(['git', 'fetch', '--quiet'])
|
|
||||||
fetch_sha = subprocess.check_output(['git', 'rev-parse', 'FETCH_HEAD']).strip()
|
|
||||||
|
|
||||||
if current_sha != fetch_sha:
|
|
||||||
print()
|
|
||||||
print('--')
|
|
||||||
subprocess.call(['git', 'merge', fetch_sha])
|
|
||||||
|
|
||||||
if remote_uri:
|
|
||||||
compare_uri = remote_uri + '/compare/' + current_sha[:7] + '...' + fetch_sha[:7]
|
|
||||||
print()
|
|
||||||
print("Compare:", compare_uri)
|
|
||||||
|
|
||||||
print('--')
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Move back to the initial directory
|
|
||||||
os.chdir(old_pwd)
|
|
||||||
|
|
||||||
|
|
||||||
# ---- Main script ----
|
|
||||||
|
|
||||||
def main(project_dir=None, dry_run=False):
|
|
||||||
|
|
||||||
# Check if user specified a directory as a parameter, if yes, use it as
|
|
||||||
# a project directory and clone DebOps playbooks inside
|
|
||||||
if project_dir:
|
|
||||||
# If it's a new project, create the directory for it
|
|
||||||
if not os.path.exists(project_dir):
|
|
||||||
print ("Creating project directory in", project_dir)
|
|
||||||
if not dry_run:
|
|
||||||
os.makedirs(project_dir)
|
|
||||||
|
|
||||||
# Make sure that playbooks and roles will be installed in project
|
|
||||||
# directory if it's specified
|
|
||||||
install_path = os.path.join(project_dir, "debops-playbooks")
|
|
||||||
|
|
||||||
# If playbooks already are installed in specified location, set them as
|
|
||||||
# currently used for eventual update
|
|
||||||
if os.path.isfile(os.path.join(install_path, DEBOPS_SITE_PLAYBOOK)):
|
|
||||||
playbooks_path = install_path
|
|
||||||
else:
|
|
||||||
playbooks_path = None
|
|
||||||
|
|
||||||
else:
|
|
||||||
# If there's no project specified, look for playbooks in known locations
|
|
||||||
project_root = find_debops_project(required=False)
|
|
||||||
config = read_config(project_root)
|
|
||||||
playbooks_path = find_playbookpath(config, project_root, required=False)
|
|
||||||
if playbooks_path:
|
|
||||||
install_path = os.path.dirname(playbooks_path)
|
|
||||||
else:
|
|
||||||
install_path = config['paths']['install-path']
|
|
||||||
|
|
||||||
roles_path = os.path.join(install_path, 'roles')
|
|
||||||
|
|
||||||
# ---- Create or update the playbooks and roles ----
|
|
||||||
|
|
||||||
# Playbooks have not been found, at this point assume playbooks are not
|
|
||||||
# installed. Install them in user home directory
|
|
||||||
if not playbooks_path:
|
|
||||||
if dry_run:
|
|
||||||
raise SystemExit("--dry-run requires DebOps playbooks.\n" \
|
|
||||||
"Run debops-update without --dry-run first.")
|
|
||||||
|
|
||||||
# Download/clone main debops-playbooks repository
|
|
||||||
print("DebOps playbooks have not been found, installing into",
|
|
||||||
install_path)
|
|
||||||
print()
|
|
||||||
|
|
||||||
clone_git_repository(PLAYBOOKS_GIT_URI, 'master', install_path, dry_run)
|
|
||||||
os.chdir(install_path)
|
|
||||||
os.makedirs(roles_path)
|
|
||||||
else:
|
|
||||||
# Update found debops-playbooks repository
|
|
||||||
print("DebOps playbooks have been found in", install_path)
|
|
||||||
update_git_repository(install_path, dry_run)
|
|
||||||
print()
|
|
||||||
os.chdir(install_path)
|
|
||||||
|
|
||||||
# Now install or update the roles into roles_path
|
|
||||||
fetch_or_clone_roles(roles_path, GALAXY_REQUIREMENTS, dry_run)
|
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--dry-run', action='store_true',
|
|
||||||
help='perform a trial run with no changes made')
|
|
||||||
parser.add_argument('project_dir', nargs='?')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
try:
|
|
||||||
main(args.project_dir, args.dry_run)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise SystemExit('... aborted')
|
|
Loading…
Reference in New Issue