Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiasmcnulty committed Sep 27, 2023
0 parents commit 318ae12
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.envrc
.direnv
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-added-large-files

- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v2.6.0"
hooks:
- id: prettier
27 changes: 27 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright (c) 2023, Caktus Consulting Group, LLC
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the Caktus Consulting Group, LLC nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# caktus.podman-containers

An Ansible role to run Podman containers on Ubuntu or RHEL-compatible servers.

## Configuration

See `defaults/main.yml` for the supported variables and their defaults.
56 changes: 56 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# The "deploy user" as which containers will be run. Note,
# you're still responsible for setting up Ansible connection details
# to SSH to the server as this user.
podman_user: ubuntu

# Home directory of podman_user
podman_user_home: "/home/{{ podman_user }}"

# Directories to create
podman_directories:
- "{{ podman_user_home }}/log/"
- "{{ podman_user_home }}/.config/systemd/user/"

# Git repositories to build. For example:
#
# podman_build_repos:
# - repo: [email protected]:my_org/my_repo.git
# version: "{{ commit_sha | default(git_branch) }}"
# dest_dir: "{{ podman_user_home }}/my_repo"
# image_name: my_repo
podman_build_repos: []

# Set podman_pod_name to put all containers in a single pod
# podman_pod_name: app

# The Podman pods to create. Can be left empty if you don't want containers
# to run in a Pod. For example:
#
# podman_pods:
# - name: "{{ podman_pod_name }}"
# publish:
# - 8000:8000
podman_pods: []

# The Podman containers to create. For example:
#
# podman_containers:
# - name: nginx
# image: docker.io/nginx
# tag: 1.24
# pod: "{{ podman_pod_name }}"
#
# Note that if podman_pod_name is set, the container will run in the named
# pod even if not explicitly set above.
podman_containers: []

# If pod hostname is unset, default to inheriting the host's hostname
podman_pod_inherit_hostname: no

# Sometimes, when changing the pod network for example, it may be necessary to delete
# the pod before recreating it to start with a clean slate. Toggle this to 'yes' if/when needed.
podman_delete_before_create: no

# Recreate pods and containers via the 'recreate' option to the podman_pod and
# podman_container Ansible modules.
podman_recreate: no
7 changes: 7 additions & 0 deletions meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
galaxy_info:
author: Caktus Consulting Group, LLC
description: Run containers with Podman on Ubuntu and RHEL-compatible servers.
company: Caktus Consulting Group, LLC
license: BSD
dependencies: []
160 changes: 160 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Required so podman containers can start without the user logged in
# https://github.com/systemd/systemd/issues/2690#issuecomment-186973083
# https://github.com/systemd/systemd/issues/2690#issuecomment-186984952
- name: Enable linger
command: "loginctl enable-linger {{ podman_user }}"
args:
creates: "/var/lib/systemd/linger/{{ podman_user }}"

- name: Create directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop: "{{ podman_directories }}"

- name: Checkout git repo(s)
ansible.builtin.git:
repo: "{{ item.repo }}"
dest: "{{ item.dest_dir }}"
version: "{{ item.version }}"
accept_newhostkey: yes
loop: "{{ podman_build_repos }}"
register: git_repo

- name: Build Docker-formatted image(s) with Podman
containers.podman.podman_image:
name: "{{ item.0.image_name }}"
path: "{{ item.0.dest_dir }}"
build:
format: docker
# Allow application to be aware of the deployed code version
extra_args: "--build-arg PODMAN_COMMIT_SHA={{ item.1.after }}"
force: "{{ git_repo.changed }}"
loop: "{{ podman_build_repos | zip(git_repo.results) }}"
register: image_build

# Prevent systemd from recreating pods before we recreate them, below
- name: Stop systemd unit for pod(s)
ansible.builtin.systemd:
name: "pod-{{ item }}"
scope: user
state: stopped
loop: "{{ podman_pods | map(attribute='name') }}"
when: podman_delete_before_create
ignore_errors: true

# Prevent systemd from recreating containers before we recreate them, below
- name: Stop systemd unit for containers(s)
ansible.builtin.systemd:
name: "container-{{ item }}"
scope: user
state: stopped
loop: "{{ podman_containers | map(attribute='name') }}"
when: podman_delete_before_create
ignore_errors: true

