Skip to content

Commit

Permalink
Roughly port to fabric 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Jan 29, 2023
1 parent 14b8724 commit 8d29bad
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 61 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v6.0.0
======

Updated API to work with fabric 2 instead of Fabric 3. Most
behaviors untested and likely broken, but tests run and pass.

v5.3.0
======

Expand Down
59 changes: 28 additions & 31 deletions jaraco/fabric/apt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@

import jaraco.apt
from jaraco.itertools import always_iterable
from fabric.operations import sudo, run
from fabric.api import task, put
from fabric.context_managers import settings
from fabric import task


__all__ = ['install_packages', 'create_installers_group', 'add_installer', 'add_ppa']


@contextlib.contextmanager
def package_context(target, action='install'):
def package_context(c, target, action='install'):
"""
A context for installing the build dependencies for a given target (or
targets). Uses apt. Removes the dependencies when the context is
exited. One may prevent the removal of some or all packages by modifying
the list within the context.
"""
target = ' '.join(always_iterable(target))
status = sudo('apt {action} -q -y {target}'.format(**vars()))
status = c.sudo('apt {action} -q -y {target}'.format(**vars()))
packages = jaraco.apt.parse_new_packages(status)
try:
yield packages
Expand All @@ -32,8 +30,8 @@ def package_context(target, action='install'):


@task
def install_packages(*packages):
with package_context(packages) as to_remove:
def install_packages(c, *packages):
with package_context(c, packages) as to_remove:
installed = list(to_remove)
to_remove[:] = []
return installed
Expand All @@ -43,15 +41,15 @@ def build_dependency_context(target):
return package_context(target, 'build-dep')


def remove_packages(packages):
def remove_packages(c, packages):
if not packages:
print("No packages specified, nothing to remove")
return
sudo('apt autoremove -y -q ' + ' '.join(packages))
c.sudo('apt autoremove -y -q ' + ' '.join(packages))


@task
def create_installers_group():
def create_installers_group(c):
"""
Create an 'installers' group that has rights to install/remove software
without typing a password.
Expand All @@ -67,63 +65,62 @@ def create_installers_group():
]
commands = ', '.join('/usr/bin/' + cmd for cmd in apt_commands)
content = "%installers ALL=NOPASSWD: {commands}\n".format(**locals())
upload_sudoersd_file('installers', content)
with settings(warn_only=True):
sudo('addgroup installers')
upload_sudoersd_file(c, 'installers', content)
c.sudo('addgroup installers', warn=True)
print(
"Grant installation privilege with 'usermod -a -G installers "
"$username' or yg-fab add_installer:$username"
)


def upload_sudoersd_file(name, content):
def upload_sudoersd_file(c, name, content):
"""
Thanks to a long-standing bug in Ubuntu Lucid
(https://bugs.launchpad.net/ubuntu/+source/sudo/+bug/553786),
we have to take special precaution when creating sudoers.d files.
"""
stream = io.BytesIO(content.encode('utf-8'))
tmp_name = '/tmp/' + name
put(stream, tmp_name, mode=0o440)
sudo('chown root:root ' + tmp_name)
sudo('mv {tmp_name} /etc/sudoers.d'.format(**vars()))
c.put(stream, tmp_name, mode=0o440)
c.sudo('chown root:root ' + tmp_name)
c.sudo('mv {tmp_name} /etc/sudoers.d'.format(**vars()))


@task
def add_installer(username):
def add_installer(c, username):
"""
Add username to the installers group, after which they should be able to
install/remove software without typing a password.
"""
sudo("usermod -a -G installers {username}".format(**vars()))
c.sudo("usermod -a -G installers {username}".format(**vars()))


def ubuntu_version():
def ubuntu_version(c):
pattern = re.compile(r'Ubuntu ([\d.]+)')
out = run('cat /etc/issue')
out = c.run('cat /etc/issue').stdout.strip()
return pattern.match(out).group(1)


@task
def add_ppa(name):
def add_ppa(c, name):
"""
Add the Personal Package Archive
"""
sudo('apt update -q')
c.sudo('apt update -q')
# need software-properties-common for apt-add-repository
sudo('apt install -q -y software-properties-common')
c.sudo('apt install -q -y software-properties-common')
# apt-add-repository returns 0 even when it failed, so check its output
# for success or failure.
cmd = ['apt-add-repository', 'ppa:' + name]
if ubuntu_version() >= '12.':
if ubuntu_version(c) >= '12.':
cmd[1:1] = ['-y']
sudo(' '.join(cmd))
sudo('apt update -q')
c.sudo(' '.join(cmd))
c.sudo('apt update -q')


def lsb_release():
return run("lsb_release -sc").strip()
def lsb_release(c):
return c.run("lsb_release -sc").strip()


def lsb_version():
return run('lsb_release -sr').strip()
def lsb_version(c):
return c.run('lsb_release -sr').strip()
58 changes: 31 additions & 27 deletions jaraco/fabric/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@

import pkg_resources
import yaml
from fabric.api import sudo, task, run
from fabric.contrib import files
from fabric.context_managers import settings
from fabric import task

from . import apt

Expand All @@ -28,7 +26,7 @@


@task
def distro_install(version="3.2"):
def distro_install(c, version="3.2"):
"""
Install mongodb as an apt package (which also configures it as a
service).
Expand All @@ -43,7 +41,12 @@ def distro_install(version="3.2"):
raise RuntimeError('Unknown version {}'.format(version))


def distro_install_2(version):
def append(c, *args, **kwargs):
# todo: used to be contrib.files.append, now patchwork.files, not ported
raise NotImplementedError()


def distro_install_2(c, version):
"""
Install MongoDB version 2.x
"""
Expand All @@ -54,16 +57,17 @@ def distro_install_2(version):
'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart ' 'dist 10gen',
)
org_list = '/etc/apt/sources.list.d/mongodb.list'
files.append(org_list, content, use_sudo=True)

