import files
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = ssh://git@github.com/1001Pharmacies/ansible-docker
|
||||
branch = master
|
||||
commit = 6217a899084cba00447195d1873b211462b60d52
|
||||
parent = 4745dad8cb8a826ee3ac47accda79f96957b5e13
|
||||
method = merge
|
||||
cmdver = 0.4.0
|
||||
@@ -0,0 +1,4 @@
|
||||
# Authors
|
||||
|
||||
* **Yann Autissier** - *Initial work* - [aya](https://github.com/aya)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## v1.0.0 (December 20, 2016)
|
||||
|
||||
Initial release.
|
||||
|
||||
* Install docker daemon
|
||||
* Start and active docker service at boot
|
||||
* Build and run docker images
|
||||
@@ -0,0 +1,20 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Yann Autissier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,237 @@
|
||||
# Ansible role to run dockers
|
||||
|
||||
An ansible role to install the [docker](https://www.docker.com/) daemon and build and run dockers.
|
||||
|
||||
It installs the docker daemon and ensure it is up and running.
|
||||
It sets the STORAGE_DRIVER if the docker host uses systemd and it configures the MTU to 1450 if it is a VM running on OpenStack.
|
||||
It builds and runs docker images on the docker host.
|
||||
|
||||
## Requirements
|
||||
|
||||
This Ansible role requires at least Ansible version 1.9.
|
||||
|
||||
## Role Variables
|
||||
|
||||
* `docker_check_kernel` - The minimum kernel version allowed on hosts to run docker.
|
||||
|
||||
``` yaml
|
||||
# minimum kernel version
|
||||
docker_check_kernel: '3.10'
|
||||
```
|
||||
|
||||
* `docker_check_machine` - The hosts architecture needed to run docker.
|
||||
|
||||
``` yaml
|
||||
# architecture
|
||||
docker_check_machine: 'x86_64'
|
||||
```
|
||||
|
||||
* `docker_package` - The name of the docker package.
|
||||
|
||||
``` yaml
|
||||
# The docker package name
|
||||
docker_package: docker
|
||||
```
|
||||
|
||||
* `docker_packages` - A list of packages to install/remove before installing the docker package.
|
||||
|
||||
``` yaml
|
||||
# A list of package to install/remove
|
||||
# docker_packages:
|
||||
# - { "name": "docker", "state": "absent" }
|
||||
```
|
||||
|
||||
* `docker_init_config_directory` - The location of the configuration file of the docker daemon init script.
|
||||
|
||||
``` yaml
|
||||
# Location of configuration files loaded by the init script
|
||||
docker_init_config_directory: "/etc/sysconfig"
|
||||
```
|
||||
|
||||
* `docker_opts` - The name of the environment variable used to pass options to the docker daemon.
|
||||
|
||||
``` yaml
|
||||
# docker daemon options environment variable
|
||||
docker_opts: "OPTIONS"
|
||||
```
|
||||
|
||||
* `docker_services` - A list of system services to start
|
||||
|
||||
``` yaml
|
||||
# services
|
||||
docker_services:
|
||||
- docker
|
||||
```
|
||||
|
||||
* `dockers` - A list of docker images to build and run on the docker host with the docker-build and docker-run commands
|
||||
|
||||
``` yaml
|
||||
# dockers
|
||||
# dockers:
|
||||
# - nginx
|
||||
```
|
||||
|
||||
* `docker_cluster` - An optional cluster name to pass to the docker-build and docker-run commands
|
||||
|
||||
``` yaml
|
||||
# docker cluster
|
||||
# docker_cluster: ""
|
||||
```
|
||||
|
||||
* `docker_cluster` - Starts the dockers if set to true.
|
||||
|
||||
``` yaml
|
||||
# Start docker
|
||||
docker_start: true
|
||||
```
|
||||
|
||||
* `docker_restart` - Restarts dockers when their image has been updated. It removes current running dockers and start new ones.
|
||||
|
||||
``` yaml
|
||||
# Stop and remove running docker to start a new one when image has been updated
|
||||
docker_restart: true
|
||||
```
|
||||
|
||||
* `docker_force_restart` - Restart dockers, even if image has not been updated. It removes current running dockers and start new ones.
|
||||
|
||||
``` yaml
|
||||
# Stop and remove running docker to start a new one even if image has not been updated
|
||||
docker_force_restart: false
|
||||
```
|
||||
|
||||
## Helper scripts
|
||||
|
||||
This role comes with a few helper scripts. Here is a short description.
|
||||
|
||||
* `docker-build` - Build a docker image, reading options to pass to the `docker build` command from a Dockeropts file.
|
||||
|
||||
* `docker-cleanup` - Remove unused dockers.
|
||||
|
||||
* `docker-cleanup-images` - Remove unused docker images.
|
||||
|
||||
* `docker-cleanup-volumes` - Remove unused docker volumes.
|
||||
|
||||
* `docker-get-image` - Return sha256 of the image used by the docker.
|
||||
|
||||
* `docker-get-status` - Return the status of the docker.
|
||||
|
||||
* `docker-log-cleanup` - Empty the file logging the docker output on the docker host.
|
||||
|
||||
* `docker-log-truncate` - Truncate the file logging the docker output on the docker host.
|
||||
|
||||
* `docker-run` - Run a docker, reading options to pass to the `docker run` command from a Dockeropts file.
|
||||
|
||||
## Example
|
||||
|
||||
To launch this role on your `docker` hosts, run the default playbook.yml.
|
||||
|
||||
``` bash
|
||||
$ ansible-playbook playbook.yml
|
||||
```
|
||||
|
||||
### Build a docker image
|
||||
|
||||
On the docker hosts, you'll be able to build docker images and run dockers, based on Dockerfile and Dockeropts files located in the /etc/docker subdirectories.
|
||||
|
||||
To create an `nginx` docker image, create a directory /etc/docker/nginx with a Dockerfile and a Dockeropts files into.
|
||||
|
||||
``` bash
|
||||
# mkdir -p /etc/docker/nginx
|
||||
# cat << EOF > /etc/docker/nginx/Dockerfile
|
||||
FROM nginx:alpine
|
||||
EOF
|
||||
# cat << EOF > /etc/docker/nginx/Dockeropts
|
||||
DOCKER_ULIMIT="nofile=65536"
|
||||
DOCKER_PORT="80:80"
|
||||
EOF
|
||||
```
|
||||
|
||||
Build your `nginx` docker image, then run it ! The docker-run command will read the Dockeropts file to add the --ulimit and --port options to the docker run command.
|
||||
|
||||
``` bash
|
||||
# docker-build nginx && docker-run nginx
|
||||
```
|
||||
|
||||
### Override your files
|
||||
|
||||
If you want to copy a file in your Dockerfile, say the default nginx.conf, you can use the DOCKER_BUILD_PREFIX and DOCKER_BUILD_SUFFIX variables to get different versions of this file giving some context.
|
||||
|
||||
``` bash
|
||||
# cat << EOF > /etc/docker/nginx/Dockerfile
|
||||
FROM nginx:alpine
|
||||
ARG DOCKER_BUILD_PREFIX
|
||||
ARG DOCKER_BUILD_SUFFIX
|
||||
COPY ./\${DOCKER_BUILD_PREFIX}nginx.conf\${DOCKER_BUILD_SUFFIX} /etc/nginx/nginx.conf
|
||||
EOF
|
||||
```
|
||||
|
||||
You can now override the nginx configuration file when you build your image.
|
||||
|
||||
* Without option, the docker-build command will search for the file beside your Dockerfile.
|
||||
|
||||
``` bash
|
||||
# docker-build nginx && docker-run nginx
|
||||
```
|
||||
|
||||
Both DOCKER_BUILD_PREFIX and DOCKER_BUILD_SUFFIX variables are empty, the Dockerfile will search for a `./nginx.conf` file, ie the /etc/docker/nginx/nginx.conf file.
|
||||
|
||||
* With a -c|--cluster option, the docker-build command will search for the file in a subdirectory below your Dockerfile.
|
||||
|
||||
``` bash
|
||||
# docker-build -c custom nginx && docker-run -c custom nginx
|
||||
```
|
||||
|
||||
The DOCKER_BUILD_PREFIX variable is populated with 'custom/' to force the Dockerfile to search for a `./custom/nginx.conf` file, ie /etc/docker/nginx/custom/nginx.conf file.
|
||||
|
||||
* Whith an image name suffixed with a dash, the docker-build command will search for a suffixed file as well.
|
||||
|
||||
``` bash
|
||||
# docker-build -c custom nginx-develop && docker-run -c custom nginx-develop
|
||||
```
|
||||
|
||||
The DOCKER_BUILD_PREFIX variable is populated with 'custom/' and the DOCKER_BUILD_SUFFIX variable is populated with '-develop' to force the Dockerfile to search for a `./custom/nginx.conf-develop` file, ie /etc/docker/nginx/custom/nginx.conf-develop file.
|
||||
|
||||
### Override your options
|
||||
|
||||
The same override principle can be used for the Dockerfile and the Dockeropts file when using the docker-build and docker-run commands.
|
||||
You can create a /etc/docker/nginx/custom/Dockeropts file that would override your default Dockeropt file, and a /etc/docker/nginx/custom/Dockeropts-develop file overriding both other files too.
|
||||
The Dockeropts file accepts the following options.
|
||||
|
||||
* `SYSCTL` - values to set on the docker host via the sysctl command before running the docker
|
||||
* `DOCKER_ARGS` - values to pass to the docker build command with --build-arg options
|
||||
* `DOCKER_ENV` - values to pass to the docker run command with -e options
|
||||
* `DOCKER_LINK` - values to pass to the docker run command with --link options
|
||||
* `DOCKER_OPT` - values to pass to the docker run command with prefixed by --
|
||||
* `DOCKER_PORT` - values to pass to the docker run command with -p options
|
||||
* `DOCKER_ULIMIT` - values to pass to the docker run command with --ulimit options
|
||||
* `DOCKER_VOLUME` - values to pass to the docker run command with -v options
|
||||
* `HOST_VOLUME` - volumes to allow write access to from the docker on selinux enabled host
|
||||
|
||||
Overriding options is done several times, reading options from the more specific to the more generic file. In our example, files are read in this order :
|
||||
/etc/docker/nginx/custom/Dockeropts-develop
|
||||
/etc/docker/nginx/custom/Dockeropts
|
||||
/etc/docker/nginx/Dockeropts
|
||||
|
||||
## Common configuration
|
||||
|
||||
Following configuration builds and runs the docker image 'nginx-develop' for the 'custom' cluster described in our example.
|
||||
The Dockerfile and Dockeropts files needed in the /etc/docker/nginx directory should be present on the docker host, likely synchronised by an other ansible role.
|
||||
|
||||
``` yaml
|
||||
docker_cluster: "custom"
|
||||
docker:
|
||||
- nginx-develop
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
To test this role on your `docker` hosts, run the tests/playbook.yml playbook.
|
||||
|
||||
``` bash
|
||||
$ ansible-playbook tests/playbook.yml
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
This role is known to work on Ubuntu, Debian, CentOS and Alpine Linux.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
# file: defaults/main.yml
|
||||
|
||||
# minimum kernel version
|
||||
docker_check_kernel: '3.10'
|
||||
|
||||
# architecture
|
||||
docker_check_machine: 'x86_64'
|
||||
|
||||
# The docker package name
|
||||
docker_package: docker
|
||||
|
||||
# A list of package to install/remove
|
||||
# docker_packages:
|
||||
# - { "name": "docker", "state": "absent" }
|
||||
|
||||
# Location of configuration files loaded by the init script
|
||||
docker_init_config_directory: "/etc/sysconfig"
|
||||
|
||||
# docker daemon options environment variable
|
||||
docker_opts: "OPTIONS"
|
||||
|
||||
# services
|
||||
docker_services:
|
||||
- docker
|
||||
|
||||
# dockers
|
||||
# dockers:
|
||||
# - nginx
|
||||
|
||||
# docker cluster
|
||||
# docker_cluster: ""
|
||||
|
||||
# Start docker
|
||||
docker_start: true
|
||||
|
||||
# Stop and remove running docker to start a new one when image has been updated
|
||||
docker_restart: true
|
||||
|
||||
# Stop and remove running docker to start a new one even if image has not been updated
|
||||
docker_force_restart: false
|
||||
+1
@@ -0,0 +1 @@
|
||||
kernel.pax.softmode=1
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
DOCKER_IMAGE_REPOSITORY="centile"
|
||||
DOCKER_BUILD_DIRECTORY="/etc/docker"
|
||||
|
||||
usage() {
|
||||
echo Usage: $0 [-c cluster] [-f] [-q] [-t] image [image [...]]
|
||||
echo -e "Build a docker image in the '${DOCKER_IMAGE_REPOSITORY}' repository."
|
||||
echo
|
||||
echo -e "image\tis a directory with a Dockerfile, default in '${DOCKER_BUILD_DIRECTORY}/image'."
|
||||
echo -e "\t'image' can contains a dash. The suffixed part after the dash is taken into account"
|
||||
echo -e "\tin the image name but not in the name of the directory containing the Dockerfile."
|
||||
echo -e "\tsuffix will be available in your Dockerfile in the DOCKER_BUILD_SUFFIX build-arg."
|
||||
echo
|
||||
echo -e "Options:"
|
||||
echo -e "\t-c 'cluster'\tAllow to override files in 'image' directory with existing files in"
|
||||
echo -e "\t\t\tthe 'image/cluster' directory. 'cluster' will be available in your"
|
||||
echo -e "\t\t\tDockerfile in the DOCKER_BUILD_PREFIX build-arg."
|
||||
echo -e "\t-f\t\tforce build, do not use cache when building image."
|
||||
echo -e "\t-q\t\tquiet mode, minimal output."
|
||||
echo -e "\t-t\t\ttest mode, do nothing but output the command that would haev been launched."
|
||||
echo
|
||||
echo -e "EXAMPLES"
|
||||
echo
|
||||
echo -e "$0 elk"
|
||||
echo -e "Build a docker image named '${DOCKER_IMAGE_REPOSITORY}/elk' with Dockerfile ${DOCKER_BUILD_DIRECTORY}/elk/Dockerfile"
|
||||
echo
|
||||
echo -e "$0 elk-es01"
|
||||
echo -e "Build a docker image named '${DOCKER_IMAGE_REPOSITORY}/elk-es01' with Dockerfile ${DOCKER_BUILD_DIRECTORY}/elk/Dockerfile"
|
||||
echo -e "and build-arg DOCKER_BUILD_SUFFIX=-es01"
|
||||
echo
|
||||
echo -e "$0 -c elisa-sdc elk-es01"
|
||||
echo -e "Build a docker image named '${DOCKER_IMAGE_REPOSITORY}/elk-es01' with Dockerfile ${DOCKER_BUILD_DIRECTORY}/elk/Dockerfile,"
|
||||
echo -e "build-arg DOCKER_BUILD_PREFIX=elisa-sdc/ and build-arg DOCKER_BUILD_SUFFIX=-es01"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-c|--cluster) shift && CLUSTER="$1"
|
||||
;;
|
||||
-f|--force) FORCE=1
|
||||
;;
|
||||
-t|--test) TEST=1
|
||||
;;
|
||||
-q|--quiet) QUIET=1
|
||||
;;
|
||||
-h|--help) usage
|
||||
;;
|
||||
*) args="${args:-} $1"
|
||||
esac
|
||||
shift
|
||||
args="${args# }"
|
||||
done
|
||||
|
||||
# check args
|
||||
[ "${args:0:1}" = "-" ] && usage
|
||||
|
||||
# grsec/pax on alpine linux with docker < 1.12
|
||||
[ -f /etc/alpine-release ] && while read major minor patch; do
|
||||
if [ "${major}" -eq 1 ] && [ "${minor:-0}" -lt 12 ]; then
|
||||
[ "$(sysctl -n kernel.grsecurity.chroot_deny_chmod 2>/dev/null)" = 1 ] && sysctl -w kernel.grsecurity.chroot_deny_chmod=0 2>/dev/null && grsec_disabled_chmod=1
|
||||
[ "$(sysctl -n kernel.grsecurity.chroot_deny_mknod 2>/dev/null)" = 1 ] && sysctl -w kernel.grsecurity.chroot_deny_mknod=0 2>/dev/null && grsec_disabled_mknod=1
|
||||
fi
|
||||
done <<< $(apk version docker |awk -F '-' '/^docker/ {print $2}' |sed 's/\./ /g')
|
||||
|
||||
for arg in $args; do
|
||||
# extract docker image name
|
||||
image="$(basename ${arg})"
|
||||
# keep part before the dash as the directory name
|
||||
dir="$(dirname ${arg})/${image%-*}"
|
||||
# keep part after the dash as an image suffix name
|
||||
[ "${image##*-}" != "${image}" ] && suffix="${image##*-}"
|
||||
|
||||
# default to ${DOCKER_BUILD_DIRECTORY}/${dir} if ${dir} does not exists
|
||||
[ ! -d "${dir}" ] && [ -d "${DOCKER_BUILD_DIRECTORY}/${dir}" ] && dir="${DOCKER_BUILD_DIRECTORY}/${dir#./}"
|
||||
|
||||
# directory exists && contains a Dockerfile
|
||||
[ -d ${dir} ] && [ -f "${dir}/Dockerfile" ] || usage
|
||||
# cluster directory exists
|
||||
[ -n "${CLUSTER}" ] && { [ -d ${dir}/${CLUSTER} ] || usage; }
|
||||
|
||||
# search for Dockeropts files
|
||||
files="${dir}/Dockeropts ${dir}/Dockeropts-${suffix}"
|
||||
[ -n "${CLUSTER}" ] && files="${files} ${dir}/${CLUSTER}/Dockeropts ${dir}/${CLUSTER}/Dockeropts-${suffix}"
|
||||
|
||||
# source the Dockeropts files
|
||||
for dockeropts in ${files}; do
|
||||
[ -f "${dockeropts}" ] && . ${dockeropts}
|
||||
done
|
||||
|
||||
# quiet build
|
||||
[ ${QUIET} ] && DOCKER_BUILD_ARGS="--quiet" || DOCKER_BUILD_ARGS=""
|
||||
|
||||
# do not use cache
|
||||
[ ${FORCE} ] && DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --no-cache"
|
||||
|
||||
# extract DOCKER_ARGS
|
||||
[ -n "${DOCKER_ARGS}" ] && for build_arg in ${DOCKER_ARGS}; do
|
||||
DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --build-arg ${build_arg}"
|
||||
done
|
||||
|
||||
# add DOCKER_BUILD_PREFIX and DOCKER_BUILD_SUFFIX
|
||||
[ -n "${CLUSTER}" ] && DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --build-arg DOCKER_BUILD_PREFIX=${CLUSTER}/"
|
||||
[ -n "${suffix}" ] && DOCKER_BUILD_ARGS="${DOCKER_BUILD_ARGS} --build-arg DOCKER_BUILD_SUFFIX=-${suffix}"
|
||||
|
||||
# search for Dockerfile
|
||||
[ -n "${CLUSTER}" ] && files="${dir}/${CLUSTER}/Dockerfile-${suffix} ${dir}/${CLUSTER}/Dockerfile" || files=""
|
||||
files="${files} ${dir}/Dockerfile-${suffix} ${dir}/Dockerfile"
|
||||
|
||||
# build docker image with 1st found Dockerfile
|
||||
for dockerfile in ${files}; do
|
||||
[ -f "${dockerfile}" ] || continue
|
||||
[ ${QUIET} ] && [ ! ${TEST} ] && echo -n "${image} "
|
||||
[ ! ${QUIET} ] && echo "Building image ${image}"
|
||||
if [ ${TEST} ]; then
|
||||
echo docker build ${DOCKER_BUILD_ARGS} -t ${DOCKER_IMAGE_REPOSITORY}/${image} -f ${dockerfile} ${dir}
|
||||
else
|
||||
docker build ${DOCKER_BUILD_ARGS} -t ${DOCKER_IMAGE_REPOSITORY}/${image} -f ${dockerfile} ${dir}
|
||||
result=$?
|
||||
fi
|
||||
[ ${result:-0} -ge ${return:-0} ] && return=${result}
|
||||
break
|
||||
done
|
||||
done
|
||||
|
||||
# grsec/pax
|
||||
[ ${grsec_disabled_chmod} ] && sysctl -w kernel.grsecurity.chroot_deny_chmod=1 2>/dev/null
|
||||
[ ${grsec_disabled_mknod} ] && sysctl -w kernel.grsecurity.chroot_deny_mknod=1 2>/dev/null
|
||||
|
||||
exit ${return:-1}
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
docker ps -q --no-trunc --filter status=exited,status=created,status=dead |while read docker; do docker rm ${docker}; done
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
docker images -q --no-trunc --filter dangling=true |while read image; do docker rmi ${image}; done
|
||||
@@ -0,0 +1,144 @@
|
||||
#! /bin/bash
|
||||
|
||||
set -eou pipefail
|
||||
|
||||
#usage: sudo ./docker-cleanup-volumes.sh [--dry-run]
|
||||
|
||||
docker_bin="$(which docker.io 2> /dev/null || which docker 2> /dev/null)"
|
||||
|
||||
# Default dir
|
||||
dockerdir=/var/lib/docker
|
||||
|
||||
# Look for an alternate docker directory with -g/--graph option
|
||||
dockerpid=$(ps ax | grep "$docker_bin" | grep -v grep | awk '{print $1; exit}') || :
|
||||
if [[ -n "$dockerpid" && $dockerpid -gt 0 ]]; then
|
||||
next_arg_is_dockerdir=false
|
||||
while read -d $'\0' arg
|
||||
do
|
||||
if [[ $arg =~ ^--graph=(.+) ]]; then
|
||||
dockerdir=${BASH_REMATCH[1]}
|
||||
break
|
||||
elif [ $arg = '-g' ]; then
|
||||
next_arg_is_dockerdir=true
|
||||
elif [ $next_arg_is_dockerdir = true ]; then
|
||||
dockerdir=$arg
|
||||
break
|
||||
fi
|
||||
done < /proc/$dockerpid/cmdline
|
||||
fi
|
||||
|
||||
dockerdir=$(readlink -f "$dockerdir")
|
||||
|
||||
volumesdir=${dockerdir}/volumes
|
||||
vfsdir=${dockerdir}/vfs/dir
|
||||
allvolumes=()
|
||||
dryrun=false
|
||||
verbose=false
|
||||
|
||||
function log_verbose() {
|
||||
if [ "${verbose}" = true ]; then
|
||||
echo "$1"
|
||||
fi;
|
||||
}
|
||||
|
||||
function delete_volumes() {
|
||||
local targetdir=$1
|
||||
echo
|
||||
if [[ ! -d "${targetdir}" || ! "$(ls -A "${targetdir}")" ]]; then
|
||||
echo "Directory ${targetdir} does not exist or is empty, skipping."
|
||||
return
|
||||
fi
|
||||
echo "Delete unused volume directories from $targetdir"
|
||||
local dir
|
||||
while read -d $'\0' dir
|
||||
do
|
||||
dir=$(basename "$dir")
|
||||
if [[ -d "${targetdir}/${dir}/_data" || "${dir}" =~ [0-9a-f]{64} ]]; then
|
||||
if [ ${#allvolumes[@]} -gt 0 ] && [[ ${allvolumes[@]} =~ "${dir}" ]]; then
|
||||
echo "In use ${dir}"
|
||||
else
|
||||
if [ "${dryrun}" = false ]; then
|
||||
echo "Deleting ${dir}"
|
||||
rm -rf "${targetdir}/${dir}"
|
||||
else
|
||||
echo "Would have deleted ${dir}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Not a volume ${dir}"
|
||||
fi
|
||||
done < <(find "${targetdir}" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null)
|
||||
}
|
||||
|
||||
if [ $UID != 0 ]; then
|
||||
echo "You need to be root to use this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$docker_bin" ] ; then
|
||||
echo "Please install docker. You can install docker by running \"wget -qO- https://get.docker.io/ | sh\"."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $# > 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-n|--dry-run)
|
||||
dryrun=true
|
||||
;;
|
||||
-v|--verbose)
|
||||
verbose=true
|
||||
;;
|
||||
*)
|
||||
echo "Cleanup docker volumes: remove unused volumes."
|
||||
echo "Usage: ${0##*/} [--dry-run] [--verbose]"
|
||||
echo " -n, --dry-run: dry run: display what would get removed."
|
||||
echo " -v, --verbose: verbose output."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Make sure that we can talk to docker daemon. If we cannot, we fail here.
|
||||
${docker_bin} version >/dev/null
|
||||
|
||||
container_ids=$(${docker_bin} ps -a -q --no-trunc)
|
||||
|
||||
#All volumes from all containers
|
||||
SAVEIFS=$IFS
|
||||
IFS=$(echo -en "\n\b")
|
||||
for container in $container_ids; do
|
||||
#add container id to list of volumes, don't think these
|
||||
#ever exists in the volumesdir but just to be safe
|
||||
allvolumes+=${container}
|
||||
#add all volumes from this container to the list of volumes
|
||||
log_verbose "Inspecting container ${container}"
|
||||
for volpath in $(
|
||||
${docker_bin} inspect --format='{{range $key, $val := .}}{{if eq $key "Volumes"}}{{range $vol, $path := .}}{{$path}}{{"\n"}}{{end}}{{end}}{{if eq $key "Mounts"}}{{range $mount := $val}}{{$mount.Source}}{{"\n"}}{{end}}{{end}}{{end}}' ${container} \
|
||||
); do
|
||||
log_verbose "Processing volumepath ${volpath}"
|
||||
#try to get volume id from the volume path
|
||||
vid=$(echo "${volpath}" | sed 's|.*/\(.*\)/_data$|\1|;s|.*/\([0-9a-f]\{64\}\)$|\1|')
|
||||
# check for either a 64 character vid or then end of a volumepath containing _data:
|
||||
if [[ "${vid}" =~ ^[0-9a-f]{64}$ || (${volpath} =~ .*/_data$ && ! "${vid}" =~ "/") ]]; then
|
||||
log_verbose "Found volume ${vid}"
|
||||
allvolumes+=("${vid}")
|
||||
else
|
||||
#check if it's a bindmount, these have a config.json file in the ${volumesdir} but no files in ${vfsdir} (docker 1.6.2 and below)
|
||||
for bmv in $(find "${volumesdir}" -name config.json -print | xargs grep -l "\"IsBindMount\":true" | xargs grep -l "\"Path\":\"${volpath}\""); do
|
||||
bmv="$(basename "$(dirname "${bmv}")")"
|
||||
log_verbose "Found bindmount ${bmv}"
|
||||
allvolumes+=("${bmv}")
|
||||
#there should be only one config for the bindmount, delete any duplicate for the same bindmount.
|
||||
break
|
||||
done
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$SAVEIFS
|
||||
|
||||
delete_volumes "${volumesdir}"
|
||||
delete_volumes "${vfsdir}"
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
[ -n "$1" ] || exit
|
||||
|
||||
for docker in $@; do
|
||||
docker inspect "${docker}" 2>/dev/null |awk '$1 == "\"Image\":" && $2 ~ /^\"sha/ {gsub(/(^\"|\",$)/, "", $2); print "'${docker}' "$2}'
|
||||
done
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
[ -n "$1" ] || exit
|
||||
|
||||
for docker in $@; do
|
||||
docker inspect "${docker}" 2>/dev/null |awk '$1 == "\"Status\":" {gsub(/(^\"|\",$)/, "", $2); print "'${docker}' "$2}'
|
||||
done
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
[ -n "$1" ] && :> $(docker inspect $1 | grep '"LogPath": "*"' | sed -e 's/.*"LogPath": "//g' | sed -e 's/",//g')
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
[ -n "$1" ] && \
|
||||
docker_log=$(docker inspect $1 2>/dev/null | grep '"LogPath": "*"' | sed -e 's/.*"LogPath": "//g' | sed -e 's/",//g') && \
|
||||
[ -f "${docker_log}" ] && \
|
||||
tail -n 100 ${docker_log} > ${docker_log}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
#!/bin/bash
|
||||
# Author: Yann Autissier <yann.autissier@gmail.com>
|
||||
|
||||
DOCKER_IMAGE_REPOSITORY="centile"
|
||||
DOCKER_BUILD_DIRECTORY="/etc/docker"
|
||||
|
||||
usage() {
|
||||
echo Usage: $0 [ -c cluster] [ -i image ] [-f] [-q] [-t] name [name [...]]
|
||||
echo -e "Run a docker from an image in the '${DOCKER_IMAGE_REPOSITORY}' repository."
|
||||
echo
|
||||
echo -e "name\t is a directory with a Dockerfile, default in '${DOCKER_BUILD_DIRECTORY}/name'."
|
||||
echo -e "\t'name' can contains a dash. The directory name will be extracted for the first part"
|
||||
echo -e "\tbefore a dash."
|
||||
echo
|
||||
echo -e "Options:"
|
||||
echo -e "\t-c 'cluster'\tAllow to override files in 'image' directory with existing files in"
|
||||
echo -e "\t\t\tthe 'image/cluster' directory."
|
||||
echo -e "\t -i 'image'\tthe docker image to run, default in '${DOCKER_IMAGE_REPOSITORY}' repository."
|
||||
echo -e "\t -f\t\tforce run, stop and remove existing docker before running a new one."
|
||||
echo -e "\t -q\t\tquiet mode, minimal output."
|
||||
echo -e "\t -t\t\ttest mode, do nothing but output the command that would have been launched."
|
||||
echo
|
||||
echo -e "EXAMPLES"
|
||||
echo
|
||||
echo -e "$0 elk"
|
||||
echo -e "Run a docker named 'elk' from the '${DOCKER_IMAGE_REPOSITORY}/elk' image"
|
||||
echo
|
||||
echo -e "$0 elk-es01"
|
||||
echo -e "Run a docker named 'elk-es01' from the '${DOCKER_IMAGE_REPOSITORY}/elk-es01' image"
|
||||
echo
|
||||
echo -e "$0 -i elk elk-es01"
|
||||
echo -e "Run a docker named 'elk-es01' from the '${DOCKER_IMAGE_REPOSITORY}/elk' image"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-c|--cluster) shift && CLUSTER="$1"
|
||||
;;
|
||||
-i|--image) shift && IMAGE="$1"
|
||||
;;
|
||||
-h|--help) usage
|
||||
;;
|
||||
-f|--force) FORCE=1
|
||||
;;
|
||||
-q|--quiet) QUIET=1
|
||||
;;
|
||||
-t|--test) TEST=1
|
||||
;;
|
||||
*) args="${args:-} $1"
|
||||
esac
|
||||
shift
|
||||
args="${args# }"
|
||||
done
|
||||
|
||||
# check args
|
||||
[ "${args:0:1}" = "-" ] && usage
|
||||
|
||||
for arg in ${args}; do
|
||||
# reset vars
|
||||
image=""; DOCKER_OPT=""
|
||||
# extract docker name
|
||||
name="$(basename ${arg})"
|
||||
# keep part before the dash as the directory name
|
||||
dir="$(dirname ${arg})/${name%-*}"
|
||||
# keep part after the dash as an image suffix name
|
||||
[ "${name##*-}" != "${name}" ] && suffix="${name##*-}"
|
||||
# if provided, set docker image from args
|
||||
if [ -n "${IMAGE}" ]; then
|
||||
# if docker image does not contain a /, add our default repository
|
||||
[ "${IMAGE##*/}" != "${IMAGE}" ] && image="${IMAGE}" || image="${DOCKER_IMAGE_REPOSITORY}/${IMAGE}"
|
||||
# else try to find an image from the docker name
|
||||
else
|
||||
# try docker name, docker name without ending numbers, docker name without suffix
|
||||
for image in ${name} ${name%%[0-9]*} ${name%-*}; do
|
||||
# search for image in ${DOCKER_IMAGE_REPOSITORY}
|
||||
[ -n "$(docker images 2>/dev/null |awk '$1 == "'${DOCKER_IMAGE_REPOSITORY}/${image}'" {print $1}')" ] && image="${DOCKER_IMAGE_REPOSITORY}/${image}" && break
|
||||
image="${name}"
|
||||
done
|
||||
fi
|
||||
|
||||
tag="$(docker images |awk '$1 == "'${image}'" {print $2}')"
|
||||
[ -z "${tag}" ] && echo "ERROR: Cannot find image '${image}'" >2 && exit 2
|
||||
|
||||
# default to ${DOCKER_BUILD_DIRECTORY}/${dir} if ${dir} does not exists
|
||||
[ ! -d "${dir}" ] && [ -d "${DOCKER_BUILD_DIRECTORY}/${dir}" ] && dir="${DOCKER_BUILD_DIRECTORY}/${dir#./}"
|
||||
|
||||
# directory exists && contains a Dockerfile
|
||||
[ -d ${dir} ] && [ -f "${dir}/Dockerfile" ] || usage
|
||||
# cluster directory exists
|
||||
[ -n "${CLUSTER}" ] && { [ -d ${dir}/${CLUSTER} ] || usage; }
|
||||
|
||||
# search for Dockeropts files
|
||||
files="${dir}/Dockeropts ${dir}/Dockeropts-${suffix}"
|
||||
[ -n "${CLUSTER}" ] && files="${files} ${dir}/${CLUSTER}/Dockeropts ${dir}/${CLUSTER}/Dockeropts-${suffix}"
|
||||
|
||||
# source the Dockeropts files
|
||||
for dockeropts in ${files}; do
|
||||
[ -f "${dockeropts}" ] && . ${dockeropts}
|
||||
done
|
||||
|
||||
# extract SYSCTL
|
||||
[ -n "${SYSCTL}" ] && for sysctl in ${SYSCTL}; do
|
||||
sysctl -w ${sysctl} 2>/dev/null
|
||||
done
|
||||
|
||||
# extract DOCKER_OPT
|
||||
[ -n "${DOCKER_OPT}" ] && DOCKER_OPTS="--${DOCKER_OPT/ / --}" || DOCKER_OPTS=""
|
||||
|
||||
# extract DOCKER_ENV
|
||||
[ -n "${DOCKER_ENV}" ] && DOCKER_OPTS="${DOCKER_OPTS} -e ${DOCKER_ENV//\" /\" -e }"
|
||||
|
||||
# extract DOCKER_LINK
|
||||
[ -n "${DOCKER_LINK}" ] && DOCKER_OPTS="--link ${DOCKER_LINK/ / --link }"
|
||||
|
||||
# extract DOCKER_PORT
|
||||
[ -n "${DOCKER_PORT}" ] && DOCKER_OPTS="${DOCKER_OPTS} -p ${DOCKER_PORT// / -p }"
|
||||
|
||||
# extract DOCKER_ULIMIT
|
||||
[ -n "${DOCKER_ULIMIT}" ] && DOCKER_OPTS="${DOCKER_OPTS} --ulimit ${DOCKER_ULIMIT// / --ulimit }"
|
||||
|
||||
# extract DOCKER_VOLUME
|
||||
[ -n "${DOCKER_VOLUME}" ] && DOCKER_OPTS="${DOCKER_OPTS} -v ${DOCKER_VOLUME// / -v }"
|
||||
|
||||
# enable access to host volumes on selinux
|
||||
for volume in ${HOST_VOLUME}; do
|
||||
chcon -Rt svirt_sandbox_file_t ${volume} 2>/dev/null
|
||||
done
|
||||
|
||||
# remove current docker
|
||||
if [ ${FORCE} ]; then
|
||||
if [ -n "$(docker ps -q --filter status=created,status=restarting,status=running,status=paused,status=exited,status=dead,name=${name})" ]; then
|
||||
[ ! ${QUIET} ] && echo -n "Removing docker ${name}... "
|
||||
if [ ${TEST} ]; then
|
||||
echo docker rm -f ${name}
|
||||
else
|
||||
eval docker rm -f ${name} >/dev/null 2>&1
|
||||
result=$? && [ ${result} -ne 0 ] && echo "ERROR" && { [ ${result:-0} -ge ${return:-0} ] && return=${result}; } && break
|
||||
[ ! ${QUIET} ] && echo "OK"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# launch docker
|
||||
[ ${QUIET} ] && [ ! ${TEST} ] && echo -n "${name} "
|
||||
[ ! ${QUIET} ] && echo -n "Running docker ${name}... "
|
||||
if [ ${TEST} ]; then
|
||||
echo docker run --restart=always ${DOCKER_OPTS} -d --name ${name} ${image} ${DOCKER_RUN:-}
|
||||
else
|
||||
eval docker run --restart=always ${DOCKER_OPTS} -d --name ${name} ${image} ${DOCKER_RUN:-} 2>/dev/null
|
||||
result=$? && [ ${result} -ne 0 ] && echo "ERROR"
|
||||
fi
|
||||
[ ${result:-0} -ge ${return:-0} ] && return=${result}
|
||||
done
|
||||
|
||||
exit ${return:-1}
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# file handlers/main.yml
|
||||
|
||||
- name: restart docker
|
||||
service:
|
||||
name: "{{docker_service}}"
|
||||
state: "restarted"
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# Copyright (c) 2016 Centile
|
||||
#
|
||||
# MIT License
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
---
|
||||
galaxy_info:
|
||||
author: Yann Autissier
|
||||
description: An ansible role to install docker
|
||||
company: Centile
|
||||
license: MIT
|
||||
min_ansible_version: 1.9
|
||||
platforms:
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- xenial
|
||||
- name: Debian
|
||||
versions:
|
||||
- jessie
|
||||
- name: EL
|
||||
versions:
|
||||
- all
|
||||
|
||||
dependencies: []
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# file: playbook.yml
|
||||
|
||||
- hosts: docker
|
||||
roles:
|
||||
- .
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
# file: tasks/build.yml
|
||||
|
||||
- name: build - Build docker image
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "/usr/local/bin/docker-build -q -c {{docker_cluster|default('\"\"')}} {{item}}"
|
||||
register: docker_build_image_command
|
||||
|
||||
- name: build - Register docker_build_image
|
||||
with_items: "{{docker_build_image_command.results}}"
|
||||
set_fact:
|
||||
docker_build_image: "{{docker_build_image |default({}) |combine( {item.item: item.stdout} ) }}"
|
||||
|
||||
- name: build - Debug docker_elk_build_image
|
||||
with_items: "{{dockers|default([])}}"
|
||||
debug: msg="{{docker_build_image[item]}}"
|
||||
when: docker_debug|default(false)
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
# file: tasks/check.yml
|
||||
|
||||
- name: check - kernel version
|
||||
fail:
|
||||
msg: >
|
||||
docker requires a minimum kernel version of {{docker_check_kernel}}
|
||||
on {{ansible_distribution}} {{ansible_distribution_version}}
|
||||
when: ansible_kernel is version(docker_check_kernel, "<")
|
||||
|
||||
- name: check - machine architecture
|
||||
fail:
|
||||
msg: >
|
||||
docker requires a {{docker_check_machine}} version
|
||||
of {{ansible_distribution}} {{ansible_distribution_version}}
|
||||
when: ansible_machine != docker_check_machine
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# file: tasks/config.yml
|
||||
|
||||
- name: config - add docker storage setup
|
||||
lineinfile: dest="{{docker_init_config_directory}}/{{docker_package}}-storage-setup" state="present" line="STORAGE_DRIVER=\"\""
|
||||
when: docker_package|length > 0 and ansible_service_mgr == "systemd" and ansible_os_family|lower == "redhat"
|
||||
become: yes
|
||||
|
||||
# - name: config - disable docker iptables setup
|
||||
# lineinfile: dest="/lib/systemd/system/docker.service" state="present" regex="^ExecStart=" line="ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=false"
|
||||
# notify: restart docker
|
||||
# when: docker_package|length > 0 and ansible_service_mgr == "systemd"
|
||||
# become: yes
|
||||
|
||||
- name: config - setup docker mtu on Openstack VMs
|
||||
lineinfile: dest="{{docker_init_config_directory}}/{{docker_package}}" state="present" backrefs=true regexp='^{{docker_opts}}=(?:\'|\")?((?:\s*[\w=\/\-\.](?<!--mtu=1450)\s*)*)(?:\'|\")?$' line='{{docker_opts}}="\1 --mtu=1450"'
|
||||
when: docker_package|length > 0 and ansible_product_name == "OpenStack Nova"
|
||||
become: yes
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# file: tasks/files.yml
|
||||
|
||||
- name: files - copy files
|
||||
with_items:
|
||||
- /usr/local/bin/docker-build
|
||||
- /usr/local/bin/docker-cleanup
|
||||
- /usr/local/bin/docker-cleanup-images
|
||||
- /usr/local/bin/docker-cleanup-volumes
|
||||
- /usr/local/bin/docker-log-cleanup
|
||||
- /usr/local/bin/docker-log-truncate
|
||||
- /usr/local/bin/docker-run
|
||||
- /usr/local/bin/docker-get-image
|
||||
- /usr/local/bin/docker-get-status
|
||||
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0755
|
||||
become: yes
|
||||
|
||||
- name: files - copy sysctl configuration files
|
||||
with_items:
|
||||
- /etc/sysctl.d/docker.conf
|
||||
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0644
|
||||
become: yes
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
# file: tasks/group.yml
|
||||
|
||||
- name: group - create docker group
|
||||
group: name="docker" state="present" system="yes"
|
||||
become: yes
|
||||
when: ansible_os_family|lower != "alpine"
|
||||
|
||||
- name: group - add me to the docker group
|
||||
user: name="{{ansible_user_id}}" groups=docker append=yes
|
||||
become: yes
|
||||
when: ansible_os_family|lower != "alpine" and ansible_user_id != "root"
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# file: tasks/main.yml
|
||||
|
||||
- import_tasks: vars.yml
|
||||
tags:
|
||||
- vars
|
||||
- import_tasks: check.yml
|
||||
tags:
|
||||
- check
|
||||
- import_tasks: files.yml
|
||||
tags:
|
||||
- files
|
||||
- import_tasks: package.yml
|
||||
tags:
|
||||
- package
|
||||
- import_tasks: config.yml
|
||||
tags:
|
||||
- config
|
||||
- import_tasks: service.yml
|
||||
tags:
|
||||
- service
|
||||
- import_tasks: group.yml
|
||||
tags:
|
||||
- group
|
||||
- import_tasks: build.yml
|
||||
tags:
|
||||
- build
|
||||
- import_tasks: run.yml
|
||||
tags:
|
||||
- run
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
# file: tasks/package.yml
|
||||
|
||||
- name: package - packages pre installation
|
||||
with_items: "{{docker_packages|default([])}}"
|
||||
package: name="{{item.name}}" state="{{item.state}}"
|
||||
become: yes
|
||||
|
||||
- name: package - add docker GPG key
|
||||
apt_key: url=https://download.docker.com/linux/debian/gpg
|
||||
when: ansible_os_family|lower == "debian"
|
||||
|
||||
- name: add docker APT repository
|
||||
apt_repository:
|
||||
repo: deb [arch=amd64] https://download.docker.com/linux/{{ansible_distribution|lower}} {{ansible_distribution_release}} stable
|
||||
when: ansible_os_family|lower == "debian"
|
||||
|
||||
- name: package - add docker package
|
||||
package: name="{{docker_package}}" state=present
|
||||
when: docker_package|length > 0
|
||||
become: yes
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
# file: tasks/run.yml
|
||||
|
||||
- name: run - Get current docker status
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "/usr/local/bin/docker-get-status {{item}}"
|
||||
register: docker_current_status_command
|
||||
|
||||
- name: run - Register docker_current_status
|
||||
with_items: "{{docker_current_status_command.results}}"
|
||||
set_fact:
|
||||
docker_current_status: "{{docker_current_status |default({}) |combine( {item.item: item.stdout} ) }}"
|
||||
|
||||
- name: run - Debug docker_current_status
|
||||
with_items: "{{dockers|default([])}}"
|
||||
debug: msg="{{docker_current_status[item]}}"
|
||||
when: docker_debug|default(false)
|
||||
|
||||
- name: run - Get current docker image
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "/usr/local/bin/docker-get-image {{item}}"
|
||||
register: docker_current_image_command
|
||||
|
||||
- name: run - Register docker_current_image
|
||||
with_items: "{{docker_current_image_command.results}}"
|
||||
set_fact:
|
||||
docker_current_image: "{{docker_current_image |default({}) |combine( {item.item: item.stdout} ) }}"
|
||||
|
||||
- name: run - Debug docker_current_image
|
||||
with_items: "{{dockers|default([])}}"
|
||||
debug: msg="{{docker_current_image[item]}}"
|
||||
when: docker_debug|default(false)
|
||||
|
||||
- name: run - Stop current docker
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "docker stop {{item}}"
|
||||
when: ( docker_restart|default(false) and "{{docker_current_image[item]}}" != "{{docker_build_image[item]}}" or docker_force_restart|default(false) ) and "{{docker_current_status[item]}}" == "{{item}} running"
|
||||
|
||||
- name: run - Remove current docker
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "docker rm {{item}}"
|
||||
when: ( docker_restart|default(false) and "{{docker_current_image[item]}}" != "{{docker_build_image[item]}}" or docker_force_restart|default(false) ) and "{{docker_current_status[item]}}" != ""
|
||||
|
||||
- name: run - Run docker image
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "/usr/local/bin/docker-run -q -c {{docker_cluster|default('\"\"')}} {{item}}"
|
||||
when: docker_start|default(true) and "{{docker_current_image[item]}}" != "{{docker_build_image[item]}}" or docker_force_restart|default(false)
|
||||
|
||||
- name: run - Start docker
|
||||
with_items: "{{dockers|default([])}}"
|
||||
command: "docker start {{item}}"
|
||||
when: docker_start|default(true) and "{{docker_current_image[item]}}" == "{{docker_build_image[item]}}" and "{{docker_current_status[item]}}" != "{{item}} running"
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
# file: tasks/service.yml
|
||||
|
||||
- name: service - start docker daemon
|
||||
with_items: "{{docker_services|default([])}}"
|
||||
service:
|
||||
name: "{{item}}"
|
||||
state: started
|
||||
enabled: yes
|
||||
become: yes
|
||||
when: ansible_service_mgr|lower != "openrc" and ansible_os_family|lower != "alpine"
|
||||
|
||||
- name: service - force openrc status
|
||||
shell: "kill -0 $(cat /run/{{item}}.pid) && [ ! -h /run/openrc/started/{{item}} ] && ln -s /etc/init.d/{{item}} /run/openrc/started/{{item}} && service {{item}} restart ||:"
|
||||
with_items: "{{docker_services|default([])}}"
|
||||
become: yes
|
||||
when: ansible_service_mgr|lower == "openrc" or ansible_os_family|lower == "alpine"
|
||||
|
||||
- name: service - start docker daemon
|
||||
with_items: "{{docker_services|default([])}}"
|
||||
service:
|
||||
name: "{{item}}"
|
||||
state: started
|
||||
enabled: yes
|
||||
runlevel: boot
|
||||
become: yes
|
||||
when: ansible_service_mgr|lower == "openrc" or ansible_os_family|lower == "alpine"
|
||||
|
||||
- name: service - force docker restart
|
||||
shell: "[ ! -d /var/lib/docker/tmp ] && service docker restart ||:"
|
||||
become: yes
|
||||
when: ansible_service_mgr|lower == "openrc" or ansible_os_family|lower == "alpine"
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
# file: tasks/vars.yml
|
||||
|
||||
- name: vars - load per operating system variables
|
||||
include_vars: "{{item}}"
|
||||
with_first_found:
|
||||
- paths:
|
||||
- "vars/"
|
||||
- files:
|
||||
- "{{ansible_distribution|lower}}-{{ansible_distribution_version|lower}}-{{ansible_machine}}.yml" # centos-6.4-i386.yml ubuntu-16.04-x86_64.yml
|
||||
- "{{ansible_distribution|lower}}-{{ansible_distribution_version|lower}}.yml" # centos-6.4.yml ubuntu-16.04.yml
|
||||
- "{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}-{{ansible_machine}}.yml" # centos-6-i386.yml ubuntu-16-x86_64.yml
|
||||
- "{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}.yml" # centos-6.yml ubuntu-16.yml
|
||||
- "{{ansible_os_family|lower}}-{{ansible_distribution_version|lower}}-{{ansible_machine}}.yml" # redhat-6.4-i386.yml debian-8.5-x86_64.yml
|
||||
- "{{ansible_os_family|lower}}-{{ansible_distribution_version|lower}}.yml" # redhat-6.4.yml debian-8.5.yml
|
||||
- "{{ansible_os_family|lower}}-{{ansible_distribution_major_version|lower}}-{{ansible_machine}}.yml" # redhat-6-i386.yml debian-8-x86_64.yml
|
||||
- "{{ansible_os_family|lower}}-{{ansible_distribution_major_version|lower}}.yml" # redhat-6.yml debian-8.yml
|
||||
- "{{ansible_distribution|lower}}-{{ansible_machine}}.yml" # centos-i386.yml ubuntu-x86_64.yml
|
||||
- "{{ansible_distribution|lower}}.yml" # centos.yml ubuntu.yml
|
||||
- "{{ansible_os_family|lower}}-{{ansible_machine}}.yml" # redhat-i386.yml debian-x86_64.yml
|
||||
- "{{ansible_os_family|lower}}.yml" # redhat.yml debian.yml
|
||||
- "{{ansible_system|lower}}-{{ansible_machine}}.yml" # linux-i386.yml linux-x86_64.yml
|
||||
- "{{ansible_system|lower}}.yml" # linux.yml
|
||||
- "default.yml" # default.yml
|
||||
skip: true
|
||||
|
||||
- name: vars - override with local variables
|
||||
include_vars: "{{item}}"
|
||||
with_first_found:
|
||||
- paths:
|
||||
- "vars/"
|
||||
- files:
|
||||
- "local.yml"
|
||||
skip: true
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
# file: tests/goss.yml
|
||||
|
||||
- name: tests - create temporary directory
|
||||
command: mktemp -d
|
||||
register: tests_mktemp
|
||||
|
||||
- name: tests - register goss installation
|
||||
environment:
|
||||
PATH: "/usr/local/bin:{{ansible_env.PATH}}"
|
||||
command: which goss
|
||||
register: tests_goss_installed
|
||||
|
||||
- name: tests - register specific OS goss files
|
||||
set_fact:
|
||||
goss_file:
|
||||
- "goss/main_{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}.yml" # main_centos-6.yml main_centos-7.yml
|
||||
- "goss/main_{{ansible_distribution|lower}}.yml" # main_centos.yml main_ubuntu.yml
|
||||
- "goss/main_{{ansible_os_family|lower}}.yml" # main_redhat.yml main_debian.yml
|
||||
- "goss/main_{{ansible_system|lower}}.yml" # main_linux.yml
|
||||
- "goss/main.yml" # main.yml
|
||||
|
||||
- name: tests - register goss file
|
||||
set_fact:
|
||||
tests_goss_file: "{{lookup('first_found', goss_file)}}"
|
||||
|
||||
- name: tests - copy test files
|
||||
copy: src=goss/ dest="{{tests_mktemp.stdout}}"
|
||||
|
||||
- name: tests - launch tests
|
||||
environment:
|
||||
PATH: "/usr/local/bin:{{ansible_env.PATH}}"
|
||||
goss: path="{{tests_mktemp.stdout}}/{{tests_goss_file|basename}}" format=rspecish
|
||||
register: tests_goss_results
|
||||
ignore_errors: true
|
||||
become: yes
|
||||
|
||||
- name: tests - remove temporary directory
|
||||
file: path="{{tests_mktemp.stdout}}" state=absent
|
||||
|
||||
- name: tests - failure message
|
||||
fail: msg="{{tests_goss_results.msg}}"
|
||||
when: tests_goss_results|failed
|
||||
@@ -0,0 +1,4 @@
|
||||
group:
|
||||
docker:
|
||||
exists: true
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
gossfile:
|
||||
package.yml: {}
|
||||
service.yml: {}
|
||||
group.yml: {}
|
||||
@@ -0,0 +1,4 @@
|
||||
gossfile:
|
||||
package_centos-6.yml: {}
|
||||
service.yml: {}
|
||||
group.yml: {}
|
||||
@@ -0,0 +1,4 @@
|
||||
gossfile:
|
||||
package_centos-7.yml: {}
|
||||
service.yml: {}
|
||||
group.yml: {}
|
||||
@@ -0,0 +1,4 @@
|
||||
gossfile:
|
||||
package_debian.yml: {}
|
||||
service.yml: {}
|
||||
group.yml: {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package:
|
||||
docker:
|
||||
installed: true
|
||||
@@ -0,0 +1,3 @@
|
||||
package:
|
||||
docker-io:
|
||||
installed: true
|
||||
@@ -0,0 +1,3 @@
|
||||
package:
|
||||
docker-latest:
|
||||
installed: true
|
||||
@@ -0,0 +1,3 @@
|
||||
package:
|
||||
docker-engine:
|
||||
installed: true
|
||||
@@ -0,0 +1,5 @@
|
||||
service:
|
||||
docker:
|
||||
enabled: true
|
||||
running: true
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
from ansible.module_utils.basic import *
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: goss
|
||||
author: Mathieu Corbin
|
||||
short_description: Launch goss (https://github.com/aelsabbahy/goss) test
|
||||
description:
|
||||
- Launch goss test. Always changed = False if success.
|
||||
options:
|
||||
path:
|
||||
required: true
|
||||
description:
|
||||
- Test file to validate. Must be on the remote machine.
|
||||
format:
|
||||
required: false
|
||||
description:
|
||||
- change the output goss format.
|
||||
- Goss format list : goss v --format => [documentation json junit nagios rspecish tap].
|
||||
- Default: rspecish
|
||||
output_file:
|
||||
required: false
|
||||
description:
|
||||
- save the result of the goss command in a file whose path is output_file
|
||||
examples:
|
||||
- name: test goss file
|
||||
goss:
|
||||
path: "/path/to/file.yml"
|
||||
|
||||
- name: test goss files
|
||||
goss:
|
||||
path: "{{ item }}"
|
||||
format: json
|
||||
output_file : /my/output/file-{{ item }}
|
||||
with_items: "{{ goss_files }}"
|
||||
'''
|
||||
|
||||
|
||||
# launch goss validate command on the file
|
||||
def check(module, test_file_path, output_format):
|
||||
cmd = ""
|
||||
if output_format is not None:
|
||||
cmd = "goss -g {0} v --format {1}".format(test_file_path, output_format)
|
||||
else:
|
||||
cmd = "goss -g {0} v".format(test_file_path)
|
||||
return module.run_command(cmd)
|
||||
|
||||
|
||||
# write goss result to output_file_path
|
||||
def output_file(output_file_path, out):
|
||||
if output_file_path is not None:
|
||||
with open(output_file_path, 'w') as output_file:
|
||||
output_file.write(out)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(required=True, type='str'),
|
||||
format=dict(required=False, type='str'),
|
||||
output_file=dict(required=False, type='str'),
|
||||
),
|
||||
supports_check_mode=False
|
||||
)
|
||||
|
||||
test_file_path = module.params['path'] # test file path
|
||||
output_format = module.params['format'] # goss output format
|
||||
output_file_path = module.params['output_file']
|
||||
|
||||
if test_file_path is None:
|
||||
module.fail_json(msg="test file path is null")
|
||||
|
||||
test_file_path = os.path.expanduser(test_file_path)
|
||||
|
||||
# test if access to test file is ok
|
||||
|
||||
if not os.access(test_file_path, os.R_OK):
|
||||
module.fail_json(msg="Test file %s not readable" % (test_file_path))
|
||||
|
||||
# test if test file is not a dir
|
||||
if os.path.isdir(test_file_path):
|
||||
module.fail_json(msg="Test file must be a file ! : %s" % (test_file_path))
|
||||
|
||||
(rc, out, err) = check(module, test_file_path, output_format)
|
||||
|
||||
if output_file_path is not None:
|
||||
output_file_path = os.path.expanduser(output_file_path)
|
||||
# check if output_file is a file
|
||||
if output_file_path.endswith(os.sep):
|
||||
module.fail_json(msg="output_file must be a file. Actually : %s "
|
||||
% (output_file_path))
|
||||
|
||||
output_dirname = os.path.dirname(output_file_path)
|
||||
|
||||
# check if output directory exists
|
||||
if not os.path.exists(output_dirname):
|
||||
module.fail_json(msg="directory %s does not exists" % (output_dirname))
|
||||
|
||||
# check if writable
|
||||
if not os.access(os.path.dirname(output_file_path), os.W_OK):
|
||||
module.fail_json(msg="Destination %s not writable" % (os.path.dirname(output_file_path)))
|
||||
# write goss result on the output file
|
||||
output_file(output_file_path, out)
|
||||
|
||||
if rc is not None and rc != 0:
|
||||
error_msg = "err : {0} ; out : {1}".format(err, out)
|
||||
module.fail_json(msg=error_msg)
|
||||
|
||||
result = {}
|
||||
result['stdout'] = out
|
||||
result['changed'] = False
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# file: tests/main.yml
|
||||
|
||||
- include: goss.yml
|
||||
tags:
|
||||
- tests
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# file: tests/playbook.yml
|
||||
|
||||
- hosts: '{{ target | default("all") }}'
|
||||
tasks:
|
||||
- import_tasks: main.yml
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# file vars/centos-6.yml
|
||||
|
||||
docker_check_kernel: '2.6.32-431'
|
||||
docker_opts: "other_args"
|
||||
docker_package: docker-io
|
||||
docker_packages: docker
|
||||
- { "name": "docker", "state": "absent" }
|
||||
- { "name": "epel-release", "state": "present" }
|
||||
- { "name": "curl", "state": "present" }
|
||||
- { "name": "device-mapper-libs", "state": "present" }
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
# file vars/centos-7.yml
|
||||
|
||||
docker_check_kernel: '3.10.0-327'
|
||||
|
||||
docker_package: docker-latest
|
||||
docker_packages:
|
||||
- { "name": "docker", "state": "absent" }
|
||||
- { "name": "curl", "state": "present" }
|
||||
- { "name": "device-mapper-libs", "state": "present" }
|
||||
docker_services:
|
||||
- docker-latest-storage-setup
|
||||
- docker-latest
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# file: vars/debian.yml
|
||||
|
||||
docker_check_kernel: '3.2'
|
||||
|
||||
docker_package: docker-ce
|
||||
docker_packages:
|
||||
- { "name": "apt-transport-https", "state": "present" }
|
||||
- { "name": "ca-certificates", "state": "present" }
|
||||
- { "name": "curl", "state": "present" }
|
||||
- { "name": "gnupg2", "state": "present" }
|
||||
- { "name": "software-properties-common", "state": "present" }
|
||||
|
||||
docker_init_config_directory: "/etc/default"
|
||||
docker_opts: "DOCKER_OPTS"
|
||||
Reference in New Issue
Block a user