- name: Delete container(s)
containers.podman.podman_container:
pod: "{{ item.pod | default(podman_pod_name) | default(omit) }}"
name: "{{ item.name }}"
state: absent
loop: "{{ podman_containers }}"
loop_control:
label: "{{ item.name }}"
when: podman_delete_before_create
ignore_errors: true

- name: Delete pod(s)
containers.podman.podman_pod:
name: "{{ item }}"
state: absent
loop: "{{ podman_pods | map(attribute='name') }}"
when: podman_delete_before_create
ignore_errors: true

- name: Create pod(s)
containers.podman.podman_pod:
name: "{{ item.name }}"
state: "{{ item.state | default('created') }}"
recreate: "{{ item.recreate | default(podman_recreate) | default(true) }}"
publish: "{{ item.publish | default(omit) }}"
network: "{{ item.network | default(omit) }}"
userns: "{{ item.userns | default(omit) }}"
hostname: "{{ item.hostname | default(podman_pod_inherit_hostname | ternary('PLACEHOLDER_HOSTNAME', omit)) }}"
loop: "{{ podman_pods }}"
loop_control:
label: "{{ item.name }}"
register: pod

- name: Create container(s)
containers.podman.podman_container:
# Create all (rootless) containers in the same pod so they can reach each other
# via localhost. See: https://www.redhat.com/sysadmin/container-networking-podman
pod: "{{ item.pod | default(podman_pod_name) | default(omit) }}"
name: "{{ item.name }}"
state: "{{ item.state | default('created') }}"
recreate: "{{ item.recreate | default(podman_recreate) | default(true) }}"
image: "{{ item.image }}:{{ item.tag }}"
command: "{{ item.command | default(omit) }}"
volumes: "{{ item.volumes | default(omit) }}"
env: "{{ item.env | default(omit) }}"
log_driver: "{{ item.log_driver | default(podman_log_driver) | default(omit) }}"
log_opt: "{{ item.log_opt | default(podman_log_opt) | default(omit) }}"
user: "{{ item.user | default(omit) }}"
userns: "{{ item.userns | default(omit) }}"
loop: "{{ podman_containers }}"
loop_control:
label: "{{ item.name }}"
register: container

- name: Create systemd unit file(s) for pod(s)
command:
# Run this command manually, rather than using generate_systemd in Ansible,
# because Ansible re-creates the Pod and does not set up the necessary dependencies
# between the Pod and its Containers. See:
# https://www.redhat.com/sysadmin/podman-run-pods-systemd-services
cmd: "podman generate systemd --new --files --name {{ item }}"
chdir: "{{ podman_user_home }}/.config/systemd/user/"
loop: "{{ podman_pods | map(attribute='name') }}"
when: pod.changed or container.changed

- name: Create systemd unit file(s) for container(s)
command:
# Run this command manually for containers without pods, since we need
# to run it manually for pods.
cmd: "podman generate systemd --new --files --name {{ item.name }}"
chdir: "{{ podman_user_home }}/.config/systemd/user/"
loop: "{{ podman_containers }}"
loop_control:
label: "{{ item.name }}"
when: podman_pod_name is not defined and not item.pod and container.changed

- name: Replace placeholder hostname with actual EC2 instance hostname
ansible.builtin.replace:
path: /home/{{ podman_user }}/.config/systemd/user/pod-{{ item }}.service
regexp: "PLACEHOLDER_HOSTNAME"
replace: '"%H"'
loop: "{{ podman_pods | map(attribute='name') }}"
when: podman_pod_inherit_hostname

- name: Enable systemd unit for pod(s)
ansible.builtin.systemd:
name: "pod-{{ item }}"
scope: user
enabled: true
state: started
daemon_reload: true
loop: "{{ podman_pods | map(attribute='name') }}"

- name: Enable systemd unit for containers(s)
ansible.builtin.systemd:
name: "container-{{ item.name }}"
scope: user
enabled: true
state: started
daemon_reload: true
loop: "{{ podman_containers }}"
loop_control:
label: "{{ item.name }}"
when: podman_pod_name is not defined and not item.pod

0 comments on commit 318ae12

Please sign in to comment.