append(c, org_list, content, use_sudo=True)


@task
def find_current_version():
output = sudo('apt list -qq mongodb-org')
def find_current_version(c):
output = c.sudo('apt list -qq mongodb-org')
return re.search(r'\d+\.\d+\.\d+', output).group(0)


def distro_install_3(version):
def distro_install_3(c, version):
"""
Install MongoDB version 3.x
"""
Expand All @@ -74,29 +78,29 @@ def distro_install_3(version):
tmpl = "deb {repo_url} {lsb_release}/mongodb-org/{version} multiverse"
content = tmpl.format(**locals())
org_list = f'/etc/apt/sources.list.d/mongodb-org-{version}.list'
files.append(org_list, content, use_sudo=True)
append(c, org_list, content, use_sudo=True)

with settings(warn_only=True):
for key in APT_KEYS:
sudo(
'apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 ' f'--recv {key}'
)
for key in APT_KEYS:
c.sudo(
'apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 ' f'--recv {key}',
warn=True,
)

sudo('apt update')
c.sudo('apt update')
version = find_current_version()
apt.install_packages('mongodb-org={version}'.format(**locals()))
install_systemd()


@task
def enable_authentication():
with yaml_config('/etc/mongod.conf', use_sudo=True) as config:
def enable_authentication(c):
with yaml_config(c, '/etc/mongod.conf', use_sudo=True) as config:
security = config.setdefault('security', {})
security['authorization'] = 'enabled'


@task
def bind_all():
def bind_all(c):
"""
Bind to all interfaces.
"""
Expand All @@ -105,16 +109,16 @@ def bind_all():


@contextlib.contextmanager
def yaml_config(path, use_sudo=False):
cmd = sudo if use_sudo else run
def yaml_config(c, path, use_sudo=False):
cmd = c.sudo if use_sudo else c.run
doc = yaml.safe_load(cmd('cat {path}'.format(**locals())))
yield doc
new_doc = io.StringIO(yaml.dump(doc, default_flow_style=False))
files.put(new_doc, path, use_sudo=use_sudo)
c.put(new_doc, path, use_sudo=use_sudo)


@task
def install_user(username=None):
def install_user(c, username=None):
default = os.environ['USER']
username = username or getpass.getuser()
password = getpass.getpass('password> ')
Expand All @@ -124,11 +128,11 @@ def install_user(username=None):
roles=[dict(role="userAdminAnyDatabase", db="admin")],
)
cmd = 'db.createUser({doc})'.format(doc=json.dumps(new_user))
run('mongo admin -eval {cmd!r}'.format(**locals()))
c.run('mongo admin -eval {cmd!r}'.format(**locals()))


@task
def install_systemd():
def install_systemd(c):
"""
On newer versions of Ubuntu, make sure that systemd is configured
to manage the service.
Expand All @@ -139,7 +143,7 @@ def install_systemd():

fn = 'mongod.service'
service_strm = pkg_resources.resource_stream(__name__, fn)
files.put(service_strm, '/lib/systemd/system/' + fn, use_sudo=True)
sudo('systemctl enable mongod')
c.put(service_strm, '/lib/systemd/system/' + fn, use_sudo=True)
c.sudo('systemctl enable mongod')
# TODO: does the service start automatically? If not,
# sudo('systemctl start mongod')
4 changes: 2 additions & 2 deletions jaraco/fabric/python.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from fabric.api import task
from fabric import task

from . import apt


@task
def install(version='3.7'):
def install(c, version='3.7'):
apt.add_ppa('deadsnakes/ppa')
apt.install_packages(f'python{version}-dev', f'python{version}-venv')
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ testing =
pytest-enabler >= 1.3

# local
Fabric3
fabric
types-setuptools
types-pyyaml

Expand Down

0 comments on commit 8d29bad

Please sign in to comment.