Verified Commit 92e129d6 authored by Maciej Delmanowski's avatar Maciej Delmanowski

Merge branch 'drybjed-add-role-machine'

parents 0d27e39a b7acf498
Pipeline #17151507 passed with stages
in 8 minutes and 55 seconds
......@@ -663,6 +663,13 @@ stages:
# --- m --- [[[2
'machine role':
<<: *test_role_no_deps
variables:
JANE_TEST_PLAY: '${DEBOPS_PLAYBOOKS}/service/machine.yml'
JANE_DIFF_PATTERN: '.*/debops.machine/.*'
JANE_LOG_PATTERN: '\[debops\.machine\]'
'mailman role':
<<: *test_role_3rd_deps
variables:
......
......@@ -37,6 +37,9 @@ Added
- :ref:`debops.locales`: configure localization and internationalization on
a given host or set of hosts.
- :ref:`debops.machine`: manage the :file:`/etc/machine-info` file,
the :file:`/etc/issue` file and a dynamic MOTD.
- You can now :ref:`use Vagrant <quick_start__vagrant>` to create an Ansible
Controller based on Debian Stretch and use it to manage itself or other hosts
over the network.
......@@ -115,6 +118,11 @@ Removed
'debops.locales' role. You will need to update the Ansible inventory
variables to reflect the changes.
- [debops.console] Remove management of the :file:`/etc/issue` and
:file:`/etc/motd` files from the ``debops.console`` role. That functionality
is now available in the :ref:`debops.machine` role. You will need to update
the Ansible inventory variables to reflect the changes.
debops v0.6.0 - 2017-10-21
--------------------------
......
......@@ -92,6 +92,9 @@
- role: debops.nsswitch
tags: [ 'role::nsswitch' ]
- role: debops.machine
tags: [ 'role::machine' ]
- role: debops.resources
tags: [ 'role::resources' ]
......
---
- name: Manage local machine information
hosts: [ 'debops_all_hosts', 'debops_service_machine' ]
become: True
environment: '{{ inventory__environment | d({})
| combine(inventory__group_environment | d({}))
| combine(inventory__host_environment | d({})) }}'
roles:
- role: debops.machine
tags: [ 'role::machine' ]
---
# Custom string added to /etc/issue
console_issue: '{{ ansible_domain.split(".")[0] | capitalize }}'
# If ``True``, show the logged in users. Note that this count does only update
# when the screen is manually refreshed.
console__issue_show_logged_in_users: True
# Enable or disable serial console (allows you to use 'lxc-console',
# 'virsh console' and other similar commands)
console_serial: False
......@@ -23,12 +16,6 @@ console_serial_term: 'xterm'
# String used to enable serial console in sysvinit /etc/inittab
console_serial_inittab: 'S0:2345:respawn:/sbin/getty -L {{ console_serial_port }} {{ console_serial_baud }} {{ console_serial_term }}'
# Contents of /etc/motd
console_motd: |
-------------------------------------------------
This system is managed by Ansible
-------------------------------------------------
# List of required console packages
console_base_packages: [ 'locales' ]
......
......@@ -37,27 +37,6 @@
console_register_inittab.stat.exists))
notify: [ 'Reload sysvinit' ]
- name: Divert original /etc/issue
command: dpkg-divert --quiet --local --divert /etc/issue.dpkg-divert --rename /etc/issue
args:
creates: '/etc/issue.dpkg-divert'
- name: Configure /etc/issue
template:
src: '{{ lookup("template_src", "etc/issue.j2") }}'
dest: '/etc/issue'
owner: 'root'
group: 'root'
mode: '0644'
- name: Configure /etc/motd
template:
src: '{{ lookup("template_src", "etc/motd.j2") }}'
dest: '/etc/motd'
owner: 'root'
group: 'root'
mode: '0644'
- name: Configure fsck behaviour on boot
lineinfile:
dest: '/etc/default/rcS'
......
debops.machine - Manage local machine information and MOTD
Copyright (C) 2018 Maciej Delmanowski <[email protected]>
Copyright (C) 2018 DebOps https://debops.org/
This Ansible role is part of DebOps.
DebOps is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
DebOps 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 DebOps. If not, see https://www.gnu.org/licenses/.
---
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
# debops.machine default variables
# ================================
# .. contents:: Sections
# :local:
# General configuration [[[
# -------------------------
# .. envvar:: machine__enabled [[[
#
# Enable or disable support for managing static machine information and MOTD.
machine__enabled: True
# ]]]
# .. envvar:: machine__packages [[[
#
# List of APT packages to install with the ``debops.machine`` role enabled.
machine__packages: []
# ]]]
# ]]]
# Machine information [[[
# -----------------------
# These variables manage contents of the :file:`/etc/machine-info`
# configuration file. See :manpage:`machine-info(5)` and
# :manpage:`hostnamectl(1)` for more details.
# .. envvar:: machine__organization [[[
#
# Human-readable name of the organization that's responsible for this machine.
machine__organization: '{{ ansible_domain.split(".")[0] | capitalize }}'
# ]]]
# .. envvar:: machine__contact [[[
#
# Human-readable contact information for this machine - e-mail, phone number or
# an URL to a web page about a person or team responsible for this host.
machine__contact: ''
# ]]]
# .. envvar:: machine__pretty_hostname [[[
#
# Human-readable hostname for this machine.
machine__pretty_hostname: ''
# ]]]
# .. envvar:: machine__icon_name [[[
#
# Name of the icon to use for this machine.
machine__icon_name: ''
# ]]]
# .. envvar:: machine__chassis [[[
#
# Specify the machine type to override the autodetected value. Currently
# recognized chassis types: 'desktop', 'laptop', 'server', 'tablet', 'handset',
# 'watch', 'vm', 'container'.
machine__chassis: ''
# ]]]
# .. envvar:: machine__deployment [[[
#
# Define the system deployment environment. Suggested values:
# 'development', 'integration', 'staging', 'production'.
machine__deployment: 'production'
# ]]]
# .. envvar:: machine__location [[[
#
# Describe the physical location where a given system can be found, for example
# a city, or a rack in which the machine is located.
machine__location: ''
# ]]]
# ]]]
# Configuration of the :file:`/etc/motd` file [[[
# -----------------------------------------------
# .. envvar:: machine__motd [[[
#
# String or YAML text block with the welcome message stored in the
# :file:`/etc/motd` configuration file.
machine__motd: ''
# ]]]
# .. envvar:: machine__etc_motd_state [[[
#
# Specofy the state of the :file:`/etc/motd` file, either ``present`` (the file
# exists) or ``absent`` (the file will be removed).
machine__etc_motd_state: '{{ "present" if machine__motd|d() else "absent" }}'
# ]]]
# .. envvar:: machine__motd_update_dir [[[
#
# Directory which contains scripts that generate the dynamic MOTD.
machine__motd_update_dir: '/etc/update-motd.d'
# ]]]
# ]]]
# Configuration of the :file:`/etc/issue` file [[[
# ------------------------------------------------
# .. envvar:: machine__etc_issue_state [[[
#
# This variable controls if the role should manage the :file:`/etc/issue`
# configuration file. If ``present``, the role will divert the distribution file
# and generate a custom one; if ``absent``, the role will revert the diverted
# version and will not modify it.
machine__etc_issue_state: 'present'
# ]]]
# .. envvar:: machine__etc_issue_template [[[
#
# Path to the Jinja2 template used to generate the :file:`/etc/issue`
# configuration file, relative to the :file:`templates/` directory of this role.
machine__etc_issue_template: 'etc/issue.j2'
# ]]]
# ]]]
# Dynamic Message Of The Day [[[
# ------------------------------
# These variables control the shell scripts that generate the dynamic MOTD.
# See :ref:`machine__ref_motd_scripts` for more details.
# .. envvar:: machine__motd_default_scripts [[[
#
# The list of the default MOTD scripts managed by the role.
machine__motd_default_scripts:
# This file comes with the 'base-files' APT package on Debian
- name: 'uname'
filename: '10-uname'
divert: '{{ False
if (ansible_distribution_release in [ "wheezy", "jessie" ])
else True }}'
content: |
#!/bin/sh
uname -snrvm
state: '{{ "present"
if (ansible_distribution_release in [ "wheezy", "jessie" ])
else "init" }}'
- name: 'ansible'
weight: 50
src: 'etc/update-motd.d/ansible'
state: 'present'
- name: 'tail'
weight: 90
content: |
#!/bin/sh
if [ -f /etc/motd.tail ] ; then
cat /etc/motd.tail
fi
state: 'present'
- name: 'fortune'
weight: 95
src: 'etc/update-motd.d/fortune'
state: 'init'
# ]]]
# .. envvar:: machine__motd_scripts [[[
#
# The list of the MOTD scripts which should be present on all hosts in the
# Ansible inventory.
machine__motd_scripts: []
# ]]]
# .. envvar:: machine__motd_group_scripts [[[
#
# The list of the MOTD scripts which should be present on hosts in a specific
# Ansible inventory group.
machine__motd_group_scripts: []
# ]]]
# .. envvar:: machine__motd_host_scripts [[[
#
# The list of the MOTD scripts which should be present on specific hosts in the
# Ansible inventory.
machine__motd_host_scripts: []
# ]]]
# .. envvar:: machine__motd_combined_packages [[[
#
# The list which combines configuration of the MOTD scripts which is passed to
# the Ansible tasks.
machine__motd_combined_scripts: '{{ machine__motd_default_scripts
+ machine__motd_scripts
+ machine__motd_group_scripts
+ machine__motd_host_scripts }}'
# ]]]
# ]]]
#!/bin/sh
BLACK='\033[49;30m'
BLACKB='\033[49;90m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[94;49m'
MAGENTA='\033[0;35m'
CYAN='\033[36;49m'
WHITE='\033[0;37m'
BOLD='\033[1m'
RESET='\033[0m'
if [ -d "/etc/ansible/facts.d" ] ; then
printf "${BLACKB}%70s${RESET}\n" | tr ' ' -
printf " ${CYAN}This system is managed by ${BOLD}Ansible${RESET}${CYAN}, manual changes will be lost${RESET}\n"
printf "${BLACKB}%70s${RESET}\n" | tr ' ' -
fi
#!/bin/sh
. /etc/default/locale
export LANG
export PATH="/usr/local/games:/usr/games:$PATH"
if [ -x /usr/games/fortune ] ; then
/usr/games/fortune -s
fi
---
dependencies:
- role: debops.ansible_plugins
galaxy_info:
author: 'Maciej Delmanowski'
description: 'Manage local machine information and MOTD'
company: 'DebOps'
license: 'GPL-3.0'
min_ansible_version: '2.4.0'
platforms:
- name: Ubuntu
versions:
- precise
- trusty
- xenial
- name: Debian
versions:
- wheezy
- jessie
- stretch
categories:
- system
- motd
- issue
- login
---
- name: Install requested packages
package:
name: '{{ item }}'
state: 'present'
with_flattened: '{{ machine__packages }}'
when: machine__enabled|bool
- name: Generate machine-info config file
template:
src: 'etc/machine-info.j2'
dest: '/etc/machine-info'
owner: 'root'
group: 'root'
mode: '0644'
when: machine__enabled|bool
- name: Divert original /etc/issue file
command: dpkg-divert --quiet --local --divert /etc/issue.dpkg-divert --rename /etc/issue
args:
creates: '/etc/issue.dpkg-divert'
when: machine__enabled|bool and machine__etc_issue_state|d('present') != 'absent'
- name: Configure /etc/issue file
template:
src: '{{ machine__etc_issue_template }}'
dest: '/etc/issue'
owner: 'root'
group: 'root'
mode: '0644'
when: machine__enabled|bool and machine__etc_issue_state|d('present') != 'absent'
- name: Revert original /etc/issue file
shell: rm -f /etc/issue ; dpkg-divert --quiet --local --rename --remove /etc/issue
args:
warn: False
removes: '/etc/issue.dpkg-divert'
when: machine__enabled|bool and machine__etc_issue_state|d('present') == 'absent'
- name: Remove static /etc/motd file if requested
file:
path: '/etc/motd'
state: 'absent'
when: machine__enabled|bool and machine__etc_motd_state == 'absent'
- name: Generate static /etc/motd file
copy:
content: "{{ machine__motd }}"
dest: '/etc/motd'
owner: 'root'
group: 'root'
mode: '0644'
when: machine__enabled|bool and machine__etc_motd_state|d('present') != 'absent' and
machine__motd|d()
- name: Ensure that required directories exist
file:
path: '{{ machine__motd_update_dir }}'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
when: machine__enabled|bool
- name: Fix issue with dynamic MOTD on older OS releases
template:
src: 'etc/tmpfiles.d/motd-dynamic.conf.j2'
dest: '/etc/tmpfiles.d/motd-dynamic.conf'
owner: 'root'
group: 'root'
mode: '0644'
register: machine__register_tmpfiles
when: machine__enabled|bool and ansible_distribution_release in [ 'wheezy', 'jessie' ]
- name: Create /run/motd.dynamic symlink
command: systemd-tmpfiles --create
when: machine__enabled|bool and ansible_service_mgr == 'systemd' and
machine__register_tmpfiles|changed
- name: Check current MOTD diversions
environment:
LC_ALL: 'C'
shell: dpkg-divert --list '/etc/update-motd.d/*.disabled' | awk '{print $NF}'
register: machine__register_motd_diversions
check_mode: False
changed_when: False
- name: Divert packaged MOTD scripts
command: dpkg-divert --quiet --local --divert /etc/update-motd.d/{{ item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name) }}.disabled --rename /etc/update-motd.d/{{ item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name) }}
args:
creates: '{{ "/etc/update-motd.d/" + (item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name)) + ".disabled" }}'
with_flattened: '{{ machine__motd_combined_scripts | parse_kv_items }}'
when: (machine__enabled|bool and
(item.filename is defined or item.name is defined) and
(item.state|d('present') not in [ 'init', 'absent', 'ignore', 'revert' ]) and
((item.divert|d())|bool and
'/etc/update-motd.d/' + (item.filename | d(item.weight|string + "-" + item.name)) + '.disabled' not in machine__register_motd_diversions.stdout_lines))
- name: Remove dynamic MOTD scripts
file:
path: '{{ machine__motd_update_dir + "/" + (item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name)) }}'
state: 'absent'
with_flattened: '{{ machine__motd_combined_scripts | parse_kv_items }}'
register: machine__register_motd_scripts_removed
when: (machine__enabled|bool and
(item.filename is defined or item.name is defined) and
item.state|d('present') == 'absent' and not (item.divert|d()|bool))
- name: Install dynamic MOTD scripts
copy:
src: '{{ item.src | d(omit) }}'
content: '{{ item.content | d(omit) }}'
dest: '{{ machine__motd_update_dir + "/" + (item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name)) }}'
owner: 'root'
group: 'root'
mode: '0755'
with_flattened: '{{ machine__motd_combined_scripts | parse_kv_items }}'
register: machine__register_motd_scripts_created
when: (machine__enabled|bool and
(item.filename is defined or item.name is defined) and
(item.src is defined or item.content is defined) and
item.state|d('present') not in [ 'init', 'absent', 'ignore', 'divert', 'revert' ])
- name: Remove unknown MOTD scripts
shell: find /etc/update-motd.d -maxdepth 1 -type f
-name '*-{{ item.item.name }}'
! -name '{{ ("%02d" | format((item.item.weight | d("0"))|int))|string + "-" + item.item.name }}' -exec rm -vf {} +
with_items:
- '{{ machine__register_motd_scripts_removed.results }}'
- '{{ machine__register_motd_scripts_created.results }}'
when: (item.item.name|d() and not (item.item.divert|d())|bool and
item.item.filename is undefined and item.changed|bool)
- name: Revert packaged MOTD scripts
shell: rm -f /etc/update-motd.d/{{ item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name) }} ; dpkg-divert --quiet --local --rename --remove /etc/update-motd.d/{{ item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name) }}
args:
warn: False
removes: '{{ "/etc/update-motd.d/" + (item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name)) + ".disabled" }}'
with_flattened: '{{ machine__motd_combined_scripts | parse_kv_items }}'
when: ((not machine__enabled|bool and (item.divert|d())|bool) or
((item.filename is defined or item.name is defined) and
item.state|d('present') in [ 'absent', 'revert' ] and
(item.divert|d())|bool and
'/etc/update-motd.d/' + (item.filename | d(("%02d" | format(item.weight|int))|string + "-" + item.name)) + '.disabled' in machine__register_motd_diversions.stdout_lines))
- name: Make sure that Ansible local facts directory exists
file:
path: '/etc/ansible/facts.d'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
- name: Save machine local facts
template:
src: 'etc/ansible/facts.d/machine.fact.j2'
dest: '/etc/ansible/facts.d/machine.fact'
owner: 'root'
group: 'root'
mode: '0755'
register: machine__register_facts
- name: Update Ansible facts if they were modified
action: setup
when: machine__register_facts|changed
#!/usr/bin/env python
# {{ ansible_managed }}
from __future__ import print_function
from json import loads, dumps
from sys import exit
import os
output = loads('''{{ {'configured': True,
'enabled': machine__enabled|bool
} | to_nice_json }}''')
machine_info = '/etc/machine-info'
if os.path.exists(machine_info) and os.path.isfile(machine_info):
with open(machine_info, "r") as f:
for line in f:
if not line.startswith('#') and '=' in line:
line = line.strip().split('=')
output.update({str(line[0]).lower(): str(line[1]).strip('"')})
print(dumps(output, sort_keys=True, indent=4))
 /\\ \n.\O
 / \\ {{ console_issue }}
 / \\ {{ machine__organization }}
 DebOps
 \\ / \l{% if (console__issue_show_logged_in_users|bool) %} / \U{% endif %}
 \\ / \l / \U
 \\/ \s \r
# {{ ansible_managed }}
{% if machine__organization|d() %}
ORGANIZATION="{{ machine__organization }}"
{% endif %}
{% if machine__contact|d() %}
CONTACT="{{ machine__contact }}"
{% endif %}
{% if machine__pretty_hostname|d() %}
PRETTY_HOSTNAME="{{ machine__pretty_hostname }}"
{% endif %}
{% if machine__icon_name|d() %}
ICON_NAME="{{ machine__icon_name }}"
{% endif %}
{% if machine__chassis|d() %}
CHASSIS="{{ machine__chassis }}"
{% endif %}
{% if machine__deployment|d() %}
DEPLOYMENT="{{ machine__deployment }}"
{% endif %}
{% if machine__location|d() %}
LOCATION="{{ machine__location }}"
{% endif %}
# {{ ansible_managed }}
# Configuration installed by debops.machine Ansible role
#
# Create a symlink to fix issues with dynamic MOTD on older OS releases.
# More details: https://unix.stackexchange.com/a/246770
#Type Path Mode UID GID Age Argument
L /run/motd.dynamic - - - - /run/motd
......@@ -238,6 +238,7 @@ System configuration
- :ref:`debops.ferm`
- :ref:`debops.locales`
- :ref:`debops.logrotate`
- :ref:`debops.machine`
- :ref:`debops.nsswitch`
- :ref:`debops.ntp`
- :ref:`debops.resources`
......
Default variable details
========================
Some of the ``debops.machine`` default variables have more extensive
configuration than simple strings or lists, here you can find documentation and
examples for them.
.. contents::
:local:
:depth: 1
.. _machine__ref_motd_scripts:
machine__motd_scripts
---------------------
This variable is a list which can be used to manage scripts in the
:file:`/etc/update-motd.d/` directory, used to generate the dynamic Message Of
The Day.
Each list entry is a YAML dictionary with specific parameters:
``name``
Required. Name of a given entry, used as a handle to merge multiple entries
together. It's also used in an autogenerated filename of the script.
``weight``
Optional. Modify the base "weight" of a given script to reorder its output in
the resulting dynamic MOTD. The base weight used by the role is ``0``, you
can use positive or negative numbers to reorder the scripts. The filename
format uses 2 digits to define the weight, therefore you should use small
range of weights, otherwise weird filenames resulting in unwanted order might
be generated.
``filename``
Optional. Define a static filename of the script. This filename won't be
affected by the ``name`` and ``weight`` parameters. It's usually used for
scripts provided by Debian packages to aid in :command:`dpkg`
diversion/reversion.
``src``
Optional, conflicts with ``content``. Path to a script which should be
installed in the :file:`/etc/update-motd.d/` directory with a given name. By
default the path is relative to the :file:`files/` directory of the
``debops.machine`` Ansible role.
The script output will be added to the dynamic MOTD. Remember that the script
is executed with ``root`` privileges!
``content``
Optional, conflicts with ``src``. YAML text block which contains a script to
be installed in the :file:`/etc/update-motd.d/` directory with a given name.
The script can contain Jinja templating which will be evaluated at Ansible
execution time.
The script output will be added to the dynamic MOTD. Remember that the script
is executed with ``root`` privileges!
``divert``
Optional, boolean. If ``True``, the script managed by this entry will be
automatically diverted/reverted as necessary. This is useful to move the
files included in the APT packages aside, so that the package manager can
still update the packages without issues.
The diverted scripts will have a ``.disabled`` extension and their output
will not be included in the dynamic MOTD.
``state``
Optional. Define the state of a particular script. If multiple list entries
define a script state, the last one wins. Recognized states:
- not specified or ``present``: the script will be installed in the