From a8bf88df54fe43f71557ff815e931d8312162d5e Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 11 May 2023 11:22:20 +0200 Subject: [PATCH 01/39] Review --- ansible-101/.gitignore | 1 + ansible-101/README.md | 73 ++++--- ansible-101/notebooks/00_teaser.ipynb | 225 ++++++++++++++++++-- ansible-101/notebooks/01_architecture.ipynb | 12 +- 4 files changed, 263 insertions(+), 48 deletions(-) diff --git a/ansible-101/.gitignore b/ansible-101/.gitignore index 80185ac..48be6b2 100644 --- a/ansible-101/.gitignore +++ b/ansible-101/.gitignore @@ -7,3 +7,4 @@ *.retry core* *_python_intro.ipynb +notebooks/rendered_notebooks/ diff --git a/ansible-101/README.md b/ansible-101/README.md index e66c906..57ae9c4 100644 --- a/ansible-101/README.md +++ b/ansible-101/README.md @@ -6,16 +6,16 @@ This course is based on Docker and Docker compose. As long as you have Docker you can run it on: - - linux - - mac - - windows +- linux +- mac +- windows Docker should be exposed via TCP on 172.17.0.1:2375 On Linux, set -``` -# vim /etc/systemd/system/multi-user.target.wants/docker.service +```bash +$ vim /etc/systemd/system/multi-user.target.wants/docker.service [Service] ... ExecStart=/usr/bin/dockerd -H fd:// -H tcp://172.17.0.1:2375 @@ -24,28 +24,29 @@ ExecStart=/usr/bin/dockerd -H fd:// -H tcp://172.17.0.1:2375 On Mac, check [the FAQ and this issue](https://github.com/docker/for-mac/issues/770#issuecomment-252560286) - Consider having enough bandwidth for the first run to download the images. - Run the environemnt with: - # make course +```bash +make course +``` or - # docker-compose scale course=1 bastion=1 web=3 - # firefox http://localhost:8888 - +```bash +docker-compose scale course=1 bastion=1 web=3 +firefox http://localhost:8888 +``` ## Playing the course on DigitalOcean DigitalOcean is a great and cheap cloud-provider - - create an Ubuntu 16.04 docker droplet from the menu and ssh into your host - - expose docker on local http port +- create an Ubuntu 16.04 docker droplet from the menu and ssh into your host +- expose docker on local http port -``` +```bash # vim /etc/systemd/system/multi-user.target.wants/docker.service [Service] ... @@ -53,33 +54,45 @@ ExecStart=/usr/bin/dockerd -H fd:// -H tcp://172.17.0.1:2375 ... ``` - - clone and run the project +- clone and run the project -``` - # git clone https://github.com/ioggstream/python-course.git - # cd python-course/ansible-101 - # make course +```bash +$ git clone https://github.com/ioggstream/python-course.git +$ cd python-course/ansible-101 +$ make course ``` - - point to the reference url +- point to the reference url See asciicast here [![asciicast](https://asciinema.org/a/9xqX4akNND7Yc0Q1sTb3ZnEhI.png)](https://asciinema.org/a/9xqX4akNND7Yc0Q1sTb3ZnEhI) +## Prerequisites + +- [Git 101](https://github.com/ioggstream/python-course/blob/master/git-101/notebooks/01-git.ipynb) +- [Python basics](https://github.com/ioggstream/python-course/blob/master/python-basic/README.md) +- Docker ## Outline +- 1. Prerequisites +- Ansible architecture +- Describe delivery layout in ansible.cfg +- Host and Group variables, Filters + +- 2. Static and dynamic inventories (docker) +- Vaults and Secrets +- Use bastions and other ssh_opts + +- 3. writing basic playbooks, test driven deployment +- Yaml pitfalls +- Inclusion and Roles +- Ansible galaxy as a role repository (bonus track) + +## Advanced topics - - Ansible architecture - - Describe delivery layout in ansible.cfg - - Host and Group variables, Filters - - Static and dynamic inventories (docker) - - Vaults and Secrets - - Use bastions and other ssh_opts - - writing basic playbooks, test driven deployment - - Yaml pitfalls - - Inclusion and Roles - - Ansible galaxy as a role repository (bonus track) +- 4. AWX Introduction +- Example usage of AWX diff --git a/ansible-101/notebooks/00_teaser.ipynb b/ansible-101/notebooks/00_teaser.ipynb index 2a4a719..ae8c2a9 100644 --- a/ansible-101/notebooks/00_teaser.ipynb +++ b/ansible-101/notebooks/00_teaser.ipynb @@ -16,18 +16,55 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/notebooks/exercise-00\n" + ] + } + ], "source": [ "cd /notebooks/exercise-00 " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "#\r\n", + "# This inventory file contains a list of server to\r\n", + "# play with - divided in groups.\r\n", + "#\r\n", + "[course]\r\n", + "# this is the local machine where you run jupyter\r\n", + "# the tutorial just works with this one.\r\n", + "pythonforsysadmin_course_1 ansible_connection=local\r\n", + "\r\n", + "\r\n", + "# Another group of servers\r\n", + "# where we can pass optional arguments\r\n", + "# Homework: you can play with this group of host\r\n", + "# once you exchange ssh-keys between the pythonforsysadmin_course_1\r\n", + "# container and the pythonforsysadmin_ansible_* ones._\r\n", + "[ansible]\r\n", + "172.17.0.[5:7]\r\n", + "\r\n", + "#\r\n", + "# Besides, ansible has two predefined groups:\r\n", + "# - all\r\n", + "# - ungrouped\r\n" + ] + } + ], "source": [ "cat inventory" ] @@ -41,11 +78,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "code_folding": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[0;32mpythonforsysadmin_course_1 | SUCCESS => {\u001b[0m\r\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\r\n", + "\u001b[0;32m \"ping\": \"pong\"\u001b[0m\r\n", + "\u001b[0;32m}\u001b[0m\r\n" + ] + } + ], "source": [ "# Check connections versus the local host in the \"course\" group\n", "\n", @@ -54,9 +102,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[0;32mpythonforsysadmin_course_1 | SUCCESS => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"ping\": \"pong\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[1;31m172.17.0.5 | UNREACHABLE! => {\u001b[0m\n", + "\u001b[1;31m \"changed\": false, \u001b[0m\n", + "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.5 port 22: No route to host\\r\\n\", \u001b[0m\n", + "\u001b[1;31m \"unreachable\": true\u001b[0m\n", + "\u001b[1;31m}\u001b[0m\n", + "\u001b[1;31m172.17.0.7 | UNREACHABLE! => {\u001b[0m\n", + "\u001b[1;31m \"changed\": false, \u001b[0m\n", + "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.7 port 22: No route to host\\r\\n\", \u001b[0m\n", + "\u001b[1;31m \"unreachable\": true\u001b[0m\n", + "\u001b[1;31m}\u001b[0m\n", + "\u001b[1;31m172.17.0.6 | UNREACHABLE! => {\u001b[0m\n", + "\u001b[1;31m \"changed\": false, \u001b[0m\n", + "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.6 port 22: No route to host\\r\\n\", \u001b[0m\n", + "\u001b[1;31m \"unreachable\": true\u001b[0m\n", + "\u001b[1;31m}\u001b[0m\n" + ] + } + ], "source": [ "# Pinging all hosts gives some errors too, due to missing hosts or no ssh-key exchange\n", "!ansible -i inventory -m ping all" @@ -161,18 +235,67 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Run this with\r\n", + "#\r\n", + "# #ansible-playbook -i inventory python-course-test.yml\r\n", + "#\r\n", + "- hosts: course\r\n", + " tasks:\r\n", + " - name: The /notebooks directory should exist\r\n", + " file: path=\"/notebooks\" state=directory\r\n", + "\r\n", + " - name: jupyter is responding on 8888\r\n", + " uri:\r\n", + " url: http://0.0.0.0:8888/notebooks\r\n", + " validate_certs: false\r\n", + " status_code: 200 # modify this line to simulate an error and see the outcome!\r\n", + "\r\n", + " - name: The template.conf is in place\r\n", + " file: path=\"/tmp/template.conf\" state=file\r\n" + ] + } + ], "source": [ "!cat python-course-test.yml" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "PLAY [course] ******************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", + "\n", + "TASK [The /notebooks directory should exist] ***********************************\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", + "\n", + "TASK [jupyter is responding on 8888] *******************************************\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", + "\n", + "TASK [The template.conf is in place] *******************************************\n", + "\u001b[0;31mfatal: [pythonforsysadmin_course_1]: FAILED! => {\"changed\": false, \"msg\": \"file (/tmp/template.conf) is absent, cannot continue\", \"path\": \"/tmp/template.conf\", \"state\": \"absent\"}\u001b[0m\n", + "\n", + "PLAY RECAP *********************************************************************\n", + "\u001b[0;31mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m changed=0 unreachable=0 \u001b[0;31mfailed=1 \u001b[0m\n", + "\n" + ] + } + ], "source": [ "!ansible-playbook -i inventory python-course-test.yml " ] @@ -190,22 +313,90 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Run this with\r\n", + "#\r\n", + "# #ansible-playbook -i inventory site.yml\r\n", + "#\r\n", + "- hosts: course\r\n", + " tasks:\r\n", + "\r\n", + " - name: Create a file from a template\r\n", + " template: src=mytemplate.j2 dest=/tmp/template.conf\r\n", + "\r\n", + " - name: Ensure needed packages are present and eventually install them\r\n", + " apt: name={{item}} state=present\r\n", + " with_items:\r\n", + " - python\r\n", + " - python-dev\r\n", + " ignore_errors: yes # ignore errors during the course (eg. connectivity)\r\n" + ] + } + ], "source": [ "!cat site.yml" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "PLAY [course] ******************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", + "\n", + "TASK [Create a file from a template] *******************************************\n", + "\u001b[0;33mchanged: [pythonforsysadmin_course_1]\u001b[0m\n", + "\n", + "TASK [Ensure needed packages are present and eventually install them] **********\n", + "\u001b[0;31mfailed: [pythonforsysadmin_course_1] (item=[u'python', u'python-dev']) => {\"changed\": false, \"cmd\": \"apt-get update\", \"item\": [\"python\", \"python-dev\"], \"msg\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\", \"rc\": 100, \"stderr\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\\n\", \"stderr_lines\": [\"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\", \"\", \"E: Some index files failed to download. They have been ignored, or old ones used instead.\"], \"stdout\": \"Ign http://security.debian.org jessie/updates InRelease\\nIgn http://deb.debian.org jessie InRelease\\nIgn http://security.debian.org jessie/updates Release.gpg\\nIgn http://security.debian.org jessie/updates Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nIgn http://deb.debian.org jessie-updates InRelease\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n 404 Not Found [IP: 151.101.130.132 80]\\nIgn http://deb.debian.org jessie Release.gpg\\nIgn http://deb.debian.org jessie-updates Release.gpg\\nIgn http://deb.debian.org jessie Release\\nIgn http://deb.debian.org jessie-updates Release\\nErr http://deb.debian.org jessie/main amd64 Packages\\n 404 Not Found\\nErr http://deb.debian.org jessie-updates/main amd64 Packages\\n 404 Not Found\\nGet:1 https://download.docker.com jessie InRelease [44.8 kB]\\nGet:2 https://download.docker.com jessie/stable amd64 Packages [6099 B]\\nFetched 50.9 kB in 6s (7660 B/s)\\n\", \"stdout_lines\": [\"Ign http://security.debian.org jessie/updates InRelease\", \"Ign http://deb.debian.org jessie InRelease\", \"Ign http://security.debian.org jessie/updates Release.gpg\", \"Ign http://security.debian.org jessie/updates Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Ign http://deb.debian.org jessie-updates InRelease\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" 404 Not Found [IP: 151.101.130.132 80]\", \"Ign http://deb.debian.org jessie Release.gpg\", \"Ign http://deb.debian.org jessie-updates Release.gpg\", \"Ign http://deb.debian.org jessie Release\", \"Ign http://deb.debian.org jessie-updates Release\", \"Err http://deb.debian.org jessie/main amd64 Packages\", \" 404 Not Found\", \"Err http://deb.debian.org jessie-updates/main amd64 Packages\", \" 404 Not Found\", \"Get:1 https://download.docker.com jessie InRelease [44.8 kB]\", \"Get:2 https://download.docker.com jessie/stable amd64 Packages [6099 B]\", \"Fetched 50.9 kB in 6s (7660 B/s)\"]}\u001b[0m\n", + "\u001b[0;36m...ignoring\u001b[0m\n", + "\n", + "PLAY RECAP *********************************************************************\n", + "\u001b[0;33mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m \u001b[0;33mchanged=1 \u001b[0m unreachable=0 failed=0 \n", + "\n" + ] + } + ], "source": [ "!ansible-playbook -i inventory site.yml --limit=course # in this case the --limit does not change anything ;)" ] }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ansible 2.4.2.0\r\n", + " config file = /notebooks/exercise-00/ansible.cfg\r\n", + " configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']\r\n", + " ansible python module location = /usr/local/lib/python2.7/site-packages/ansible\r\n", + " executable location = /usr/local/bin/ansible\r\n", + " python version = 2.7.14 (default, Dec 12 2017, 16:55:09) [GCC 4.9.2]\r\n" + ] + } + ], + "source": [ + "!ansible --version" + ] + }, { "cell_type": "code", "execution_count": null, @@ -230,7 +421,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.15" + "version": "2.7.14" } }, "nbformat": 4, diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index 162db31..14d67d9 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -20,7 +20,17 @@ " # Configuration Manager\n", " \n", "Explain infrastructure as code\n", - " " + "\n", + "- managing data centers through machine-readable definition files;\n", + "- install, configure, decommission physical and virtual resources;\n", + "- avoid manual processes;\n", + "- speed ++, costs --, risk --;\n", + "- declarative (describe the expected state) or imperative (describe the steps) approaches;\n", + "- push or pull model;\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9VB0Q4e1p0U9KDaTCLElT5LbuXH-fZQVrw2wATvuYpPPj-QjKetAc1UAzWgQBExaYUvIyI3caG6sbnLbaCDckCskMdlztprXO_L5G5NMFvA0GjH6Tq5N_d4_Nzzb8KAxoIk3S15bVb-lsD7wZNPx2CW-JJ2nOzlB3ZRloOFHA8Yi27nk5HZo1Go1emUjwUFGWKVbdEyuRW0NWhaquuQWnL1Txprxo68FciskuA68RbAz0l0i7e62I-Ks_V6sI3Qf8PvtXfcabJq1n4aHVjf8ilz7hF7eFrg2WJNLXrZGmH6E5ImXouBWKHnId5Dvjx4uoC5VW4G0TlZxVuBc0up8QVigEBpyl5E8fMR5aVWsGP2Kr6ZHUbgXhGt5-r2ZPzgDD-XxNTdDH39xB7YE-6z0PnhGFQX5R4zRR7chY1Hpg9_z_6nxtItSyP29bUsgM4KjV3vIHOMNHg_4VgNgBJ3QCnTFRYH_14FJQhi1O6iA0QzNAja8KS2jTB6R2tQoGa4Ld4xphruFCeWNVfetzAffcz4Jjqeioii3NIjWXH5XqhpI6NLsQH_SLJrPp_MwSaJwHs8Wy3A5oS3N4mUyTZNlOovTNI4X0cVxQl_6-HCaRkkcJlG6uIjnYRpGEwq9oC_-kujviuMvPMh_JQ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9VB0Q4e1p0U9KDaTCLElT5LbuXH-fZQVrw2wATvuYpPPj-QjKetAc1UAzWgQBExaYUvIyI3caG6sbnLbaCDckCskMdlztprXO_L5G5NMFvA0GjH6Tq5N_d4_Nzzb8KAxoIk3S15bVb-lsD7wZNPx2CW-JJ2nOzlB3ZRloOFHA8Yi27nk5HZo1Go1emUjwUFGWKVbdEyuRW0NWhaquuQWnL1Txprxo68FciskuA68RbAz0l0i7e62I-Ks_V6sI3Qf8PvtXfcabJq1n4aHVjf8ilz7hF7eFrg2WJNLXrZGmH6E5ImXouBWKHnId5Dvjx4uoC5VW4G0TlZxVuBc0up8QVigEBpyl5E8fMR5aVWsGP2Kr6ZHUbgXhGt5-r2ZPzgDD-XxNTdDH39xB7YE-6z0PnhGFQX5R4zRR7chY1Hpg9_z_6nxtItSyP29bUsgM4KjV3vIHOMNHg_4VgNgBJ3QCnTFRYH_14FJQhi1O6iA0QzNAja8KS2jTB6R2tQoGa4Ld4xphruFCeWNVfetzAffcz4Jjqeioii3NIjWXH5XqhpI6NLsQH_SLJrPp_MwSaJwHs8Wy3A5oS3N4mUyTZNlOovTNI4X0cVxQl_6-HCaRkkcJlG6uIjnYRpGEwq9oC_-kujviuMvPMh_JQ)\n", + "\n", + "Ansible uses the push model and supports both declarative and imperative approaches." ] }, { From 4edf9b8645fc2cc77d5dfb73615190ea19f1ae0f Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 11 May 2023 11:40:52 +0200 Subject: [PATCH 02/39] clean output --- ansible-101/notebooks/01_architecture.ipynb | 168 ++++---------------- 1 file changed, 33 insertions(+), 135 deletions(-) diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index 14d67d9..e16b9d9 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -16,7 +17,14 @@ " - playbook repository\n", " - used by openstack, openshift & tonns of project\n", " \n", - " \n", + " \n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ " # Configuration Manager\n", " \n", "Explain infrastructure as code\n", @@ -28,14 +36,17 @@ "- declarative (describe the expected state) or imperative (describe the steps) approaches;\n", "- push or pull model;\n", "\n", - "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9VB0Q4e1p0U9KDaTCLElT5LbuXH-fZQVrw2wATvuYpPPj-QjKetAc1UAzWgQBExaYUvIyI3caG6sbnLbaCDckCskMdlztprXO_L5G5NMFvA0GjH6Tq5N_d4_Nzzb8KAxoIk3S15bVb-lsD7wZNPx2CW-JJ2nOzlB3ZRloOFHA8Yi27nk5HZo1Go1emUjwUFGWKVbdEyuRW0NWhaquuQWnL1Txprxo68FciskuA68RbAz0l0i7e62I-Ks_V6sI3Qf8PvtXfcabJq1n4aHVjf8ilz7hF7eFrg2WJNLXrZGmH6E5ImXouBWKHnId5Dvjx4uoC5VW4G0TlZxVuBc0up8QVigEBpyl5E8fMR5aVWsGP2Kr6ZHUbgXhGt5-r2ZPzgDD-XxNTdDH39xB7YE-6z0PnhGFQX5R4zRR7chY1Hpg9_z_6nxtItSyP29bUsgM4KjV3vIHOMNHg_4VgNgBJ3QCnTFRYH_14FJQhi1O6iA0QzNAja8KS2jTB6R2tQoGa4Ld4xphruFCeWNVfetzAffcz4Jjqeioii3NIjWXH5XqhpI6NLsQH_SLJrPp_MwSaJwHs8Wy3A5oS3N4mUyTZNlOovTNI4X0cVxQl_6-HCaRkkcJlG6uIjnYRpGEwq9oC_-kujviuMvPMh_JQ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9VB0Q4e1p0U9KDaTCLElT5LbuXH-fZQVrw2wATvuYpPPj-QjKetAc1UAzWgQBExaYUvIyI3caG6sbnLbaCDckCskMdlztprXO_L5G5NMFvA0GjH6Tq5N_d4_Nzzb8KAxoIk3S15bVb-lsD7wZNPx2CW-JJ2nOzlB3ZRloOFHA8Yi27nk5HZo1Go1emUjwUFGWKVbdEyuRW0NWhaquuQWnL1Txprxo68FciskuA68RbAz0l0i7e62I-Ks_V6sI3Qf8PvtXfcabJq1n4aHVjf8ilz7hF7eFrg2WJNLXrZGmH6E5ImXouBWKHnId5Dvjx4uoC5VW4G0TlZxVuBc0up8QVigEBpyl5E8fMR5aVWsGP2Kr6ZHUbgXhGt5-r2ZPzgDD-XxNTdDH39xB7YE-6z0PnhGFQX5R4zRR7chY1Hpg9_z_6nxtItSyP29bUsgM4KjV3vIHOMNHg_4VgNgBJ3QCnTFRYH_14FJQhi1O6iA0QzNAja8KS2jTB6R2tQoGa4Ld4xphruFCeWNVfetzAffcz4Jjqeioii3NIjWXH5XqhpI6NLsQH_SLJrPp_MwSaJwHs8Wy3A5oS3N4mUyTZNlOovTNI4X0cVxQl_6-HCaRkkcJlG6uIjnYRpGEwq9oC_-kujviuMvPMh_JQ)\n", + "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ)\n", "\n", "Ansible uses the push model and supports both declarative and imperative approaches." ] }, { + "attachments": {}, "cell_type": "markdown", - "metadata": {}, + "metadata": { + "solution": "hidden" + }, "source": [ " # Advantages\n", " \n", @@ -67,53 +78,27 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "solution": "hidden" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/notebooks/exercise-00\n" - ] - } - ], + "outputs": [], "source": [ "cd /notebooks/exercise-00/" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - ".\r\n", - "├── ansible.cfg\r\n", - "├── group_vars\r\n", - "│   ├── all\r\n", - "│   └── staging\r\n", - "├── inventory\r\n", - "├── mytemplate.j2\r\n", - "├── python-course-test.yml\r\n", - "├── site.yml\r\n", - "└── staging\r\n", - "\r\n", - "1 directory, 8 files\r\n" - ] - } - ], + "outputs": [], "source": [ "# Let's check our ansible directory\n", "!tree" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -136,51 +121,15 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#\r\n", - "# Always use ansible.cfg and inventory files to \r\n", - "# describe your deployment! \r\n", - "#\r\n", - "# This will save time and helps your colleagues to\r\n", - "# keep in touch with the environment.\r\n", - "#\r\n", - "[defaults]\r\n", - "# define our inventory file or ansible defaults\r\n", - "# to /etc/ansible/hosts.\r\n", - "inventory = inventory\r\n", - "\r\n", - "# It's just for testing purposes (or if you're on a secure cloud)\r\n", - "# you may want to avoid typing yes to all host keys.\r\n", - "# Once you get host keys, you can comment this out and re-enable\r\n", - "# checks.\r\n", - "host_key_checking = False\r\n", - "\r\n", - "# When an ansible plabook fails, it creates a retry file which may\r\n", - "# pollute the current directory ;) You can move this out using\r\n", - "# further variables\r\n", - "retry_files_enabled = False\r\n", - "\r\n", - "# Search password file in here\r\n", - "# vault_password_file = ~/.ssh/pin\r\n", - "\r\n", - "\r\n", - "# [ssh_connection]\r\n", - "# ssh_args = -F ./ssh_config/config -o ControlMaster=auto -o ControlPersist=30m\r\n", - "# control_path = ./ssh_config/ansible-%%r@%%h:%%p\r\n" - ] - } - ], + "outputs": [], "source": [ "!cat ansible.cfg" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -194,38 +143,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#\r\n", - "# This inventory file contains a list of server to \r\n", - "# play with - divided in groups.\r\n", - "#\r\n", - "[course]\r\n", - "# this is the local machine where you run jupyter\r\n", - "# the tutorial just works with this one.\r\n", - "pythonforsysadmin_course_1 ansible_connection=local\r\n", - "\r\n", - "\r\n", - "# Another group of servers\r\n", - "# where we can pass optional arguments\r\n", - "# Homework: you can play with this group of host\r\n", - "# once you exchange ssh-keys between the pythonforsysadmin_course_1\r\n", - "# container and the pythonforsysadmin_ansible_* ones._\r\n", - "[ansible]\r\n", - "172.17.0.[5:7] \r\n", - "\r\n", - "#\r\n", - "# Besides, ansible has two predefined groups: \r\n", - "# - all \r\n", - "# - ungrouped\r\n" - ] - } - ], + "outputs": [], "source": [ "!cat inventory" ] @@ -241,6 +161,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -261,21 +182,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "group_vars\r\n", - "├── all\r\n", - "└── staging\r\n", - "\r\n", - "0 directories, 2 files\r\n" - ] - } - ], + "outputs": [], "source": [ "# group_vars - a directory containing environment files for various host groups.\n", "!tree group_vars" @@ -283,22 +192,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "group_vars/all:env_name: default\n", - "group_vars/staging:env_name: staging\n", - "#\n", - "# Pur here the variables for the staging inventory.\n", - "#\n", - "env_name: staging\n" - ] - } - ], + "outputs": [], "source": [ "# I set env_name in two different files\n", "!grep env_name -r group_vars/\n", @@ -319,9 +215,10 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { - "solution": "hidden", + "solution": "shown", "solution_first": true }, "source": [ @@ -340,7 +237,7 @@ "code_folding": [ 0 ], - "solution": "hidden" + "solution": "shown" }, "outputs": [], "source": [ @@ -359,6 +256,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ From 2655dfc9a2dd36c9c4564c0273b767fde506717c Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 11 May 2023 17:41:03 +0200 Subject: [PATCH 03/39] fix installer. --- ansible-101/Dockerfile.ssh | 12 +++++- .../notebooks/02_delivery_layout.ipynb | 2 +- ansible-101/site-digitalocean.yml | 43 ++++++++++++------- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/ansible-101/Dockerfile.ssh b/ansible-101/Dockerfile.ssh index 6f2ca1b..89df961 100644 --- a/ansible-101/Dockerfile.ssh +++ b/ansible-101/Dockerfile.ssh @@ -1,7 +1,15 @@ -FROM itscaro/debian-ssh:latest -RUN apt-get -y update && apt-get -y install python sshpass +FROM debian:stable-slim +RUN apt-get -y update && apt-get -y install python sshpass openssh-server RUN apt-get -y clean RUN apt-get -y autoremove +# Since this is a tutorial machine, we +# need to simplify things a bit. RUN echo "UseDNS no" >> /etc/ssh/sshd_config RUN echo "PermitRootLogin yes" >> /etc/ssh/sshd_config + +# Create privilege separation directory. +RUN mkdir -p /run/sshd + +ENTRYPOINT ["/usr/sbin/sshd"] +CMD [ "-D", "-e"] diff --git a/ansible-101/notebooks/02_delivery_layout.ipynb b/ansible-101/notebooks/02_delivery_layout.ipynb index 9e9af69..466af1b 100644 --- a/ansible-101/notebooks/02_delivery_layout.ipynb +++ b/ansible-101/notebooks/02_delivery_layout.ipynb @@ -317,7 +317,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.13" + "version": "2.7.14" } }, "nbformat": 4, diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 2a2cd50..9722ce2 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -10,26 +10,34 @@ # over again. # - hosts: localhost + gather_facts: false + vars: + oauth_token: "{{ lookup('ansible.builtin.env', 'DO_API_TOKEN') }}" + tasks: - name: Retrieve ssh key id. - digital_ocean: - state: present - command: ssh - name: rpolli - register: do_key + community.digitalocean.digital_ocean_sshkey_info: + oauth_token: "{{ oauth_token }}" + register: ssh_keys check_mode: no + - name: Set facts based on the gathered information + set_fact: + do_key: "{{ item }}" + loop: "{{ ssh_keys.data | community.general.json_query(ssh_pubkey) }}" + vars: + ssh_pubkey: "[?name=='rpolli-ed25519']" + - name: Create enough machine for the course. - digital_ocean: + community.digitalocean.digital_ocean_droplet: state: present - command: droplet name: "{{item}}" unique_name: yes - ssh_key_ids: >- - {{do_key.ssh_key.id}} - size_id: 2gb - region_id: fra1 - image_id: docker-18-04 + ssh_keys: + - "{{ do_key.fingerprint }}" + size: s-2vcpu-4gb + region: fra1 + image: docker-18-04 wait_timeout: 500 register: my_droplet with_items: @@ -38,9 +46,9 @@ - name: Dynamically add the new servers to the inventory. add_host: - hostname: > - {{ item.droplet.networks.v4[0].ip_address }} - groups: do + hostname: "{{ item.data.droplet.networks.v4[0].ip_address }}" + groups: + - do ansible_user: root host_key_checking: no with_items: "{{my_droplet.results}}" @@ -57,13 +65,15 @@ - lineinfile: path: /tmp/inventory.do line: > - {{ item.droplet.networks.v4[0].ip_address }} droplet_id={{item.droplet.id}} + {{ item.data.droplet.networks.v4[0].ip_address }} droplet_id={{item.data.droplet.id}} with_items: "{{my_droplet.results}}" # # Configure the newly created machines # - hosts: do + tags: + - setup vars: - ansible_python_interpreter: /usr/bin/python3 - ansible_user: root @@ -96,6 +106,7 @@ - name: Download course git: repo: https://github.com/ioggstream/python-course.git + version: ansible-2023 dest: /root/python-course ignore_errors: true From fab2e95c6c20145efce375aff76e7252d04a88e9 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 11 May 2023 19:12:46 +0200 Subject: [PATCH 04/39] New sshd container. --- ansible-101/README.md | 5 ++ ansible-101/notebooks/diagrams.md | 75 +++++++++++++++++++ .../notebooks/exercise-01/inventory.docker | 12 +++ 3 files changed, 92 insertions(+) create mode 100644 ansible-101/notebooks/diagrams.md create mode 100644 ansible-101/notebooks/exercise-01/inventory.docker diff --git a/ansible-101/README.md b/ansible-101/README.md index 57ae9c4..11db637 100644 --- a/ansible-101/README.md +++ b/ansible-101/README.md @@ -72,6 +72,11 @@ See asciicast here ## Prerequisites +After `make course`, prerequisites are in `/notebooks/rendered_notebooks`. + +Prerequisites can be found in the home directory: + +- Introduction to jupyter: logging in, showing the python interface, working with notebooks, opening terminals. - [Git 101](https://github.com/ioggstream/python-course/blob/master/git-101/notebooks/01-git.ipynb) - [Python basics](https://github.com/ioggstream/python-course/blob/master/python-basic/README.md) - Docker diff --git a/ansible-101/notebooks/diagrams.md b/ansible-101/notebooks/diagrams.md new file mode 100644 index 0000000..f55c9a8 --- /dev/null +++ b/ansible-101/notebooks/diagrams.md @@ -0,0 +1,75 @@ +# Ansible architecture + +```mermaid +graph + +vault[vault fa:fa-lock] +keys[ssh keys fa:fa-key] +subgraph ansible.cfg[ansible.cfg fa:fa-file ] +other +vault_config +auth_config +end + +subgraph inventory[inventory fa:fa-file / fa:fa-globe] +s1[prod fa:fa-server] +s2[test fa:fa-server] +s3[other... fa:fa-server] +end + +subgraph group_vars[group_vars fa:fa-folder / fa:fa-globe ] +gv1[prod] +gv2[test] +end + +ansible.cfg -->|references| inventory +s1 -.- gv1 +s2 -.- gv2 + +vault_config --> vault +auth_config --> keys +``` + + +# IaC + +```mermaid +--- +title: Infrastructure as Code +--- +graph LR + +dev(("  fa:fa-user fa:fa-laptop  \ndev ")) +--> |fa:fa-code-pull-request\npull request| repo[(fa:fa-code\nrepository\nscripts\ntemplates\nhosts)] +--> engine + +engine --- |>\nOK| infrastructure +dev ---|<\nKO|engine +engine -.-o|get data| ITSM[ITSM fa:fa-server fa:fa-gears] +subgraph engine[IaC Engine fa:fa-gears] +analysis +--- validation{check} +--- deployment +end + +subgraph infrastructure[Infrastructure] +direction TB +prod["Production\nfa:fa-server fa:fa-server fa:fa-server +fa:fa-database fa:fa-database fa:fa-database +fa:fa-network-wired fa:fa-network-wired fa:fa-network-wired"] +test["Test\nfa:fa-server fa:fa-server fa:fa-server +fa:fa-database fa:fa-database fa:fa-database +fa:fa-network-wired fa:fa-network-wired fa:fa-network-wired"] +end + +linkStyle 3 stroke:red +linkStyle 2 stroke:green +``` + +# Ansible + +- a static or dynamic inventory of all the nodes to manage +- ssh keys to use +- users and secrets to connect to the hosts +- whether to do privilege escalation (eg. sudo, ...) before running tasks +- if nodes should be accessed via a bastion host, docker, ... diff --git a/ansible-101/notebooks/exercise-01/inventory.docker b/ansible-101/notebooks/exercise-01/inventory.docker new file mode 100644 index 0000000..57ed669 --- /dev/null +++ b/ansible-101/notebooks/exercise-01/inventory.docker @@ -0,0 +1,12 @@ +# +# This inventory file is used to access the course machines +# using the docker connection plugin and perform +# some management tasks. For example, you can change the root +# password of the machines using the following command: +# +# ansible -i inventory.docker \ +# -m shell -a "echo 'root:password' | chpasswd" docker +# +[docker] +ansible-101_web_[1:2] ansible_connection=docker +ansible-101_bastion_1 ansible_connection=docker From 82257bcd6c9894b0c792c8e1a1c78f7f85e32480 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 11 May 2023 19:16:11 +0200 Subject: [PATCH 05/39] add deleteme. --- ansible-101/deleteme-digitalocean.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 ansible-101/deleteme-digitalocean.yml diff --git a/ansible-101/deleteme-digitalocean.yml b/ansible-101/deleteme-digitalocean.yml new file mode 100644 index 0000000..ff99659 --- /dev/null +++ b/ansible-101/deleteme-digitalocean.yml @@ -0,0 +1,27 @@ +# +# Provision current infrastructure on digitalocean +# $ export DO_API_TOKEN=xxxx +# $ ansible-playbook -v site-digitalocean.yml +# +# This will output a series of jupyter urls with their associate ips. +# +# BEWARE: unless you populate accordingly the digital_ocean droplet ids +# the digital_ocean module will create those droplets over and +# over again. +# +- hosts: localhost + gather_facts: false + tasks: + - name: Delete machine for the course. + community.digitalocean.digital_ocean_droplet: + state: absent + name: "{{item}}" + unique_name: yes + region: fra1 +# size: s-2vcpu-4gb + image: docker-18-04 + wait_timeout: 500 + register: my_droplet + with_items: + - deleteme-1 + - deleteme-2 From b6108c05d3d79148665d518a21f3a2d9fca9f357 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Fri, 12 May 2023 16:01:13 +0200 Subject: [PATCH 06/39] more files. --- ansible-101/deleteme-digitalocean.yml | 5 +- .../notebooks/02_delivery_layout.ipynb | 84 ++++++++++++------- ansible-101/notebooks/02_vaults.ipynb | 33 +++++++- ansible-101/site-digitalocean.yml | 2 +- 4 files changed, 88 insertions(+), 36 deletions(-) diff --git a/ansible-101/deleteme-digitalocean.yml b/ansible-101/deleteme-digitalocean.yml index ff99659..86279e6 100644 --- a/ansible-101/deleteme-digitalocean.yml +++ b/ansible-101/deleteme-digitalocean.yml @@ -1,7 +1,7 @@ # -# Provision current infrastructure on digitalocean +# Delete the current infrastructure on digitalocean # $ export DO_API_TOKEN=xxxx -# $ ansible-playbook -v site-digitalocean.yml +# $ ansible-playbook -v deleteme-digitalocean.yml # # This will output a series of jupyter urls with their associate ips. # @@ -18,7 +18,6 @@ name: "{{item}}" unique_name: yes region: fra1 -# size: s-2vcpu-4gb image: docker-18-04 wait_timeout: 500 register: my_droplet diff --git a/ansible-101/notebooks/02_delivery_layout.ipynb b/ansible-101/notebooks/02_delivery_layout.ipynb index 466af1b..11fcd42 100644 --- a/ansible-101/notebooks/02_delivery_layout.ipynb +++ b/ansible-101/notebooks/02_delivery_layout.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -16,19 +17,29 @@ " \n", "Put those informations, together with a brief description of the playbook usage (eg. 2/3 lines) into ansible.cfg\n", "\n", - "![delivery layout](https://cdn.pbrd.co/images/39e3p1vlg.png)\n" + "[![](https://mermaid.ink/img/pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA?type=png)](https://mermaid.live/edit#pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Errno 2] No such file or directory: '/notebooks/exercise-00'\n", + "/home/rpolli/workspace-py/python-course/ansible-101/notebooks\n" + ] + } + ], "source": [ "cd /notebooks/exercise-00" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -54,12 +65,13 @@ "\n", "```\n", "\n", - "Always check [ansible source code](https://raw.github.com/ansible/ansible/devel/examples/ansible.cfg) to get in touch with new parameters.\n", + "Always check [ansible source code](https://raw.github.com/ansible/ansible/devel/examples/ansible.cfg) to get in touch with new parameters, for example see the [ansible.cfg stable-2.4](https://github.com/ansible/ansible/blob/stable-2.4/examples/ansible.cfg)\n", "\n", - "We'll create a new ansible.cfg for every project!" + "We'll create a new `ansible.cfg` for every project!" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -81,15 +93,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cat: ansible.cfg: File o directory non esistente\n" + ] + } + ], "source": [ "# When running ansible, the first file to be read is\n", "!cat ansible.cfg" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "shown", @@ -107,30 +128,31 @@ "cell_type": "code", "execution_count": null, "metadata": { - "code_folding": [], "solution": "shown" }, "outputs": [], "source": [ - "# Solution\n", - "!sed -i 's/^inventory/#inventory/' ansible.cfg\n", - "!ansible -m ping all\n", - "!sed -i 's/#inventory/inventory/' ansible.cfg" + "# Use this cell for the exercise\n", + "!ansible -m ping all" ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "code_folding": [], "solution": "shown" }, "outputs": [], "source": [ - "# Use this cell for the exercise\n", - "!ansible -m ping all" + "# Solution\n", + "!sed -i 's/^inventory/#inventory/' ansible.cfg\n", + "!ansible -m ping all\n", + "!sed -i 's/#inventory/inventory/' ansible.cfg" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -148,29 +170,30 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "code_folding": [ - 0 - ], - "solution": "hidden" - }, + "metadata": {}, "outputs": [], "source": [ - "# Solution\n", + "# Use this cell for the exercise\n", "!ansible -m ping all[0]" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "code_folding": [ + 0 + ], + "solution": "hidden" + }, "outputs": [], "source": [ - "# Use this cell for the exercise\n", + "# Solution\n", "!ansible -m ping all[0]" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -182,6 +205,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -221,6 +245,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -238,6 +263,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -260,6 +286,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -281,6 +308,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -303,21 +331,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.14" + "pygments_lexer": "ipython3", + "version": "3.9.9" } }, "nbformat": 4, diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index ba1832e..231d98a 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -55,13 +55,25 @@ "! rm id_ansible.pub id_ansible -rf" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a new ssh key for the project:\n", + "\n", + "- the default name is `id_ansible`;\n", + "- the algorithm is `ed25519`, which is the most efficient one. For further information on ed25519 see [RFC8032](https://datatracker.ietf.org/doc/html/rfc8032).\n", + "\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "! test -f id_ansible || ssh-keygen -q -t ecdsa -f id_ansible -N ''" + "! test -f id_ansible || ssh-keygen -q -t ed25519 -f id_ansible -N ''" ] }, { @@ -84,6 +96,17 @@ "!cat ansible.cfg" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Exercise\n", + "\n", + "What is the meaning of the `-q` and `-N` options of `ssh-keygen`?\n", + "\n", + "Hint: open a [terminal](/terminals/man) and use `man ssh-keygen`.\n" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -109,9 +132,11 @@ "source": [ "## Gotta ping 'em all\n", "\n", - "Everything set up now. \n", + "Everything is set up now. \n", + "\n", + "Let's ping all hosts, eventually adjusting the ip ranges in the [inventory](/edit/notebooks/exercise-01/inventory).\n", "\n", - "Ping all hosts now, eventually adjusting ip ranges in then [inventory](/edit/notebooks/exercise-01/inventory)." + "Open a [terminal](/terminals/man) and use `docker inspect` to retrieve the container IPs." ] }, { @@ -328,7 +353,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.13" + "version": "2.7.14" } }, "nbformat": 4, diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 9722ce2..3b77449 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -42,7 +42,7 @@ register: my_droplet with_items: - deleteme-1 - - deleteme-2 +# - deleteme-2 - name: Dynamically add the new servers to the inventory. add_host: From e34806140d934679fb49dfa298d5322e6c8a3cff Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Fri, 12 May 2023 17:36:45 +0200 Subject: [PATCH 07/39] Add docker-101 --- ansible-101/README.md | 10 +- ansible-101/notebooks/00_teaser.ipynb | 38 ++--- ansible-101/notebooks/intro.ipynb | 2 +- docker-101/notebooks/01-docker.ipynb | 210 ++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 26 deletions(-) create mode 100644 docker-101/notebooks/01-docker.ipynb diff --git a/ansible-101/README.md b/ansible-101/README.md index 11db637..afafd1e 100644 --- a/ansible-101/README.md +++ b/ansible-101/README.md @@ -57,11 +57,9 @@ ExecStart=/usr/bin/dockerd -H fd:// -H tcp://172.17.0.1:2375 - clone and run the project ```bash -$ git clone https://github.com/ioggstream/python-course.git -$ cd python-course/ansible-101 -$ make course - - +git clone https://github.com/ioggstream/python-course.git +cd python-course/ansible-101 +make course ``` - point to the reference url @@ -83,7 +81,7 @@ Prerequisites can be found in the home directory: ## Outline -- 1. Prerequisites +- 1. Prerequisites linked in [intro.ipynb](intro.ipynb) - Ansible architecture - Describe delivery layout in ansible.cfg - Host and Group variables, Filters diff --git a/ansible-101/notebooks/00_teaser.ipynb b/ansible-101/notebooks/00_teaser.ipynb index ae8c2a9..98608d9 100644 --- a/ansible-101/notebooks/00_teaser.ipynb +++ b/ansible-101/notebooks/00_teaser.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 13, "metadata": { "code_folding": [] }, @@ -102,7 +102,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -113,6 +113,11 @@ "\u001b[0;32m \"changed\": false, \u001b[0m\n", "\u001b[0;32m \"ping\": \"pong\"\u001b[0m\n", "\u001b[0;32m}\u001b[0m\n", + "\u001b[1;31m172.17.0.6 | UNREACHABLE! => {\u001b[0m\n", + "\u001b[1;31m \"changed\": false, \u001b[0m\n", + "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.6 port 22: No route to host\\r\\n\", \u001b[0m\n", + "\u001b[1;31m \"unreachable\": true\u001b[0m\n", + "\u001b[1;31m}\u001b[0m\n", "\u001b[1;31m172.17.0.5 | UNREACHABLE! => {\u001b[0m\n", "\u001b[1;31m \"changed\": false, \u001b[0m\n", "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.5 port 22: No route to host\\r\\n\", \u001b[0m\n", @@ -122,11 +127,6 @@ "\u001b[1;31m \"changed\": false, \u001b[0m\n", "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.7 port 22: No route to host\\r\\n\", \u001b[0m\n", "\u001b[1;31m \"unreachable\": true\u001b[0m\n", - "\u001b[1;31m}\u001b[0m\n", - "\u001b[1;31m172.17.0.6 | UNREACHABLE! => {\u001b[0m\n", - "\u001b[1;31m \"changed\": false, \u001b[0m\n", - "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.6 port 22: No route to host\\r\\n\", \u001b[0m\n", - "\u001b[1;31m \"unreachable\": true\u001b[0m\n", "\u001b[1;31m}\u001b[0m\n" ] } @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -268,7 +268,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -288,10 +288,10 @@ "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", "\n", "TASK [The template.conf is in place] *******************************************\n", - "\u001b[0;31mfatal: [pythonforsysadmin_course_1]: FAILED! => {\"changed\": false, \"msg\": \"file (/tmp/template.conf) is absent, cannot continue\", \"path\": \"/tmp/template.conf\", \"state\": \"absent\"}\u001b[0m\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", "\n", "PLAY RECAP *********************************************************************\n", - "\u001b[0;31mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m changed=0 unreachable=0 \u001b[0;31mfailed=1 \u001b[0m\n", + "\u001b[0;32mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=4 \u001b[0m changed=0 unreachable=0 failed=0 \n", "\n" ] } @@ -313,7 +313,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -345,7 +345,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -359,14 +359,14 @@ "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", "\n", "TASK [Create a file from a template] *******************************************\n", - "\u001b[0;33mchanged: [pythonforsysadmin_course_1]\u001b[0m\n", + "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", "\n", "TASK [Ensure needed packages are present and eventually install them] **********\n", - "\u001b[0;31mfailed: [pythonforsysadmin_course_1] (item=[u'python', u'python-dev']) => {\"changed\": false, \"cmd\": \"apt-get update\", \"item\": [\"python\", \"python-dev\"], \"msg\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\", \"rc\": 100, \"stderr\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\\n\", \"stderr_lines\": [\"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\", \"\", \"E: Some index files failed to download. They have been ignored, or old ones used instead.\"], \"stdout\": \"Ign http://security.debian.org jessie/updates InRelease\\nIgn http://deb.debian.org jessie InRelease\\nIgn http://security.debian.org jessie/updates Release.gpg\\nIgn http://security.debian.org jessie/updates Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nIgn http://deb.debian.org jessie-updates InRelease\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n 404 Not Found [IP: 151.101.130.132 80]\\nIgn http://deb.debian.org jessie Release.gpg\\nIgn http://deb.debian.org jessie-updates Release.gpg\\nIgn http://deb.debian.org jessie Release\\nIgn http://deb.debian.org jessie-updates Release\\nErr http://deb.debian.org jessie/main amd64 Packages\\n 404 Not Found\\nErr http://deb.debian.org jessie-updates/main amd64 Packages\\n 404 Not Found\\nGet:1 https://download.docker.com jessie InRelease [44.8 kB]\\nGet:2 https://download.docker.com jessie/stable amd64 Packages [6099 B]\\nFetched 50.9 kB in 6s (7660 B/s)\\n\", \"stdout_lines\": [\"Ign http://security.debian.org jessie/updates InRelease\", \"Ign http://deb.debian.org jessie InRelease\", \"Ign http://security.debian.org jessie/updates Release.gpg\", \"Ign http://security.debian.org jessie/updates Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Ign http://deb.debian.org jessie-updates InRelease\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" 404 Not Found [IP: 151.101.130.132 80]\", \"Ign http://deb.debian.org jessie Release.gpg\", \"Ign http://deb.debian.org jessie-updates Release.gpg\", \"Ign http://deb.debian.org jessie Release\", \"Ign http://deb.debian.org jessie-updates Release\", \"Err http://deb.debian.org jessie/main amd64 Packages\", \" 404 Not Found\", \"Err http://deb.debian.org jessie-updates/main amd64 Packages\", \" 404 Not Found\", \"Get:1 https://download.docker.com jessie InRelease [44.8 kB]\", \"Get:2 https://download.docker.com jessie/stable amd64 Packages [6099 B]\", \"Fetched 50.9 kB in 6s (7660 B/s)\"]}\u001b[0m\n", + "\u001b[0;31mfailed: [pythonforsysadmin_course_1] (item=[u'python', u'python-dev']) => {\"changed\": false, \"cmd\": \"apt-get update\", \"item\": [\"python\", \"python-dev\"], \"msg\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\", \"rc\": 100, \"stderr\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\\n\", \"stderr_lines\": [\"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\", \"\", \"E: Some index files failed to download. They have been ignored, or old ones used instead.\"], \"stdout\": \"Ign http://deb.debian.org jessie InRelease\\nIgn http://security.debian.org jessie/updates InRelease\\nIgn http://deb.debian.org jessie-updates InRelease\\nIgn http://security.debian.org jessie/updates Release.gpg\\nIgn http://deb.debian.org jessie Release.gpg\\nIgn http://deb.debian.org jessie-updates Release.gpg\\nIgn http://security.debian.org jessie/updates Release\\nHit https://download.docker.com jessie InRelease\\nIgn http://deb.debian.org jessie Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nIgn http://deb.debian.org jessie-updates Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n 404 Not Found [IP: 151.101.130.132 80]\\nErr http://deb.debian.org jessie/main amd64 Packages\\n 404 Not Found\\nErr http://deb.debian.org jessie-updates/main amd64 Packages\\n 404 Not Found\\nGet:1 https://download.docker.com jessie/stable amd64 Packages [6099 B]\\nFetched 6099 B in 1s (5411 B/s)\\n\", \"stdout_lines\": [\"Ign http://deb.debian.org jessie InRelease\", \"Ign http://security.debian.org jessie/updates InRelease\", \"Ign http://deb.debian.org jessie-updates InRelease\", \"Ign http://security.debian.org jessie/updates Release.gpg\", \"Ign http://deb.debian.org jessie Release.gpg\", \"Ign http://deb.debian.org jessie-updates Release.gpg\", \"Ign http://security.debian.org jessie/updates Release\", \"Hit https://download.docker.com jessie InRelease\", \"Ign http://deb.debian.org jessie Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Ign http://deb.debian.org jessie-updates Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" 404 Not Found [IP: 151.101.130.132 80]\", \"Err http://deb.debian.org jessie/main amd64 Packages\", \" 404 Not Found\", \"Err http://deb.debian.org jessie-updates/main amd64 Packages\", \" 404 Not Found\", \"Get:1 https://download.docker.com jessie/stable amd64 Packages [6099 B]\", \"Fetched 6099 B in 1s (5411 B/s)\"]}\u001b[0m\n", "\u001b[0;36m...ignoring\u001b[0m\n", "\n", "PLAY RECAP *********************************************************************\n", - "\u001b[0;33mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m \u001b[0;33mchanged=1 \u001b[0m unreachable=0 failed=0 \n", + "\u001b[0;32mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m changed=0 unreachable=0 failed=0 \n", "\n" ] } @@ -377,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 19, "metadata": {}, "outputs": [ { diff --git a/ansible-101/notebooks/intro.ipynb b/ansible-101/notebooks/intro.ipynb index 13065c3..1d0e75e 100644 --- a/ansible-101/notebooks/intro.ipynb +++ b/ansible-101/notebooks/intro.ipynb @@ -176,7 +176,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.13" + "version": "2.7.14" } }, "nbformat": 4, diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb new file mode 100644 index 0000000..8c8821c --- /dev/null +++ b/docker-101/notebooks/01-docker.ipynb @@ -0,0 +1,210 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "code_folding": [ + 0 + ] + }, + "source": [ + "# Docker 101\n", + "\n", + "This is a crash docker course.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Look at our machine\n", + "\n", + "At first, we will inspect this machine: the operating system, the IP address and the rest." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Debian GNU/Linux 8 \\n \\l\n", + "\n", + "Linux d152a5a9b4e2 4.15.0-122-generic #124-Ubuntu SMP Thu Oct 15 13:03:05 UTC 2020 x86_64 GNU/Linux\n", + "5: eth0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0\\ valid_lft forever preferred_lft forever\n" + ] + } + ], + "source": [ + "# Distro\n", + "!cat /etc/issue\n", + "\n", + "# Linux version\n", + "!uname -a\n", + "\n", + "# IP address\n", + "! ip -4 -o address show eth0" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Docker version 17.12.0-ce, build c97c6d6\r\n" + ] + } + ], + "source": [ + "# Docker CLI version.\n", + "\n", + "!docker --version\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Docker version 17.12.0-ce, build c97c6d6\r\n" + ] + } + ], + "source": [ + "# Docker server version\n", + "\n", + "!dockerd --version" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Docker\n", + "\n", + "Docker is an application that simulates the creation of virtual machines using Linux isolation capabilities, including chroot, network namespaces, cgroups and capabilities. Those \"virtual machines\" are named \"containers\".\n", + "\n", + "Docker comes with a catalog of possible operating systems and applications named Docker Registry. You can deploy your custom registry too." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME DESCRIPTION STARS OFFICIAL AUTOMATED\r\n", + "ubuntu Ubuntu is a Debian-based Linux operating sys… 15936 [OK] \r\n", + "websphere-liberty WebSphere Liberty multi-architecture images … 294 [OK] \r\n", + "ubuntu-upstart DEPRECATED, as is Upstart (find other proces… 114 [OK] \r\n", + "neurodebian NeuroDebian provides neuroscience research s… 99 [OK] \r\n", + "ubuntu/nginx Nginx, a high-performance reverse proxy & we… 89 \r\n", + "open-liberty Open Liberty multi-architecture images based… 59 [OK] \r\n", + "ubuntu/apache2 Apache, a secure & extensible open-source HT… 58 \r\n", + "ubuntu/squid Squid is a caching proxy for the Web. Long-t… 56 \r\n", + "ubuntu-debootstrap DEPRECATED; use \"ubuntu\" instead 51 [OK] \r\n" + ] + } + ], + "source": [ + "# Search images from catalog\n", + "\n", + "!docker search ubuntu|head\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "22.04: Pulling from library/ubuntu\n", + "\n", + "\u001b[1BDigest: sha256:dfd64a3b4296d8c9b62aa3309984f8620b98d87e47492599ee20739e8eb54fbf\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\n", + "Status: Downloaded newer image for ubuntu:22.04\n" + ] + } + ], + "source": [ + "# Download the ubuntu image\n", + "!docker pull ubuntu:22.04\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open a [terminal](/terminals/docker) and run an interactive shell with a terminal (tty) in a new container based on ubuntu:22.04\n", + "\n", + "```\n", + "docker run --rm --tty --interactive ubuntu:22.04 /bin/bash\n", + "```\n", + "\n", + "Then run the above commands to ensure that you are on another virtual hosts.\n", + "\n", + "```\n", + "# Operating System\n", + "cat /etc/issue\n", + "# Linux version\n", + "uname -a\n", + "```\n", + "\n", + "#### Exercise\n", + "\n", + "What happens if you try to get the IP address using the following command?\n", + "\n", + "```\n", + "ip -4 -o a\n", + "```\n", + "\n", + "Can you retrieve the IP address in another way?\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 55b2df5d0e9b8829491ee33a4c12c3ad4f6ab927 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 15 May 2023 13:30:52 +0200 Subject: [PATCH 08/39] Add docker-101 --- ansible-101/Makefile | 2 +- ansible-101/notebooks/02_vaults.ipynb | 14 +- .../notebooks/03_facts_and_variables.ipynb | 20 +- ansible-101/notebooks/intro.ipynb | 9 +- docker-101/notebooks/01-docker.ipynb | 315 ++++++++++-------- 5 files changed, 199 insertions(+), 161 deletions(-) diff --git a/ansible-101/Makefile b/ansible-101/Makefile index c0df8b6..e692fa1 100644 --- a/ansible-101/Makefile +++ b/ansible-101/Makefile @@ -6,7 +6,7 @@ .PHONY: course MAIN_IP = $(shell ip -4 -o a s scope global | awk -F'[/ ]+' '{print $$4; exit} ') -EXTERNAL_COURSES = git-101 python-basic +EXTERNAL_COURSES = git-101 python-basic docker-101 course: .prepare diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index 231d98a..30d7cf2 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -25,9 +25,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/notebooks/exercise-01\n" + ] + } + ], "source": [ "cd /notebooks/exercise-01/" ] @@ -47,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 1a32289..8875f72 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -34,6 +35,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -42,7 +44,7 @@ " - run the following command\n", " - what does it do?\n", " - where's its output ?\n", - " - use the json module to reindent it" + " - use the json python module to make it readable" ] }, { @@ -75,12 +77,13 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "\n", - "Gather the following infos from the output of the previous command.\n", + "Gather the following information from the output of the previous command.\n", "\n", " - hostname\n", " - first ip address\n", @@ -99,6 +102,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -123,6 +127,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -130,11 +135,11 @@ "\n", "Essentially, facts are per-host variables gathered by ansible.\n", "\n", - "In the vault lesson we've seen variables in action loaded it via -e @variables.yml.\n", + "In the vault lesson, we've seen variables in action loaded it via `-e @variables.yml`.\n", "\n", "Now we'll define them with \n", "\n", - "```\n", + "```yaml\n", "- hosts: localhost\n", " vars:\n", " - one_variable: 1\n", @@ -144,6 +149,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -157,7 +163,7 @@ "\n", "Here's a template example\n", "\n", - "```\n", + "```html\n", "\n", " \n", "\n", @@ -206,12 +212,13 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## filters\n", "\n", - "Inside {{ braces }} you can process expressions using filters.\n", + "Inside `{{` braces `}}` you can process expressions using filters.\n", "\n", "```\n", "\n", @@ -266,6 +273,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/intro.ipynb b/ansible-101/notebooks/intro.ipynb index 1d0e75e..a9be364 100644 --- a/ansible-101/notebooks/intro.ipynb +++ b/ansible-101/notebooks/intro.ipynb @@ -64,14 +64,9 @@ "\n", "Docker is a lightweight container environment. Jupyter and all other \"machines\" are based on docker.\n", "\n", - "[Slideshare presentation](https://www.slideshare.net/ioggstream/docker-virtualizzazione-leggera)\n", + "[Presentation (in Italian)](https://docs.google.com/presentation/d/15swQ2gHWAKYAm_ZbBme9rmzV1CpLNl1npvgrUyODu1s/)\n", "\n", - "[Reveal JS](http://www.piumalab.org/dockerslide)\n", - "\n", - "Some examples via a [local terminal](/terminals/example)\n", - "\n", - "\n", - "Go to your [docker-101course](/notebooks/notebooks/rendered_notebooks/docker-101/01-docker.ipynb)" + "Go to your [docker beginners course](/notebooks/notebooks/rendered_notebooks/docker-101/)\n" ] }, { diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb index 8c8821c..7b2dd90 100644 --- a/docker-101/notebooks/01-docker.ipynb +++ b/docker-101/notebooks/01-docker.ipynb @@ -2,209 +2,236 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "code_folding": [ - 0 - ] - }, + "id": "f331e170", + "metadata": {}, "source": [ "# Docker 101\n", "\n", - "This is a crash docker course.\n" + "This is a crash docker course.\n", + "\n", + "## What is?\n", + "\n", + "Docker is a platform for developers and sysadmins to develop,\n", + " ship, and run applications." ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "1f596524", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ - "## Look at our machine\n", + "---\n", + "\n", + "## Why it was born?\n", "\n", - "At first, we will inspect this machine: the operating system, the IP address and the rest." + "To resolve a necessity\n", + "\n", + "Mobility workload in cloud systems" ] }, { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Debian GNU/Linux 8 \\n \\l\n", - "\n", - "Linux d152a5a9b4e2 4.15.0-122-generic #124-Ubuntu SMP Thu Oct 15 13:03:05 UTC 2020 x86_64 GNU/Linux\n", - "5: eth0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0\\ valid_lft forever preferred_lft forever\n" - ] + "cell_type": "markdown", + "id": "5c1e3bd3", + "metadata": { + "slideshow": { + "slide_type": "slide" } - ], + }, "source": [ - "# Distro\n", - "!cat /etc/issue\n", + "---\n", "\n", - "# Linux version\n", - "!uname -a\n", + "### Cargo transport pre-1960\n", "\n", - "# IP address\n", - "! ip -4 -o address show eth0" + "![text](slides/image/cargo-transport-pre-1960.png)" ] }, { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Docker version 17.12.0-ce, build c97c6d6\r\n" - ] + "cell_type": "markdown", + "id": "fd4c7aba", + "metadata": { + "slideshow": { + "slide_type": "slide" } - ], + }, "source": [ - "# Docker CLI version.\n", + "---\n", "\n", - "!docker --version\n" + "### Solution: Intermodal Shipping Container\n", + "\n", + "![text](slides/image/standard_container.jpg)" ] }, { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Docker version 17.12.0-ce, build c97c6d6\r\n" - ] + "cell_type": "markdown", + "id": "8171d744", + "metadata": { + "slideshow": { + "slide_type": "slide" } - ], + }, "source": [ - "# Docker server version\n", + "---\n", "\n", - "!dockerd --version" + "### Docker is a Container System for Code\n", + "\n", + "![text](slides/image/container.png)\n", + "\n", + "Docker leverages LXC (Linux Containers), which encompasses Linux\n", + "features like cgroups and namespaces for strong process isolation and\n", + "resource control.\n", + "\n", + "They are lightweight and consume less resources than a virtual machine." ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "c6f40cfe", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Benefits for developers\n", + "\n", + "- portability, build once... run anywhere\n", + "- no worries about missing dependencies, packages and other pain\n", + " points during subsequent deployments\n", + "- tracking changes\n", + "- run each app in its own isolated container, so you can run various\n", + " versions of libraries and other dependencies for each app without\n", + " worrying\n", + "- reduce/eliminate concerns about compatibility on different\n", + " platforms, either your own or your customers'." + ] + }, + { + "cell_type": "markdown", + "id": "8828d397", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Benefits for sysadmins\n", + "\n", + "- portability, configure once... run anywhere\n", + "- tracking changes\n", + "- simple to understand what application do\n", + "- simplify to upgrade application processes. Significantly improves\n", + " the speed and reliability of continuous deployment and continuous\n", + " integration systems\n", + "- eliminate inconsistencies between different enviroments (develop, testing, production)\n", + "- re-use other people images\n", + "- do you not need an hypervisor. Because the containers are so\n", + " lightweight, address significant performance, costs, deployment, and\n", + " portability issues normally associated with VMs" + ] + }, + { + "cell_type": "markdown", + "id": "4cde50ac", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ - "## Docker\n", + "---\n", "\n", - "Docker is an application that simulates the creation of virtual machines using Linux isolation capabilities, including chroot, network namespaces, cgroups and capabilities. Those \"virtual machines\" are named \"containers\".\n", + "## Docker Concepts and Interactions\n", "\n", - "Docker comes with a catalog of possible operating systems and applications named Docker Registry. You can deploy your custom registry too." + "- **Host**, the machine that is running the containers.\n", + "- **Image**, a hierarchy of files, with meta-data for how to run a container.\n", + "- **Container**, a contained running process, started from an image.\n", + "- **Registry**, a repository of images.\n", + "- **Volume**, storage outside the container.\n", + "- **Dockerfile**, a script for creating images." ] }, { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NAME DESCRIPTION STARS OFFICIAL AUTOMATED\r\n", - "ubuntu Ubuntu is a Debian-based Linux operating sys… 15936 [OK] \r\n", - "websphere-liberty WebSphere Liberty multi-architecture images … 294 [OK] \r\n", - "ubuntu-upstart DEPRECATED, as is Upstart (find other proces… 114 [OK] \r\n", - "neurodebian NeuroDebian provides neuroscience research s… 99 [OK] \r\n", - "ubuntu/nginx Nginx, a high-performance reverse proxy & we… 89 \r\n", - "open-liberty Open Liberty multi-architecture images based… 59 [OK] \r\n", - "ubuntu/apache2 Apache, a secure & extensible open-source HT… 58 \r\n", - "ubuntu/squid Squid is a caching proxy for the Web. Long-t… 56 \r\n", - "ubuntu-debootstrap DEPRECATED; use \"ubuntu\" instead 51 [OK] \r\n" - ] + "cell_type": "markdown", + "id": "33b87580", + "metadata": { + "slideshow": { + "slide_type": "subslide" } - ], + }, "source": [ - "# Search images from catalog\n", + "----\n", "\n", - "!docker search ubuntu|head\n" + "[![](https://mermaid.ink/img/pako:eNptU8lu2zAQ_RWBZ8moZctVdOilKdAeekmBHirmMJLGFhMuAjkM6lr-91JbbCcBD3qjefM4G0-sNg2ygiVJwjUJklhE96Z-RhsJTWihJmG043okHCx0LddcO1-NOHrAg3Bkj-UDKkP4akd7qIo9JM2o9ci1WJec_VBwQBd8g6v2FTo-qM1ci00LtET6ymvyi_UEL7Dg7kit0ZwFVdTNTTrfjSOupwL2QmJ5gfOtM7xN7sVIr9CVv6fvTG2AoAKHgVAbTSA0WleWX1_xVSGPgSRNDTJUMXfkfbGXhIdzlVqSfOkrL2TTR7cigyfqCQ5vHdcpTaTaKCXoA4HBab3uo0vE2-hemdDsPpr78M7tCCzFjkwXWxyNWzWuh8aP1M67NgxVDMVf195fVmOiSfkxbRohi5lCq0A0YTlPXEcRZ9SiQs6KABvcg5fEGdfnQPVdmBV-awQZywqyHmMGnsyvo64Xe-LcCwiboli4ULrwtwP9xxi1kILJihP7y4p1lq-263SzyfI83WTp5zRmR1akd7vVLrvb5Vm-2W6zcM4x-zcqfFplMcMxh5_Toxrf1vk_Byk2hw?type=png)](https://mermaid.live/edit#pako:eNptU8lu2zAQ_RWBZ8moZctVdOilKdAeekmBHirmMJLGFhMuAjkM6lr-91JbbCcBD3qjefM4G0-sNg2ygiVJwjUJklhE96Z-RhsJTWihJmG043okHCx0LddcO1-NOHrAg3Bkj-UDKkP4akd7qIo9JM2o9ci1WJec_VBwQBd8g6v2FTo-qM1ci00LtET6ymvyi_UEL7Dg7kit0ZwFVdTNTTrfjSOupwL2QmJ5gfOtM7xN7sVIr9CVv6fvTG2AoAKHgVAbTSA0WleWX1_xVSGPgSRNDTJUMXfkfbGXhIdzlVqSfOkrL2TTR7cigyfqCQ5vHdcpTaTaKCXoA4HBab3uo0vE2-hemdDsPpr78M7tCCzFjkwXWxyNWzWuh8aP1M67NgxVDMVf195fVmOiSfkxbRohi5lCq0A0YTlPXEcRZ9SiQs6KABvcg5fEGdfnQPVdmBV-awQZywqyHmMGnsyvo64Xe-LcCwiboli4ULrwtwP9xxi1kILJihP7y4p1lq-263SzyfI83WTp5zRmR1akd7vVLrvb5Vm-2W6zcM4x-zcqfFplMcMxh5_Toxrf1vk_Byk2hw)" ] }, { - "cell_type": "code", - "execution_count": 10, + "cell_type": "markdown", + "id": "ec5425fb", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "22.04: Pulling from library/ubuntu\n", - "\n", - "\u001b[1BDigest: sha256:dfd64a3b4296d8c9b62aa3309984f8620b98d87e47492599ee20739e8eb54fbf\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\u001b[1A\u001b[1K\u001b[K\n", - "Status: Downloaded newer image for ubuntu:22.04\n" - ] + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "id": "746dbadb", + "metadata": { + "slideshow": { + "slide_type": "slide" } - ], + }, "source": [ - "# Download the ubuntu image\n", - "!docker pull ubuntu:22.04\n", - " " + "---\n", + "\n", + "## Separation of concerns\n", + "\n", + "- inside the container:\n", + " - libreries\n", + " - package manager\n", + " - application\n", + " - data\n", + " - code\n", + "- outside the container:\n", + " - logging\n", + " - remote access\n", + " - network configuration\n", + " - monitoring" ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "92fa0ff8", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ - "Open a [terminal](/terminals/docker) and run an interactive shell with a terminal (tty) in a new container based on ubuntu:22.04\n", - "\n", - "```\n", - "docker run --rm --tty --interactive ubuntu:22.04 /bin/bash\n", - "```\n", - "\n", - "Then run the above commands to ensure that you are on another virtual hosts.\n", + "---\n", "\n", - "```\n", - "# Operating System\n", - "cat /etc/issue\n", - "# Linux version\n", - "uname -a\n", - "```\n", + "## Difference between docker and virtual machine\n", "\n", - "#### Exercise\n", - "\n", - "What happens if you try to get the IP address using the following command?\n", - "\n", - "```\n", - "ip -4 -o a\n", - "```\n", - "\n", - "Can you retrieve the IP address in another way?\n" + "![text](slides/image/VM-Diagram.png)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", + "id": "0189dd8d", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "---" + ] } ], - "metadata": { - "kernelspec": { - "display_name": "Python 2", - "language": "python", - "name": "python2" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.14" - } - }, + "metadata": {}, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 5 } From 1a61c77755396c81d3eb91d2833b254b3cd7c889 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 15 May 2023 15:35:57 +0200 Subject: [PATCH 09/39] Docker stuff --- ansible-101/notebooks/diagrams.md | 2 + ansible-101/notebooks/intro.ipynb | 120 ++++- docker-101/01-docker.md | 113 ++++ docker-101/02-docker.md | 345 ++++++++++++ docker-101/Makefile | 10 + docker-101/notebooks/01-docker.ipynb | 26 +- docker-101/notebooks/02-docker.ipynb | 775 +++++++++++++++++++++++++++ docker-101/tox.ini | 11 + 8 files changed, 1381 insertions(+), 21 deletions(-) create mode 100644 docker-101/01-docker.md create mode 100644 docker-101/02-docker.md create mode 100644 docker-101/Makefile create mode 100644 docker-101/notebooks/02-docker.ipynb create mode 100644 docker-101/tox.ini diff --git a/ansible-101/notebooks/diagrams.md b/ansible-101/notebooks/diagrams.md index f55c9a8..86409ff 100644 --- a/ansible-101/notebooks/diagrams.md +++ b/ansible-101/notebooks/diagrams.md @@ -28,6 +28,8 @@ s2 -.- gv2 vault_config --> vault auth_config --> keys + +ansible.cfg --->|references| modules & roles[roles fa:fa-folder] ``` diff --git a/ansible-101/notebooks/intro.ipynb b/ansible-101/notebooks/intro.ipynb index a9be364..5209432 100644 --- a/ansible-101/notebooks/intro.ipynb +++ b/ansible-101/notebooks/intro.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden" @@ -13,6 +14,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -28,14 +30,26 @@ " - [edit an existing file](/edit/notebooks/untitled.txt)\n", " - add more cells with `ALT+ENTER`\n", " \n", - "Go to the [basic python course](/tree/notebooks/rendered_notebooks/python-basic)" + "## Python terminal\n", + "\n", + "With Jupyter, you have a Python terminal at your disposal.\n", + "You can run Python code:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a string and the number 1\n", + "now s is increased 2\n" + ] + } + ], "source": [ "# You can evaluate maths and strings\n", "s = 1\n", @@ -46,6 +60,92 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run simple, non interactive bash commands in a python cell, prefix them with `!`.\n", + "When you run a cell, the output is displayed below the cell.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "totale 576\n", + "-rw-rw-r--. 1 rpolli rpolli 16659 12 mag 17.10 00_teaser.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 8833 11 mag 11.38 01_architecture.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 9772 12 mag 15.25 02_delivery_layout.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 8312 15 mag 10.50 02_vaults.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 7433 15 mag 10.24 03_facts_and_variables.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 8258 6 lug 2019 04_loops_and_conditions.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 9868 22 set 2021 05_inventories.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 7306 6 lug 2019 06_bastion_and_ssh.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 14130 6 lug 2019 07_playbooks.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 5240 6 lug 2019 07_templates.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 8942 6 lug 2019 08_yaml_pitfalls.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 5892 6 lug 2019 09_roles.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 3260 6 lug 2019 10_galaxy_ok.ipynb\n", + "-rw-rw-r--. 1 rpolli rpolli 408823 22 set 2021 ansible-101.graphml\n", + "-rwxrwxr-x. 1 rpolli rpolli 263 22 set 2021 cleanup.sh\n", + "-rw-rw-r--. 1 rpolli rpolli 395 22 set 2021 custom.css\n", + "-rw-rw-r--. 1 rpolli rpolli 1718 15 mag 15.19 diagrams.md\n", + "drwxrwxr-x. 3 rpolli rpolli 142 11 mag 11.22 exercise-00\n", + "drwxrwxr-x. 2 rpolli rpolli 116 15 mag 10.48 exercise-01\n", + "drwxrwxr-x. 2 rpolli rpolli 169 11 mag 11.22 exercise-03\n", + "drwxrwxr-x. 3 rpolli rpolli 147 11 mag 11.21 exercise-05\n", + "drwxrwxr-x. 2 rpolli rpolli 129 11 mag 11.22 exercise-06\n", + "drwxrwxr-x. 2 rpolli rpolli 4096 11 mag 11.22 exercise-07\n", + "drwxrwxr-x. 3 rpolli rpolli 89 6 lug 2019 exercise-08\n", + "drwxrwxr-x. 2 rpolli rpolli 87 11 mag 11.22 exercise-09\n", + "drwxrwxr-x. 2 rpolli rpolli 67 6 lug 2019 images\n", + "-rw-rw-r--. 1 rpolli rpolli 5519 15 mag 15.31 intro.ipynb\n", + "drwxrwxr-x. 5 rpolli rpolli 59 15 mag 10.58 rendered_notebooks\n", + "-rw-rw-r--. 1 rpolli rpolli 35 22 set 2021 untitled.txt\n", + "-rw-rw-r--. 1 rpolli rpolli 163 22 set 2021 web\n" + ] + } + ], + "source": [ + "! ls -l" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "During the course, you will need to execute some shell code, that is rendered like the following\n", + "\n", + "```bash\n", + "# This is a bash cell.\n", + "echo \"What is your name?\"\n", + "read name\n", + "echo \"Hello $name!\"\n", + "```\n", + "\n", + "In these cases, you need to [open a terminal on the local machine](/terminals/example), for example following links like [this one](/terminals/example) and type the commands there. This is especially required for interactive tasks. \n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python\n", + "\n", + "Go to the [basic python course](/tree/notebooks/rendered_notebooks/python-basic)" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -57,6 +157,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -70,6 +171,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -90,6 +192,7 @@ "source": [] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -110,6 +213,7 @@ "source": [] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -157,21 +261,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.14" + "pygments_lexer": "ipython3", + "version": "3.9.9" } }, "nbformat": 4, diff --git a/docker-101/01-docker.md b/docker-101/01-docker.md new file mode 100644 index 0000000..644e54b --- /dev/null +++ b/docker-101/01-docker.md @@ -0,0 +1,113 @@ + +# Docker 101 + +This is a crash docker course. + +## What is? + +Docker is a platform for developers and sysadmins to develop, + ship, and run applications. + +--- + +## Why it was born? + +To resolve a necessity + +Mobility workload in cloud systems + +--- + +### Cargo transport pre-1960 + +![text](slides/image/cargo-transport-pre-1960.png) + +--- + +### Solution: Intermodal Shipping Container + +![text](slides/image/standard_container.jpg) + +--- + +### Docker is a Container System for Code + +![text](slides/image/container.png) + +Docker leverages LXC (Linux Containers), which encompasses Linux +features like cgroups and namespaces for strong process isolation and +resource control. + +They are lightweight and consume less resources than a virtual machine. + +--- + +## Benefits for developers + +- portability, build once... run anywhere +- no worries about missing dependencies, packages and other pain + points during subsequent deployments +- tracking changes +- run each app in its own isolated container, so you can run various + versions of libraries and other dependencies for each app without + worrying +- reduce/eliminate concerns about compatibility on different + platforms, either your own or your customers'. + +--- + +## Benefits for sysadmins + +- portability, configure once... run anywhere +- tracking changes +- simple to understand what application do +- simplify to upgrade application processes. Significantly improves + the speed and reliability of continuous deployment and continuous + integration systems +- eliminate inconsistencies between different enviroments (develop, testing, production) +- re-use other people images +- do you not need an hypervisor. Because the containers are so + lightweight, address significant performance, costs, deployment, and + portability issues normally associated with VMs + +--- + +## Docker Concepts and Interactions + +- **Host**, the machine that is running the containers. +- **Image**, a hierarchy of files, with meta-data for how to run a container. +- **Container**, a contained running process, started from an image. +- **Registry**, a repository of images. +- **Volume**, storage outside the container. +- **Dockerfile**, a script for creating images. + +---- + +[![](https://mermaid.ink/img/pako:eNptU8lu2zAQ_RWBZ8moZctVdOilKdAeekmBHirmMJLGFhMuAjkM6lr-91JbbCcBD3qjefM4G0-sNg2ygiVJwjUJklhE96Z-RhsJTWihJmG043okHCx0LddcO1-NOHrAg3Bkj-UDKkP4akd7qIo9JM2o9ci1WJec_VBwQBd8g6v2FTo-qM1ci00LtET6ymvyi_UEL7Dg7kit0ZwFVdTNTTrfjSOupwL2QmJ5gfOtM7xN7sVIr9CVv6fvTG2AoAKHgVAbTSA0WleWX1_xVSGPgSRNDTJUMXfkfbGXhIdzlVqSfOkrL2TTR7cigyfqCQ5vHdcpTaTaKCXoA4HBab3uo0vE2-hemdDsPpr78M7tCCzFjkwXWxyNWzWuh8aP1M67NgxVDMVf195fVmOiSfkxbRohi5lCq0A0YTlPXEcRZ9SiQs6KABvcg5fEGdfnQPVdmBV-awQZywqyHmMGnsyvo64Xe-LcCwiboli4ULrwtwP9xxi1kILJihP7y4p1lq-263SzyfI83WTp5zRmR1akd7vVLrvb5Vm-2W6zcM4x-zcqfFplMcMxh5_Toxrf1vk_Byk2hw?type=png)](https://mermaid.live/edit#pako:eNptU8lu2zAQ_RWBZ8moZctVdOilKdAeekmBHirmMJLGFhMuAjkM6lr-91JbbCcBD3qjefM4G0-sNg2ygiVJwjUJklhE96Z-RhsJTWihJmG043okHCx0LddcO1-NOHrAg3Bkj-UDKkP4akd7qIo9JM2o9ci1WJec_VBwQBd8g6v2FTo-qM1ci00LtET6ymvyi_UEL7Dg7kit0ZwFVdTNTTrfjSOupwL2QmJ5gfOtM7xN7sVIr9CVv6fvTG2AoAKHgVAbTSA0WleWX1_xVSGPgSRNDTJUMXfkfbGXhIdzlVqSfOkrL2TTR7cigyfqCQ5vHdcpTaTaKCXoA4HBab3uo0vE2-hemdDsPpr78M7tCCzFjkwXWxyNWzWuh8aP1M67NgxVDMVf195fVmOiSfkxbRohi5lCq0A0YTlPXEcRZ9SiQs6KABvcg5fEGdfnQPVdmBV-awQZywqyHmMGnsyvo64Xe-LcCwiboli4ULrwtwP9xxi1kILJihP7y4p1lq-263SzyfI83WTp5zRmR1akd7vVLrvb5Vm-2W6zcM4x-zcqfFplMcMxh5_Toxrf1vk_Byk2hw) + + +---- + +--- + +## Separation of concerns + +- inside the container: + - libreries + - package manager + - application + - data + - code +- outside the container: + - logging + - remote access + - network configuration + - monitoring + +--- + +## Difference between docker and virtual machine + +![text](slides/image/VM-Diagram.png) + +--- diff --git a/docker-101/02-docker.md b/docker-101/02-docker.md new file mode 100644 index 0000000..983badd --- /dev/null +++ b/docker-101/02-docker.md @@ -0,0 +1,345 @@ +## Inspect the Docker host + +At first, we will inspect this machine: the operating system, the IP address and the rest. + +```python +# Distro +!cat /etc/issue +``` + +```python +# Linux version +!uname -a +``` + +```python +# IP address +! ip -4 -o address show eth0 +``` + +--- + +## Docker installation + +Check docker tools. + +```python +# Docker CLI version. +!docker --version +``` + +```python +# Docker server version + +!dockerd --version +``` + +--- + +## Running a container + +Docker comes with a catalog of possible operating systems and applications named Docker Registry. You can deploy your custom registry too. + +Let's pull and run an image + +[![](https://mermaid.ink/img/pako:eNptU8tu2zAQ_BWCQG6SUT_kODr00hRoD70kQA8Vc6DEtcVaXArkMq1r5d9LPRzbScADZ7XD0exyeeSVVcBznqapQNLUQM7ubbUHxzQSOFmRtugFDoSdk20tUKAP5YDZA-y0J3coHsBYgteYbWWZb2WqBq0ngXpeCP7dyB34mOtTVSjBi15t4jpQtaTTyVAGpHCKfstnecLtgWqLgkdVQHVl55v1JHAsYKsbKM5w-usEr8092yYY8MXPcZ-oSpIspYdIqCyS1AjOF8WXV3xRyFMkNbaSTaxi6sj7Ys-G-3VhLU0_d2XQjerYtUifYR3J3dvEpaWRVFljNH0g0CddwI6dT7w93Rkbm92xqQ_v0p6ko8STbRMHQ3CtJrBv_EBtg6_jpeq--Mvau_NojLSm-Zg2XqHAmxvWk5hExaL9uLOBPYuN1rh_pENs3DK5ZVHT7iGP05OMMP2jFdV5xhNuwBmpVRzwo0DGBKcaDAieR6hgK0NDggt8idTQxvuGr0qTdTwnFyDhMpB9PGB1ikfOvZZx2gyPphsfv7YSf1lrTqQY8vzI__J8nm1mq_liucw2m8UyW9wuEn7g-eJuPVtnd-tNtlmuVllcLwn_Nyh8mmUJh8HDj_FhDu_z5T_yHk5s?type=png)](https://mermaid.live/edit#pako:eNptU8tu2zAQ_BWCQG6SUT_kODr00hRoD70kQA8Vc6DEtcVaXArkMq1r5d9LPRzbScADZ7XD0exyeeSVVcBznqapQNLUQM7ubbUHxzQSOFmRtugFDoSdk20tUKAP5YDZA-y0J3coHsBYgteYbWWZb2WqBq0ngXpeCP7dyB34mOtTVSjBi15t4jpQtaTTyVAGpHCKfstnecLtgWqLgkdVQHVl55v1JHAsYKsbKM5w-usEr8092yYY8MXPcZ-oSpIspYdIqCyS1AjOF8WXV3xRyFMkNbaSTaxi6sj7Ys-G-3VhLU0_d2XQjerYtUifYR3J3dvEpaWRVFljNH0g0CddwI6dT7w93Rkbm92xqQ_v0p6ko8STbRMHQ3CtJrBv_EBtg6_jpeq--Mvau_NojLSm-Zg2XqHAmxvWk5hExaL9uLOBPYuN1rh_pENs3DK5ZVHT7iGP05OMMP2jFdV5xhNuwBmpVRzwo0DGBKcaDAieR6hgK0NDggt8idTQxvuGr0qTdTwnFyDhMpB9PGB1ikfOvZZx2gyPphsfv7YSf1lrTqQY8vzI__J8nm1mq_liucw2m8UyW9wuEn7g-eJuPVtnd-tNtlmuVllcLwn_Nyh8mmUJh8HDj_FhDu_z5T_yHk5s) + +```python +# Search images from catalog + +!docker search ubuntu|head + +``` + +Download an image from the remote registry. + +```python +# Download the ubuntu image +!docker pull ubuntu:22.04 + +``` + +Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`) +in a new container based on `ubuntu:22.04`. The `--rm` option removes the container when it exits. + +**NB: run the following commands in the terminal, not in the jupyter notebook** + +```bash +docker run --rm --tty --interactive ubuntu:22.04 /bin/bash +``` + +Then run the above commands to ensure that you are on another virtual hosts. + +```bash +# Operating System +cat /etc/issue +# Linux version +uname -a +``` + +--- + +#### Exercise + +What happens if you try to get the IP address using the following command? + +```bash +ip -4 -o a +``` + +Can you retrieve the IP address in another way? +Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`. + +--- + +## Dockerizing Applications + +`busybox` is a lightweight Linux distribution. You can run an one-shot command in a container. + +```bash +docker run busybox /bin/echo 'Hello world' +``` + +--- + +## Docker commands + +Here is a list of docker commands. + +```text +docker create # creates a container but does not start it. +docker run # creates and starts a container. +docker stop # stops it. +docker start # will start it again. +docker restart # restarts a container. +docker rm # deletes a container. +docker kill # sends a SIGKILL to a container. +docker attach # will connect to a running container. +docker wait # blocks until container stops. +docker exec # executes a command in a running container. +``` + +You can inspect containers + +```text +docker ps # shows running containers. +docker inspect # information on a container (incl. IP address). +docker logs # gets logs from container. +docker events # gets events from container. +docker port # shows public facing port of container. +docker top # shows running processes in container. +docker diff # shows changed files in container's FS. +docker stats # shows metrics, memory, cpu, filsystem +``` + +#### Exercise + +1. List the running containers. + +```python +# Use this cell to run the correct docker command. +``` + +2a. Inspect the `ansible-101_bastion_1` container. +2b. Use the `--format` option to get the IP address. Hint: you can google for the solution. + +```python +# Use this cell to run the correct docker command. +``` + +--- + +## Images + +### Like VMs template images + +Docker leverages a [copy-on-write filesystem](https://docs.docker.com/storage/storagedriver/). +This allows Docker to instantiate containers very quickly. +Docker use to layering one container filesytem on top of another. +For example, you might create a container that is based on +a base Debian image, and then in turn create another container that is +based on the first container. + +[![](https://mermaid.ink/img/pako:eNpVkstO6zAQhl_FmnVS2U7iNFmwQLBAiBVIR6I-QtPYoRaxXSW2RE_Vd8ckp7Ts5vLN7dccofNKQwvvI-530kk3xe1sk867gMbpcfNnNAG3g76EyIAHPf6VLnyGzcvOTEuAeDccztQkU3qnSW8GPZGww0Bw1MR6ZXqjVSrWTn1PvJppLL7rt7nX5sHauIyN2-hCbDlf0XJBSI9tj_ngu4_UZ4uTznl-Xdw0VVV0NSGMPt6eEfYLqRWvFWWE8OLpB6G_kJ6KAouCEEFn5P_CFxny_OZ65-8kZGD1aNGopOpROkIkJBmsltAmU-ke4xAkSHdKaNwrDPpemeBHaMMYdQYYg38-uO7sL8ydwaSRhXT3MKXoHt2r9_YMJRfaI3xCy8pyVdKqYrTkxbqhTQYHaHlTrUTViIILwfma1acM_s31dCVYxWnFxLrmJRWUZaDnhZ6W15g_5PQF27i6QA?type=png)](https://mermaid.live/edit#pako:eNpVkstO6zAQhl_FmnVS2U7iNFmwQLBAiBVIR6I-QtPYoRaxXSW2RE_Vd8ckp7Ts5vLN7dccofNKQwvvI-530kk3xe1sk867gMbpcfNnNAG3g76EyIAHPf6VLnyGzcvOTEuAeDccztQkU3qnSW8GPZGww0Bw1MR6ZXqjVSrWTn1PvJppLL7rt7nX5sHauIyN2-hCbDlf0XJBSI9tj_ngu4_UZ4uTznl-Xdw0VVV0NSGMPt6eEfYLqRWvFWWE8OLpB6G_kJ6KAouCEEFn5P_CFxny_OZ65-8kZGD1aNGopOpROkIkJBmsltAmU-ke4xAkSHdKaNwrDPpemeBHaMMYdQYYg38-uO7sL8ydwaSRhXT3MKXoHt2r9_YMJRfaI3xCy8pyVdKqYrTkxbqhTQYHaHlTrUTViIILwfma1acM_s31dCVYxWnFxLrmJRWUZaDnhZ6W15g_5PQF27i6QA) + +This mechanism allows an efficient storage usage, since multiple containers can +reuse the same filesystem layers. + +[![](https://mermaid.ink/img/pako:eNqlkk2P0zAQhv_KyAdOSRU7cb4OHBY4ILQnONEg5MaTrUVsV44ttnT733GTDaQSN-LL2HnmnZnXvpDeSiQteXLidOxMZ6ZwmGPorfFCGXR0_24NgcJPp7w4jAijOKP71hn_7On-y1FNywlYM57X5KmL_48IgxpxAn8UHoRD0FaqQaGM2Wjkv2qyTU22LcX-s9TdiEqLJ_w-a-0_ah2WwcIhGB9axnZZsSAwiHYQ6Wj7H1HnICZMWbpNbhrO874CoNmnhxWhd0glWSUzCsDyxz9IdocMWZmLPAcosxl5bfjvRcCbjUOQpm_hxaGQ6c2HOL7DMCHchNe2b168bMe86ZGEaHRaKBnv_dIZgI5E5zR2pI2hxEGE0XekM9eIhpMUHj9I5a0jrXcBEyKCt5_Ppl_3C_NeiWirJtGqcYqnJ2G-WqtXKG5JeyHPpKW83hWU5Tmva5ZzVrGEnEnLmnJX8qaseZ0XBY_rmpBfs0K249nyFVXDGOc0ITi39Lg83_kVX38DC_v2ew?type=png)](https://mermaid.live/edit#pako:eNqlkk2P0zAQhv_KyAdOSRU7cb4OHBY4ILQnONEg5MaTrUVsV44ttnT733GTDaQSN-LL2HnmnZnXvpDeSiQteXLidOxMZ6ZwmGPorfFCGXR0_24NgcJPp7w4jAijOKP71hn_7On-y1FNywlYM57X5KmL_48IgxpxAn8UHoRD0FaqQaGM2Wjkv2qyTU22LcX-s9TdiEqLJ_w-a-0_ah2WwcIhGB9axnZZsSAwiHYQ6Wj7H1HnICZMWbpNbhrO874CoNmnhxWhd0glWSUzCsDyxz9IdocMWZmLPAcosxl5bfjvRcCbjUOQpm_hxaGQ6c2HOL7DMCHchNe2b168bMe86ZGEaHRaKBnv_dIZgI5E5zR2pI2hxEGE0XekM9eIhpMUHj9I5a0jrXcBEyKCt5_Ppl_3C_NeiWirJtGqcYqnJ2G-WqtXKG5JeyHPpKW83hWU5Tmva5ZzVrGEnEnLmnJX8qaseZ0XBY_rmpBfs0K249nyFVXDGOc0ITi39Lg83_kVX38DC_v2ew) + +---- + + +## Commands for interacting with images + +```text +docker images # shows all images. +docker import # creates an image from a tarball. +docker build # creates image from Dockerfile. +docker commit # creates image from a container. +docker rmi # removes an image. +docker history # list changes of an image. +``` + +--- + +## Building images with Dockerfile + +The Dockerfile is a text file that contains all the commands a user could +call on the command line to assemble an image. + +```dockerfile +FROM debian:7.8 +MAINTAINER Piuma "piuma@piumalab.org" +RUN apt-get update && apt-get -y install apache2 +EXPOSE 80 +CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] +``` + +Docker will execute all the commands in the Dockerfile and create a new image. + +```python +!docker build -t apache-example . +``` + +--- + +## docker-compose + +[Docker Compose](https://docs.docker.com/compose/) is a tool for defining and running complex applications with +Docker. + +With Compose, you define a multi-container application in a +single file, then spin your application up in a single command which +does everything that needs to be done to get it running. + +---- + +## docker-compose + +Using Compose is basically a three-step process: + +1. define your app's image with a `Dockerfile` +1. define the services that make up your app in +`docker-compose.yaml` so they can be run together in an isolated +environment. +1. run `docker-compose up` and Compose will start and run your + entire app. + +---- + +## docker-compose + +docker-compose.yaml + +```docker-compose +version: '2' +services: + web: + build: . + command: python app.py + ports: + - "5000:5000" + volumes: + - .:/code + links: + - redis + redis: + image: redis +``` + +Now run docker-compose up and Compose will start and run your entire app. + +Docker Compose is a basic example of Infrastructure as Code. +The infrastructure setup is defined in a file and can be versioned. +All the changes are tracked and can be reverted. +Administrators do not have to run commands on the server to setup the infrastructure. + +```bash +docker-compose up -d +``` + +--- + +## docker-compose example + +``` +version: "2" +services: + web: + image: piuma/phpsysinfo + ports: + - "80:80" +``` + +---- + +## docker-compose example + +```docker-compose +version: "2" +services: + web1: + image: piuma/phpsysinfo + web2: + image: piuma/phpsysinfo + proxy: + image: tutum/haproxy + links: + - web1 + - web2 + ports: + - "80:80" +``` + +---- + +## docker-compose example + +``` +version: "2" +services: + web1: + image: piuma/phpsysinfo + web2: + image: piuma/phpsysinfo + web3: + image: piuma/phpsysinfo + proxy: + image: tutum/haproxy + links: + - web1 + - web2 + - web3 + ports: + - "80:80" +``` + +---- + +## docker-compose example + +``` +version: "2" +services: + phpmyadmin: + image: nazarpc/phpmyadmin + links: + - mysql + ports: + - "8080:80" + mysql: + image: mysql + environment: + - MYSQL_ROOT_PASSWORD=secret +``` + +--- + +## What next? + +```python +!docker run --rm mribeiro/cowsay "Any questions?" +``` + +--- diff --git a/docker-101/Makefile b/docker-101/Makefile new file mode 100644 index 0000000..1642cb3 --- /dev/null +++ b/docker-101/Makefile @@ -0,0 +1,10 @@ +FILES=$(wildcard *.md) +BOOKS = $(patsubst %.md,notebooks/%.ipynb,$(FILES)) + + +all: $(BOOKS) + @echo $(BOOKS) + +notebooks/%.ipynb: %.md + + notedown --to notebook $^ > $@ diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb index 7b2dd90..d63b7c1 100644 --- a/docker-101/notebooks/01-docker.ipynb +++ b/docker-101/notebooks/01-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "f331e170", + "id": "d1622201", "metadata": {}, "source": [ "# Docker 101\n", @@ -17,7 +17,7 @@ }, { "cell_type": "markdown", - "id": "1f596524", + "id": "c93e3b43", "metadata": { "slideshow": { "slide_type": "slide" @@ -35,7 +35,7 @@ }, { "cell_type": "markdown", - "id": "5c1e3bd3", + "id": "25a5e40b", "metadata": { "slideshow": { "slide_type": "slide" @@ -51,7 +51,7 @@ }, { "cell_type": "markdown", - "id": "fd4c7aba", + "id": "aae78c63", "metadata": { "slideshow": { "slide_type": "slide" @@ -67,7 +67,7 @@ }, { "cell_type": "markdown", - "id": "8171d744", + "id": "de60e58f", "metadata": { "slideshow": { "slide_type": "slide" @@ -89,7 +89,7 @@ }, { "cell_type": "markdown", - "id": "c6f40cfe", + "id": "636d87c1", "metadata": { "slideshow": { "slide_type": "slide" @@ -113,7 +113,7 @@ }, { "cell_type": "markdown", - "id": "8828d397", + "id": "038b5755", "metadata": { "slideshow": { "slide_type": "slide" @@ -139,7 +139,7 @@ }, { "cell_type": "markdown", - "id": "4cde50ac", + "id": "7bee342a", "metadata": { "slideshow": { "slide_type": "slide" @@ -160,7 +160,7 @@ }, { "cell_type": "markdown", - "id": "33b87580", + "id": "5c660c08", "metadata": { "slideshow": { "slide_type": "subslide" @@ -174,7 +174,7 @@ }, { "cell_type": "markdown", - "id": "ec5425fb", + "id": "711982d2", "metadata": {}, "source": [ "----" @@ -182,7 +182,7 @@ }, { "cell_type": "markdown", - "id": "746dbadb", + "id": "a07406b5", "metadata": { "slideshow": { "slide_type": "slide" @@ -208,7 +208,7 @@ }, { "cell_type": "markdown", - "id": "92fa0ff8", + "id": "ca8aac3c", "metadata": { "slideshow": { "slide_type": "slide" @@ -224,7 +224,7 @@ }, { "cell_type": "markdown", - "id": "0189dd8d", + "id": "7aa111c2", "metadata": {}, "source": [ "---" diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb new file mode 100644 index 0000000..ab18853 --- /dev/null +++ b/docker-101/notebooks/02-docker.ipynb @@ -0,0 +1,775 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a8fbf123", + "metadata": {}, + "source": [ + "## Inspect the Docker host\n", + "\n", + "At first, we will inspect this machine: the operating system, the IP address and the rest." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4bed24d1", + "metadata": {}, + "outputs": [], + "source": [ + "# Distro\n", + "!cat /etc/issue" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed4edb97", + "metadata": {}, + "outputs": [], + "source": [ + "# Linux version\n", + "!uname -a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaca4370", + "metadata": {}, + "outputs": [], + "source": [ + "# IP address\n", + "! ip -4 -o address show eth0" + ] + }, + { + "cell_type": "markdown", + "id": "c0ad6e26", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Docker installation\n", + "\n", + "Check docker tools." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43ed1c9b", + "metadata": {}, + "outputs": [], + "source": [ + "# Docker CLI version.\n", + "!docker --version" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0e0745ae", + "metadata": {}, + "outputs": [], + "source": [ + "# Docker server version\n", + "\n", + "!dockerd --version" + ] + }, + { + "cell_type": "markdown", + "id": "2fa100df", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Running a container\n", + "\n", + "Docker comes with a catalog of possible operating systems and applications named Docker Registry. You can deploy your custom registry too.\n", + "\n", + "Let's pull and run an image\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNptU8tu2zAQ_BWCQG6SUT_kODr00hRoD70kQA8Vc6DEtcVaXArkMq1r5d9LPRzbScADZ7XD0exyeeSVVcBznqapQNLUQM7ubbUHxzQSOFmRtugFDoSdk20tUKAP5YDZA-y0J3coHsBYgteYbWWZb2WqBq0ngXpeCP7dyB34mOtTVSjBi15t4jpQtaTTyVAGpHCKfstnecLtgWqLgkdVQHVl55v1JHAsYKsbKM5w-usEr8092yYY8MXPcZ-oSpIspYdIqCyS1AjOF8WXV3xRyFMkNbaSTaxi6sj7Ys-G-3VhLU0_d2XQjerYtUifYR3J3dvEpaWRVFljNH0g0CddwI6dT7w93Rkbm92xqQ_v0p6ko8STbRMHQ3CtJrBv_EBtg6_jpeq--Mvau_NojLSm-Zg2XqHAmxvWk5hExaL9uLOBPYuN1rh_pENs3DK5ZVHT7iGP05OMMP2jFdV5xhNuwBmpVRzwo0DGBKcaDAieR6hgK0NDggt8idTQxvuGr0qTdTwnFyDhMpB9PGB1ikfOvZZx2gyPphsfv7YSf1lrTqQY8vzI__J8nm1mq_liucw2m8UyW9wuEn7g-eJuPVtnd-tNtlmuVllcLwn_Nyh8mmUJh8HDj_FhDu_z5T_yHk5s?type=png)](https://mermaid.live/edit#pako:eNptU8tu2zAQ_BWCQG6SUT_kODr00hRoD70kQA8Vc6DEtcVaXArkMq1r5d9LPRzbScADZ7XD0exyeeSVVcBznqapQNLUQM7ubbUHxzQSOFmRtugFDoSdk20tUKAP5YDZA-y0J3coHsBYgteYbWWZb2WqBq0ngXpeCP7dyB34mOtTVSjBi15t4jpQtaTTyVAGpHCKfstnecLtgWqLgkdVQHVl55v1JHAsYKsbKM5w-usEr8092yYY8MXPcZ-oSpIspYdIqCyS1AjOF8WXV3xRyFMkNbaSTaxi6sj7Ys-G-3VhLU0_d2XQjerYtUifYR3J3dvEpaWRVFljNH0g0CddwI6dT7w93Rkbm92xqQ_v0p6ko8STbRMHQ3CtJrBv_EBtg6_jpeq--Mvau_NojLSm-Zg2XqHAmxvWk5hExaL9uLOBPYuN1rh_pENs3DK5ZVHT7iGP05OMMP2jFdV5xhNuwBmpVRzwo0DGBKcaDAieR6hgK0NDggt8idTQxvuGr0qTdTwnFyDhMpB9PGB1ikfOvZZx2gyPphsfv7YSf1lrTqQY8vzI__J8nm1mq_liucw2m8UyW9wuEn7g-eJuPVtnd-tNtlmuVllcLwn_Nyh8mmUJh8HDj_FhDu_z5T_yHk5s)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c262edf0", + "metadata": {}, + "outputs": [], + "source": [ + "# Search images from catalog\n", + "\n", + "!docker search ubuntu|head\n" + ] + }, + { + "cell_type": "markdown", + "id": "e5a8ad4f", + "metadata": {}, + "source": [ + "Download an image from the remote registry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fba50f5c", + "metadata": {}, + "outputs": [], + "source": [ + "# Download the ubuntu image\n", + "!docker pull ubuntu:22.04\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "fab9b00c", + "metadata": {}, + "source": [ + "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", + "in a new container based on `ubuntu:22.04`. The `--rm` option removes the container when it exits.\n", + "\n", + "**NB: run the following commands in the terminal, not in the jupyter notebook**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d9bd01f", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "docker run --rm --tty --interactive ubuntu:22.04 /bin/bash" + ] + }, + { + "cell_type": "markdown", + "id": "8b071727", + "metadata": {}, + "source": [ + "Then run the above commands to ensure that you are on another virtual hosts." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0978cb56", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "# Operating System\n", + "cat /etc/issue\n", + "# Linux version\n", + "uname -a" + ] + }, + { + "cell_type": "markdown", + "id": "a79ffbe7", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "#### Exercise\n", + "\n", + "What happens if you try to get the IP address using the following command?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "189b15a9", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "ip -4 -o a" + ] + }, + { + "cell_type": "markdown", + "id": "96f470e9", + "metadata": {}, + "source": [ + "Can you retrieve the IP address in another way?\n", + "Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`." + ] + }, + { + "cell_type": "markdown", + "id": "56425673", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Dockerizing Applications\n", + "\n", + "`busybox` is a lightweight Linux distribution. You can run an one-shot command in a container." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70148621", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "docker run busybox /bin/echo 'Hello world'" + ] + }, + { + "cell_type": "markdown", + "id": "b96b1008", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Docker commands\n", + "\n", + "Here is a list of docker commands." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88c6655a", + "metadata": { + "attributes": { + "classes": [ + "text" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "docker create # creates a container but does not start it.\n", + "docker run # creates and starts a container.\n", + "docker stop # stops it.\n", + "docker start # will start it again.\n", + "docker restart # restarts a container.\n", + "docker rm # deletes a container.\n", + "docker kill # sends a SIGKILL to a container.\n", + "docker attach # will connect to a running container.\n", + "docker wait # blocks until container stops.\n", + "docker exec # executes a command in a running container." + ] + }, + { + "cell_type": "markdown", + "id": "7a552578", + "metadata": {}, + "source": [ + "You can inspect containers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cfaa44de", + "metadata": { + "attributes": { + "classes": [ + "text" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "docker ps # shows running containers.\n", + "docker inspect # information on a container (incl. IP address).\n", + "docker logs # gets logs from container.\n", + "docker events # gets events from container.\n", + "docker port # shows public facing port of container.\n", + "docker top # shows running processes in container.\n", + "docker diff # shows changed files in container's FS.\n", + "docker stats # shows metrics, memory, cpu, filsystem" + ] + }, + { + "cell_type": "markdown", + "id": "b5c88d3b", + "metadata": {}, + "source": [ + "#### Exercise\n", + "\n", + "1. List the running containers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b6b4ca6", + "metadata": {}, + "outputs": [], + "source": [ + "# Use this cell to run the correct docker command." + ] + }, + { + "cell_type": "markdown", + "id": "a3c4b2df", + "metadata": {}, + "source": [ + "2a. Inspect the `ansible-101_bastion_1` container.\n", + "2b. Use the `--format` option to get the IP address. Hint: you can google for the solution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16edfe2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Use this cell to run the correct docker command." + ] + }, + { + "cell_type": "markdown", + "id": "d288124c", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Images\n", + "\n", + "### Like VMs template images\n", + "\n", + "Docker leverages a [copy-on-write filesystem](https://docs.docker.com/storage/storagedriver/).\n", + "This allows Docker to instantiate containers very quickly.\n", + "Docker use to layering one container filesytem on top of another.\n", + "For example, you might create a container that is based on\n", + "a base Debian image, and then in turn create another container that is\n", + "based on the first container.\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNpVkstO6zAQhl_FmnVS2U7iNFmwQLBAiBVIR6I-QtPYoRaxXSW2RE_Vd8ckp7Ts5vLN7dccofNKQwvvI-530kk3xe1sk867gMbpcfNnNAG3g76EyIAHPf6VLnyGzcvOTEuAeDccztQkU3qnSW8GPZGww0Bw1MR6ZXqjVSrWTn1PvJppLL7rt7nX5sHauIyN2-hCbDlf0XJBSI9tj_ngu4_UZ4uTznl-Xdw0VVV0NSGMPt6eEfYLqRWvFWWE8OLpB6G_kJ6KAouCEEFn5P_CFxny_OZ65-8kZGD1aNGopOpROkIkJBmsltAmU-ke4xAkSHdKaNwrDPpemeBHaMMYdQYYg38-uO7sL8ydwaSRhXT3MKXoHt2r9_YMJRfaI3xCy8pyVdKqYrTkxbqhTQYHaHlTrUTViIILwfma1acM_s31dCVYxWnFxLrmJRWUZaDnhZ6W15g_5PQF27i6QA?type=png)](https://mermaid.live/edit#pako:eNpVkstO6zAQhl_FmnVS2U7iNFmwQLBAiBVIR6I-QtPYoRaxXSW2RE_Vd8ckp7Ts5vLN7dccofNKQwvvI-530kk3xe1sk867gMbpcfNnNAG3g76EyIAHPf6VLnyGzcvOTEuAeDccztQkU3qnSW8GPZGww0Bw1MR6ZXqjVSrWTn1PvJppLL7rt7nX5sHauIyN2-hCbDlf0XJBSI9tj_ngu4_UZ4uTznl-Xdw0VVV0NSGMPt6eEfYLqRWvFWWE8OLpB6G_kJ6KAouCEEFn5P_CFxny_OZ65-8kZGD1aNGopOpROkIkJBmsltAmU-ke4xAkSHdKaNwrDPpemeBHaMMYdQYYg38-uO7sL8ydwaSRhXT3MKXoHt2r9_YMJRfaI3xCy8pyVdKqYrTkxbqhTQYHaHlTrUTViIILwfma1acM_s31dCVYxWnFxLrmJRWUZaDnhZ6W15g_5PQF27i6QA)\n", + "\n", + "This mechanism allows an efficient storage usage, since multiple containers can\n", + "reuse the same filesystem layers.\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNqlkk2P0zAQhv_KyAdOSRU7cb4OHBY4ILQnONEg5MaTrUVsV44ttnT733GTDaQSN-LL2HnmnZnXvpDeSiQteXLidOxMZ6ZwmGPorfFCGXR0_24NgcJPp7w4jAijOKP71hn_7On-y1FNywlYM57X5KmL_48IgxpxAn8UHoRD0FaqQaGM2Wjkv2qyTU22LcX-s9TdiEqLJ_w-a-0_ah2WwcIhGB9axnZZsSAwiHYQ6Wj7H1HnICZMWbpNbhrO874CoNmnhxWhd0glWSUzCsDyxz9IdocMWZmLPAcosxl5bfjvRcCbjUOQpm_hxaGQ6c2HOL7DMCHchNe2b168bMe86ZGEaHRaKBnv_dIZgI5E5zR2pI2hxEGE0XekM9eIhpMUHj9I5a0jrXcBEyKCt5_Ppl_3C_NeiWirJtGqcYqnJ2G-WqtXKG5JeyHPpKW83hWU5Tmva5ZzVrGEnEnLmnJX8qaseZ0XBY_rmpBfs0K249nyFVXDGOc0ITi39Lg83_kVX38DC_v2ew?type=png)](https://mermaid.live/edit#pako:eNqlkk2P0zAQhv_KyAdOSRU7cb4OHBY4ILQnONEg5MaTrUVsV44ttnT733GTDaQSN-LL2HnmnZnXvpDeSiQteXLidOxMZ6ZwmGPorfFCGXR0_24NgcJPp7w4jAijOKP71hn_7On-y1FNywlYM57X5KmL_48IgxpxAn8UHoRD0FaqQaGM2Wjkv2qyTU22LcX-s9TdiEqLJ_w-a-0_ah2WwcIhGB9axnZZsSAwiHYQ6Wj7H1HnICZMWbpNbhrO874CoNmnhxWhd0glWSUzCsDyxz9IdocMWZmLPAcosxl5bfjvRcCbjUOQpm_hxaGQ6c2HOL7DMCHchNe2b168bMe86ZGEaHRaKBnv_dIZgI5E5zR2pI2hxEGE0XekM9eIhpMUHj9I5a0jrXcBEyKCt5_Ppl_3C_NeiWirJtGqcYqnJ2G-WqtXKG5JeyHPpKW83hWU5Tmva5ZzVrGEnEnLmnJX8qaseZ0XBY_rmpBfs0K249nyFVXDGOc0ITi39Lg83_kVX38DC_v2ew)" + ] + }, + { + "cell_type": "markdown", + "id": "df26a81d", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "\n", + "## Commands for interacting with images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51af0612", + "metadata": { + "attributes": { + "classes": [ + "text" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "docker images # shows all images.\n", + "docker import # creates an image from a tarball.\n", + "docker build # creates image from Dockerfile.\n", + "docker commit # creates image from a container.\n", + "docker rmi # removes an image.\n", + "docker history # list changes of an image." + ] + }, + { + "cell_type": "markdown", + "id": "b14a2427", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## Building images with Dockerfile\n", + "\n", + "The Dockerfile is a text file that contains all the commands a user could\n", + "call on the command line to assemble an image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e04a0531", + "metadata": { + "attributes": { + "classes": [ + "dockerfile" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "FROM debian:7.8\n", + "MAINTAINER Piuma \"piuma@piumalab.org\"\n", + "RUN apt-get update && apt-get -y install apache2\n", + "EXPOSE 80\n", + "CMD [\"/usr/sbin/apache2ctl\", \"-D\", \"FOREGROUND\"]" + ] + }, + { + "cell_type": "markdown", + "id": "e99985fe", + "metadata": {}, + "source": [ + "Docker will execute all the commands in the Dockerfile and create a new image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fb83c34", + "metadata": {}, + "outputs": [], + "source": [ + "!docker build -t apache-example ." + ] + }, + { + "cell_type": "markdown", + "id": "8205f6df", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## docker-compose\n", + "\n", + "[Docker Compose](https://docs.docker.com/compose/) is a tool for defining and running complex applications with\n", + "Docker.\n", + "\n", + "With Compose, you define a multi-container application in a\n", + "single file, then spin your application up in a single command which\n", + "does everything that needs to be done to get it running." + ] + }, + { + "cell_type": "markdown", + "id": "4191d72f", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "## docker-compose\n", + "\n", + "Using Compose is basically a three-step process:\n", + "\n", + "1. define your app's image with a `Dockerfile`\n", + "1. define the services that make up your app in\n", + "`docker-compose.yaml` so they can be run together in an isolated\n", + "environment.\n", + "1. run `docker-compose up` and Compose will start and run your\n", + " entire app." + ] + }, + { + "cell_type": "markdown", + "id": "d37afab8", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "## docker-compose\n", + "\n", + "docker-compose.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4692986", + "metadata": { + "attributes": { + "classes": [ + "docker-compose" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "version: '2'\n", + "services:\n", + " web:\n", + " build: .\n", + " command: python app.py\n", + " ports:\n", + " - \"5000:5000\"\n", + " volumes:\n", + " - .:/code\n", + " links:\n", + " - redis\n", + " redis:\n", + " image: redis" + ] + }, + { + "cell_type": "markdown", + "id": "481813f5", + "metadata": {}, + "source": [ + "Now run docker-compose up and Compose will start and run your entire app.\n", + "\n", + "Docker Compose is a basic example of Infrastructure as Code.\n", + "The infrastructure setup is defined in a file and can be versioned.\n", + "All the changes are tracked and can be reverted.\n", + "Administrators do not have to run commands on the server to setup the infrastructure." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09d7b2da", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "docker-compose up -d" + ] + }, + { + "cell_type": "markdown", + "id": "aca5db1c", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## docker-compose example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c24b5239", + "metadata": {}, + "outputs": [], + "source": [ + "version: \"2\"\n", + "services:\n", + " web:\n", + " image: piuma/phpsysinfo\n", + " ports:\n", + " - \"80:80\"" + ] + }, + { + "cell_type": "markdown", + "id": "3dd28183", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "## docker-compose example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d1b7da6", + "metadata": { + "attributes": { + "classes": [ + "docker-compose" + ], + "id": "" + } + }, + "outputs": [], + "source": [ + "version: \"2\"\n", + "services:\n", + " web1:\n", + " image: piuma/phpsysinfo\n", + " web2:\n", + " image: piuma/phpsysinfo\n", + " proxy:\n", + " image: tutum/haproxy\n", + " links:\n", + " - web1\n", + " - web2\n", + " ports:\n", + " - \"80:80\"" + ] + }, + { + "cell_type": "markdown", + "id": "a2a7b44c", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "## docker-compose example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45e0ab9d", + "metadata": {}, + "outputs": [], + "source": [ + "version: \"2\"\n", + "services:\n", + " web1:\n", + " image: piuma/phpsysinfo\n", + " web2:\n", + " image: piuma/phpsysinfo\n", + " web3:\n", + " image: piuma/phpsysinfo\n", + " proxy:\n", + " image: tutum/haproxy\n", + " links:\n", + " - web1\n", + " - web2\n", + " - web3\n", + " ports:\n", + " - \"80:80\"" + ] + }, + { + "cell_type": "markdown", + "id": "bbd2b44d", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "## docker-compose example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "732bcd89", + "metadata": {}, + "outputs": [], + "source": [ + "version: \"2\"\n", + "services:\n", + " phpmyadmin:\n", + " image: nazarpc/phpmyadmin\n", + " links:\n", + " - mysql\n", + " ports:\n", + " - \"8080:80\"\n", + " mysql:\n", + " image: mysql\n", + " environment:\n", + " - MYSQL_ROOT_PASSWORD=secret" + ] + }, + { + "cell_type": "markdown", + "id": "276f4050", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "## What next?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b123ec2", + "metadata": {}, + "outputs": [], + "source": [ + "!docker run --rm mribeiro/cowsay \"Any questions?\"" + ] + }, + { + "cell_type": "markdown", + "id": "2b0eafd0", + "metadata": {}, + "source": [ + "---" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docker-101/tox.ini b/docker-101/tox.ini new file mode 100644 index 0000000..268e6e7 --- /dev/null +++ b/docker-101/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py3 +skipsdist = True + +[testenv] +deps = + git+https://github.com/ioggstream/notedown +whitelist_externals = + make +commands = + make From 132c22995942a35305997a9ac06e30e3a75dee36 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 15 May 2023 17:50:57 +0200 Subject: [PATCH 10/39] More vaults. --- ansible-101/.gitignore | 3 + ansible-101/notebooks/02_vaults.ipynb | 134 ++++++++++++++---- ansible-101/notebooks/diagrams.md | 31 ++++ ansible-101/notebooks/exercise-01/.pin | 1 - .../notebooks/exercise-01/inventory.docker | 5 +- ansible-101/notebooks/intro.ipynb | 20 +-- 6 files changed, 150 insertions(+), 44 deletions(-) delete mode 100644 ansible-101/notebooks/exercise-01/.pin diff --git a/ansible-101/.gitignore b/ansible-101/.gitignore index 48be6b2..5c88495 100644 --- a/ansible-101/.gitignore +++ b/ansible-101/.gitignore @@ -8,3 +8,6 @@ core* *_python_intro.ipynb notebooks/rendered_notebooks/ +vault.yml +vault.yaml +.pin diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index 30d7cf2..e0339ee 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -25,22 +26,15 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/notebooks/exercise-01\n" - ] - } - ], + "outputs": [], "source": [ "cd /notebooks/exercise-01/" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -55,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -64,6 +58,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -90,8 +85,18 @@ "metadata": {}, "outputs": [], "source": [ - "# Now a `secret` password ;) We'll reference this in ansible.cfg\n", - "!echo secret > .pin " + "# Use the `lookup` plugin to create a password file.\n", + "!ansible localhost -m copy -a \"content='{{ lookup('password', '/dev/null length=20 chars=ascii_letters,digits') }}' dest=$PWD/.pin\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's show the password :)\n", + "! cat .pin" ] }, { @@ -105,6 +110,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -116,6 +122,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -135,12 +142,70 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- use the `copy` module to generate the `vault.yaml` file with the following content\n", + "\n", + "```yaml\n", + "root_password: \n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Solution\n", + "!ansible localhost -mcopy \\\n", + " -a \"content='root_password: {{lookup('password','/dev/null')}}' dest=$PWD/vault.yaml\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "- use the ansible_connection=docker method specified in `inventory.docker` to copy the ssh key to the docker containers. Without this, the ssh key will not be available to the docker containers and you cannot access them via ssh.\n", + "\n", + "In real infrastructures, the ssh keys are usually provisioned at boot.\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNp1U1Fr2zAQ_itCDyMFK8xKnLmmFArdw6CFsr3NCkORLo2pLQVJbpsl-e87W3bTdBQ_6O6-T3efPll7qqwGWlDGmDChCjUU5Mb4alUDUdYYUKGyhjQQNlZ7YXreo5PbDbn7KYwwvl3FVFv1BK6MC1nLVbGWLGbLd7St1CXBgkpL7B9kZcClSO_Yql1BB_ETxM8hn04mPx7IuMFAeLHuib1UDvTFBeK8x_lnOBgtTBSl_WQSIyEM7vlkx0Auy9uR68E998EozT76D-ddDpN8StiUXROVdtKGmJ_ZJqPZf05mI-g3rDLPYIJ1uxIz0ljd4o3EgTUOWY7K3hEH69-45zfQC_rQmzB2fcDKgaDSL8Tz_7v2lFg8kNG5k4cdPMSku1TsovCgjB2u3ug0oQ24RlYaf7Q9-kYEDRtoQNACQw1r2dZBUGGOSG23Wgb4riucTovgWkiobIP9tTNqzCPntpLoYUPxmLXH6laa39Y2IwlTWuzpKy3SLJ_OUz6bZXnOZxn_xhO6owW_XEwX2eUiz_LZfJ7hd0zo377D12mWUOg13McH0r-T4z9VnhsC?type=png)](https://mermaid.live/edit#pako:eNp1U1Fr2zAQ_itCDyMFK8xKnLmmFArdw6CFsr3NCkORLo2pLQVJbpsl-e87W3bTdBQ_6O6-T3efPll7qqwGWlDGmDChCjUU5Mb4alUDUdYYUKGyhjQQNlZ7YXreo5PbDbn7KYwwvl3FVFv1BK6MC1nLVbGWLGbLd7St1CXBgkpL7B9kZcClSO_Yql1BB_ETxM8hn04mPx7IuMFAeLHuib1UDvTFBeK8x_lnOBgtTBSl_WQSIyEM7vlkx0Auy9uR68E998EozT76D-ddDpN8StiUXROVdtKGmJ_ZJqPZf05mI-g3rDLPYIJ1uxIz0ljd4o3EgTUOWY7K3hEH69-45zfQC_rQmzB2fcDKgaDSL8Tz_7v2lFg8kNG5k4cdPMSku1TsovCgjB2u3ug0oQ24RlYaf7Q9-kYEDRtoQNACQw1r2dZBUGGOSG23Wgb4riucTovgWkiobIP9tTNqzCPntpLoYUPxmLXH6laa39Y2IwlTWuzpKy3SLJ_OUz6bZXnOZxn_xhO6owW_XEwX2eUiz_LZfJ7hd0zo377D12mWUOg13McH0r-T4z9VnhsC)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Provision the ssh keys using the docker_connector\n", + "!cat inventory.docker\n", + "!ansible docker -i inventory.docker -m shell \\\n", + " -a \"echo 'root:{{root_password}}' | chpasswd\" \\\n", + " -e@vault.yaml " + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Gotta ping 'em all\n", "\n", - "Everything is set up now. \n", + "Our Ansible environment is all set, but we still need to check if we can reach all the hosts.\n", "\n", "Let's ping all hosts, eventually adjusting the ip ranges in the [inventory](/edit/notebooks/exercise-01/inventory).\n", "\n", @@ -154,10 +219,11 @@ "outputs": [], "source": [ "# Let's get an error: root_password is UNDEFINED. \n", - "!ansible -m ping all\n" + "!ansible -m ping all" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -174,9 +240,8 @@ "source": [ "# A vault is just a yaml file containing a dictionary of secrets.\n", "# We can put here as many information as we want, but for now\n", - "# just put the `root_password`.\n", - "\n", - "!echo \"root_password: root\" > vault.yml" + "# just set a `root_password` generated using the lookup plugin.\n", + "!cat vault.yaml" ] }, { @@ -186,10 +251,11 @@ "outputs": [], "source": [ "# We need to encrypt it. \n", - "!ansible-vault encrypt vault.yml" + "!ansible-vault encrypt vault.yml\n" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -207,7 +273,7 @@ "outputs": [], "source": [ "# And show the anatomy of the vault.\n", - "!cat vault.yml" + "!cat vault.yaml" ] }, { @@ -217,7 +283,7 @@ "outputs": [], "source": [ "# Can we decrypt it?\n", - "!ansible-vault view vault.yml" + "!ansible-vault view vault.yaml" ] }, { @@ -226,10 +292,11 @@ "metadata": {}, "outputs": [], "source": [ - "!ansible -m ping all -e@vault.yml" + "!ansible -m ping all -e@vault.yaml" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -249,19 +316,28 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## SSH Authentication\n", "\n", - "We want to switch from password to ssh authentication. Create a playbook to install ssh keys: it reads the password from vault.yml\n" + "We want to switch from password to ssh authentication. Create a playbook to install ssh keys: it reads the password from vault.yaml\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cat: copy-key.yml: File o directory non esistente\n" + ] + } + ], "source": [ "!cat copy-key.yml" ] @@ -285,6 +361,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "shown", @@ -325,17 +402,20 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "\n", "Run ansible in verbose mode to se all the injected ssh argument. If the output is too verbose, reduce it either with:\n", - " - `--limit ipaddress` to contact only one node\n", - " - host indexing/subscript eg: `all[0]` " + "\n", + "- `--limit ipaddress` to contact only one node\n", + "- host indexing/subscript eg: `all[0]` " ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/diagrams.md b/ansible-101/notebooks/diagrams.md index 86409ff..1f38588 100644 --- a/ansible-101/notebooks/diagrams.md +++ b/ansible-101/notebooks/diagrams.md @@ -1,3 +1,34 @@ +# Docker connectors + + +```mermaid +graph LR + +subgraph docker[docker fab:fa-docker] +subgraph pad[ ] +c1[container1 fa:fa-cube] +c2[container2 fa:fa-cube] +s1((IP 1 fa:fa-network-wired)) +s2((IP 2 fa:fa-network-wired)) +end +dockerds((docker\nIP fa:fa-network-wired)) +dockerd[[Docker\nserver\n fa:fa-cogs fab:fa-docker]] +end +s1 -.-> c1 +s2 -.-> c2 + +subgraph ansible_connection +ssh-inventory[ssh module fa:fa-lock] +docker-inventory[docker module fab:fa-docker] +end + +ssh-inventory -->|ssh| s1 & s2 +docker-inventory -->|docker| dockerds +dockerds -->dockerd +c1 & c2 ---|<| dockerd + +``` + # Ansible architecture ```mermaid diff --git a/ansible-101/notebooks/exercise-01/.pin b/ansible-101/notebooks/exercise-01/.pin deleted file mode 100644 index d97c5ea..0000000 --- a/ansible-101/notebooks/exercise-01/.pin +++ /dev/null @@ -1 +0,0 @@ -secret diff --git a/ansible-101/notebooks/exercise-01/inventory.docker b/ansible-101/notebooks/exercise-01/inventory.docker index 57ed669..35423e7 100644 --- a/ansible-101/notebooks/exercise-01/inventory.docker +++ b/ansible-101/notebooks/exercise-01/inventory.docker @@ -5,7 +5,10 @@ # password of the machines using the following command: # # ansible -i inventory.docker \ -# -m shell -a "echo 'root:password' | chpasswd" docker +# -m shell \ +# -a "echo 'root:{{root_password}}' | chpasswd" \ +# -e@vault.yml \ +# docker # [docker] ansible-101_web_[1:2] ansible_connection=docker diff --git a/ansible-101/notebooks/intro.ipynb b/ansible-101/notebooks/intro.ipynb index 5209432..ae81eee 100644 --- a/ansible-101/notebooks/intro.ipynb +++ b/ansible-101/notebooks/intro.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden" @@ -14,7 +13,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -60,7 +58,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -116,7 +113,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -135,7 +131,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -145,7 +140,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -157,7 +151,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -171,7 +164,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -192,7 +184,6 @@ "source": [] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -213,7 +204,6 @@ "source": [] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -261,21 +251,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 2", "language": "python", - "name": "python3" + "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.9" + "pygments_lexer": "ipython2", + "version": "2.7.14" } }, "nbformat": 4, From c52f14b1b98cc4f1353fa9dc5439950f3a4f415e Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 15 May 2023 18:25:37 +0200 Subject: [PATCH 11/39] Fix lint. --- .../exercise-03/get-facts-solution.yml | 26 ++++++++++++++++ .../notebooks/exercise-03/get-facts.yml | 31 +++++++++++-------- 2 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 ansible-101/notebooks/exercise-03/get-facts-solution.yml diff --git a/ansible-101/notebooks/exercise-03/get-facts-solution.yml b/ansible-101/notebooks/exercise-03/get-facts-solution.yml new file mode 100644 index 0000000..131ed15 --- /dev/null +++ b/ansible-101/notebooks/exercise-03/get-facts-solution.yml @@ -0,0 +1,26 @@ +# +# Use this playbook to dump ansible facts +# +- hosts: localhost + name: > + Use this section to complete the exercise, + and the next section as a reference for + the debug module. + tasks: + - name: "Dump the requested facts." + debug: + msg: "A string" + - name: Hostname + debug: + msg: >- + {{ ansible_hostname }} + - name: First ip address + debug: + msg: >- + {{ ansible_all_ipv4_addresses[0] }} + - name: Distribution + debug: + msg: "{{ ansible_distribution }}" + - name: Kernel release + debug: + msg: "{{ ansible_kernel }}" diff --git a/ansible-101/notebooks/exercise-03/get-facts.yml b/ansible-101/notebooks/exercise-03/get-facts.yml index 24125eb..f1a4981 100644 --- a/ansible-101/notebooks/exercise-03/get-facts.yml +++ b/ansible-101/notebooks/exercise-03/get-facts.yml @@ -7,8 +7,9 @@ and the next section as a reference for the debug module. tasks: - - name: Dump the requested facts. - debug: msg="A string" + - name: Dump the requested facts. + debug: + msg: "A string" # @@ -17,17 +18,21 @@ - hosts: localhost name: Those tasks are run on localhost only tasks: - - name: This is the debug module. - debug: msg="A string" + - name: This is the debug module. + debug: + msg: "A string" - - name: The debug module can print variables too - debug: var=ansible_hostname + - name: The debug module can print variables too + debug: + var: ansible_hostname - - name: We can iterate too - debug: msg="{{item}}" - with_items: "{{ansible_system_capabilities}}" + - name: We can iterate too... + debug: + msg: "{{ item }}" + with_items: "{{ ansible_system_capabilities }}" - - name: and inspect/format variables - debug: msg="The device is {{item.device}}" - with_items: > - {{ansible_mounts}} + - name: ..and inspect/format variables + debug: + msg: "The device is {{ item.device }}" + with_items: > + {{ ansible_mounts }} From 2a963cc16402f036c31b777e5b6571bdf6c9918f Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 15 May 2023 19:16:29 +0200 Subject: [PATCH 12/39] vars and facts. --- .../notebooks/exercise-03/cartesian.yml | 15 ++++---- .../notebooks/exercise-03/conditions.yml | 23 ++++++----- .../notebooks/exercise-03/environment.yml | 11 +++--- .../notebooks/exercise-03/fileglob.yml | 29 +++++++------- .../exercise-03/get-facts-solution.yml | 5 ++- .../notebooks/exercise-03/get-facts.yml | 8 ++-- .../exercise-03/vars-and-facts-solution.yml | 38 +++++++++++++++++++ .../notebooks/exercise-03/vars-and-facts.yml | 36 +++++++++--------- 8 files changed, 103 insertions(+), 62 deletions(-) create mode 100644 ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml diff --git a/ansible-101/notebooks/exercise-03/cartesian.yml b/ansible-101/notebooks/exercise-03/cartesian.yml index 2d679b9..4ab37f5 100644 --- a/ansible-101/notebooks/exercise-03/cartesian.yml +++ b/ansible-101/notebooks/exercise-03/cartesian.yml @@ -1,3 +1,4 @@ +--- # # Ansible can generate cartesian products # which are useful for checking @@ -5,10 +6,10 @@ # - hosts: localhost tasks: - - name: Here is a cartesian product - debug: - msg: > - {{ 'Installing ' + item[0] + "-" + item[1] }} - with_cartesian: - - ["python", "python3"] - - [ "tox", "nose", "dnspython" ] + - name: Here is a cartesian product + debug: + msg: > + {{ 'Installing ' + item[0] + "-" + item[1] }} + with_cartesian: + - [python, python3] + - [tox, nose, dnspython] diff --git a/ansible-101/notebooks/exercise-03/conditions.yml b/ansible-101/notebooks/exercise-03/conditions.yml index 271d84d..1eb50e0 100644 --- a/ansible-101/notebooks/exercise-03/conditions.yml +++ b/ansible-101/notebooks/exercise-03/conditions.yml @@ -1,24 +1,23 @@ - +--- - hosts: localhost tags: when tasks: - - debug: msg="This always happens" - when: true - - debug: msg="This never does" - when: false + - debug: msg="This always happens" + when: true + - debug: msg="This never does" + when: false - hosts: localhost tags: assert tasks: - - debug: msg="This is Linux!" - when: ansible_system == 'Linux' - - - fail: msg="Stop processing now!" - when: ansible_architecture == 'x86_64' + - debug: msg="This is Linux!" + when: ansible_system == 'Linux' + - fail: msg="Stop processing now!" + when: ansible_architecture == 'x86_64' - hosts: localhost tags: exercise tasks: - - debug: msg="Replace me" - when: true + - debug: msg="Replace me" + when: true diff --git a/ansible-101/notebooks/exercise-03/environment.yml b/ansible-101/notebooks/exercise-03/environment.yml index 92f0d78..5ef9d13 100644 --- a/ansible-101/notebooks/exercise-03/environment.yml +++ b/ansible-101/notebooks/exercise-03/environment.yml @@ -1,8 +1,9 @@ +--- - hosts: localhost tasks: - - name: Iterate thru environment - debug: - var: > - ansible_env.{{item}} - with_items: > + - name: Iterate thru environment + debug: + var: > + ansible_env.{{item}} + with_items: > {{ansible_env | map('regex_search', '^PATH') | select('string') | list }} diff --git a/ansible-101/notebooks/exercise-03/fileglob.yml b/ansible-101/notebooks/exercise-03/fileglob.yml index 874070c..a698e06 100644 --- a/ansible-101/notebooks/exercise-03/fileglob.yml +++ b/ansible-101/notebooks/exercise-03/fileglob.yml @@ -1,15 +1,16 @@ +--- - hosts: web tags: fileglob tasks: - - name: You can implement a remote fileglob in 2 steps - shell: > - ls /etc/host* - register: fileglob_remote + - name: You can implement a remote fileglob in 2 steps + shell: > + ls /etc/host* + register: fileglob_remote - - name: Here we go - debug: msg="{{item}}" - with_items: > - {{fileglob_remote.stdout_lines}} + - name: Here we go + debug: msg="{{item}}" + with_items: > + {{fileglob_remote.stdout_lines}} - hosts: web, localhost @@ -17,9 +18,9 @@ environment: WELCOME: Benvenuti a Rimini! tasks: - - name: Passing a shell variable to the whole play - shell: > - echo $WELCOME - register: o - - name: EuroPython is here - debug: var=o.stdout + - name: Passing a shell variable to the whole play + shell: > + echo $WELCOME + register: o + - name: EuroPython is here + debug: var=o.stdout diff --git a/ansible-101/notebooks/exercise-03/get-facts-solution.yml b/ansible-101/notebooks/exercise-03/get-facts-solution.yml index 131ed15..b89fba1 100644 --- a/ansible-101/notebooks/exercise-03/get-facts-solution.yml +++ b/ansible-101/notebooks/exercise-03/get-facts-solution.yml @@ -1,3 +1,4 @@ +--- # # Use this playbook to dump ansible facts # @@ -7,9 +8,9 @@ and the next section as a reference for the debug module. tasks: - - name: "Dump the requested facts." + - name: Dump the requested facts. debug: - msg: "A string" + msg: A string - name: Hostname debug: msg: >- diff --git a/ansible-101/notebooks/exercise-03/get-facts.yml b/ansible-101/notebooks/exercise-03/get-facts.yml index f1a4981..afb9dd0 100644 --- a/ansible-101/notebooks/exercise-03/get-facts.yml +++ b/ansible-101/notebooks/exercise-03/get-facts.yml @@ -1,3 +1,4 @@ +--- # # Use this playbook to dump ansible facts # @@ -9,8 +10,7 @@ tasks: - name: Dump the requested facts. debug: - msg: "A string" - + msg: A string # # Read this for reference @@ -20,7 +20,7 @@ tasks: - name: This is the debug module. debug: - msg: "A string" + msg: A string - name: The debug module can print variables too debug: @@ -33,6 +33,6 @@ - name: ..and inspect/format variables debug: - msg: "The device is {{ item.device }}" + msg: The device is {{ item.device }} with_items: > {{ ansible_mounts }} diff --git a/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml b/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml new file mode 100644 index 0000000..c9afb5f --- /dev/null +++ b/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml @@ -0,0 +1,38 @@ +--- +- hosts: localhost + tags: variables + vars: + - one: 1 + - pi: 3.1415 + tasks: + - debug: + msg: > + {{ansible_hostname }} {{ one }} + - debug: + msg: > + The output is {{ one + pi }} + + +- hosts: localhost + tags: filters + vars: + - one: 1 + - pi: 3.1415 + tasks: + - name: Ansible can process expressions using filters + debug: + msg: > + Floor it {{ ( one + pi ) | int }} + +- hosts: localhost + tags: exercise + name: Use this cell for the exercise + tasks: + - name: > + Show the free percentage of the local disk using + facts and filters. Restricted to unique devices. + debug: + msg: > + {{item.device}} {{ (100 * item.size_available / item.size_total) | int }}% + with_items: >- + {{ ansible_mounts}} diff --git a/ansible-101/notebooks/exercise-03/vars-and-facts.yml b/ansible-101/notebooks/exercise-03/vars-and-facts.yml index 289edfc..4207a8a 100644 --- a/ansible-101/notebooks/exercise-03/vars-and-facts.yml +++ b/ansible-101/notebooks/exercise-03/vars-and-facts.yml @@ -2,33 +2,33 @@ - hosts: localhost tags: variables vars: - - one: 1 - - pi: 3.1415 + - one: 1 + - pi: 3.1415 tasks: - - debug: - msg: > - {{ansible_hostname }} {{ one }} - - debug: - msg: > - The output is {{ one + pi }} + - debug: + msg: > + {{ansible_hostname }} {{ one }} + - debug: + msg: > + The output is {{ one + pi }} - hosts: localhost tags: filters vars: - - one: 1 - - pi: 3.1415 + - one: 1 + - pi: 3.1415 tasks: - - name: Ansible can process expressions using filters - debug: - msg: > - Floor it {{ ( one + pi ) | int }} + - name: Ansible can process expressions using filters + debug: + msg: > + Floor it {{ ( one + pi ) | int }} - hosts: localhost tags: exercise name: Use this cell for the exercise tasks: - - name: > - Show the free percentage of the local disk using - facts and filters - debug: msg="Replace me" + - name: > + Show the free percentage of the local disk using + facts and filters + debug: msg="Replace me" From 732cd559723752df20b8734e87a17638f928cfd2 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Tue, 16 May 2023 18:16:29 +0200 Subject: [PATCH 13/39] Use json-query for listing IPs. --- .../notebooks/03_facts_and_variables.ipynb | 1 - ansible-101/site-digitalocean.yml | 11 +- docker-101/02-docker.md | 2 +- docker-101/notebooks/01-docker.ipynb | 26 +- docker-101/notebooks/02-docker.ipynb | 109 +- docker-101/tox.ini | 2 +- git-101/notebooks/01-git.slides.html | 15318 ++++++++++++++++ 7 files changed, 15394 insertions(+), 75 deletions(-) create mode 100644 git-101/notebooks/01-git.slides.html diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 8875f72..a7485de 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 3b77449..2c9d833 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -46,13 +46,15 @@ - name: Dynamically add the new servers to the inventory. add_host: - hostname: "{{ item.data.droplet.networks.v4[0].ip_address }}" + hostname: >- + {{ item.data.droplet.networks.v4 | community.general.json_query(jq) | first }} groups: - do ansible_user: root host_key_checking: no with_items: "{{my_droplet.results}}" - + vars: + jq: "[?(@.type=='public')].ip_address" - name: Create a sample inventory file with the server ips. file: @@ -65,8 +67,10 @@ - lineinfile: path: /tmp/inventory.do line: > - {{ item.data.droplet.networks.v4[0].ip_address }} droplet_id={{item.data.droplet.id}} + {{ item.data.droplet.networks.v4 | community.general.json_query(jq) | first }} droplet_id={{item.data.droplet.id}} with_items: "{{my_droplet.results}}" + vars: + jq: "[?(@.type=='public')].ip_address" # # Configure the newly created machines @@ -97,7 +101,6 @@ state: restarted name: docker daemon_reload: yes - when: systemd_updated.changed - name: Check socket shell: | diff --git a/docker-101/02-docker.md b/docker-101/02-docker.md index 983badd..2772fdd 100644 --- a/docker-101/02-docker.md +++ b/docker-101/02-docker.md @@ -189,7 +189,7 @@ The Dockerfile is a text file that contains all the commands a user could call on the command line to assemble an image. ```dockerfile -FROM debian:7.8 +FROM debian:stable-slim MAINTAINER Piuma "piuma@piumalab.org" RUN apt-get update && apt-get -y install apache2 EXPOSE 80 diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb index d63b7c1..489aefa 100644 --- a/docker-101/notebooks/01-docker.ipynb +++ b/docker-101/notebooks/01-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "d1622201", + "id": "746e1975", "metadata": {}, "source": [ "# Docker 101\n", @@ -17,7 +17,7 @@ }, { "cell_type": "markdown", - "id": "c93e3b43", + "id": "f9cd05d0", "metadata": { "slideshow": { "slide_type": "slide" @@ -35,7 +35,7 @@ }, { "cell_type": "markdown", - "id": "25a5e40b", + "id": "f824fd53", "metadata": { "slideshow": { "slide_type": "slide" @@ -51,7 +51,7 @@ }, { "cell_type": "markdown", - "id": "aae78c63", + "id": "42552d18", "metadata": { "slideshow": { "slide_type": "slide" @@ -67,7 +67,7 @@ }, { "cell_type": "markdown", - "id": "de60e58f", + "id": "29333b51", "metadata": { "slideshow": { "slide_type": "slide" @@ -89,7 +89,7 @@ }, { "cell_type": "markdown", - "id": "636d87c1", + "id": "8f33b98f", "metadata": { "slideshow": { "slide_type": "slide" @@ -113,7 +113,7 @@ }, { "cell_type": "markdown", - "id": "038b5755", + "id": "ed52bb22", "metadata": { "slideshow": { "slide_type": "slide" @@ -139,7 +139,7 @@ }, { "cell_type": "markdown", - "id": "7bee342a", + "id": "67d20a1b", "metadata": { "slideshow": { "slide_type": "slide" @@ -160,7 +160,7 @@ }, { "cell_type": "markdown", - "id": "5c660c08", + "id": "c8d01195", "metadata": { "slideshow": { "slide_type": "subslide" @@ -174,7 +174,7 @@ }, { "cell_type": "markdown", - "id": "711982d2", + "id": "5816158e", "metadata": {}, "source": [ "----" @@ -182,7 +182,7 @@ }, { "cell_type": "markdown", - "id": "a07406b5", + "id": "193740ca", "metadata": { "slideshow": { "slide_type": "slide" @@ -208,7 +208,7 @@ }, { "cell_type": "markdown", - "id": "ca8aac3c", + "id": "dce46733", "metadata": { "slideshow": { "slide_type": "slide" @@ -224,7 +224,7 @@ }, { "cell_type": "markdown", - "id": "7aa111c2", + "id": "455f1217", "metadata": {}, "source": [ "---" diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb index ab18853..e065088 100644 --- a/docker-101/notebooks/02-docker.ipynb +++ b/docker-101/notebooks/02-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "a8fbf123", + "id": "dc612eda", "metadata": {}, "source": [ "## Inspect the Docker host\n", @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4bed24d1", + "id": "21b474be", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ed4edb97", + "id": "8fcd2e14", "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ { "cell_type": "code", "execution_count": null, - "id": "aaca4370", + "id": "d31c3250", "metadata": {}, "outputs": [], "source": [ @@ -45,7 +45,7 @@ }, { "cell_type": "markdown", - "id": "c0ad6e26", + "id": "f9f13604", "metadata": { "slideshow": { "slide_type": "slide" @@ -62,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "43ed1c9b", + "id": "fe3cb657", "metadata": {}, "outputs": [], "source": [ @@ -73,7 +73,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0e0745ae", + "id": "42716b2c", "metadata": {}, "outputs": [], "source": [ @@ -84,7 +84,7 @@ }, { "cell_type": "markdown", - "id": "2fa100df", + "id": "b6f2eb30", "metadata": { "slideshow": { "slide_type": "slide" @@ -105,7 +105,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c262edf0", + "id": "57b08db2", "metadata": {}, "outputs": [], "source": [ @@ -116,7 +116,7 @@ }, { "cell_type": "markdown", - "id": "e5a8ad4f", + "id": "46cb9d92", "metadata": {}, "source": [ "Download an image from the remote registry." @@ -125,18 +125,17 @@ { "cell_type": "code", "execution_count": null, - "id": "fba50f5c", + "id": "2cfd7064", "metadata": {}, "outputs": [], "source": [ "# Download the ubuntu image\n", - "!docker pull ubuntu:22.04\n", - " " + "!docker pull ubuntu:22.04\n" ] }, { "cell_type": "markdown", - "id": "fab9b00c", + "id": "43b274b6", "metadata": {}, "source": [ "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", @@ -148,7 +147,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5d9bd01f", + "id": "32a6d829", "metadata": {}, "outputs": [], "source": [ @@ -158,7 +157,7 @@ }, { "cell_type": "markdown", - "id": "8b071727", + "id": "85dc8c97", "metadata": {}, "source": [ "Then run the above commands to ensure that you are on another virtual hosts." @@ -167,7 +166,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0978cb56", + "id": "3cd8ba8f", "metadata": {}, "outputs": [], "source": [ @@ -180,7 +179,7 @@ }, { "cell_type": "markdown", - "id": "a79ffbe7", + "id": "93736886", "metadata": { "slideshow": { "slide_type": "slide" @@ -197,7 +196,7 @@ { "cell_type": "code", "execution_count": null, - "id": "189b15a9", + "id": "9799bb7d", "metadata": {}, "outputs": [], "source": [ @@ -207,7 +206,7 @@ }, { "cell_type": "markdown", - "id": "96f470e9", + "id": "9163c1d8", "metadata": {}, "source": [ "Can you retrieve the IP address in another way?\n", @@ -216,7 +215,7 @@ }, { "cell_type": "markdown", - "id": "56425673", + "id": "9e5a36a3", "metadata": { "slideshow": { "slide_type": "slide" @@ -233,7 +232,7 @@ { "cell_type": "code", "execution_count": null, - "id": "70148621", + "id": "a4a3dbde", "metadata": {}, "outputs": [], "source": [ @@ -243,7 +242,7 @@ }, { "cell_type": "markdown", - "id": "b96b1008", + "id": "18cf86c5", "metadata": { "slideshow": { "slide_type": "slide" @@ -260,7 +259,7 @@ { "cell_type": "code", "execution_count": null, - "id": "88c6655a", + "id": "6e0258a4", "metadata": { "attributes": { "classes": [ @@ -285,7 +284,7 @@ }, { "cell_type": "markdown", - "id": "7a552578", + "id": "90effc1d", "metadata": {}, "source": [ "You can inspect containers" @@ -294,7 +293,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cfaa44de", + "id": "465445e2", "metadata": { "attributes": { "classes": [ @@ -317,7 +316,7 @@ }, { "cell_type": "markdown", - "id": "b5c88d3b", + "id": "07b32264", "metadata": {}, "source": [ "#### Exercise\n", @@ -328,7 +327,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6b6b4ca6", + "id": "27ad1435", "metadata": {}, "outputs": [], "source": [ @@ -337,7 +336,7 @@ }, { "cell_type": "markdown", - "id": "a3c4b2df", + "id": "1cec6a1c", "metadata": {}, "source": [ "2a. Inspect the `ansible-101_bastion_1` container.\n", @@ -347,7 +346,7 @@ { "cell_type": "code", "execution_count": null, - "id": "16edfe2c", + "id": "5bd63f74", "metadata": {}, "outputs": [], "source": [ @@ -356,7 +355,7 @@ }, { "cell_type": "markdown", - "id": "d288124c", + "id": "d57fc893", "metadata": { "slideshow": { "slide_type": "slide" @@ -386,7 +385,7 @@ }, { "cell_type": "markdown", - "id": "df26a81d", + "id": "28368959", "metadata": { "slideshow": { "slide_type": "subslide" @@ -402,7 +401,7 @@ { "cell_type": "code", "execution_count": null, - "id": "51af0612", + "id": "3f21f792", "metadata": { "attributes": { "classes": [ @@ -423,7 +422,7 @@ }, { "cell_type": "markdown", - "id": "b14a2427", + "id": "7f8fc456", "metadata": { "slideshow": { "slide_type": "slide" @@ -441,7 +440,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e04a0531", + "id": "34f52f8b", "metadata": { "attributes": { "classes": [ @@ -452,7 +451,7 @@ }, "outputs": [], "source": [ - "FROM debian:7.8\n", + "FROM debian:stable-slim\n", "MAINTAINER Piuma \"piuma@piumalab.org\"\n", "RUN apt-get update && apt-get -y install apache2\n", "EXPOSE 80\n", @@ -461,7 +460,7 @@ }, { "cell_type": "markdown", - "id": "e99985fe", + "id": "fd765428", "metadata": {}, "source": [ "Docker will execute all the commands in the Dockerfile and create a new image." @@ -470,7 +469,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0fb83c34", + "id": "df96a21b", "metadata": {}, "outputs": [], "source": [ @@ -479,7 +478,7 @@ }, { "cell_type": "markdown", - "id": "8205f6df", + "id": "ca0ab3af", "metadata": { "slideshow": { "slide_type": "slide" @@ -500,7 +499,7 @@ }, { "cell_type": "markdown", - "id": "4191d72f", + "id": "3dde296b", "metadata": { "slideshow": { "slide_type": "subslide" @@ -523,7 +522,7 @@ }, { "cell_type": "markdown", - "id": "d37afab8", + "id": "c522c0ba", "metadata": { "slideshow": { "slide_type": "subslide" @@ -540,7 +539,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d4692986", + "id": "bdd63fb2", "metadata": { "attributes": { "classes": [ @@ -568,7 +567,7 @@ }, { "cell_type": "markdown", - "id": "481813f5", + "id": "523baed8", "metadata": {}, "source": [ "Now run docker-compose up and Compose will start and run your entire app.\n", @@ -582,7 +581,7 @@ { "cell_type": "code", "execution_count": null, - "id": "09d7b2da", + "id": "2e03601c", "metadata": {}, "outputs": [], "source": [ @@ -592,7 +591,7 @@ }, { "cell_type": "markdown", - "id": "aca5db1c", + "id": "3545f93c", "metadata": { "slideshow": { "slide_type": "slide" @@ -607,7 +606,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c24b5239", + "id": "e4e4d77a", "metadata": {}, "outputs": [], "source": [ @@ -621,7 +620,7 @@ }, { "cell_type": "markdown", - "id": "3dd28183", + "id": "c0c7a41e", "metadata": { "slideshow": { "slide_type": "subslide" @@ -636,7 +635,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5d1b7da6", + "id": "0fa1d43e", "metadata": { "attributes": { "classes": [ @@ -664,7 +663,7 @@ }, { "cell_type": "markdown", - "id": "a2a7b44c", + "id": "efa64860", "metadata": { "slideshow": { "slide_type": "subslide" @@ -679,7 +678,7 @@ { "cell_type": "code", "execution_count": null, - "id": "45e0ab9d", + "id": "96af8b25", "metadata": {}, "outputs": [], "source": [ @@ -703,7 +702,7 @@ }, { "cell_type": "markdown", - "id": "bbd2b44d", + "id": "fc082e1f", "metadata": { "slideshow": { "slide_type": "subslide" @@ -718,7 +717,7 @@ { "cell_type": "code", "execution_count": null, - "id": "732bcd89", + "id": "7e298968", "metadata": {}, "outputs": [], "source": [ @@ -738,7 +737,7 @@ }, { "cell_type": "markdown", - "id": "276f4050", + "id": "40ef4e37", "metadata": { "slideshow": { "slide_type": "slide" @@ -753,7 +752,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5b123ec2", + "id": "ee290e57", "metadata": {}, "outputs": [], "source": [ @@ -762,7 +761,7 @@ }, { "cell_type": "markdown", - "id": "2b0eafd0", + "id": "f5293886", "metadata": {}, "source": [ "---" diff --git a/docker-101/tox.ini b/docker-101/tox.ini index 268e6e7..cee54b2 100644 --- a/docker-101/tox.ini +++ b/docker-101/tox.ini @@ -5,7 +5,7 @@ skipsdist = True [testenv] deps = git+https://github.com/ioggstream/notedown -whitelist_externals = +allowlist_externals = make commands = make diff --git a/git-101/notebooks/01-git.slides.html b/git-101/notebooks/01-git.slides.html new file mode 100644 index 0000000..1c72edd --- /dev/null +++ b/git-101/notebooks/01-git.slides.html @@ -0,0 +1,15318 @@ + + + + + + + + + +01-git slides + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + From ecdbb752c903735354c194508f5657e1271002d3 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 17 May 2023 09:06:48 +0200 Subject: [PATCH 14/39] update docker-101 --- docker-101/01-docker.md | 21 +----- docker-101/notebooks/01-docker.ipynb | 73 ++++--------------- docker-101/notebooks/02-docker.ipynb | 104 +++++++++++++-------------- 3 files changed, 67 insertions(+), 131 deletions(-) diff --git a/docker-101/01-docker.md b/docker-101/01-docker.md index 644e54b..c7b6c69 100644 --- a/docker-101/01-docker.md +++ b/docker-101/01-docker.md @@ -16,24 +16,13 @@ To resolve a necessity Mobility workload in cloud systems ---- - -### Cargo transport pre-1960 - -![text](slides/image/cargo-transport-pre-1960.png) - ---- - -### Solution: Intermodal Shipping Container - -![text](slides/image/standard_container.jpg) +- Cargo transport pre-1960 +- Solution: Intermodal Shipping Container --- ### Docker is a Container System for Code -![text](slides/image/container.png) - Docker leverages LXC (Linux Containers), which encompasses Linux features like cgroups and namespaces for strong process isolation and resource control. @@ -105,9 +94,3 @@ They are lightweight and consume less resources than a virtual machine. - monitoring --- - -## Difference between docker and virtual machine - -![text](slides/image/VM-Diagram.png) - ---- diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb index 489aefa..743bbd4 100644 --- a/docker-101/notebooks/01-docker.ipynb +++ b/docker-101/notebooks/01-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "746e1975", + "id": "15a5b48e", "metadata": {}, "source": [ "# Docker 101\n", @@ -17,7 +17,7 @@ }, { "cell_type": "markdown", - "id": "f9cd05d0", + "id": "bf995d0a", "metadata": { "slideshow": { "slide_type": "slide" @@ -30,44 +30,15 @@ "\n", "To resolve a necessity\n", "\n", - "Mobility workload in cloud systems" - ] - }, - { - "cell_type": "markdown", - "id": "f824fd53", - "metadata": { - "slideshow": { - "slide_type": "slide" - } - }, - "source": [ - "---\n", - "\n", - "### Cargo transport pre-1960\n", + "Mobility workload in cloud systems\n", "\n", - "![text](slides/image/cargo-transport-pre-1960.png)" + "- Cargo transport pre-1960\n", + "- Solution: Intermodal Shipping Container" ] }, { "cell_type": "markdown", - "id": "42552d18", - "metadata": { - "slideshow": { - "slide_type": "slide" - } - }, - "source": [ - "---\n", - "\n", - "### Solution: Intermodal Shipping Container\n", - "\n", - "![text](slides/image/standard_container.jpg)" - ] - }, - { - "cell_type": "markdown", - "id": "29333b51", + "id": "ed8cfa5e", "metadata": { "slideshow": { "slide_type": "slide" @@ -78,8 +49,6 @@ "\n", "### Docker is a Container System for Code\n", "\n", - "![text](slides/image/container.png)\n", - "\n", "Docker leverages LXC (Linux Containers), which encompasses Linux\n", "features like cgroups and namespaces for strong process isolation and\n", "resource control.\n", @@ -89,7 +58,7 @@ }, { "cell_type": "markdown", - "id": "8f33b98f", + "id": "b273230d", "metadata": { "slideshow": { "slide_type": "slide" @@ -113,7 +82,7 @@ }, { "cell_type": "markdown", - "id": "ed52bb22", + "id": "162e4fc0", "metadata": { "slideshow": { "slide_type": "slide" @@ -139,7 +108,7 @@ }, { "cell_type": "markdown", - "id": "67d20a1b", + "id": "d6252bc0", "metadata": { "slideshow": { "slide_type": "slide" @@ -160,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "c8d01195", + "id": "fc69394e", "metadata": { "slideshow": { "slide_type": "subslide" @@ -174,7 +143,7 @@ }, { "cell_type": "markdown", - "id": "5816158e", + "id": "ec969156", "metadata": {}, "source": [ "----" @@ -182,7 +151,7 @@ }, { "cell_type": "markdown", - "id": "193740ca", + "id": "4301aa63", "metadata": { "slideshow": { "slide_type": "slide" @@ -208,23 +177,7 @@ }, { "cell_type": "markdown", - "id": "dce46733", - "metadata": { - "slideshow": { - "slide_type": "slide" - } - }, - "source": [ - "---\n", - "\n", - "## Difference between docker and virtual machine\n", - "\n", - "![text](slides/image/VM-Diagram.png)" - ] - }, - { - "cell_type": "markdown", - "id": "455f1217", + "id": "621bbc76", "metadata": {}, "source": [ "---" diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb index e065088..8a69d21 100644 --- a/docker-101/notebooks/02-docker.ipynb +++ b/docker-101/notebooks/02-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "dc612eda", + "id": "350125bd", "metadata": {}, "source": [ "## Inspect the Docker host\n", @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": null, - "id": "21b474be", + "id": "a79dffce", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8fcd2e14", + "id": "49102cf0", "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d31c3250", + "id": "1d69ab76", "metadata": {}, "outputs": [], "source": [ @@ -45,7 +45,7 @@ }, { "cell_type": "markdown", - "id": "f9f13604", + "id": "5805bc05", "metadata": { "slideshow": { "slide_type": "slide" @@ -62,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fe3cb657", + "id": "f7e0116a", "metadata": {}, "outputs": [], "source": [ @@ -73,7 +73,7 @@ { "cell_type": "code", "execution_count": null, - "id": "42716b2c", + "id": "ecd4347e", "metadata": {}, "outputs": [], "source": [ @@ -84,7 +84,7 @@ }, { "cell_type": "markdown", - "id": "b6f2eb30", + "id": "e61881d2", "metadata": { "slideshow": { "slide_type": "slide" @@ -105,7 +105,7 @@ { "cell_type": "code", "execution_count": null, - "id": "57b08db2", + "id": "dd3c640b", "metadata": {}, "outputs": [], "source": [ @@ -116,7 +116,7 @@ }, { "cell_type": "markdown", - "id": "46cb9d92", + "id": "254d2a48", "metadata": {}, "source": [ "Download an image from the remote registry." @@ -125,7 +125,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2cfd7064", + "id": "252945d7", "metadata": {}, "outputs": [], "source": [ @@ -135,7 +135,7 @@ }, { "cell_type": "markdown", - "id": "43b274b6", + "id": "d6ee9e8f", "metadata": {}, "source": [ "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", @@ -147,7 +147,7 @@ { "cell_type": "code", "execution_count": null, - "id": "32a6d829", + "id": "4434533d", "metadata": {}, "outputs": [], "source": [ @@ -157,7 +157,7 @@ }, { "cell_type": "markdown", - "id": "85dc8c97", + "id": "77dddb0b", "metadata": {}, "source": [ "Then run the above commands to ensure that you are on another virtual hosts." @@ -166,7 +166,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3cd8ba8f", + "id": "ff33f2de", "metadata": {}, "outputs": [], "source": [ @@ -179,7 +179,7 @@ }, { "cell_type": "markdown", - "id": "93736886", + "id": "c36a9fae", "metadata": { "slideshow": { "slide_type": "slide" @@ -196,7 +196,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9799bb7d", + "id": "aed1a523", "metadata": {}, "outputs": [], "source": [ @@ -206,7 +206,7 @@ }, { "cell_type": "markdown", - "id": "9163c1d8", + "id": "5df65bff", "metadata": {}, "source": [ "Can you retrieve the IP address in another way?\n", @@ -215,7 +215,7 @@ }, { "cell_type": "markdown", - "id": "9e5a36a3", + "id": "55a25019", "metadata": { "slideshow": { "slide_type": "slide" @@ -232,7 +232,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a4a3dbde", + "id": "c16d2285", "metadata": {}, "outputs": [], "source": [ @@ -242,7 +242,7 @@ }, { "cell_type": "markdown", - "id": "18cf86c5", + "id": "4f615fc5", "metadata": { "slideshow": { "slide_type": "slide" @@ -259,7 +259,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6e0258a4", + "id": "7ecb6360", "metadata": { "attributes": { "classes": [ @@ -284,7 +284,7 @@ }, { "cell_type": "markdown", - "id": "90effc1d", + "id": "361d2779", "metadata": {}, "source": [ "You can inspect containers" @@ -293,7 +293,7 @@ { "cell_type": "code", "execution_count": null, - "id": "465445e2", + "id": "21a7bacb", "metadata": { "attributes": { "classes": [ @@ -316,7 +316,7 @@ }, { "cell_type": "markdown", - "id": "07b32264", + "id": "4002d76f", "metadata": {}, "source": [ "#### Exercise\n", @@ -327,7 +327,7 @@ { "cell_type": "code", "execution_count": null, - "id": "27ad1435", + "id": "c6536de7", "metadata": {}, "outputs": [], "source": [ @@ -336,7 +336,7 @@ }, { "cell_type": "markdown", - "id": "1cec6a1c", + "id": "c49a4766", "metadata": {}, "source": [ "2a. Inspect the `ansible-101_bastion_1` container.\n", @@ -346,7 +346,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5bd63f74", + "id": "4527211f", "metadata": {}, "outputs": [], "source": [ @@ -355,7 +355,7 @@ }, { "cell_type": "markdown", - "id": "d57fc893", + "id": "84a4248f", "metadata": { "slideshow": { "slide_type": "slide" @@ -385,7 +385,7 @@ }, { "cell_type": "markdown", - "id": "28368959", + "id": "aeef9b1a", "metadata": { "slideshow": { "slide_type": "subslide" @@ -401,7 +401,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3f21f792", + "id": "7a7765cb", "metadata": { "attributes": { "classes": [ @@ -422,7 +422,7 @@ }, { "cell_type": "markdown", - "id": "7f8fc456", + "id": "101b66f1", "metadata": { "slideshow": { "slide_type": "slide" @@ -440,7 +440,7 @@ { "cell_type": "code", "execution_count": null, - "id": "34f52f8b", + "id": "29001131", "metadata": { "attributes": { "classes": [ @@ -460,7 +460,7 @@ }, { "cell_type": "markdown", - "id": "fd765428", + "id": "7c5f55f9", "metadata": {}, "source": [ "Docker will execute all the commands in the Dockerfile and create a new image." @@ -469,7 +469,7 @@ { "cell_type": "code", "execution_count": null, - "id": "df96a21b", + "id": "be0504aa", "metadata": {}, "outputs": [], "source": [ @@ -478,7 +478,7 @@ }, { "cell_type": "markdown", - "id": "ca0ab3af", + "id": "220702e2", "metadata": { "slideshow": { "slide_type": "slide" @@ -499,7 +499,7 @@ }, { "cell_type": "markdown", - "id": "3dde296b", + "id": "4eb0a2b2", "metadata": { "slideshow": { "slide_type": "subslide" @@ -522,7 +522,7 @@ }, { "cell_type": "markdown", - "id": "c522c0ba", + "id": "d4173c0d", "metadata": { "slideshow": { "slide_type": "subslide" @@ -539,7 +539,7 @@ { "cell_type": "code", "execution_count": null, - "id": "bdd63fb2", + "id": "2ba9453f", "metadata": { "attributes": { "classes": [ @@ -567,7 +567,7 @@ }, { "cell_type": "markdown", - "id": "523baed8", + "id": "47ce104a", "metadata": {}, "source": [ "Now run docker-compose up and Compose will start and run your entire app.\n", @@ -581,7 +581,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2e03601c", + "id": "8bd5d0ed", "metadata": {}, "outputs": [], "source": [ @@ -591,7 +591,7 @@ }, { "cell_type": "markdown", - "id": "3545f93c", + "id": "a22b0787", "metadata": { "slideshow": { "slide_type": "slide" @@ -606,7 +606,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e4e4d77a", + "id": "ee8ccf31", "metadata": {}, "outputs": [], "source": [ @@ -620,7 +620,7 @@ }, { "cell_type": "markdown", - "id": "c0c7a41e", + "id": "525fc958", "metadata": { "slideshow": { "slide_type": "subslide" @@ -635,7 +635,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0fa1d43e", + "id": "c6caa4af", "metadata": { "attributes": { "classes": [ @@ -663,7 +663,7 @@ }, { "cell_type": "markdown", - "id": "efa64860", + "id": "79ecea9b", "metadata": { "slideshow": { "slide_type": "subslide" @@ -678,7 +678,7 @@ { "cell_type": "code", "execution_count": null, - "id": "96af8b25", + "id": "623e233f", "metadata": {}, "outputs": [], "source": [ @@ -702,7 +702,7 @@ }, { "cell_type": "markdown", - "id": "fc082e1f", + "id": "e5be61ee", "metadata": { "slideshow": { "slide_type": "subslide" @@ -717,7 +717,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7e298968", + "id": "ad7ef3e3", "metadata": {}, "outputs": [], "source": [ @@ -737,7 +737,7 @@ }, { "cell_type": "markdown", - "id": "40ef4e37", + "id": "c06db7dd", "metadata": { "slideshow": { "slide_type": "slide" @@ -752,7 +752,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ee290e57", + "id": "811a3f7c", "metadata": {}, "outputs": [], "source": [ @@ -761,7 +761,7 @@ }, { "cell_type": "markdown", - "id": "f5293886", + "id": "72894dd9", "metadata": {}, "source": [ "---" From 71f8d8fde59e0f72448e25519fab597cc856d87c Mon Sep 17 00:00:00 2001 From: tucsolo Date: Wed, 17 May 2023 09:07:28 +0200 Subject: [PATCH 15/39] Disabled APT auto update in droplets for Ansible-101 (#60) --- ansible-101/cloudinit.txt | 12 ++++++++++++ ansible-101/site-digitalocean.yml | 1 + 2 files changed, 13 insertions(+) create mode 100644 ansible-101/cloudinit.txt diff --git a/ansible-101/cloudinit.txt b/ansible-101/cloudinit.txt new file mode 100644 index 0000000..0691fc7 --- /dev/null +++ b/ansible-101/cloudinit.txt @@ -0,0 +1,12 @@ +#!/bin/bash +# This is NOT a cloud-init file +# as https://docs.digitalocean.com/products/droplets/how-to/provide-user-data/ suggests, +# we may insert a payload script. + +# If we had cloud-init file, we could have used this: +# package_update: false +# package_upgrade: false + +# but we are simply rewriting this config file +echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades +echo "APT::Periodic::Unattended-Upgrade \"0\";" >> /etc/apt/apt.conf.d/20auto-upgrades diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 2c9d833..3187ed3 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -39,6 +39,7 @@ region: fra1 image: docker-18-04 wait_timeout: 500 + user_data: "{{ lookup('file', 'cloudinit.txt') }}" # b64encode is not needed in Ansible register: my_droplet with_items: - deleteme-1 From 1f96b29154e235bdf971f9f054acedd3bd2f80c3 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 17 May 2023 17:55:54 +0200 Subject: [PATCH 16/39] More text on prereq. --- .../notebooks/03_facts_and_variables.ipynb | 1166 ++++++++++++++++- docker-101/02-docker.md | 26 +- docker-101/notebooks/01-docker.ipynb | 20 +- docker-101/notebooks/02-docker.ipynb | 151 ++- git-101/01-git.md | 162 ++- git-101/notebooks/01-git.ipynb | 592 +++++++-- git-101/tox.ini | 2 +- 7 files changed, 1899 insertions(+), 220 deletions(-) diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index a7485de..54cf559 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -15,18 +15,1175 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/notebooks/exercise-03\n" + ] + } + ], "source": [ "cd /notebooks/exercise-03" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", + "\u001b[1;35msource\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[0;32mlocalhost | SUCCESS => {\u001b[0m\n", + "\u001b[0;32m \"ansible_facts\": {\u001b[0m\n", + "\u001b[0;32m \"ansible_all_ipv4_addresses\": [\u001b[0m\n", + "\u001b[0;32m \"172.17.0.2\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"ansible_all_ipv6_addresses\": [], \u001b[0m\n", + "\u001b[0;32m \"ansible_apparmor\": {\u001b[0m\n", + "\u001b[0;32m \"status\": \"disabled\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_architecture\": \"x86_64\", \u001b[0m\n", + "\u001b[0;32m \"ansible_bios_date\": \"11/28/2019\", \u001b[0m\n", + "\u001b[0;32m \"ansible_bios_version\": \"1.3.1\", \u001b[0m\n", + "\u001b[0;32m \"ansible_cmdline\": {\u001b[0m\n", + "\u001b[0;32m \"BOOT_IMAGE\": \"(hd0,gpt7)/vmlinuz-5.14.18-100.fc33.x86_64\", \u001b[0m\n", + "\u001b[0;32m \"quiet\": true, \u001b[0m\n", + "\u001b[0;32m \"rd.lvm.lv\": \"fedora_localhost-live/swap\", \u001b[0m\n", + "\u001b[0;32m \"resume\": \"/dev/mapper/fedora_localhost--live-swap\", \u001b[0m\n", + "\u001b[0;32m \"rhgb\": true, \u001b[0m\n", + "\u001b[0;32m \"ro\": true, \u001b[0m\n", + "\u001b[0;32m \"root\": \"/dev/mapper/fedora_localhost--live-root\", \u001b[0m\n", + "\u001b[0;32m \"systemd.unified_cgroup_hierarchy\": \"0\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_date_time\": {\u001b[0m\n", + "\u001b[0;32m \"date\": \"2023-05-15\", \u001b[0m\n", + "\u001b[0;32m \"day\": \"15\", \u001b[0m\n", + "\u001b[0;32m \"epoch\": \"1684168092\", \u001b[0m\n", + "\u001b[0;32m \"hour\": \"16\", \u001b[0m\n", + "\u001b[0;32m \"iso8601\": \"2023-05-15T16:28:12Z\", \u001b[0m\n", + "\u001b[0;32m \"iso8601_basic\": \"20230515T162812599788\", \u001b[0m\n", + "\u001b[0;32m \"iso8601_basic_short\": \"20230515T162812\", \u001b[0m\n", + "\u001b[0;32m \"iso8601_micro\": \"2023-05-15T16:28:12.599831Z\", \u001b[0m\n", + "\u001b[0;32m \"minute\": \"28\", \u001b[0m\n", + "\u001b[0;32m \"month\": \"05\", \u001b[0m\n", + "\u001b[0;32m \"second\": \"12\", \u001b[0m\n", + "\u001b[0;32m \"time\": \"16:28:12\", \u001b[0m\n", + "\u001b[0;32m \"tz\": \"UTC\", \u001b[0m\n", + "\u001b[0;32m \"tz_offset\": \"+0000\", \u001b[0m\n", + "\u001b[0;32m \"weekday\": \"Monday\", \u001b[0m\n", + "\u001b[0;32m \"weekday_number\": \"1\", \u001b[0m\n", + "\u001b[0;32m \"weeknumber\": \"20\", \u001b[0m\n", + "\u001b[0;32m \"year\": \"2023\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_default_ipv4\": {\u001b[0m\n", + "\u001b[0;32m \"address\": \"172.17.0.2\", \u001b[0m\n", + "\u001b[0;32m \"alias\": \"eth0\", \u001b[0m\n", + "\u001b[0;32m \"broadcast\": \"172.17.255.255\", \u001b[0m\n", + "\u001b[0;32m \"gateway\": \"172.17.0.1\", \u001b[0m\n", + "\u001b[0;32m \"interface\": \"eth0\", \u001b[0m\n", + "\u001b[0;32m \"macaddress\": \"02:42:ac:11:00:02\", \u001b[0m\n", + "\u001b[0;32m \"mtu\": 1500, \u001b[0m\n", + "\u001b[0;32m \"netmask\": \"255.255.0.0\", \u001b[0m\n", + "\u001b[0;32m \"network\": \"172.17.0.0\", \u001b[0m\n", + "\u001b[0;32m \"type\": \"ether\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_default_ipv6\": {}, \u001b[0m\n", + "\u001b[0;32m \"ansible_device_links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": {}, \u001b[0m\n", + "\u001b[0;32m \"labels\": {}, \u001b[0m\n", + "\u001b[0;32m \"masters\": {\u001b[0m\n", + "\u001b[0;32m \"dm-3\": [\u001b[0m\n", + "\u001b[0;32m \"dm-4\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"nvme0n1p8\": [\u001b[0m\n", + "\u001b[0;32m \"dm-0\", \u001b[0m\n", + "\u001b[0;32m \"dm-1\", \u001b[0m\n", + "\u001b[0;32m \"dm-2\", \u001b[0m\n", + "\u001b[0;32m \"dm-3\"\u001b[0m\n", + "\u001b[0;32m ]\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"uuids\": {}\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_devices\": {\u001b[0m\n", + "\u001b[0;32m \"dm-0\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"177537024\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"84.66 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"dm-1\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"16777216\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"8.00 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"dm-2\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"567967744\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"270.83 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"dm-3\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [\u001b[0m\n", + "\u001b[0;32m \"luks-f770bef1-f11a-4d08-8103-9429f9fd25b0\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [\u001b[0m\n", + "\u001b[0;32m \"dm-4\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"55902208\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"26.66 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"dm-4\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"55869440\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"26.64 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop0\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"8\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"4.00 KB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop1\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"113896\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"55.61 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop10\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"716160\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"349.69 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop11\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"166424\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"81.26 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop12\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"187776\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"91.69 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop13\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"265904\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"129.84 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop14\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"22872\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"11.17 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop15\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"109032\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"53.24 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop16\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"22440\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"10.96 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop17\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"149720\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"73.11 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop18\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"229112\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"111.87 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop19\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"245848\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"120.04 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop2\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"149488\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"72.99 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop20\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"21680\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"10.59 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop21\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"109032\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"53.24 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop22\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"447264\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"218.39 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop23\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"716168\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"349.69 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop24\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"943224\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"460.56 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop25\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"129952\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"63.45 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop3\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"113944\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"55.64 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop4\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"0.00 Bytes\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop5\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"337560\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"164.82 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop6\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"337560\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"164.82 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop7\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"129712\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"63.34 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop8\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"447264\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"218.39 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"loop9\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"360104\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"175.83 MB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"nvme0n1\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": \"PC SN520 NVMe WDC 512GB\", \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"none\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"1000215216\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"476.94 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"zram0\": {\u001b[0m\n", + "\u001b[0;32m \"holders\": [], \u001b[0m\n", + "\u001b[0;32m \"host\": \"\", \u001b[0m\n", + "\u001b[0;32m \"links\": {\u001b[0m\n", + "\u001b[0;32m \"ids\": [], \u001b[0m\n", + "\u001b[0;32m \"labels\": [], \u001b[0m\n", + "\u001b[0;32m \"masters\": [], \u001b[0m\n", + "\u001b[0;32m \"uuids\": []\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"model\": null, \u001b[0m\n", + "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", + "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", + "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", + "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", + "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", + "\u001b[0;32m \"sectors\": \"8388608\", \u001b[0m\n", + "\u001b[0;32m \"sectorsize\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"size\": \"32.00 GB\", \u001b[0m\n", + "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", + "\u001b[0;32m \"vendor\": null, \u001b[0m\n", + "\u001b[0;32m \"virtual\": 1\u001b[0m\n", + "\u001b[0;32m }\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution\": \"Debian\", \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_file_parsed\": true, \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_file_path\": \"/etc/os-release\", \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_file_variety\": \"Debian\", \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_major_version\": \"8\", \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_release\": \"jessie\", \u001b[0m\n", + "\u001b[0;32m \"ansible_distribution_version\": \"8.10\", \u001b[0m\n", + "\u001b[0;32m \"ansible_dns\": {\u001b[0m\n", + "\u001b[0;32m \"nameservers\": [\u001b[0m\n", + "\u001b[0;32m \"8.8.8.8\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"search\": [\u001b[0m\n", + "\u001b[0;32m \"fritz.box\"\u001b[0m\n", + "\u001b[0;32m ]\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_domain\": \"\", \u001b[0m\n", + "\u001b[0;32m \"ansible_effective_group_id\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_effective_user_id\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_env\": {\u001b[0m\n", + "\u001b[0;32m \"CLICOLOR\": \"1\", \u001b[0m\n", + "\u001b[0;32m \"DOCKER_HOST\": \"172.17.0.1\", \u001b[0m\n", + "\u001b[0;32m \"GIT_PAGER\": \"cat\", \u001b[0m\n", + "\u001b[0;32m \"GPG_KEY\": \"C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF\", \u001b[0m\n", + "\u001b[0;32m \"HOME\": \"/root\", \u001b[0m\n", + "\u001b[0;32m \"HOSTNAME\": \"f063a33adb7a\", \u001b[0m\n", + "\u001b[0;32m \"JPY_PARENT_PID\": \"7\", \u001b[0m\n", + "\u001b[0;32m \"LANG\": \"C.UTF-8\", \u001b[0m\n", + "\u001b[0;32m \"MPLBACKEND\": \"module://ipykernel.pylab.backend_inline\", \u001b[0m\n", + "\u001b[0;32m \"PAGER\": \"cat\", \u001b[0m\n", + "\u001b[0;32m \"PATH\": \"/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\", \u001b[0m\n", + "\u001b[0;32m \"PWD\": \"/notebooks/exercise-03\", \u001b[0m\n", + "\u001b[0;32m \"PYTHON_PIP_VERSION\": \"9.0.1\", \u001b[0m\n", + "\u001b[0;32m \"PYTHON_VERSION\": \"2.7.14\", \u001b[0m\n", + "\u001b[0;32m \"TERM\": \"xterm-color\", \u001b[0m\n", + "\u001b[0;32m \"USE_HTTP\": \"1\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_eth0\": {\u001b[0m\n", + "\u001b[0;32m \"active\": true, \u001b[0m\n", + "\u001b[0;32m \"device\": \"eth0\", \u001b[0m\n", + "\u001b[0;32m \"ipv4\": {\u001b[0m\n", + "\u001b[0;32m \"address\": \"172.17.0.2\", \u001b[0m\n", + "\u001b[0;32m \"broadcast\": \"172.17.255.255\", \u001b[0m\n", + "\u001b[0;32m \"netmask\": \"255.255.0.0\", \u001b[0m\n", + "\u001b[0;32m \"network\": \"172.17.0.0\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"macaddress\": \"02:42:ac:11:00:02\", \u001b[0m\n", + "\u001b[0;32m \"mtu\": 1500, \u001b[0m\n", + "\u001b[0;32m \"promisc\": false, \u001b[0m\n", + "\u001b[0;32m \"speed\": 10000, \u001b[0m\n", + "\u001b[0;32m \"type\": \"ether\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_fips\": false, \u001b[0m\n", + "\u001b[0;32m \"ansible_form_factor\": \"unknown (31)\", \u001b[0m\n", + "\u001b[0;32m \"ansible_fqdn\": \"f063a33adb7a\", \u001b[0m\n", + "\u001b[0;32m \"ansible_hostname\": \"f063a33adb7a\", \u001b[0m\n", + "\u001b[0;32m \"ansible_interfaces\": [\u001b[0m\n", + "\u001b[0;32m \"lo\", \u001b[0m\n", + "\u001b[0;32m \"eth0\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"ansible_kernel\": \"5.14.18-100.fc33.x86_64\", \u001b[0m\n", + "\u001b[0;32m \"ansible_lo\": {\u001b[0m\n", + "\u001b[0;32m \"active\": true, \u001b[0m\n", + "\u001b[0;32m \"device\": \"lo\", \u001b[0m\n", + "\u001b[0;32m \"ipv4\": {\u001b[0m\n", + "\u001b[0;32m \"address\": \"127.0.0.1\", \u001b[0m\n", + "\u001b[0;32m \"broadcast\": \"host\", \u001b[0m\n", + "\u001b[0;32m \"netmask\": \"255.0.0.0\", \u001b[0m\n", + "\u001b[0;32m \"network\": \"127.0.0.0\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"mtu\": 65536, \u001b[0m\n", + "\u001b[0;32m \"promisc\": false, \u001b[0m\n", + "\u001b[0;32m \"type\": \"loopback\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_local\": {}, \u001b[0m\n", + "\u001b[0;32m \"ansible_lsb\": {}, \u001b[0m\n", + "\u001b[0;32m \"ansible_machine\": \"x86_64\", \u001b[0m\n", + "\u001b[0;32m \"ansible_machine_id\": \"8c859f2bde9e41155bca40d2d85aebb5\", \u001b[0m\n", + "\u001b[0;32m \"ansible_memfree_mb\": 176, \u001b[0m\n", + "\u001b[0;32m \"ansible_memory_mb\": {\u001b[0m\n", + "\u001b[0;32m \"nocache\": {\u001b[0m\n", + "\u001b[0;32m \"free\": 3953, \u001b[0m\n", + "\u001b[0;32m \"used\": 11824\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"real\": {\u001b[0m\n", + "\u001b[0;32m \"free\": 176, \u001b[0m\n", + "\u001b[0;32m \"total\": 15777, \u001b[0m\n", + "\u001b[0;32m \"used\": 15601\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"swap\": {\u001b[0m\n", + "\u001b[0;32m \"cached\": 18, \u001b[0m\n", + "\u001b[0;32m \"free\": 9748, \u001b[0m\n", + "\u001b[0;32m \"total\": 12287, \u001b[0m\n", + "\u001b[0;32m \"used\": 2539\u001b[0m\n", + "\u001b[0;32m }\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_memtotal_mb\": 15777, \u001b[0m\n", + "\u001b[0;32m \"ansible_mounts\": [\u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"ansible_nodename\": \"f063a33adb7a\", \u001b[0m\n", + "\u001b[0;32m \"ansible_os_family\": \"Debian\", \u001b[0m\n", + "\u001b[0;32m \"ansible_pkg_mgr\": \"apt\", \u001b[0m\n", + "\u001b[0;32m \"ansible_processor\": [\u001b[0m\n", + "\u001b[0;32m \"0\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"1\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"2\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"3\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"4\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"5\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"6\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", + "\u001b[0;32m \"7\", \u001b[0m\n", + "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", + "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"ansible_processor_cores\": 4, \u001b[0m\n", + "\u001b[0;32m \"ansible_processor_count\": 1, \u001b[0m\n", + "\u001b[0;32m \"ansible_processor_threads_per_core\": 2, \u001b[0m\n", + "\u001b[0;32m \"ansible_processor_vcpus\": 8, \u001b[0m\n", + "\u001b[0;32m \"ansible_product_name\": \"Inspiron 7391 2n1\", \u001b[0m\n", + "\u001b[0;32m \"ansible_product_serial\": \"BNV8KW2\", \u001b[0m\n", + "\u001b[0;32m \"ansible_product_uuid\": \"4c4c4544-004e-5610-8038-c2c04f4b5732\", \u001b[0m\n", + "\u001b[0;32m \"ansible_product_version\": \"NA\", \u001b[0m\n", + "\u001b[0;32m \"ansible_python\": {\u001b[0m\n", + "\u001b[0;32m \"executable\": \"/usr/local/bin/python\", \u001b[0m\n", + "\u001b[0;32m \"has_sslcontext\": true, \u001b[0m\n", + "\u001b[0;32m \"type\": \"CPython\", \u001b[0m\n", + "\u001b[0;32m \"version\": {\u001b[0m\n", + "\u001b[0;32m \"major\": 2, \u001b[0m\n", + "\u001b[0;32m \"micro\": 14, \u001b[0m\n", + "\u001b[0;32m \"minor\": 7, \u001b[0m\n", + "\u001b[0;32m \"releaselevel\": \"final\", \u001b[0m\n", + "\u001b[0;32m \"serial\": 0\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"version_info\": [\u001b[0m\n", + "\u001b[0;32m 2, \u001b[0m\n", + "\u001b[0;32m 7, \u001b[0m\n", + "\u001b[0;32m 14, \u001b[0m\n", + "\u001b[0;32m \"final\", \u001b[0m\n", + "\u001b[0;32m 0\u001b[0m\n", + "\u001b[0;32m ]\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_python_version\": \"2.7.14\", \u001b[0m\n", + "\u001b[0;32m \"ansible_real_group_id\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_real_user_id\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_selinux\": {\u001b[0m\n", + "\u001b[0;32m \"status\": \"Missing selinux Python library\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"ansible_selinux_python_present\": false, \u001b[0m\n", + "\u001b[0;32m \"ansible_service_mgr\": \"upstart\", \u001b[0m\n", + "\u001b[0;32m \"ansible_swapfree_mb\": 9748, \u001b[0m\n", + "\u001b[0;32m \"ansible_swaptotal_mb\": 12287, \u001b[0m\n", + "\u001b[0;32m \"ansible_system\": \"Linux\", \u001b[0m\n", + "\u001b[0;32m \"ansible_system_capabilities\": [\u001b[0m\n", + "\u001b[0;32m \"cap_chown\", \u001b[0m\n", + "\u001b[0;32m \"cap_dac_override\", \u001b[0m\n", + "\u001b[0;32m \"cap_fowner\", \u001b[0m\n", + "\u001b[0;32m \"cap_fsetid\", \u001b[0m\n", + "\u001b[0;32m \"cap_kill\", \u001b[0m\n", + "\u001b[0;32m \"cap_setgid\", \u001b[0m\n", + "\u001b[0;32m \"cap_setuid\", \u001b[0m\n", + "\u001b[0;32m \"cap_setpcap\", \u001b[0m\n", + "\u001b[0;32m \"cap_net_bind_service\", \u001b[0m\n", + "\u001b[0;32m \"cap_net_raw\", \u001b[0m\n", + "\u001b[0;32m \"cap_sys_chroot\", \u001b[0m\n", + "\u001b[0;32m \"cap_mknod\", \u001b[0m\n", + "\u001b[0;32m \"cap_audit_write\", \u001b[0m\n", + "\u001b[0;32m \"cap_setfcap+eip\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"ansible_system_capabilities_enforced\": \"True\", \u001b[0m\n", + "\u001b[0;32m \"ansible_system_vendor\": \"Dell Inc.\", \u001b[0m\n", + "\u001b[0;32m \"ansible_uptime_seconds\": 1691606, \u001b[0m\n", + "\u001b[0;32m \"ansible_user_dir\": \"/root\", \u001b[0m\n", + "\u001b[0;32m \"ansible_user_gecos\": \"root\", \u001b[0m\n", + "\u001b[0;32m \"ansible_user_gid\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_user_id\": \"root\", \u001b[0m\n", + "\u001b[0;32m \"ansible_user_shell\": \"/bin/bash\", \u001b[0m\n", + "\u001b[0;32m \"ansible_user_uid\": 0, \u001b[0m\n", + "\u001b[0;32m \"ansible_userspace_architecture\": \"x86_64\", \u001b[0m\n", + "\u001b[0;32m \"ansible_userspace_bits\": \"64\", \u001b[0m\n", + "\u001b[0;32m \"ansible_virtualization_role\": \"guest\", \u001b[0m\n", + "\u001b[0;32m \"ansible_virtualization_type\": \"docker\", \u001b[0m\n", + "\u001b[0;32m \"gather_subset\": [\u001b[0m\n", + "\u001b[0;32m \"all\"\u001b[0m\n", + "\u001b[0;32m ], \u001b[0m\n", + "\u001b[0;32m \"module_setup\": true\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"changed\": false\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n" + ] + } + ], "source": [ "# Let's run the setup module\n", "\n", @@ -34,7 +1191,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/docker-101/02-docker.md b/docker-101/02-docker.md index 2772fdd..0ca254a 100644 --- a/docker-101/02-docker.md +++ b/docker-101/02-docker.md @@ -30,7 +30,6 @@ Check docker tools. ```python # Docker server version - !dockerd --version ``` @@ -46,9 +45,7 @@ Let's pull and run an image ```python # Search images from catalog - !docker search ubuntu|head - ``` Download an image from the remote registry. @@ -56,7 +53,6 @@ Download an image from the remote registry. ```python # Download the ubuntu image !docker pull ubuntu:22.04 - ``` Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`) @@ -88,7 +84,7 @@ ip -4 -o a ``` Can you retrieve the IP address in another way? -Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`. +**Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`.** --- @@ -140,8 +136,8 @@ docker stats # shows metrics, memory, cpu, filsystem # Use this cell to run the correct docker command. ``` -2a. Inspect the `ansible-101_bastion_1` container. -2b. Use the `--format` option to get the IP address. Hint: you can google for the solution. +1. Inspect the `ansible-101_bastion_1` container. +1. Use the `--format` option to get the IP address. Hint: you can google for the solution. ```python # Use this cell to run the correct docker command. @@ -202,6 +198,22 @@ Docker will execute all the commands in the Dockerfile and create a new image. !docker build -t apache-example . ``` +Open the [terminal](/terminals/docker) and: + +- inspect the image +- run the image with + +```bash +docker run --rm --detach apache-example +``` + +- check the running container with `docker ps` +- use `curl` to check if the webserver works +- stop the container with `docker stop` +- check the running container with `docker ps` +- check the stopped container with `docker ps -a` +- remove the container with `docker rm` + --- ## docker-compose diff --git a/docker-101/notebooks/01-docker.ipynb b/docker-101/notebooks/01-docker.ipynb index 743bbd4..d2c5383 100644 --- a/docker-101/notebooks/01-docker.ipynb +++ b/docker-101/notebooks/01-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "15a5b48e", + "id": "bd72a566", "metadata": {}, "source": [ "# Docker 101\n", @@ -17,7 +17,7 @@ }, { "cell_type": "markdown", - "id": "bf995d0a", + "id": "819672e8", "metadata": { "slideshow": { "slide_type": "slide" @@ -38,7 +38,7 @@ }, { "cell_type": "markdown", - "id": "ed8cfa5e", + "id": "c8a2c20e", "metadata": { "slideshow": { "slide_type": "slide" @@ -58,7 +58,7 @@ }, { "cell_type": "markdown", - "id": "b273230d", + "id": "69ef6e0c", "metadata": { "slideshow": { "slide_type": "slide" @@ -82,7 +82,7 @@ }, { "cell_type": "markdown", - "id": "162e4fc0", + "id": "6fbc76a7", "metadata": { "slideshow": { "slide_type": "slide" @@ -108,7 +108,7 @@ }, { "cell_type": "markdown", - "id": "d6252bc0", + "id": "bfae8933", "metadata": { "slideshow": { "slide_type": "slide" @@ -129,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "fc69394e", + "id": "fed50018", "metadata": { "slideshow": { "slide_type": "subslide" @@ -143,7 +143,7 @@ }, { "cell_type": "markdown", - "id": "ec969156", + "id": "cd2f36a2", "metadata": {}, "source": [ "----" @@ -151,7 +151,7 @@ }, { "cell_type": "markdown", - "id": "4301aa63", + "id": "30d28c29", "metadata": { "slideshow": { "slide_type": "slide" @@ -177,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "621bbc76", + "id": "b1141f06", "metadata": {}, "source": [ "---" diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb index 8a69d21..8d9c86b 100644 --- a/docker-101/notebooks/02-docker.ipynb +++ b/docker-101/notebooks/02-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "350125bd", + "id": "a01a6b89", "metadata": {}, "source": [ "## Inspect the Docker host\n", @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a79dffce", + "id": "6093cdd8", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "49102cf0", + "id": "1de2c383", "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1d69ab76", + "id": "c02f1de0", "metadata": {}, "outputs": [], "source": [ @@ -45,7 +45,7 @@ }, { "cell_type": "markdown", - "id": "5805bc05", + "id": "8819937b", "metadata": { "slideshow": { "slide_type": "slide" @@ -62,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f7e0116a", + "id": "82ff3167", "metadata": {}, "outputs": [], "source": [ @@ -73,18 +73,17 @@ { "cell_type": "code", "execution_count": null, - "id": "ecd4347e", + "id": "b53c0828", "metadata": {}, "outputs": [], "source": [ "# Docker server version\n", - "\n", "!dockerd --version" ] }, { "cell_type": "markdown", - "id": "e61881d2", + "id": "775edbab", "metadata": { "slideshow": { "slide_type": "slide" @@ -105,18 +104,17 @@ { "cell_type": "code", "execution_count": null, - "id": "dd3c640b", + "id": "fc43ca83", "metadata": {}, "outputs": [], "source": [ "# Search images from catalog\n", - "\n", - "!docker search ubuntu|head\n" + "!docker search ubuntu|head" ] }, { "cell_type": "markdown", - "id": "254d2a48", + "id": "3cff75bb", "metadata": {}, "source": [ "Download an image from the remote registry." @@ -125,17 +123,17 @@ { "cell_type": "code", "execution_count": null, - "id": "252945d7", + "id": "a64d1a21", "metadata": {}, "outputs": [], "source": [ "# Download the ubuntu image\n", - "!docker pull ubuntu:22.04\n" + "!docker pull ubuntu:22.04" ] }, { "cell_type": "markdown", - "id": "d6ee9e8f", + "id": "103802a1", "metadata": {}, "source": [ "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", @@ -147,7 +145,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4434533d", + "id": "3743b57f", "metadata": {}, "outputs": [], "source": [ @@ -157,7 +155,7 @@ }, { "cell_type": "markdown", - "id": "77dddb0b", + "id": "6b1dca8e", "metadata": {}, "source": [ "Then run the above commands to ensure that you are on another virtual hosts." @@ -166,7 +164,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ff33f2de", + "id": "395c2403", "metadata": {}, "outputs": [], "source": [ @@ -179,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "c36a9fae", + "id": "1c9d3e78", "metadata": { "slideshow": { "slide_type": "slide" @@ -196,7 +194,7 @@ { "cell_type": "code", "execution_count": null, - "id": "aed1a523", + "id": "72e40858", "metadata": {}, "outputs": [], "source": [ @@ -206,16 +204,16 @@ }, { "cell_type": "markdown", - "id": "5df65bff", + "id": "762d26aa", "metadata": {}, "source": [ "Can you retrieve the IP address in another way?\n", - "Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`." + "**Hint: the `/proc` filesystem contains information about the system. Try to find the IP address in one of the files in `/proc`.**" ] }, { "cell_type": "markdown", - "id": "55a25019", + "id": "ef49f6c1", "metadata": { "slideshow": { "slide_type": "slide" @@ -232,7 +230,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c16d2285", + "id": "a9eb4484", "metadata": {}, "outputs": [], "source": [ @@ -242,7 +240,7 @@ }, { "cell_type": "markdown", - "id": "4f615fc5", + "id": "e79e15fe", "metadata": { "slideshow": { "slide_type": "slide" @@ -259,7 +257,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7ecb6360", + "id": "5b1d74f8", "metadata": { "attributes": { "classes": [ @@ -284,7 +282,7 @@ }, { "cell_type": "markdown", - "id": "361d2779", + "id": "193f7868", "metadata": {}, "source": [ "You can inspect containers" @@ -293,7 +291,7 @@ { "cell_type": "code", "execution_count": null, - "id": "21a7bacb", + "id": "1dde4d12", "metadata": { "attributes": { "classes": [ @@ -316,7 +314,7 @@ }, { "cell_type": "markdown", - "id": "4002d76f", + "id": "9dd9d674", "metadata": {}, "source": [ "#### Exercise\n", @@ -327,7 +325,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c6536de7", + "id": "fdaf1ecd", "metadata": {}, "outputs": [], "source": [ @@ -336,17 +334,17 @@ }, { "cell_type": "markdown", - "id": "c49a4766", + "id": "23e6c883", "metadata": {}, "source": [ - "2a. Inspect the `ansible-101_bastion_1` container.\n", - "2b. Use the `--format` option to get the IP address. Hint: you can google for the solution." + "1. Inspect the `ansible-101_bastion_1` container.\n", + "1. Use the `--format` option to get the IP address. Hint: you can google for the solution." ] }, { "cell_type": "code", "execution_count": null, - "id": "4527211f", + "id": "8053b13a", "metadata": {}, "outputs": [], "source": [ @@ -355,7 +353,7 @@ }, { "cell_type": "markdown", - "id": "84a4248f", + "id": "d10e46a9", "metadata": { "slideshow": { "slide_type": "slide" @@ -385,7 +383,7 @@ }, { "cell_type": "markdown", - "id": "aeef9b1a", + "id": "bd1ba26f", "metadata": { "slideshow": { "slide_type": "subslide" @@ -401,7 +399,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7a7765cb", + "id": "45ed0543", "metadata": { "attributes": { "classes": [ @@ -422,7 +420,7 @@ }, { "cell_type": "markdown", - "id": "101b66f1", + "id": "30197228", "metadata": { "slideshow": { "slide_type": "slide" @@ -440,7 +438,7 @@ { "cell_type": "code", "execution_count": null, - "id": "29001131", + "id": "42339314", "metadata": { "attributes": { "classes": [ @@ -460,7 +458,7 @@ }, { "cell_type": "markdown", - "id": "7c5f55f9", + "id": "f8577fe9", "metadata": {}, "source": [ "Docker will execute all the commands in the Dockerfile and create a new image." @@ -469,7 +467,7 @@ { "cell_type": "code", "execution_count": null, - "id": "be0504aa", + "id": "f86164a1", "metadata": {}, "outputs": [], "source": [ @@ -478,7 +476,42 @@ }, { "cell_type": "markdown", - "id": "220702e2", + "id": "5a47f022", + "metadata": {}, + "source": [ + "Open the [terminal](/terminals/docker) and:\n", + "\n", + "- inspect the image\n", + "- run the image with" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1488821c", + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "docker run --rm --detach apache-example" + ] + }, + { + "cell_type": "markdown", + "id": "57bd2970", + "metadata": {}, + "source": [ + "- check the running container with `docker ps`\n", + "- use `curl` to check if the webserver works\n", + "- stop the container with `docker stop`\n", + "- check the running container with `docker ps`\n", + "- check the stopped container with `docker ps -a`\n", + "- remove the container with `docker rm`" + ] + }, + { + "cell_type": "markdown", + "id": "f8d0f29d", "metadata": { "slideshow": { "slide_type": "slide" @@ -499,7 +532,7 @@ }, { "cell_type": "markdown", - "id": "4eb0a2b2", + "id": "10c52150", "metadata": { "slideshow": { "slide_type": "subslide" @@ -522,7 +555,7 @@ }, { "cell_type": "markdown", - "id": "d4173c0d", + "id": "7d6d3849", "metadata": { "slideshow": { "slide_type": "subslide" @@ -539,7 +572,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2ba9453f", + "id": "fe83cfc1", "metadata": { "attributes": { "classes": [ @@ -567,7 +600,7 @@ }, { "cell_type": "markdown", - "id": "47ce104a", + "id": "f3859dd3", "metadata": {}, "source": [ "Now run docker-compose up and Compose will start and run your entire app.\n", @@ -581,7 +614,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8bd5d0ed", + "id": "4ae4f092", "metadata": {}, "outputs": [], "source": [ @@ -591,7 +624,7 @@ }, { "cell_type": "markdown", - "id": "a22b0787", + "id": "27e0b0dc", "metadata": { "slideshow": { "slide_type": "slide" @@ -606,7 +639,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ee8ccf31", + "id": "4e8ace61", "metadata": {}, "outputs": [], "source": [ @@ -620,7 +653,7 @@ }, { "cell_type": "markdown", - "id": "525fc958", + "id": "9e81f374", "metadata": { "slideshow": { "slide_type": "subslide" @@ -635,7 +668,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c6caa4af", + "id": "4714eee9", "metadata": { "attributes": { "classes": [ @@ -663,7 +696,7 @@ }, { "cell_type": "markdown", - "id": "79ecea9b", + "id": "a420adc4", "metadata": { "slideshow": { "slide_type": "subslide" @@ -678,7 +711,7 @@ { "cell_type": "code", "execution_count": null, - "id": "623e233f", + "id": "fa6a114b", "metadata": {}, "outputs": [], "source": [ @@ -702,7 +735,7 @@ }, { "cell_type": "markdown", - "id": "e5be61ee", + "id": "5a4b46b8", "metadata": { "slideshow": { "slide_type": "subslide" @@ -717,7 +750,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ad7ef3e3", + "id": "2ec2f720", "metadata": {}, "outputs": [], "source": [ @@ -737,7 +770,7 @@ }, { "cell_type": "markdown", - "id": "c06db7dd", + "id": "4d8563b3", "metadata": { "slideshow": { "slide_type": "slide" @@ -752,7 +785,7 @@ { "cell_type": "code", "execution_count": null, - "id": "811a3f7c", + "id": "91fd8470", "metadata": {}, "outputs": [], "source": [ @@ -761,7 +794,7 @@ }, { "cell_type": "markdown", - "id": "72894dd9", + "id": "5d5cdd6c", "metadata": {}, "source": [ "---" diff --git a/git-101/01-git.md b/git-101/01-git.md index dcf9783..ba77430 100644 --- a/git-101/01-git.md +++ b/git-101/01-git.md @@ -2,10 +2,10 @@ ## Agenda - - VCS intro - - tracking modifications - - using a local git repository - - remote repositories +- VCS intro +- tracking modifications +- using a local git repository +- remote repositories *Beware*: commands contain small typos. You must fix them to properly complete the course! @@ -15,10 +15,10 @@ The importance of tracking changes. VCS basics: - - initialize a local repo - - change the software - - acknowledge (commit) changes - - eventually revert changes +- initialize a local repo +- change the software +- acknowledge (commit) changes +- eventually revert changes --- @@ -28,7 +28,7 @@ Track modifications of our config files without messing with the real /etc. ``` -! mkdir -p /repo-path +!mkdir -p /repo-path !cp -v /etc/host* /etc/s* /repo-path ``` @@ -47,7 +47,6 @@ Always timestamp backup copies, don't `.ori`. Exercise: Use `date +%s` to timestamp a backup copy of `hosts`. - ``` # Use this cell for the exercise. ``` @@ -62,10 +61,8 @@ Used to maintain the Linux Kernel. Distributed approach. - ![Checkout and Push](https://git-scm.com/figures/18333fig0106-tn.png) - --- ## Tracing requires identification @@ -93,15 +90,16 @@ Track modifications with `git` ### Exercise - - get the previous `git config ... user.email` - - remove the `--global` flag from the previous command - - run it +- get the previous `git config ... user.email` +- remove the `--global` flag from the previous command +- run it ``` # Write here the command # and show the git config file. !cat .git/config ``` + --- Enter in the repo directory and check the status: there @@ -128,7 +126,7 @@ Now we have all `host*` files to be tracked. Add files to the index ``` -! git add hosts +!git add hosts ``` The file is now *staged* for commit. It's not archived though. @@ -140,7 +138,7 @@ The file is now *staged* for commit. It's not archived though. Save files to the local index ``` -! git commit -m "Initial snapshot of hosts" +!git commit -m "Initial snapshot of hosts" ``` ![Git areas](https://git-scm.com/images/about/index1@2x.png) @@ -168,18 +166,18 @@ and finally save them in the repo. ``` !git commit "Added localhost2 to hosts" ``` + --- ## History changes Now we have an history with two changes, containing: - - commit messages - - a commit hash +- commit messages +- a commit hash HEAD is the last commit. - ``` !git log ``` @@ -193,7 +191,7 @@ HEAD is the last commit. We can revert a change using the hash or an history log ``` -! git checkout HEAD~1 -- hosts # revert hosts to the previous commit +!git checkout HEAD~1 -- hosts # revert hosts to the previous commit ``` --- @@ -203,10 +201,11 @@ We can revert a change using the hash or an history log Now some git commands, but first create a dir. ``` -! mkdir -p /repo-path +!mkdir -p /repo-path !date >> /repo-path/file.txt !date >> /repo-path/hi.txt ``` + --- ``` @@ -217,7 +216,7 @@ Now some git commands, but first create a dir. ### Exercise - - add `file.txt` to the index and commit +- add `file.txt` to the index and commit ``` # Use this cell for the exercise @@ -225,7 +224,6 @@ Now some git commands, but first create a dir. --- - ``` !date >> /repo-path/file.txt !git diff @@ -234,7 +232,6 @@ Now some git commands, but first create a dir. --- - ``` !git log /repo-path/file.txt # show changes ``` @@ -258,14 +255,14 @@ Now some git commands, but first create a dir. Writing codes and configuration we may want to follow different strategies and save our different attempts. - - *tag* makes an unmodifiable snapshot of the repo instead. +- *tag* makes an unmodifiable snapshot of the repo instead. ``` !git tag myconfig-v1 # create a tag !git tag -l # list tags ``` - - *branch* create a modifiable copy of the code, allowing +- *branch* create a modifiable copy of the code, allowing to save and work on different features ![Branches](https://git-scm.com/figures/18333fig0313-tn.png) @@ -341,10 +338,10 @@ And switch back ### Exercise - - Create a new branch named `antani` - - modify `new-file.txt` as you please - - open a terminal, and use `git add -p` to stage the changes. What does it do? - - commit the changes +- Create a new branch named `antani` +- modify `new-file.txt` as you please +- [open a terminal](/terminals/git), and use `git add -p` to stage the changes. What does it do? +- commit the changes ``` # Use this cell for the exercise @@ -368,23 +365,34 @@ You have to remove the changes or commit them (in another branch too) # Use this cell for the exercise. ``` - --- ## Merge -Once we have consolidated some changes (Eg. test, ...) +Once we have consolidated some changes (e.g., test, ...) we can *merge* the changes into the master branch ``` !git checkout master +``` + +Before merging, we have to check the differences + +``` !git diff work-on-my-changes +``` + +And finally merge + +``` !git merge work-on-my-changes ``` --- After a merge, if the branch is no more useful, we can remove it. +Note: before deleting a branch, you can double-check available +branches with `git branch -a`. ``` !git branch -d work-on-changes @@ -394,9 +402,9 @@ If there are unmerged changes, git doesn't allow deleting a branch. Exercise: - - use `git branch -d` to remove the `antani` branch - - what happens? - - replace `-d` with `-D`. Does it work now? +- use `git branch -d` to remove the `antani` branch +- what happens? +- replace `-d` with `-D`. Does it work now? ``` # use this cell for the exrcise @@ -413,16 +421,28 @@ You can stage partial changes with: !git add -p ``` - --- ## Remote repositories Remote repos may be either https, ssh or files. +``` +! mkdir -p /repo-tmp && cd /repo-tmp && pwd # use another directory ;) +``` + +Exercise: + +- what happens in the following cell? ``` -! mkdir -p /repo-tmp && cd /repo-tmp # use another directory +!pwd +``` + +Go to the correct directory now. + +``` +cd /repo-tmp ``` --- @@ -433,18 +453,23 @@ Git clone downloads a remote repo, with all its changes and history. Try with a remote https repo. ``` -! git clone https://github.com/ioggstream/python-course/ python-course -cd /repo-tmp/python-course +!git clone https://github.com/ioggstream/python-course/ python-course ``` -Show repository configuration. Remote origin. +Now enter in the repo directory ``` -! git config -l +cd /repo-tmp/python-course +``` +Show repository configuration. Which is the remote origin? + +``` +!git config -l ``` The remote repo is retrieved with all its changes and history + ``` ! du -ms .git ``` @@ -454,22 +479,28 @@ And `log` can show branches and merges. ``` !git log --graph ``` + --- ### file repo A local repo can be cloned too, and has the same features -of a remote one. It's actually a remote file:// uri. +of a remote one. It's actually a remote `file://` uri. ``` -! git clone /repo-tmp/python-course /repo-tmp/my-course +!git clone /repo-tmp/python-course /repo-tmp/my-course ``` -Show repository configuration. Remote origin. +Now move to the new directory ``` -! git config -l +cd /repo-tmp/my-course +``` +Show repository configuration. Which is the remote origin? + +``` +!git config -l ``` --- @@ -478,33 +509,54 @@ Show repository configuration. Remote origin. You can add new files to a repo with the above workflow: - - create a branch with `git checkout -b test-1` - - add a new file - - stage changes with `git add` - - commit with `git commit` +- create a branch with `git checkout -b test-1` +- add a new file +- stage changes with `git add` +- commit with `git commit` + +``` +# Use this cell for the exercise +``` Now that your changes are on your local repo, you can synchronize / upload them to the remote copy with: ``` -! git push origin test-1 +!git push origin test-1 ``` Remember: - - origin is the URI specified by `git config -l` - - `test-1` is the branch name where you want to upload +- origin is the URI specified by `git config -l` +- `test-1` is the branch name where you want to upload To upload changes to the remote master (default) branch, you need to - - merge the changes to your local master +- merge the changes to your local master ``` !git checkout master +``` + +Check the differences + +``` +!git diff test-1 +``` + +And finally merge + +``` !git merge test-1 ``` - - push changes to master +Exercise: + +- check the master history; +- check the difference with the last commit. + + +Finally, push changes to `origin/master` ``` !git push origin master diff --git a/git-101/notebooks/01-git.ipynb b/git-101/notebooks/01-git.ipynb index f9f779e..cd265cf 100644 --- a/git-101/notebooks/01-git.ipynb +++ b/git-101/notebooks/01-git.ipynb @@ -2,16 +2,17 @@ "cells": [ { "cell_type": "markdown", + "id": "7f120a0a", "metadata": {}, "source": [ "# Git - simple repository management\n", "\n", "## Agenda\n", "\n", - " - VCS intro\n", - " - tracking modifications\n", - " - using a local git repository\n", - " - remote repositories\n", + "- VCS intro\n", + "- tracking modifications\n", + "- using a local git repository\n", + "- remote repositories\n", "\n", "*Beware*: commands contain small typos. You must fix them to properly complete the course!\n", "\n", @@ -21,16 +22,23 @@ "\n", "VCS basics:\n", "\n", - " - initialize a local repo\n", - " - change the software\n", - " - acknowledge (commit) changes\n", - " - eventually revert changes" + "- initialize a local repo\n", + "- change the software\n", + "- acknowledge (commit) changes\n", + "- eventually revert changes" ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "c4538aef", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Tracking modifications\n", "\n", "Track modifications of our config files without messing\n", @@ -40,15 +48,17 @@ { "cell_type": "code", "execution_count": null, + "id": "700a7a3a", "metadata": {}, "outputs": [], "source": [ - "! mkdir -p /repo-path\n", + "!mkdir -p /repo-path\n", "!cp -v /etc/host* /etc/s* /repo-path" ] }, { "cell_type": "markdown", + "id": "9d560d87", "metadata": {}, "source": [ "All operations are local to /repo-path" @@ -57,6 +67,7 @@ { "cell_type": "code", "execution_count": null, + "id": "4e7bc3b2", "metadata": {}, "outputs": [], "source": [ @@ -65,6 +76,7 @@ }, { "cell_type": "markdown", + "id": "99c3bcd9", "metadata": {}, "source": [ "Always timestamp backup copies, don't `.ori`." @@ -73,6 +85,7 @@ { "cell_type": "code", "execution_count": null, + "id": "cd27bc4d", "metadata": {}, "outputs": [], "source": [ @@ -82,6 +95,7 @@ }, { "cell_type": "markdown", + "id": "d6cd9236", "metadata": {}, "source": [ "Exercise: Use `date +%s` to timestamp a backup copy of `hosts`." @@ -90,6 +104,7 @@ { "cell_type": "code", "execution_count": null, + "id": "000235a9", "metadata": {}, "outputs": [], "source": [ @@ -98,8 +113,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "01f6ef62", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Git\n", "\n", "A better way of tracking changes.\n", @@ -108,23 +130,30 @@ "\n", "Distributed approach.\n", "\n", - "\n", "![Checkout and Push](https://git-scm.com/figures/18333fig0106-tn.png)" ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "4786f164", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Tracing requires identification\n", "\n", - "Declare who's modifying files. This will be inserted in \n", + "Declare who's modifying files. This will be inserted in\n", "the commit." ] }, { "cell_type": "code", "execution_count": null, + "id": "7319e718", "metadata": {}, "outputs": [], "source": [ @@ -134,6 +163,7 @@ }, { "cell_type": "markdown", + "id": "8d9e2062", "metadata": {}, "source": [ "Note: authentication can not be enforced on a local repository." @@ -141,8 +171,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "6051c86d", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Create a repository\n", "\n", "Track modifications with `git`" @@ -151,6 +188,7 @@ { "cell_type": "code", "execution_count": null, + "id": "fdf04eb4", "metadata": {}, "outputs": [], "source": [ @@ -160,18 +198,20 @@ }, { "cell_type": "markdown", + "id": "b8c78e39", "metadata": {}, "source": [ "### Exercise\n", "\n", - " - get the previous `git config ... user.email` \n", - " - remove the `--global` flag from the previous command\n", - " - run it" + "- get the previous `git config ... user.email`\n", + "- remove the `--global` flag from the previous command\n", + "- run it" ] }, { "cell_type": "code", "execution_count": null, + "id": "69557bf0", "metadata": {}, "outputs": [], "source": [ @@ -182,7 +222,12 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "a981eecc", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "---\n", "\n", @@ -193,14 +238,16 @@ { "cell_type": "code", "execution_count": null, + "id": "29a73ba6", "metadata": {}, "outputs": [], "source": [ - "!git status " + "!git status" ] }, { "cell_type": "markdown", + "id": "d9e41818", "metadata": {}, "source": [ "`.gitignore` lists the files we're not interested in" @@ -209,16 +256,18 @@ { "cell_type": "code", "execution_count": null, + "id": "7e24aaf6", "metadata": {}, "outputs": [], "source": [ "# Ignore all files not starting with h\n", "!echo \"[^h]*\" >> .gitignore\n", - "!git status " + "!git status" ] }, { "cell_type": "markdown", + "id": "c0463059", "metadata": {}, "source": [ "Now we have all `host*` files to be tracked." @@ -226,8 +275,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "93276090", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Populate the repo\n", "\n", "Add files to the index" @@ -236,14 +292,16 @@ { "cell_type": "code", "execution_count": null, + "id": "ba250a13", "metadata": {}, "outputs": [], "source": [ - "! git add hosts" + "!git add hosts" ] }, { "cell_type": "markdown", + "id": "7fdde7cd", "metadata": {}, "source": [ "The file is now *staged* for commit. It's not archived though." @@ -252,6 +310,7 @@ { "cell_type": "code", "execution_count": null, + "id": "4a45be06", "metadata": {}, "outputs": [], "source": [ @@ -260,6 +319,7 @@ }, { "cell_type": "markdown", + "id": "ced6d9a3", "metadata": {}, "source": [ "Save files to the local index" @@ -268,14 +328,16 @@ { "cell_type": "code", "execution_count": null, + "id": "2246b5da", "metadata": {}, "outputs": [], "source": [ - "! git commit -m \"Initial snapshot of hosts\"" + "!git commit -m \"Initial snapshot of hosts\"" ] }, { "cell_type": "markdown", + "id": "e40f0406", "metadata": {}, "source": [ "![Git areas](https://git-scm.com/images/about/index1@2x.png)" @@ -283,8 +345,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "5c47fc45", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Basic workflow\n", "\n", "Adding a line to the file we discover that" @@ -293,15 +362,17 @@ { "cell_type": "code", "execution_count": null, + "id": "61a489ee", "metadata": {}, "outputs": [], "source": [ - "!echo \"127.0.0.2 localhost2.localdomain\" >> hosts \n", + "!echo \"127.0.0.2 localhost2.localdomain\" >> hosts\n", "!git diff hosts" ] }, { "cell_type": "markdown", + "id": "7b3d7ccc", "metadata": {}, "source": [ "If we like the changes, we can stage them" @@ -310,15 +381,17 @@ { "cell_type": "code", "execution_count": null, + "id": "89f6d0d0", "metadata": {}, "outputs": [], "source": [ "!git add hosts\n", - "!git status " + "!git status" ] }, { "cell_type": "markdown", + "id": "4f57b9e5", "metadata": {}, "source": [ "and finally save them in the repo." @@ -327,6 +400,7 @@ { "cell_type": "code", "execution_count": null, + "id": "0b48ff38", "metadata": {}, "outputs": [], "source": [ @@ -335,7 +409,12 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "75973a82", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "---\n", "\n", @@ -343,8 +422,8 @@ "\n", "Now we have an history with two changes, containing:\n", "\n", - " - commit messages\n", - " - a commit hash\n", + "- commit messages\n", + "- a commit hash\n", "\n", "HEAD is the last commit." ] @@ -352,14 +431,16 @@ { "cell_type": "code", "execution_count": null, + "id": "b1a64497", "metadata": {}, "outputs": [], "source": [ - "!git log " + "!git log" ] }, { "cell_type": "markdown", + "id": "42aad7f8", "metadata": {}, "source": [ "![Basic branch](https://git-scm.com/figures/18333fig0310-tn.png)" @@ -367,8 +448,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "f45574e8", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Reverting changes\n", "\n", "We can revert a change using the hash or an history log" @@ -377,16 +465,24 @@ { "cell_type": "code", "execution_count": null, + "id": "ec0651ef", "metadata": {}, "outputs": [], "source": [ - "! git checkout HEAD~1 -- hosts # revert hosts to the previous commit" + "!git checkout HEAD~1 -- hosts # revert hosts to the previous commit" ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "96eba2fc", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Cheatsheet\n", "\n", "Now some git commands, but first create a dir." @@ -395,16 +491,18 @@ { "cell_type": "code", "execution_count": null, + "id": "c7f5263e", "metadata": {}, "outputs": [], "source": [ - "! mkdir -p /repo-path\n", + "!mkdir -p /repo-path\n", "!date >> /repo-path/file.txt\n", "!date >> /repo-path/hi.txt" ] }, { "cell_type": "markdown", + "id": "1b486c01", "metadata": {}, "source": [ "---" @@ -413,6 +511,7 @@ { "cell_type": "code", "execution_count": null, + "id": "d625983f", "metadata": {}, "outputs": [], "source": [ @@ -423,25 +522,36 @@ }, { "cell_type": "markdown", + "id": "12c36cb1", "metadata": {}, "source": [ "### Exercise\n", "\n", - " - add `file.txt` to the index and commit" + "- add `file.txt` to the index and commit" ] }, { "cell_type": "code", "execution_count": null, + "id": "f2875a20", "metadata": {}, "outputs": [], "source": [ "# Use this cell for the exercise" ] }, + { + "cell_type": "markdown", + "id": "176dabc2", + "metadata": {}, + "source": [ + "---" + ] + }, { "cell_type": "code", "execution_count": null, + "id": "2786502f", "metadata": {}, "outputs": [], "source": [ @@ -450,9 +560,18 @@ "!git commit -a -m \"Save all previously added files\"" ] }, + { + "cell_type": "markdown", + "id": "5e605932", + "metadata": {}, + "source": [ + "---" + ] + }, { "cell_type": "code", "execution_count": null, + "id": "f3aa8b5d", "metadata": {}, "outputs": [], "source": [ @@ -462,6 +581,7 @@ { "cell_type": "code", "execution_count": null, + "id": "809cb347", "metadata": {}, "outputs": [], "source": [ @@ -471,6 +591,7 @@ { "cell_type": "code", "execution_count": null, + "id": "5f408bf2", "metadata": {}, "outputs": [], "source": [ @@ -480,6 +601,7 @@ { "cell_type": "code", "execution_count": null, + "id": "51681f21", "metadata": {}, "outputs": [], "source": [ @@ -488,19 +610,27 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "ff306b1d", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ - "## Tags & Branches \n", + "---\n", + "\n", + "## Tags & Branches\n", "\n", "Writing codes and configuration we may want to follow\n", "different strategies and save our different attempts.\n", "\n", - " - *tag* makes an unmodifiable snapshot of the repo instead." + "- *tag* makes an unmodifiable snapshot of the repo instead." ] }, { "cell_type": "code", "execution_count": null, + "id": "effd478b", "metadata": {}, "outputs": [], "source": [ @@ -510,9 +640,10 @@ }, { "cell_type": "markdown", + "id": "4b05fced", "metadata": {}, "source": [ - "- *branch* create a modifiable copy of the code, allowing \n", + "- *branch* create a modifiable copy of the code, allowing\n", " to save and work on different features\n", "\n", "![Branches](https://git-scm.com/figures/18333fig0313-tn.png)" @@ -520,8 +651,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "65f48039", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Branches\n", "\n", "`master` is the default branch" @@ -530,6 +668,7 @@ { "cell_type": "code", "execution_count": null, + "id": "d0f52580", "metadata": {}, "outputs": [], "source": [ @@ -538,6 +677,7 @@ }, { "cell_type": "markdown", + "id": "440c9e9d", "metadata": {}, "source": [ "Create a branch" @@ -546,6 +686,7 @@ { "cell_type": "code", "execution_count": null, + "id": "1cbdaefc", "metadata": {}, "outputs": [], "source": [ @@ -554,6 +695,7 @@ }, { "cell_type": "markdown", + "id": "15d4499e", "metadata": {}, "source": [ "And list the branches, check the active one!" @@ -562,6 +704,7 @@ { "cell_type": "code", "execution_count": null, + "id": "15b4fb9e", "metadata": {}, "outputs": [], "source": [ @@ -570,14 +713,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "7a767353", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "Modify a file in a branch" ] }, { "cell_type": "code", "execution_count": null, + "id": "a4631b97", "metadata": {}, "outputs": [], "source": [ @@ -587,6 +738,7 @@ }, { "cell_type": "markdown", + "id": "38365710", "metadata": {}, "source": [ "With commit we consolidate the new file in the branch" @@ -595,6 +747,7 @@ { "cell_type": "code", "execution_count": null, + "id": "0f8e151b", "metadata": {}, "outputs": [], "source": [ @@ -603,14 +756,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "284b07da", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "Compare branches" ] }, { "cell_type": "code", "execution_count": null, + "id": "64d828f6", "metadata": {}, "outputs": [], "source": [ @@ -619,6 +780,7 @@ }, { "cell_type": "markdown", + "id": "af639d85", "metadata": {}, "source": [ "Diff supports some parameters" @@ -627,6 +789,7 @@ { "cell_type": "code", "execution_count": null, + "id": "ce494335", "metadata": {}, "outputs": [], "source": [ @@ -635,14 +798,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "ff806888", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "We can now switch between branches" ] }, { "cell_type": "code", "execution_count": null, + "id": "f9fcf98f", "metadata": {}, "outputs": [], "source": [ @@ -652,6 +823,7 @@ }, { "cell_type": "markdown", + "id": "8eceeeb6", "metadata": {}, "source": [ "And switch back" @@ -660,6 +832,7 @@ { "cell_type": "code", "execution_count": null, + "id": "4a90452a", "metadata": {}, "outputs": [], "source": [ @@ -669,19 +842,27 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "60f1a8f7", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "### Exercise\n", "\n", - " - Create a new branch named `antani`\n", - " - modify `new-file.txt` as you please\n", - " - open a terminal, and use `git add -p` to stage the changes. What does it do?\n", - " - commit the changes" + "- Create a new branch named `antani`\n", + "- modify `new-file.txt` as you please\n", + "- [open a terminal](/terminals/git), and use `git add -p` to stage the changes. What does it do?\n", + "- commit the changes" ] }, { "cell_type": "code", "execution_count": null, + "id": "e2c7bd22", "metadata": {}, "outputs": [], "source": [ @@ -690,8 +871,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "1cd00765", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Checkout troubleshooting\n", "\n", "If you change a file, git won't make you checkout\n", @@ -701,6 +889,7 @@ { "cell_type": "code", "execution_count": null, + "id": "59e5a254", "metadata": {}, "outputs": [], "source": [ @@ -710,6 +899,7 @@ }, { "cell_type": "markdown", + "id": "71da518c", "metadata": {}, "source": [ "You have to remove the changes or commit them (in another branch too)" @@ -718,6 +908,7 @@ { "cell_type": "code", "execution_count": null, + "id": "e22fd009", "metadata": {}, "outputs": [], "source": [ @@ -726,35 +917,87 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "0b77d8f6", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Merge\n", "\n", - "Once we have consolidated some changes (Eg. test, ...)\n", + "Once we have consolidated some changes (e.g., test, ...)\n", "we can *merge* the changes into the master branch" ] }, { "cell_type": "code", "execution_count": null, + "id": "770704f3", "metadata": {}, "outputs": [], "source": [ - "!git checkout master\n", - "!git diff work-on-my-changes\n", - "!git merge work-on-my-changes" + "!git checkout master" + ] + }, + { + "cell_type": "markdown", + "id": "92138e82", + "metadata": {}, + "source": [ + "Before merging, we have to check the differences" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f91d8d41", + "metadata": {}, + "outputs": [], + "source": [ + "!git diff work-on-my-changes" ] }, { "cell_type": "markdown", + "id": "c3610538", "metadata": {}, "source": [ - "After a merge, if the branch is no more useful, we can remove it." + "And finally merge" ] }, { "cell_type": "code", "execution_count": null, + "id": "e64c822b", + "metadata": {}, + "outputs": [], + "source": [ + "!git merge work-on-my-changes" + ] + }, + { + "cell_type": "markdown", + "id": "a31db651", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", + "After a merge, if the branch is no more useful, we can remove it.\n", + "Note: before deleting a branch, you can double-check available\n", + "branches with `git branch -a`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71b22af5", "metadata": {}, "outputs": [], "source": [ @@ -763,20 +1006,22 @@ }, { "cell_type": "markdown", + "id": "3216d35a", "metadata": {}, "source": [ "If there are unmerged changes, git doesn't allow deleting a branch.\n", "\n", "Exercise:\n", "\n", - " - use `git branch -d` to remove the `antani` branch\n", - " - what happens?\n", - " - replace `-d` with `-D`. Does it work now?" + "- use `git branch -d` to remove the `antani` branch\n", + "- what happens?\n", + "- replace `-d` with `-D`. Does it work now?" ] }, { "cell_type": "code", "execution_count": null, + "id": "762915dd", "metadata": {}, "outputs": [], "source": [ @@ -785,8 +1030,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "869b3fda", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Selective adding\n", "\n", "You can stage partial changes with:" @@ -795,16 +1047,24 @@ { "cell_type": "code", "execution_count": null, + "id": "e49ff846", "metadata": {}, "outputs": [], "source": [ - "!git add -p " + "!git add -p" ] }, { "cell_type": "markdown", - "metadata": {}, + "id": "1ffb0b4b", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ + "---\n", + "\n", "## Remote repositories\n", "\n", "Remote repos may be either https, ssh or files." @@ -813,16 +1073,62 @@ { "cell_type": "code", "execution_count": null, + "id": "e4db9adc", + "metadata": {}, + "outputs": [], + "source": [ + "! mkdir -p /repo-tmp && cd /repo-tmp && pwd # use another directory ;)" + ] + }, + { + "cell_type": "markdown", + "id": "3f42676a", + "metadata": {}, + "source": [ + "Exercise:\n", + "\n", + "- what happens in the following cell?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaa4aac3", "metadata": {}, "outputs": [], "source": [ - "! mkdir -p /repo-tmp && cd /repo-tmp # use another directory" + "!pwd" ] }, { "cell_type": "markdown", + "id": "5558113b", "metadata": {}, "source": [ + "Go to the correct directory now." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c80c152", + "metadata": {}, + "outputs": [], + "source": [ + "cd /repo-tmp" + ] + }, + { + "cell_type": "markdown", + "id": "00d2f691", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", "### https repo\n", "\n", "Git clone downloads a remote repo, with all its changes and history.\n", @@ -832,31 +1138,52 @@ { "cell_type": "code", "execution_count": null, + "id": "93194032", + "metadata": {}, + "outputs": [], + "source": [ + "!git clone https://github.com/ioggstream/python-course/ python-course" + ] + }, + { + "cell_type": "markdown", + "id": "7e364def", + "metadata": {}, + "source": [ + "Now enter in the repo directory" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "908d6e35", "metadata": {}, "outputs": [], "source": [ - "! git clone https://github.com/ioggstream/python-course/ python-course\n", "cd /repo-tmp/python-course" ] }, { "cell_type": "markdown", + "id": "f67f6120", "metadata": {}, "source": [ - "Show repository configuration. Remote origin." + "Show repository configuration. Which is the remote origin?" ] }, { "cell_type": "code", "execution_count": null, + "id": "9d125c4b", "metadata": {}, "outputs": [], "source": [ - "! git config -l \n" + "!git config -l" ] }, { "cell_type": "markdown", + "id": "74dccdd3", "metadata": {}, "source": [ "The remote repo is retrieved with all its changes and history" @@ -865,6 +1192,7 @@ { "cell_type": "code", "execution_count": null, + "id": "72d8a61c", "metadata": {}, "outputs": [], "source": [ @@ -873,6 +1201,7 @@ }, { "cell_type": "markdown", + "id": "ce9dc27b", "metadata": {}, "source": [ "And `log` can show branches and merges." @@ -881,6 +1210,7 @@ { "cell_type": "code", "execution_count": null, + "id": "99152bbc", "metadata": {}, "outputs": [], "source": [ @@ -889,54 +1219,103 @@ }, { "cell_type": "markdown", - "metadata": {}, + "id": "da3f94c6", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "---\n", "\n", "### file repo\n", "\n", "A local repo can be cloned too, and has the same features\n", - "of a remote one. It's actually a remote file:// uri." + "of a remote one. It's actually a remote `file://` uri." ] }, { "cell_type": "code", "execution_count": null, + "id": "172e28c4", "metadata": {}, "outputs": [], "source": [ - "! git clone /repo-tmp/python-course /repo-tmp/my-course" + "!git clone /repo-tmp/python-course /repo-tmp/my-course" ] }, { "cell_type": "markdown", + "id": "5142954c", "metadata": {}, "source": [ - "Show repository configuration. Remote origin." + "Now move to the new directory" ] }, { "cell_type": "code", "execution_count": null, + "id": "024280c5", "metadata": {}, "outputs": [], "source": [ - "! git config -l\n" + "cd /repo-tmp/my-course" ] }, { "cell_type": "markdown", + "id": "99ee299e", "metadata": {}, "source": [ + "Show repository configuration. Which is the remote origin?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "505037a8", + "metadata": {}, + "outputs": [], + "source": [ + "!git config -l" + ] + }, + { + "cell_type": "markdown", + "id": "22ce0715", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "---\n", + "\n", "## Pull & push\n", "\n", "You can add new files to a repo with the above workflow:\n", "\n", - " - create a branch with `git checkout -b test-1`\n", - " - add a new file\n", - " - stage changes with `git add`\n", - " - commit with `git commit`\n", - "\n", + "- create a branch with `git checkout -b test-1`\n", + "- add a new file\n", + "- stage changes with `git add`\n", + "- commit with `git commit`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42505c18", + "metadata": {}, + "outputs": [], + "source": [ + "# Use this cell for the exercise" + ] + }, + { + "cell_type": "markdown", + "id": "73ce1851", + "metadata": {}, + "source": [ "Now that your changes are on your local repo, you can synchronize / upload them to the remote copy\n", "with:" ] @@ -944,46 +1323,92 @@ { "cell_type": "code", "execution_count": null, + "id": "420e52e1", "metadata": {}, "outputs": [], "source": [ - "! git push origin test-1" + "!git push origin test-1" ] }, { "cell_type": "markdown", + "id": "af356259", "metadata": {}, "source": [ "Remember:\n", "\n", - " - origin is the URI specified by `git config -l`\n", - " - `test-1` is the branch name where you want to upload\n", + "- origin is the URI specified by `git config -l`\n", + "- `test-1` is the branch name where you want to upload\n", "\n", "To upload changes to the remote master (default) branch, you need to\n", "\n", - " - merge the changes to your local master" + "- merge the changes to your local master" ] }, { "cell_type": "code", "execution_count": null, + "id": "f1cc68b6", + "metadata": {}, + "outputs": [], + "source": [ + "!git checkout master" + ] + }, + { + "cell_type": "markdown", + "id": "3d948893", + "metadata": {}, + "source": [ + "Check the differences" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62cdee76", + "metadata": {}, + "outputs": [], + "source": [ + "!git diff test-1" + ] + }, + { + "cell_type": "markdown", + "id": "0b3bf0a4", + "metadata": {}, + "source": [ + "And finally merge" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "583a589e", "metadata": {}, "outputs": [], "source": [ - "!git checkout master\n", "!git merge test-1" ] }, { "cell_type": "markdown", + "id": "bc785752", "metadata": {}, "source": [ - "- push changes to master" + "Exercise:\n", + "\n", + "- check the master history;\n", + "- check the difference with the last commit.\n", + "\n", + "\n", + "Finally, push changes to `origin/master`" ] }, { "cell_type": "code", "execution_count": null, + "id": "81dfa372", "metadata": {}, "outputs": [], "source": [ @@ -992,6 +1417,7 @@ }, { "cell_type": "markdown", + "id": "a65f7a63", "metadata": {}, "source": [ "To make it work, you need to be authenticated/authorized with the remote repo ;)" @@ -1000,5 +1426,5 @@ ], "metadata": {}, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 5 } diff --git a/git-101/tox.ini b/git-101/tox.ini index 268e6e7..cee54b2 100644 --- a/git-101/tox.ini +++ b/git-101/tox.ini @@ -5,7 +5,7 @@ skipsdist = True [testenv] deps = git+https://github.com/ioggstream/notedown -whitelist_externals = +allowlist_externals = make commands = make From 97dc3a819f1bf13d9f736ad4b9eb0b13472c9f49 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 17 May 2023 18:30:03 +0200 Subject: [PATCH 17/39] Retrieving hosts with ansible. --- ansible-101/site-digitalocean.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 3187ed3..8e16d9e 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -9,6 +9,11 @@ # the digital_ocean module will create those droplets over and # over again. # +# You can retrieve the list of provisioned hosts with +# +# $ ansible --user=root -i /tmp/inventory.do -mshell \ +# -a 'docker exec -ti ansible-101_course_1 jupyter-notebook list | sed -e "s/0.0.0.0/{{ansible_host}}/" ' do +# - hosts: localhost gather_facts: false vars: From 8fdc49d4f799122191a525409a9a722a0ee4453c Mon Sep 17 00:00:00 2001 From: tucsolo Date: Thu, 18 May 2023 09:08:09 +0200 Subject: [PATCH 18/39] added multiple SSH key import and moved droplet names in a list (#61) --- ansible-101/site-digitalocean.yml | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 8e16d9e..17cdc5b 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -18,6 +18,13 @@ gather_facts: false vars: oauth_token: "{{ lookup('ansible.builtin.env', 'DO_API_TOKEN') }}" + ssh_pubkeys: + - rpolli-ed25519 + - esavo-rsa + - dabbasciano-rsa + droplet_names: + - deleteme-1 + - deleteme-2 tasks: - name: Retrieve ssh key id. @@ -28,27 +35,29 @@ - name: Set facts based on the gathered information set_fact: - do_key: "{{ item }}" - loop: "{{ ssh_keys.data | community.general.json_query(ssh_pubkey) }}" + do_key: "{{ do_key | default([]) + ssh_keys | community.general.json_query(search_query) | default(item) }}" vars: - ssh_pubkey: "[?name=='rpolli-ed25519']" - + search_query: "data[?name=='{{ item }}'].fingerprint" + # search_query: "data[?(@.name.match('{{ ssh_pubkeys | join ('|') }}'))].fingerprint" + # + # This should be the correct query, but Ansible fatals: + # + # fatal: [localhost]: FAILED! => {"msg": "JMESPathError in json_query filter plugin:\nUnknown function: match()"} + loop: "{{ ssh_pubkeys }}" + - name: Create enough machine for the course. community.digitalocean.digital_ocean_droplet: state: present name: "{{item}}" unique_name: yes - ssh_keys: - - "{{ do_key.fingerprint }}" + ssh_keys: "{{ do_key }}" size: s-2vcpu-4gb region: fra1 image: docker-18-04 wait_timeout: 500 user_data: "{{ lookup('file', 'cloudinit.txt') }}" # b64encode is not needed in Ansible register: my_droplet - with_items: - - deleteme-1 -# - deleteme-2 + with_items: "{{ droplet_names }}" - name: Dynamically add the new servers to the inventory. add_host: From 25cb50406bb5c6928d0d45ef78389a48fda207c9 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 18 May 2023 12:41:49 +0200 Subject: [PATCH 19/39] Improve docker. --- docker-101/02-docker.md | 33 ++++-- docker-101/Dockerfile | 22 ++++ docker-101/Makefile | 1 + docker-101/notebooks/02-docker.ipynb | 167 +++++++++++++++------------ docker-101/notebooks/Dockerfile | 22 ++++ 5 files changed, 163 insertions(+), 82 deletions(-) create mode 100644 docker-101/Dockerfile create mode 100644 docker-101/notebooks/Dockerfile diff --git a/docker-101/02-docker.md b/docker-101/02-docker.md index 0ca254a..022b2c3 100644 --- a/docker-101/02-docker.md +++ b/docker-101/02-docker.md @@ -137,12 +137,17 @@ docker stats # shows metrics, memory, cpu, filsystem ``` 1. Inspect the `ansible-101_bastion_1` container. -1. Use the `--format` option to get the IP address. Hint: you can google for the solution. +1. Use the `--format` option to get the IP address on a [terminal](/terminals/docker). + **Hint 1: you can google for the solution.** +1. Try to run the `docker inspect --format ...` command above in the jupyter notebook. + Does it work? If not, why? ```python # Use this cell to run the correct docker command. ``` +💬 Discuss how python treats the `{` character. + --- ## Images @@ -176,6 +181,15 @@ docker commit # creates image from a container. docker rmi # removes an image. docker history # list changes of an image. ``` +---- + +Images are stored in a Docker registry such as [Docker Hub](https://hub.docker.com/) +or Github's [Container Registry](). You can also host your own registry. + +`docker commit` can create an image from a container. This is similar to the +snapshot feature of Virtual Machines. + +[![](https://mermaid.ink/img/pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC?type=png)](https://mermaid.live/edit#pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC) --- @@ -184,12 +198,8 @@ docker history # list changes of an image. The Dockerfile is a text file that contains all the commands a user could call on the command line to assemble an image. -```dockerfile -FROM debian:stable-slim -MAINTAINER Piuma "piuma@piumalab.org" -RUN apt-get update && apt-get -y install apache2 -EXPOSE 80 -CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] +``` +! cat Dockerfile ``` Docker will execute all the commands in the Dockerfile and create a new image. @@ -207,11 +217,14 @@ Open the [terminal](/terminals/docker) and: docker run --rm --detach apache-example ``` -- check the running container with `docker ps` +#### Exercise + +Open the [terminal](/terminals/docker) and: + +- check if the container is running `docker ps` - use `curl` to check if the webserver works - stop the container with `docker stop` -- check the running container with `docker ps` -- check the stopped container with `docker ps -a` +- check the container status with `docker ps -a` - remove the container with `docker rm` --- diff --git a/docker-101/Dockerfile b/docker-101/Dockerfile new file mode 100644 index 0000000..8f70b36 --- /dev/null +++ b/docker-101/Dockerfile @@ -0,0 +1,22 @@ +# +# This is a simple Dockerfile to build an image with Apache2. +# You can build it with: +# +# $ docker build -t test-apache2 . +# +FROM debian:stable-slim + +# Set the maintainer. See https://docs.docker.com/engine/reference/builder/#maintainer-deprecated +LABEL org.opencontainers.image.authors="piuma@piumalab.org" + +# Install Apache2 and finally clean up the APT cache. +# There are different opinions on whether to `apt-get -y upgrade` or not. +# Check this interesting discussion: https://github.com/docker/docs/pull/12571 +RUN apt-get update && apt-get -y install apache2 && apt-get clean + +# Expose the default ports. https://docs.docker.com/engine/reference/builder/#expose +EXPOSE 80/tcp +EXPOSE 443/tcp + +# Set the default command to run when starting the container +CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] diff --git a/docker-101/Makefile b/docker-101/Makefile index 1642cb3..7d2e24f 100644 --- a/docker-101/Makefile +++ b/docker-101/Makefile @@ -4,6 +4,7 @@ BOOKS = $(patsubst %.md,notebooks/%.ipynb,$(FILES)) all: $(BOOKS) @echo $(BOOKS) + cp Dockerfile notebooks/Dockerfile notebooks/%.ipynb: %.md diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb index 8d9c86b..9618b54 100644 --- a/docker-101/notebooks/02-docker.ipynb +++ b/docker-101/notebooks/02-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "a01a6b89", + "id": "af25ee55", "metadata": {}, "source": [ "## Inspect the Docker host\n", @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6093cdd8", + "id": "087a454d", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1de2c383", + "id": "eaf95c65", "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c02f1de0", + "id": "2c3bb55c", "metadata": {}, "outputs": [], "source": [ @@ -45,7 +45,7 @@ }, { "cell_type": "markdown", - "id": "8819937b", + "id": "5085d17e", "metadata": { "slideshow": { "slide_type": "slide" @@ -62,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "82ff3167", + "id": "abf9ae06", "metadata": {}, "outputs": [], "source": [ @@ -73,7 +73,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b53c0828", + "id": "3b60a124", "metadata": {}, "outputs": [], "source": [ @@ -83,7 +83,7 @@ }, { "cell_type": "markdown", - "id": "775edbab", + "id": "b16358a4", "metadata": { "slideshow": { "slide_type": "slide" @@ -104,7 +104,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fc43ca83", + "id": "5f1d0acf", "metadata": {}, "outputs": [], "source": [ @@ -114,7 +114,7 @@ }, { "cell_type": "markdown", - "id": "3cff75bb", + "id": "9997b2b3", "metadata": {}, "source": [ "Download an image from the remote registry." @@ -123,7 +123,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a64d1a21", + "id": "3171326c", "metadata": {}, "outputs": [], "source": [ @@ -133,7 +133,7 @@ }, { "cell_type": "markdown", - "id": "103802a1", + "id": "23ad6b0a", "metadata": {}, "source": [ "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", @@ -145,7 +145,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3743b57f", + "id": "a5b9317e", "metadata": {}, "outputs": [], "source": [ @@ -155,7 +155,7 @@ }, { "cell_type": "markdown", - "id": "6b1dca8e", + "id": "bec24ae4", "metadata": {}, "source": [ "Then run the above commands to ensure that you are on another virtual hosts." @@ -164,7 +164,7 @@ { "cell_type": "code", "execution_count": null, - "id": "395c2403", + "id": "da9d22e5", "metadata": {}, "outputs": [], "source": [ @@ -177,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "1c9d3e78", + "id": "c0637596", "metadata": { "slideshow": { "slide_type": "slide" @@ -194,7 +194,7 @@ { "cell_type": "code", "execution_count": null, - "id": "72e40858", + "id": "d542d8c4", "metadata": {}, "outputs": [], "source": [ @@ -204,7 +204,7 @@ }, { "cell_type": "markdown", - "id": "762d26aa", + "id": "c73e6c52", "metadata": {}, "source": [ "Can you retrieve the IP address in another way?\n", @@ -213,7 +213,7 @@ }, { "cell_type": "markdown", - "id": "ef49f6c1", + "id": "d5d03d15", "metadata": { "slideshow": { "slide_type": "slide" @@ -230,7 +230,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a9eb4484", + "id": "aa665e9d", "metadata": {}, "outputs": [], "source": [ @@ -240,7 +240,7 @@ }, { "cell_type": "markdown", - "id": "e79e15fe", + "id": "4b06c007", "metadata": { "slideshow": { "slide_type": "slide" @@ -257,7 +257,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5b1d74f8", + "id": "8b59b38e", "metadata": { "attributes": { "classes": [ @@ -282,7 +282,7 @@ }, { "cell_type": "markdown", - "id": "193f7868", + "id": "169a6f56", "metadata": {}, "source": [ "You can inspect containers" @@ -291,7 +291,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1dde4d12", + "id": "f4ab7ae6", "metadata": { "attributes": { "classes": [ @@ -314,7 +314,7 @@ }, { "cell_type": "markdown", - "id": "9dd9d674", + "id": "f1c1dcef", "metadata": {}, "source": [ "#### Exercise\n", @@ -325,7 +325,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fdaf1ecd", + "id": "67cb7aa4", "metadata": {}, "outputs": [], "source": [ @@ -334,17 +334,20 @@ }, { "cell_type": "markdown", - "id": "23e6c883", + "id": "1b0cbf90", "metadata": {}, "source": [ "1. Inspect the `ansible-101_bastion_1` container.\n", - "1. Use the `--format` option to get the IP address. Hint: you can google for the solution." + "1. Use the `--format` option to get the IP address on a [terminal](/terminals/docker).\n", + " **Hint 1: you can google for the solution.**\n", + "1. Try to run the `docker inspect --format ...` command above in the jupyter notebook.\n", + " Does it work? If not, why?" ] }, { "cell_type": "code", "execution_count": null, - "id": "8053b13a", + "id": "0dcf9458", "metadata": {}, "outputs": [], "source": [ @@ -353,7 +356,15 @@ }, { "cell_type": "markdown", - "id": "d10e46a9", + "id": "bbcc0cda", + "metadata": {}, + "source": [ + "💬 Discuss how python treats the `{` character." + ] + }, + { + "cell_type": "markdown", + "id": "af726bf4", "metadata": { "slideshow": { "slide_type": "slide" @@ -383,7 +394,7 @@ }, { "cell_type": "markdown", - "id": "bd1ba26f", + "id": "f1449c94", "metadata": { "slideshow": { "slide_type": "subslide" @@ -399,7 +410,7 @@ { "cell_type": "code", "execution_count": null, - "id": "45ed0543", + "id": "8c4317cc", "metadata": { "attributes": { "classes": [ @@ -420,7 +431,27 @@ }, { "cell_type": "markdown", - "id": "30197228", + "id": "d99e9300", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "----\n", + "\n", + "Images are stored in a Docker registry such as [Docker Hub](https://hub.docker.com/)\n", + "or Github's [Container Registry](). You can also host your own registry.\n", + "\n", + "`docker commit` can create an image from a container. This is similar to the\n", + "snapshot feature of Virtual Machines.\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC?type=png)](https://mermaid.live/edit#pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC)" + ] + }, + { + "cell_type": "markdown", + "id": "445cf617", "metadata": { "slideshow": { "slide_type": "slide" @@ -438,27 +469,16 @@ { "cell_type": "code", "execution_count": null, - "id": "42339314", - "metadata": { - "attributes": { - "classes": [ - "dockerfile" - ], - "id": "" - } - }, + "id": "275d6521", + "metadata": {}, "outputs": [], "source": [ - "FROM debian:stable-slim\n", - "MAINTAINER Piuma \"piuma@piumalab.org\"\n", - "RUN apt-get update && apt-get -y install apache2\n", - "EXPOSE 80\n", - "CMD [\"/usr/sbin/apache2ctl\", \"-D\", \"FOREGROUND\"]" + "! cat Dockerfile" ] }, { "cell_type": "markdown", - "id": "f8577fe9", + "id": "df3c135a", "metadata": {}, "source": [ "Docker will execute all the commands in the Dockerfile and create a new image." @@ -467,7 +487,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f86164a1", + "id": "f0b183ca", "metadata": {}, "outputs": [], "source": [ @@ -476,7 +496,7 @@ }, { "cell_type": "markdown", - "id": "5a47f022", + "id": "27de786f", "metadata": {}, "source": [ "Open the [terminal](/terminals/docker) and:\n", @@ -488,7 +508,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1488821c", + "id": "dd2aa813", "metadata": {}, "outputs": [], "source": [ @@ -498,20 +518,23 @@ }, { "cell_type": "markdown", - "id": "57bd2970", + "id": "219a9077", "metadata": {}, "source": [ - "- check the running container with `docker ps`\n", + "#### Exercise\n", + "\n", + "Open the [terminal](/terminals/docker) and:\n", + "\n", + "- check if the container is running `docker ps`\n", "- use `curl` to check if the webserver works\n", "- stop the container with `docker stop`\n", - "- check the running container with `docker ps`\n", - "- check the stopped container with `docker ps -a`\n", + "- check the container status with `docker ps -a`\n", "- remove the container with `docker rm`" ] }, { "cell_type": "markdown", - "id": "f8d0f29d", + "id": "71b3cc39", "metadata": { "slideshow": { "slide_type": "slide" @@ -532,7 +555,7 @@ }, { "cell_type": "markdown", - "id": "10c52150", + "id": "a40f4cc2", "metadata": { "slideshow": { "slide_type": "subslide" @@ -555,7 +578,7 @@ }, { "cell_type": "markdown", - "id": "7d6d3849", + "id": "ae054f71", "metadata": { "slideshow": { "slide_type": "subslide" @@ -572,7 +595,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fe83cfc1", + "id": "5eed9464", "metadata": { "attributes": { "classes": [ @@ -600,7 +623,7 @@ }, { "cell_type": "markdown", - "id": "f3859dd3", + "id": "411abcfd", "metadata": {}, "source": [ "Now run docker-compose up and Compose will start and run your entire app.\n", @@ -614,7 +637,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4ae4f092", + "id": "fa27ecd3", "metadata": {}, "outputs": [], "source": [ @@ -624,7 +647,7 @@ }, { "cell_type": "markdown", - "id": "27e0b0dc", + "id": "1f230ad4", "metadata": { "slideshow": { "slide_type": "slide" @@ -639,7 +662,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4e8ace61", + "id": "8271bbd4", "metadata": {}, "outputs": [], "source": [ @@ -653,7 +676,7 @@ }, { "cell_type": "markdown", - "id": "9e81f374", + "id": "3ad47479", "metadata": { "slideshow": { "slide_type": "subslide" @@ -668,7 +691,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4714eee9", + "id": "e0a5218b", "metadata": { "attributes": { "classes": [ @@ -696,7 +719,7 @@ }, { "cell_type": "markdown", - "id": "a420adc4", + "id": "36beef23", "metadata": { "slideshow": { "slide_type": "subslide" @@ -711,7 +734,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fa6a114b", + "id": "268716d2", "metadata": {}, "outputs": [], "source": [ @@ -735,7 +758,7 @@ }, { "cell_type": "markdown", - "id": "5a4b46b8", + "id": "4fb67d7a", "metadata": { "slideshow": { "slide_type": "subslide" @@ -750,7 +773,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2ec2f720", + "id": "888f959d", "metadata": {}, "outputs": [], "source": [ @@ -770,7 +793,7 @@ }, { "cell_type": "markdown", - "id": "4d8563b3", + "id": "3642bdc5", "metadata": { "slideshow": { "slide_type": "slide" @@ -785,7 +808,7 @@ { "cell_type": "code", "execution_count": null, - "id": "91fd8470", + "id": "3bd00f13", "metadata": {}, "outputs": [], "source": [ @@ -794,7 +817,7 @@ }, { "cell_type": "markdown", - "id": "5d5cdd6c", + "id": "5d4f1cba", "metadata": {}, "source": [ "---" diff --git a/docker-101/notebooks/Dockerfile b/docker-101/notebooks/Dockerfile new file mode 100644 index 0000000..8f70b36 --- /dev/null +++ b/docker-101/notebooks/Dockerfile @@ -0,0 +1,22 @@ +# +# This is a simple Dockerfile to build an image with Apache2. +# You can build it with: +# +# $ docker build -t test-apache2 . +# +FROM debian:stable-slim + +# Set the maintainer. See https://docs.docker.com/engine/reference/builder/#maintainer-deprecated +LABEL org.opencontainers.image.authors="piuma@piumalab.org" + +# Install Apache2 and finally clean up the APT cache. +# There are different opinions on whether to `apt-get -y upgrade` or not. +# Check this interesting discussion: https://github.com/docker/docs/pull/12571 +RUN apt-get update && apt-get -y install apache2 && apt-get clean + +# Expose the default ports. https://docs.docker.com/engine/reference/builder/#expose +EXPOSE 80/tcp +EXPOSE 443/tcp + +# Set the default command to run when starting the container +CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] From 957095453a4efa15815ca95851f3ab394a4d6c8a Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Fri, 19 May 2023 15:57:12 +0200 Subject: [PATCH 20/39] more stuff. --- ansible-101/README.md | 4 +- ansible-101/notebooks/01_architecture.ipynb | 22 +- ansible-101/notebooks/02_vaults.ipynb | 6 +- .../notebooks/03_facts_and_variables.ipynb | 602 +++++++++++++++++- 4 files changed, 594 insertions(+), 40 deletions(-) diff --git a/ansible-101/README.md b/ansible-101/README.md index afafd1e..2556d33 100644 --- a/ansible-101/README.md +++ b/ansible-101/README.md @@ -91,9 +91,9 @@ Prerequisites can be found in the home directory: - Use bastions and other ssh_opts - 3. writing basic playbooks, test driven deployment -- Yaml pitfalls +- YAML pitfalls - Inclusion and Roles -- Ansible galaxy as a role repository (bonus track) +- Ansible galaxy as a role repository ## Advanced topics diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index e16b9d9..e70ae19 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -15,7 +15,7 @@ " - broad community\n", " - many external tools\n", " - playbook repository\n", - " - used by openstack, openshift & tonns of project\n", + " - used by openstack & tonns of project\n", " \n", " \n" ] @@ -27,7 +27,7 @@ "source": [ " # Configuration Manager\n", " \n", - "Explain infrastructure as code\n", + "Explain infrastructure as code (e.g., remember `docker-compose`?):\n", "\n", "- managing data centers through machine-readable definition files;\n", "- install, configure, decommission physical and virtual resources;\n", @@ -58,20 +58,19 @@ " \n", " Authentication can be passwordless (ssh/pki, kerberos) or with password.\n", " \n", - " Automation jobs (Playbooks) are described via YAML - a very concise and simple language. You can validate and lint files with yamllint and ansible-lint.\n", + " Automation jobs (Playbooks) are described via YAML - a very concise and simple language.\n", + " You can validate and lint files with yamllint and [ansible-lint](https://github.com/ansible/ansible-lint).\n", " \n", - "```\n", + "```yaml\n", "this_is:\n", " a: yaml\n", "\n", "file:\n", "- with dict\n", "- a list\n", - " \n", - " \n", "```\n", " \n", - " Passwords are supported, but SSH keys with ssh-agent are one of the best ways to use Ansible. Though if you want to use Kerberos, that's good too. \n", + "Passwords are supported, but SSH keys with ssh-agent are one of the best ways to use Ansible. Though if you want to use Kerberos, that's good too. \n", " \n", "You have a lot of options! Root logins are not required, you can login as any user, and then su or sudo to any user." ] @@ -104,12 +103,12 @@ "source": [ "## ansible.cfg \n", "\n", - "It's the main configuration file. While all ansible are in `yaml`, ansible.cfg is in .ini format. Eg.\n", + "It's the main configuration file. While all ansible are in YAML, `ansible.cfg` is in .ini format. Eg.\n", "\n", "```\n", + "# This is a .ini file.\n", "[stanza]\n", "key = value\n", - "\n", "```\n", "\n", "Let's check the content of a sample ansible.cfg:\n", @@ -135,7 +134,7 @@ "source": [ "## Inventories\n", "\n", - "a simple inventory file contains a static list of nodes to contact.\n", + "A simple inventory file contains a static list of nodes to contact.\n", "\n", "Generally, an [inventory can be static or dynamic](http://docs.ansible.com/ansible/intro_inventory.html), as we will see in the following lessons.\n", "\n" @@ -211,7 +210,7 @@ "source": [ "# The debug module (-m debug) shows variables' content or dumps messages.\n", "# by default uses the inventory set into ansible.cfg, thus writing\n", - "!ansible all -m debug -a 'var=env_name'\n" + "!ansible all -m debug -a 'var=env_name'" ] }, { @@ -242,7 +241,6 @@ "outputs": [], "source": [ "# Solution\n", - "\n", "!ansible all -i staging -m debug -a 'var=env_name'" ] }, diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index e0339ee..63be027 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -427,9 +427,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -441,7 +441,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.14" + "version": "3.9.9" } }, "nbformat": 4, diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 54cf559..16e8c05 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -1204,24 +1204,57 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "solution": "shown", "solution_first": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\n", + "source\n", + " [WARNING]: No inventory was parsed, only implicit localhost is available\n", + " [WARNING]: Could not match supplied host pattern, ignoring: all\n", + " [WARNING]: provided hosts list is empty, only localhost is available\n" + ] + } + ], "source": [ "!ansible >/dev/null -i inventory -m setup localhost --tree host_status" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "code_folding": [], "solution": "shown" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "host_status\r\n", + "└── localhost\r\n", + "\r\n", + "0 directories, 1 file\r\n" + ] + }, + { + "data": { + "text/plain": [ + "[u'172.17.0.2']" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Solution\n", "!tree host_status\n", @@ -1232,7 +1265,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1249,15 +1281,15 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ - "# use this cell for the exercise" + "# use this cell for the exercise\n", + "!ansible-pla" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1274,15 +1306,253 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", + "\u001b[1;35msource\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\n", + "PLAY [Use this section to complete the exercise, and the next section as a reference for the debug module.] ***\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "TASK [Dump the requested facts.] ***********************************************\n", + "\u001b[0;32mok: [localhost] => {\u001b[0m\n", + "\u001b[0;32m \"msg\": \"A string\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "PLAY [Those tasks are run on localhost only] ***********************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "TASK [This is the debug module.] ***********************************************\n", + "\u001b[0;32mok: [localhost] => {\u001b[0m\n", + "\u001b[0;32m \"msg\": \"A string\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "TASK [The debug module can print variables too] ********************************\n", + "\u001b[0;32mok: [localhost] => {\u001b[0m\n", + "\u001b[0;32m \"ansible_hostname\": \"f063a33adb7a\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "TASK [We can iterate too...] ***************************************************\n", + "\u001b[0;32mok: [localhost] => (item=cap_chown) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_chown\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_chown\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_dac_override) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_dac_override\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_dac_override\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_fowner) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_fowner\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_fowner\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_fsetid) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_fsetid\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_fsetid\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_kill) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_kill\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_kill\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_setgid) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_setgid\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_setgid\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_setuid) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_setuid\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_setuid\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_setpcap) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_setpcap\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_setpcap\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_net_bind_service) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_net_bind_service\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_net_bind_service\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_net_raw) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_net_raw\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_net_raw\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_sys_chroot) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_sys_chroot\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_sys_chroot\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_mknod) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_mknod\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_mknod\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_audit_write) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_audit_write\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_audit_write\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item=cap_setfcap+eip) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": \"cap_setfcap+eip\", \u001b[0m\n", + "\u001b[0;32m \"msg\": \"cap_setfcap+eip\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "TASK [..and inspect/format variables] ******************************************\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/code'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/notebooks'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/resolv.conf'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/hostname'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/hosts'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/root/.jupyter/custom/custom.css'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "PLAY RECAP *********************************************************************\n", + "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=7 \u001b[0m changed=0 unreachable=0 failed=0 \n", + "\n" + ] + } + ], "source": [ "!ansible-playbook get-facts.yml" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1304,7 +1574,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1338,9 +1607,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", + "\u001b[1;35msource\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[0;32mlocalhost | SUCCESS => {\u001b[0m\n", + "\u001b[0;32m \"ansible_user[:2]\": \"ro\", \u001b[0m\n", + "\u001b[0;32m \"changed\": false\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n" + ] + } + ], "source": [ "# Use the debug module to process a variable\n", "# Modify the command to print the last two letters.\n", @@ -1349,25 +1638,110 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "- hosts: localhost\r\n", + " tags: variables\r\n", + " vars:\r\n", + " - one: 1\r\n", + " - pi: 3.1415\r\n", + " tasks:\r\n", + " - debug:\r\n", + " msg: >\r\n", + " {{ansible_hostname }} {{ one }}\r\n", + " - debug:\r\n", + " msg: >\r\n", + " The output is {{ one + pi }}\r\n", + "\r\n", + "\r\n", + "- hosts: localhost\r\n", + " tags: filters\r\n", + " vars:\r\n", + " - one: 1\r\n", + " - pi: 3.1415\r\n", + " tasks:\r\n", + " - name: Ansible can process expressions using filters\r\n", + " debug:\r\n", + " msg: >\r\n", + " Floor it {{ ( one + pi ) | int }}\r\n", + "\r\n", + "- hosts: localhost\r\n", + " tags: exercise\r\n", + " name: Use this cell for the exercise\r\n", + " tasks:\r\n", + " - name: >\r\n", + " Show the free percentage of the local disk using\r\n", + " facts and filters\r\n", + " debug: msg=\"Replace me\"\r\n" + ] + } + ], "source": [ "!cat vars-and-facts.yml" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", + "\u001b[1;35msource\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\n", + "PLAY [localhost] ***************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "TASK [debug] *******************************************************************\n", + "\u001b[0;32mok: [localhost] => {\u001b[0m\n", + "\u001b[0;32m \"msg\": \"f063a33adb7a 1\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "TASK [debug] *******************************************************************\n", + "\u001b[0;32mok: [localhost] => {\u001b[0m\n", + "\u001b[0;32m \"msg\": \"The output is 4.1415\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "PLAY [localhost] ***************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "PLAY [Use this cell for the exercise] ******************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "PLAY RECAP *********************************************************************\n", + "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=5 \u001b[0m changed=0 unreachable=0 failed=0 \n", + "\n" + ] + } + ], "source": [ "# This playbook mixes variables and facts\n", "!ansible-playbook vars-and-facts.yml --tags variables" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1428,7 +1802,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1446,13 +1819,196 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", + "\u001b[1;35msource\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", + "\u001b[1;35m\u001b[0m\n", + "\n", + "PLAY [localhost] ***************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "PLAY [localhost] ***************************************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "PLAY [Use this cell for the exercise] ******************************************\n", + "\n", + "TASK [Gathering Facts] *********************************************************\n", + "\u001b[0;32mok: [localhost]\u001b[0m\n", + "\n", + "TASK [Show the free percentage of the local disk using facts and filters] ******\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/code'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/code 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/notebooks'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/notebooks 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/resolv.conf'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/etc/resolv.conf 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/hostname'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/etc/hostname 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/hosts'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/etc/hosts 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/root/.jupyter/custom/custom.css'}) => {\u001b[0m\n", + "\u001b[0;32m \"changed\": false, \u001b[0m\n", + "\u001b[0;32m \"item\": {\u001b[0m\n", + "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", + "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", + "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", + "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", + "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", + "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", + "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", + "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", + "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", + "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", + "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", + "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", + "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", + "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", + "\u001b[0;32m }, \u001b[0m\n", + "\u001b[0;32m \"msg\": \"/root/.jupyter/custom/custom.css 0%\\n\"\u001b[0m\n", + "\u001b[0;32m}\u001b[0m\n", + "\n", + "PLAY RECAP *********************************************************************\n", + "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=4 \u001b[0m changed=0 unreachable=0 failed=0 \n", + "\n" + ] + } + ], "source": [ "!ansible-playbook vars-and-facts.yml --tags exercise" ] }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Filesystem Size Used Avail Use% Mounted on\r\n", + "overlay 271G 269G 2.3G 100% /\r\n", + "tmpfs 64M 0 64M 0% /dev\r\n", + "tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup\r\n", + "shm 64M 0 64M 0% /dev/shm\r\n", + "/dev/mapper/fedora_localhost--live-home 271G 269G 2.3G 100% /code\r\n", + "tmpfs 7.8G 0 7.8G 0% /proc/asound\r\n", + "tmpfs 7.8G 0 7.8G 0% /proc/acpi\r\n", + "tmpfs 7.8G 0 7.8G 0% /proc/scsi\r\n", + "tmpfs 7.8G 0 7.8G 0% /sys/firmware\r\n" + ] + } + ], + "source": [ + "!df -h\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1477,7 +2033,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.13" + "version": "2.7.14" } }, "nbformat": 4, From 53f407304c10d40c629babf2e8464202966b605e Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 22 May 2023 20:02:48 +0200 Subject: [PATCH 21/39] Improve readability. --- ansible-101/notebooks/01_architecture.ipynb | 19 +- .../notebooks/02_delivery_layout.ipynb | 32 +- ansible-101/notebooks/02_vaults.ipynb | 93 +- .../notebooks/03_facts_and_variables.ipynb | 1774 +---------------- .../notebooks/04_loops_and_conditions.ipynb | 35 +- .../notebooks/06_bastion_and_ssh.ipynb | 26 +- ansible-101/notebooks/exercise-01/ansible.cfg | 5 + ansible-101/notebooks/exercise-03/ansible.cfg | 3 + .../notebooks/exercise-03/conditions.yml | 9 +- .../notebooks/exercise-03/environment.yml | 4 +- .../notebooks/exercise-03/fileglob.yml | 9 +- .../exercise-03/vars-and-facts-solution.yml | 4 +- .../notebooks/exercise-03/vars-and-facts.yml | 3 +- 13 files changed, 182 insertions(+), 1834 deletions(-) diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index e70ae19..fefad3a 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -38,6 +38,12 @@ "\n", "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ)\n", "\n", + "Tricks:\n", + "\n", + "- use a light development environment\n", + "\n", + "[![](https://mermaid.ink/img/pako:eNp1Uk1v2zAM_SsCD0MCxEVqp67jFru0OwxoL91tVjEoNpMYtSVNH0HdJP99lK1g62EwRJDy4-MjqSPUqkEoIUkSLl3rOizZd7k1wjrja-cNMmHZA4G4HDE7I_SePb1wGb4GD7MZhy9yY_XdZLei3IrEWzRscjuhndL_QviYGH2YzwOT9ZuJ2qBW1QsZ2zplhkgSZJK7Cf6uda_E0BqsXavkKCZk_apmuhPDRqk3OydErxrfoa1m0bnk68HtlQwIlE3sInT3lZ3-Fku077rE4G-P1pHgELIYnkaRUwrKXSvxUwdEh_JQPeKB_h4-TYFq1qqn3rB6UNIJSjWW2KOyRtVv49z-G71GtVF5JGO0mtP9KVRmXMICejS9aBta7JFLxji4PfbIoSS3wa3wnePA5ZmgXjfC4bcmTBtK2jouQHinfgyyvsQT5rEV1GAPpKazdKuF_KlUfwFRCOUR3qG8zourPF2u8tt0nRbrfFUsYKDroriis86DSW-y2-y8gI-RYUn4LE2z6_Rmna3y5ZIycJT0PL3P8Zme_wCRge2O?type=png)](https://mermaid.live/edit#pako:eNp1Uk1v2zAM_SsCD0MCxEVqp67jFru0OwxoL91tVjEoNpMYtSVNH0HdJP99lK1g62EwRJDy4-MjqSPUqkEoIUkSLl3rOizZd7k1wjrja-cNMmHZA4G4HDE7I_SePb1wGb4GD7MZhy9yY_XdZLei3IrEWzRscjuhndL_QviYGH2YzwOT9ZuJ2qBW1QsZ2zplhkgSZJK7Cf6uda_E0BqsXavkKCZk_apmuhPDRqk3OydErxrfoa1m0bnk68HtlQwIlE3sInT3lZ3-Fku077rE4G-P1pHgELIYnkaRUwrKXSvxUwdEh_JQPeKB_h4-TYFq1qqn3rB6UNIJSjWW2KOyRtVv49z-G71GtVF5JGO0mtP9KVRmXMICejS9aBta7JFLxji4PfbIoSS3wa3wnePA5ZmgXjfC4bcmTBtK2jouQHinfgyyvsQT5rEV1GAPpKazdKuF_KlUfwFRCOUR3qG8zourPF2u8tt0nRbrfFUsYKDroriis86DSW-y2-y8gI-RYUn4LE2z6_Rmna3y5ZIycJT0PL3P8Zme_wCRge2O)\n", + "\n", "Ansible uses the push model and supports both declarative and imperative approaches." ] }, @@ -53,9 +59,7 @@ " No agents: ansible copies python and all deployment scripts/modules to the target machine via ssh and executes them remotely. Some modules though require that target hosts contain specific python libraries.\n", " \n", " Jobs are executed in parallel, but you can configure for serialization using different strategies for speed up, rollout or other purposes: (link)\n", - " \n", - " ![Ansible architecture](https://cdn.pbrd.co/images/390yWc9H0.png \"Ansible architecture\")\n", - " \n", + " \n", " Authentication can be passwordless (ssh/pki, kerberos) or with password.\n", " \n", " Automation jobs (Playbooks) are described via YAML - a very concise and simple language.\n", @@ -136,7 +140,7 @@ "\n", "A simple inventory file contains a static list of nodes to contact.\n", "\n", - "Generally, an [inventory can be static or dynamic](http://docs.ansible.com/ansible/intro_inventory.html), as we will see in the following lessons.\n", + "Generally, an [inventory can be static or dynamic](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html), as we will see in the following lessons.\n", "\n" ] }, @@ -168,13 +172,18 @@ "\n", "**N.B. ansible environment variables are not related with process environment**\n", "\n", + "Exercise:\n", + "\n", + "- using [the terminal](/terminals/ps) identify the process executing this notebook by the current working directory `/proc/*/cwd`;\n", + "- check the environment variables of the process with `cat /proc//environ | od -a`;\n", + "\n", "You defined your host groups in the environment, eg:\n", "\n", " - course\n", " - ansible\n", " - staging\n", " \n", - "Ansible defines [two default groups: all and ungrouped](http://docs.ansible.com/ansible/intro_inventory.html#default-groups).\n", + "Ansible defines [two default groups: all and ungrouped](http://docs.ansible.com/ansible/latest/intro_inventory.html#default-groups).\n", "\n", "You can assign variables to all hosts using the `all` group." ] diff --git a/ansible-101/notebooks/02_delivery_layout.ipynb b/ansible-101/notebooks/02_delivery_layout.ipynb index 11fcd42..555fff8 100644 --- a/ansible-101/notebooks/02_delivery_layout.ipynb +++ b/ansible-101/notebooks/02_delivery_layout.ipynb @@ -22,18 +22,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[Errno 2] No such file or directory: '/notebooks/exercise-00'\n", - "/home/rpolli/workspace-py/python-course/ansible-101/notebooks\n" - ] - } - ], + "outputs": [], "source": [ "cd /notebooks/exercise-00" ] @@ -93,17 +84,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cat: ansible.cfg: File o directory non esistente\n" - ] - } - ], + "outputs": [], "source": [ "# When running ansible, the first file to be read is\n", "!cat ansible.cfg" @@ -173,8 +156,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Use this cell for the exercise\n", - "!ansible -m ping all[0]" + "# Use this cell for the exercise" ] }, { @@ -239,9 +221,7 @@ }, "outputs": [], "source": [ - "# Write here the answer!\n", - "[defaults] # ansible.cfg\n", - "private_key_file = " + "# Write here the answer!" ] }, { diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index 63be027..b75aa6d 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -12,15 +12,16 @@ " - ansible.cfg\n", " - inventory\n", "\n", + "[![](https://mermaid.ink/img/pako:eNpVkUFTgzAQhf9KZg-eKAMp0MLBk3rSi94kjpPC0mYKCZMAim3_uwFKxdt7mW_37WZPkKkcIYG95vWBPL8yyaRpd5Pl0ohdiW5W7NOFJgVPCr4qRInkg0mU-VC1BFar-7PGAjXKDM2ZDOhnx9uyIXeTOWJvrBayQ9ko3f_LHQjTmwar9GmQi0Cb99csnVrW3JgvpfMrVqrsOGNDTGrMgdRadLxBYh-umFWWug2Q3tQYf4UM6g71vCQ4UKGuuMjtj52YJIRBc8AKGSRW5lgM8zBg8mLRts5t4mMubFNIGt2iA7xt1Fsvs9lPzIPgdvEKbGJp7GvN5btS1QxZC8kJviHxg8ANvDD0vYCut7EXO9BDQuPQjcI4WtMoonTrby4O_Iz1nhv5IfVCP9puaOBFnu8AjgO9TGcfr3_5BZh-syk?type=png)](https://mermaid.live/edit#pako:eNpVkUFTgzAQhf9KZg-eKAMp0MLBk3rSi94kjpPC0mYKCZMAim3_uwFKxdt7mW_37WZPkKkcIYG95vWBPL8yyaRpd5Pl0ohdiW5W7NOFJgVPCr4qRInkg0mU-VC1BFar-7PGAjXKDM2ZDOhnx9uyIXeTOWJvrBayQ9ko3f_LHQjTmwar9GmQi0Cb99csnVrW3JgvpfMrVqrsOGNDTGrMgdRadLxBYh-umFWWug2Q3tQYf4UM6g71vCQ4UKGuuMjtj52YJIRBc8AKGSRW5lgM8zBg8mLRts5t4mMubFNIGt2iA7xt1Fsvs9lPzIPgdvEKbGJp7GvN5btS1QxZC8kJviHxg8ANvDD0vYCut7EXO9BDQuPQjcI4WtMoonTrby4O_Iz1nhv5IfVCP9puaOBFnu8AjgO9TGcfr3_5BZh-syk)\n", "\n", "We're going to describe the following setup:\n", "\n", - " - direct access to client machines (eg. no bastion)\n", - " - one `inventory` file\n", - " - no host_key_check\n", - " - no retry files\n", - " - client machine username/password is `root:root`\n", - " - no public key is installed by default\n", + " - direct access to client machines (eg. no bastion);\n", + " - one `inventory` file;\n", + " - no host_key_check;\n", + " - no retry files;\n", + " - client machine username is `root`. The password will be generated via the ansible `lookup()` plugin;\n", + " - no public key is installed by default.\n", "\n" ] }, @@ -40,11 +41,11 @@ "source": [ "## Preparation\n", "\n", - "The first steps include creating:\n", + "The preparation steps include creating:\n", "\n", - " - all secret files (ssh identity, vault pin file)\n", - " - ansible.cfg (the deployment descriptor) \n", - " - and the inventory." + "1. `ansible.cfg` (the deployment descriptor) referencing the files we're going to create;\n", + "1. all secret files (ssh identity, vault pin file);\n", + "1. and the inventory." ] }, { @@ -53,7 +54,27 @@ "metadata": {}, "outputs": [], "source": [ - "# At first create a proper ssh key for the project\n", + "# Prepare a deployment descriptor referencing the .pin file\n", + "!cat ansible.cfg" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a new ssh keypair for the project:\n", + "\n", + "- cleanup previously existing keys;\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Remove existing keys.\n", "! rm id_ansible.pub id_ansible -rf" ] }, @@ -62,9 +83,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now create a new ssh key for the project:\n", "\n", - "- the default name is `id_ansible`;\n", + "- the key filename is `id_ansible`;\n", "- the algorithm is `ed25519`, which is the most efficient one. For further information on ed25519 see [RFC8032](https://datatracker.ietf.org/doc/html/rfc8032).\n", "\n", "\n" @@ -76,17 +96,16 @@ "metadata": {}, "outputs": [], "source": [ + "# Eventually create the new keypair.\n", "! test -f id_ansible || ssh-keygen -q -t ed25519 -f id_ansible -N ''" ] }, { - "cell_type": "code", - "execution_count": null, + "attachments": {}, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# Use the `lookup` plugin to create a password file.\n", - "!ansible localhost -m copy -a \"content='{{ lookup('password', '/dev/null length=20 chars=ascii_letters,digits') }}' dest=$PWD/.pin\"" + "Create the vault password file named `.pin` using the `lookup` plugin. We'll use this password to encrypt the vault later on.\n" ] }, { @@ -95,8 +114,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Let's show the password :)\n", - "! cat .pin" + "# Use the `lookup` plugin to create a password file named `.pin`.\n", + "!ansible localhost -m copy -a \"content='{{ lookup('password', '/dev/null length=64') }}' dest=$PWD/.pin\"" ] }, { @@ -105,8 +124,8 @@ "metadata": {}, "outputs": [], "source": [ - "# then prepare a deployment descriptor referencing the .pin file\n", - "!cat ansible.cfg" + "# Let's show the vault password :)\n", + "! cat .pin" ] }, { @@ -161,7 +180,7 @@ "source": [ "# Solution\n", "!ansible localhost -mcopy \\\n", - " -a \"content='root_password: {{lookup('password','/dev/null')}}' dest=$PWD/vault.yaml\"" + " -a \"content='root_password: \\\"{{lookup('password','/dev/null')}}\\\"' dest=$PWD/vault.yaml\"" ] }, { @@ -171,7 +190,7 @@ "source": [ "\n", "\n", - "- use the ansible_connection=docker method specified in `inventory.docker` to copy the ssh key to the docker containers. Without this, the ssh key will not be available to the docker containers and you cannot access them via ssh.\n", + "- use the `ansible_connection=docker` method specified in `inventory.docker` to copy the ssh key to the docker containers. Without this, the ssh key will not be available to the docker containers and you cannot access them via ssh.\n", "\n", "In real infrastructures, the ssh keys are usually provisioned at boot.\n", "\n", @@ -183,7 +202,9 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "!cat inventory.docker" + ] }, { "cell_type": "code", @@ -191,10 +212,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Provision the ssh keys using the docker_connector\n", - "!cat inventory.docker\n", + "# Provision the ssh keys using the docker_connector.\n", + "# Why do we need to use double braces?\n", "!ansible docker -i inventory.docker -m shell \\\n", - " -a \"echo 'root:{{root_password}}' | chpasswd\" \\\n", + " -a \"echo 'root:{{{{root_password}}}}' | chpasswd\" \\\n", " -e@vault.yaml " ] }, @@ -251,7 +272,7 @@ "outputs": [], "source": [ "# We need to encrypt it. \n", - "!ansible-vault encrypt vault.yml\n" + "!ansible-vault encrypt vault.yml" ] }, { @@ -327,17 +348,9 @@ }, { "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cat: copy-key.yml: File o directory non esistente\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "!cat copy-key.yml" ] diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 16e8c05..2e8b7f6 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -15,1182 +16,25 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/notebooks/exercise-03\n" - ] - } - ], + "outputs": [], "source": [ "cd /notebooks/exercise-03" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", - "\u001b[1;35msource\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[0;32mlocalhost | SUCCESS => {\u001b[0m\n", - "\u001b[0;32m \"ansible_facts\": {\u001b[0m\n", - "\u001b[0;32m \"ansible_all_ipv4_addresses\": [\u001b[0m\n", - "\u001b[0;32m \"172.17.0.2\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"ansible_all_ipv6_addresses\": [], \u001b[0m\n", - "\u001b[0;32m \"ansible_apparmor\": {\u001b[0m\n", - "\u001b[0;32m \"status\": \"disabled\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_architecture\": \"x86_64\", \u001b[0m\n", - "\u001b[0;32m \"ansible_bios_date\": \"11/28/2019\", \u001b[0m\n", - "\u001b[0;32m \"ansible_bios_version\": \"1.3.1\", \u001b[0m\n", - "\u001b[0;32m \"ansible_cmdline\": {\u001b[0m\n", - "\u001b[0;32m \"BOOT_IMAGE\": \"(hd0,gpt7)/vmlinuz-5.14.18-100.fc33.x86_64\", \u001b[0m\n", - "\u001b[0;32m \"quiet\": true, \u001b[0m\n", - "\u001b[0;32m \"rd.lvm.lv\": \"fedora_localhost-live/swap\", \u001b[0m\n", - "\u001b[0;32m \"resume\": \"/dev/mapper/fedora_localhost--live-swap\", \u001b[0m\n", - "\u001b[0;32m \"rhgb\": true, \u001b[0m\n", - "\u001b[0;32m \"ro\": true, \u001b[0m\n", - "\u001b[0;32m \"root\": \"/dev/mapper/fedora_localhost--live-root\", \u001b[0m\n", - "\u001b[0;32m \"systemd.unified_cgroup_hierarchy\": \"0\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_date_time\": {\u001b[0m\n", - "\u001b[0;32m \"date\": \"2023-05-15\", \u001b[0m\n", - "\u001b[0;32m \"day\": \"15\", \u001b[0m\n", - "\u001b[0;32m \"epoch\": \"1684168092\", \u001b[0m\n", - "\u001b[0;32m \"hour\": \"16\", \u001b[0m\n", - "\u001b[0;32m \"iso8601\": \"2023-05-15T16:28:12Z\", \u001b[0m\n", - "\u001b[0;32m \"iso8601_basic\": \"20230515T162812599788\", \u001b[0m\n", - "\u001b[0;32m \"iso8601_basic_short\": \"20230515T162812\", \u001b[0m\n", - "\u001b[0;32m \"iso8601_micro\": \"2023-05-15T16:28:12.599831Z\", \u001b[0m\n", - "\u001b[0;32m \"minute\": \"28\", \u001b[0m\n", - "\u001b[0;32m \"month\": \"05\", \u001b[0m\n", - "\u001b[0;32m \"second\": \"12\", \u001b[0m\n", - "\u001b[0;32m \"time\": \"16:28:12\", \u001b[0m\n", - "\u001b[0;32m \"tz\": \"UTC\", \u001b[0m\n", - "\u001b[0;32m \"tz_offset\": \"+0000\", \u001b[0m\n", - "\u001b[0;32m \"weekday\": \"Monday\", \u001b[0m\n", - "\u001b[0;32m \"weekday_number\": \"1\", \u001b[0m\n", - "\u001b[0;32m \"weeknumber\": \"20\", \u001b[0m\n", - "\u001b[0;32m \"year\": \"2023\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_default_ipv4\": {\u001b[0m\n", - "\u001b[0;32m \"address\": \"172.17.0.2\", \u001b[0m\n", - "\u001b[0;32m \"alias\": \"eth0\", \u001b[0m\n", - "\u001b[0;32m \"broadcast\": \"172.17.255.255\", \u001b[0m\n", - "\u001b[0;32m \"gateway\": \"172.17.0.1\", \u001b[0m\n", - "\u001b[0;32m \"interface\": \"eth0\", \u001b[0m\n", - "\u001b[0;32m \"macaddress\": \"02:42:ac:11:00:02\", \u001b[0m\n", - "\u001b[0;32m \"mtu\": 1500, \u001b[0m\n", - "\u001b[0;32m \"netmask\": \"255.255.0.0\", \u001b[0m\n", - "\u001b[0;32m \"network\": \"172.17.0.0\", \u001b[0m\n", - "\u001b[0;32m \"type\": \"ether\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_default_ipv6\": {}, \u001b[0m\n", - "\u001b[0;32m \"ansible_device_links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": {}, \u001b[0m\n", - "\u001b[0;32m \"labels\": {}, \u001b[0m\n", - "\u001b[0;32m \"masters\": {\u001b[0m\n", - "\u001b[0;32m \"dm-3\": [\u001b[0m\n", - "\u001b[0;32m \"dm-4\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"nvme0n1p8\": [\u001b[0m\n", - "\u001b[0;32m \"dm-0\", \u001b[0m\n", - "\u001b[0;32m \"dm-1\", \u001b[0m\n", - "\u001b[0;32m \"dm-2\", \u001b[0m\n", - "\u001b[0;32m \"dm-3\"\u001b[0m\n", - "\u001b[0;32m ]\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"uuids\": {}\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_devices\": {\u001b[0m\n", - "\u001b[0;32m \"dm-0\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"177537024\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"84.66 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"dm-1\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"16777216\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"8.00 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"dm-2\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"567967744\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"270.83 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"dm-3\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [\u001b[0m\n", - "\u001b[0;32m \"luks-f770bef1-f11a-4d08-8103-9429f9fd25b0\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [\u001b[0m\n", - "\u001b[0;32m \"dm-4\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"55902208\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"26.66 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"dm-4\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"55869440\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"26.64 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop0\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"8\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"4.00 KB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop1\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"113896\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"55.61 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop10\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"716160\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"349.69 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop11\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"166424\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"81.26 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop12\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"187776\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"91.69 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop13\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"265904\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"129.84 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop14\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"22872\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"11.17 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop15\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"109032\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"53.24 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop16\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"22440\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"10.96 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop17\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"149720\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"73.11 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop18\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"229112\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"111.87 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop19\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"245848\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"120.04 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop2\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"149488\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"72.99 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop20\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"21680\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"10.59 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop21\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"109032\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"53.24 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop22\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"447264\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"218.39 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop23\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"716168\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"349.69 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop24\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"943224\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"460.56 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop25\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"129952\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"63.45 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop3\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"113944\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"55.64 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop4\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"0.00 Bytes\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop5\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"337560\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"164.82 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop6\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"337560\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"164.82 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop7\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"129712\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"63.34 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop8\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"447264\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"218.39 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"loop9\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"mq-deadline\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"360104\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"175.83 MB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"nvme0n1\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": \"PC SN520 NVMe WDC 512GB\", \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"none\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"1000215216\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"476.94 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"512\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"zram0\": {\u001b[0m\n", - "\u001b[0;32m \"holders\": [], \u001b[0m\n", - "\u001b[0;32m \"host\": \"\", \u001b[0m\n", - "\u001b[0;32m \"links\": {\u001b[0m\n", - "\u001b[0;32m \"ids\": [], \u001b[0m\n", - "\u001b[0;32m \"labels\": [], \u001b[0m\n", - "\u001b[0;32m \"masters\": [], \u001b[0m\n", - "\u001b[0;32m \"uuids\": []\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"model\": null, \u001b[0m\n", - "\u001b[0;32m \"partitions\": {}, \u001b[0m\n", - "\u001b[0;32m \"removable\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"rotational\": \"0\", \u001b[0m\n", - "\u001b[0;32m \"sas_address\": null, \u001b[0m\n", - "\u001b[0;32m \"sas_device_handle\": null, \u001b[0m\n", - "\u001b[0;32m \"scheduler_mode\": \"\", \u001b[0m\n", - "\u001b[0;32m \"sectors\": \"8388608\", \u001b[0m\n", - "\u001b[0;32m \"sectorsize\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"size\": \"32.00 GB\", \u001b[0m\n", - "\u001b[0;32m \"support_discard\": \"4096\", \u001b[0m\n", - "\u001b[0;32m \"vendor\": null, \u001b[0m\n", - "\u001b[0;32m \"virtual\": 1\u001b[0m\n", - "\u001b[0;32m }\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution\": \"Debian\", \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_file_parsed\": true, \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_file_path\": \"/etc/os-release\", \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_file_variety\": \"Debian\", \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_major_version\": \"8\", \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_release\": \"jessie\", \u001b[0m\n", - "\u001b[0;32m \"ansible_distribution_version\": \"8.10\", \u001b[0m\n", - "\u001b[0;32m \"ansible_dns\": {\u001b[0m\n", - "\u001b[0;32m \"nameservers\": [\u001b[0m\n", - "\u001b[0;32m \"8.8.8.8\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"search\": [\u001b[0m\n", - "\u001b[0;32m \"fritz.box\"\u001b[0m\n", - "\u001b[0;32m ]\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_domain\": \"\", \u001b[0m\n", - "\u001b[0;32m \"ansible_effective_group_id\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_effective_user_id\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_env\": {\u001b[0m\n", - "\u001b[0;32m \"CLICOLOR\": \"1\", \u001b[0m\n", - "\u001b[0;32m \"DOCKER_HOST\": \"172.17.0.1\", \u001b[0m\n", - "\u001b[0;32m \"GIT_PAGER\": \"cat\", \u001b[0m\n", - "\u001b[0;32m \"GPG_KEY\": \"C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF\", \u001b[0m\n", - "\u001b[0;32m \"HOME\": \"/root\", \u001b[0m\n", - "\u001b[0;32m \"HOSTNAME\": \"f063a33adb7a\", \u001b[0m\n", - "\u001b[0;32m \"JPY_PARENT_PID\": \"7\", \u001b[0m\n", - "\u001b[0;32m \"LANG\": \"C.UTF-8\", \u001b[0m\n", - "\u001b[0;32m \"MPLBACKEND\": \"module://ipykernel.pylab.backend_inline\", \u001b[0m\n", - "\u001b[0;32m \"PAGER\": \"cat\", \u001b[0m\n", - "\u001b[0;32m \"PATH\": \"/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\", \u001b[0m\n", - "\u001b[0;32m \"PWD\": \"/notebooks/exercise-03\", \u001b[0m\n", - "\u001b[0;32m \"PYTHON_PIP_VERSION\": \"9.0.1\", \u001b[0m\n", - "\u001b[0;32m \"PYTHON_VERSION\": \"2.7.14\", \u001b[0m\n", - "\u001b[0;32m \"TERM\": \"xterm-color\", \u001b[0m\n", - "\u001b[0;32m \"USE_HTTP\": \"1\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_eth0\": {\u001b[0m\n", - "\u001b[0;32m \"active\": true, \u001b[0m\n", - "\u001b[0;32m \"device\": \"eth0\", \u001b[0m\n", - "\u001b[0;32m \"ipv4\": {\u001b[0m\n", - "\u001b[0;32m \"address\": \"172.17.0.2\", \u001b[0m\n", - "\u001b[0;32m \"broadcast\": \"172.17.255.255\", \u001b[0m\n", - "\u001b[0;32m \"netmask\": \"255.255.0.0\", \u001b[0m\n", - "\u001b[0;32m \"network\": \"172.17.0.0\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"macaddress\": \"02:42:ac:11:00:02\", \u001b[0m\n", - "\u001b[0;32m \"mtu\": 1500, \u001b[0m\n", - "\u001b[0;32m \"promisc\": false, \u001b[0m\n", - "\u001b[0;32m \"speed\": 10000, \u001b[0m\n", - "\u001b[0;32m \"type\": \"ether\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_fips\": false, \u001b[0m\n", - "\u001b[0;32m \"ansible_form_factor\": \"unknown (31)\", \u001b[0m\n", - "\u001b[0;32m \"ansible_fqdn\": \"f063a33adb7a\", \u001b[0m\n", - "\u001b[0;32m \"ansible_hostname\": \"f063a33adb7a\", \u001b[0m\n", - "\u001b[0;32m \"ansible_interfaces\": [\u001b[0m\n", - "\u001b[0;32m \"lo\", \u001b[0m\n", - "\u001b[0;32m \"eth0\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"ansible_kernel\": \"5.14.18-100.fc33.x86_64\", \u001b[0m\n", - "\u001b[0;32m \"ansible_lo\": {\u001b[0m\n", - "\u001b[0;32m \"active\": true, \u001b[0m\n", - "\u001b[0;32m \"device\": \"lo\", \u001b[0m\n", - "\u001b[0;32m \"ipv4\": {\u001b[0m\n", - "\u001b[0;32m \"address\": \"127.0.0.1\", \u001b[0m\n", - "\u001b[0;32m \"broadcast\": \"host\", \u001b[0m\n", - "\u001b[0;32m \"netmask\": \"255.0.0.0\", \u001b[0m\n", - "\u001b[0;32m \"network\": \"127.0.0.0\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"mtu\": 65536, \u001b[0m\n", - "\u001b[0;32m \"promisc\": false, \u001b[0m\n", - "\u001b[0;32m \"type\": \"loopback\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_local\": {}, \u001b[0m\n", - "\u001b[0;32m \"ansible_lsb\": {}, \u001b[0m\n", - "\u001b[0;32m \"ansible_machine\": \"x86_64\", \u001b[0m\n", - "\u001b[0;32m \"ansible_machine_id\": \"8c859f2bde9e41155bca40d2d85aebb5\", \u001b[0m\n", - "\u001b[0;32m \"ansible_memfree_mb\": 176, \u001b[0m\n", - "\u001b[0;32m \"ansible_memory_mb\": {\u001b[0m\n", - "\u001b[0;32m \"nocache\": {\u001b[0m\n", - "\u001b[0;32m \"free\": 3953, \u001b[0m\n", - "\u001b[0;32m \"used\": 11824\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"real\": {\u001b[0m\n", - "\u001b[0;32m \"free\": 176, \u001b[0m\n", - "\u001b[0;32m \"total\": 15777, \u001b[0m\n", - "\u001b[0;32m \"used\": 15601\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"swap\": {\u001b[0m\n", - "\u001b[0;32m \"cached\": 18, \u001b[0m\n", - "\u001b[0;32m \"free\": 9748, \u001b[0m\n", - "\u001b[0;32m \"total\": 12287, \u001b[0m\n", - "\u001b[0;32m \"used\": 2539\u001b[0m\n", - "\u001b[0;32m }\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_memtotal_mb\": 15777, \u001b[0m\n", - "\u001b[0;32m \"ansible_mounts\": [\u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590798, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370504, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732655, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10736144, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003489, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419908608, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"ansible_nodename\": \"f063a33adb7a\", \u001b[0m\n", - "\u001b[0;32m \"ansible_os_family\": \"Debian\", \u001b[0m\n", - "\u001b[0;32m \"ansible_pkg_mgr\": \"apt\", \u001b[0m\n", - "\u001b[0;32m \"ansible_processor\": [\u001b[0m\n", - "\u001b[0;32m \"0\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"1\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"2\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"3\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"4\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"5\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"6\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\", \u001b[0m\n", - "\u001b[0;32m \"7\", \u001b[0m\n", - "\u001b[0;32m \"GenuineIntel\", \u001b[0m\n", - "\u001b[0;32m \"Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"ansible_processor_cores\": 4, \u001b[0m\n", - "\u001b[0;32m \"ansible_processor_count\": 1, \u001b[0m\n", - "\u001b[0;32m \"ansible_processor_threads_per_core\": 2, \u001b[0m\n", - "\u001b[0;32m \"ansible_processor_vcpus\": 8, \u001b[0m\n", - "\u001b[0;32m \"ansible_product_name\": \"Inspiron 7391 2n1\", \u001b[0m\n", - "\u001b[0;32m \"ansible_product_serial\": \"BNV8KW2\", \u001b[0m\n", - "\u001b[0;32m \"ansible_product_uuid\": \"4c4c4544-004e-5610-8038-c2c04f4b5732\", \u001b[0m\n", - "\u001b[0;32m \"ansible_product_version\": \"NA\", \u001b[0m\n", - "\u001b[0;32m \"ansible_python\": {\u001b[0m\n", - "\u001b[0;32m \"executable\": \"/usr/local/bin/python\", \u001b[0m\n", - "\u001b[0;32m \"has_sslcontext\": true, \u001b[0m\n", - "\u001b[0;32m \"type\": \"CPython\", \u001b[0m\n", - "\u001b[0;32m \"version\": {\u001b[0m\n", - "\u001b[0;32m \"major\": 2, \u001b[0m\n", - "\u001b[0;32m \"micro\": 14, \u001b[0m\n", - "\u001b[0;32m \"minor\": 7, \u001b[0m\n", - "\u001b[0;32m \"releaselevel\": \"final\", \u001b[0m\n", - "\u001b[0;32m \"serial\": 0\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"version_info\": [\u001b[0m\n", - "\u001b[0;32m 2, \u001b[0m\n", - "\u001b[0;32m 7, \u001b[0m\n", - "\u001b[0;32m 14, \u001b[0m\n", - "\u001b[0;32m \"final\", \u001b[0m\n", - "\u001b[0;32m 0\u001b[0m\n", - "\u001b[0;32m ]\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_python_version\": \"2.7.14\", \u001b[0m\n", - "\u001b[0;32m \"ansible_real_group_id\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_real_user_id\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_selinux\": {\u001b[0m\n", - "\u001b[0;32m \"status\": \"Missing selinux Python library\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"ansible_selinux_python_present\": false, \u001b[0m\n", - "\u001b[0;32m \"ansible_service_mgr\": \"upstart\", \u001b[0m\n", - "\u001b[0;32m \"ansible_swapfree_mb\": 9748, \u001b[0m\n", - "\u001b[0;32m \"ansible_swaptotal_mb\": 12287, \u001b[0m\n", - "\u001b[0;32m \"ansible_system\": \"Linux\", \u001b[0m\n", - "\u001b[0;32m \"ansible_system_capabilities\": [\u001b[0m\n", - "\u001b[0;32m \"cap_chown\", \u001b[0m\n", - "\u001b[0;32m \"cap_dac_override\", \u001b[0m\n", - "\u001b[0;32m \"cap_fowner\", \u001b[0m\n", - "\u001b[0;32m \"cap_fsetid\", \u001b[0m\n", - "\u001b[0;32m \"cap_kill\", \u001b[0m\n", - "\u001b[0;32m \"cap_setgid\", \u001b[0m\n", - "\u001b[0;32m \"cap_setuid\", \u001b[0m\n", - "\u001b[0;32m \"cap_setpcap\", \u001b[0m\n", - "\u001b[0;32m \"cap_net_bind_service\", \u001b[0m\n", - "\u001b[0;32m \"cap_net_raw\", \u001b[0m\n", - "\u001b[0;32m \"cap_sys_chroot\", \u001b[0m\n", - "\u001b[0;32m \"cap_mknod\", \u001b[0m\n", - "\u001b[0;32m \"cap_audit_write\", \u001b[0m\n", - "\u001b[0;32m \"cap_setfcap+eip\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"ansible_system_capabilities_enforced\": \"True\", \u001b[0m\n", - "\u001b[0;32m \"ansible_system_vendor\": \"Dell Inc.\", \u001b[0m\n", - "\u001b[0;32m \"ansible_uptime_seconds\": 1691606, \u001b[0m\n", - "\u001b[0;32m \"ansible_user_dir\": \"/root\", \u001b[0m\n", - "\u001b[0;32m \"ansible_user_gecos\": \"root\", \u001b[0m\n", - "\u001b[0;32m \"ansible_user_gid\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_user_id\": \"root\", \u001b[0m\n", - "\u001b[0;32m \"ansible_user_shell\": \"/bin/bash\", \u001b[0m\n", - "\u001b[0;32m \"ansible_user_uid\": 0, \u001b[0m\n", - "\u001b[0;32m \"ansible_userspace_architecture\": \"x86_64\", \u001b[0m\n", - "\u001b[0;32m \"ansible_userspace_bits\": \"64\", \u001b[0m\n", - "\u001b[0;32m \"ansible_virtualization_role\": \"guest\", \u001b[0m\n", - "\u001b[0;32m \"ansible_virtualization_type\": \"docker\", \u001b[0m\n", - "\u001b[0;32m \"gather_subset\": [\u001b[0m\n", - "\u001b[0;32m \"all\"\u001b[0m\n", - "\u001b[0;32m ], \u001b[0m\n", - "\u001b[0;32m \"module_setup\": true\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"changed\": false\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "# Let's run the setup module\n", - "\n", "!ansible -i inventory -m setup localhost " ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1204,57 +48,24 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "solution": "shown", "solution_first": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\n", - "source\n", - " [WARNING]: No inventory was parsed, only implicit localhost is available\n", - " [WARNING]: Could not match supplied host pattern, ignoring: all\n", - " [WARNING]: provided hosts list is empty, only localhost is available\n" - ] - } - ], + "outputs": [], "source": [ "!ansible >/dev/null -i inventory -m setup localhost --tree host_status" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "code_folding": [], "solution": "shown" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "host_status\r\n", - "└── localhost\r\n", - "\r\n", - "0 directories, 1 file\r\n" - ] - }, - { - "data": { - "text/plain": [ - "[u'172.17.0.2']" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Solution\n", "!tree host_status\n", @@ -1265,6 +76,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1281,15 +93,15 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "# use this cell for the exercise\n", - "!ansible-pla" + "# use this cell for the exercise" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1306,253 +118,15 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", - "\u001b[1;35msource\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\n", - "PLAY [Use this section to complete the exercise, and the next section as a reference for the debug module.] ***\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "TASK [Dump the requested facts.] ***********************************************\n", - "\u001b[0;32mok: [localhost] => {\u001b[0m\n", - "\u001b[0;32m \"msg\": \"A string\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "PLAY [Those tasks are run on localhost only] ***********************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "TASK [This is the debug module.] ***********************************************\n", - "\u001b[0;32mok: [localhost] => {\u001b[0m\n", - "\u001b[0;32m \"msg\": \"A string\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "TASK [The debug module can print variables too] ********************************\n", - "\u001b[0;32mok: [localhost] => {\u001b[0m\n", - "\u001b[0;32m \"ansible_hostname\": \"f063a33adb7a\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "TASK [We can iterate too...] ***************************************************\n", - "\u001b[0;32mok: [localhost] => (item=cap_chown) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_chown\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_chown\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_dac_override) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_dac_override\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_dac_override\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_fowner) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_fowner\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_fowner\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_fsetid) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_fsetid\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_fsetid\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_kill) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_kill\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_kill\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_setgid) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_setgid\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_setgid\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_setuid) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_setuid\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_setuid\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_setpcap) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_setpcap\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_setpcap\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_net_bind_service) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_net_bind_service\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_net_bind_service\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_net_raw) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_net_raw\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_net_raw\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_sys_chroot) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_sys_chroot\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_sys_chroot\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_mknod) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_mknod\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_mknod\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_audit_write) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_audit_write\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_audit_write\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item=cap_setfcap+eip) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": \"cap_setfcap+eip\", \u001b[0m\n", - "\u001b[0;32m \"msg\": \"cap_setfcap+eip\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "TASK [..and inspect/format variables] ******************************************\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/code'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/notebooks'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/resolv.conf'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/hostname'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/etc/hosts'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370581, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4732036, u'block_available': 590721, u'size_available': 2419593216, u'fstype': u'xfs', u'inode_total': 10735528, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003492, u'block_size': 4096, u'mount': u'/root/.jupyter/custom/custom.css'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 590721, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370581, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4732036, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10735528, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003492, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2419593216, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"The device is /dev/mapper/fedora_localhost--live-home\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "PLAY RECAP *********************************************************************\n", - "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=7 \u001b[0m changed=0 unreachable=0 failed=0 \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "!ansible-playbook get-facts.yml" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1574,6 +148,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1607,29 +182,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", - "\u001b[1;35msource\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[0;32mlocalhost | SUCCESS => {\u001b[0m\n", - "\u001b[0;32m \"ansible_user[:2]\": \"ro\", \u001b[0m\n", - "\u001b[0;32m \"changed\": false\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "# Use the debug module to process a variable\n", "# Modify the command to print the last two letters.\n", @@ -1638,110 +193,25 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---\r\n", - "- hosts: localhost\r\n", - " tags: variables\r\n", - " vars:\r\n", - " - one: 1\r\n", - " - pi: 3.1415\r\n", - " tasks:\r\n", - " - debug:\r\n", - " msg: >\r\n", - " {{ansible_hostname }} {{ one }}\r\n", - " - debug:\r\n", - " msg: >\r\n", - " The output is {{ one + pi }}\r\n", - "\r\n", - "\r\n", - "- hosts: localhost\r\n", - " tags: filters\r\n", - " vars:\r\n", - " - one: 1\r\n", - " - pi: 3.1415\r\n", - " tasks:\r\n", - " - name: Ansible can process expressions using filters\r\n", - " debug:\r\n", - " msg: >\r\n", - " Floor it {{ ( one + pi ) | int }}\r\n", - "\r\n", - "- hosts: localhost\r\n", - " tags: exercise\r\n", - " name: Use this cell for the exercise\r\n", - " tasks:\r\n", - " - name: >\r\n", - " Show the free percentage of the local disk using\r\n", - " facts and filters\r\n", - " debug: msg=\"Replace me\"\r\n" - ] - } - ], + "outputs": [], "source": [ "!cat vars-and-facts.yml" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", - "\u001b[1;35msource\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\n", - "PLAY [localhost] ***************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "TASK [debug] *******************************************************************\n", - "\u001b[0;32mok: [localhost] => {\u001b[0m\n", - "\u001b[0;32m \"msg\": \"f063a33adb7a 1\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "TASK [debug] *******************************************************************\n", - "\u001b[0;32mok: [localhost] => {\u001b[0m\n", - "\u001b[0;32m \"msg\": \"The output is 4.1415\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "PLAY [localhost] ***************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "PLAY [Use this cell for the exercise] ******************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "PLAY RECAP *********************************************************************\n", - "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=5 \u001b[0m changed=0 unreachable=0 failed=0 \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# This playbook mixes variables and facts\n", "!ansible-playbook vars-and-facts.yml --tags variables" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1802,6 +272,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1819,202 +290,23 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1;35m [WARNING]: Unable to parse /notebooks/exercise-03/inventory as an inventory\u001b[0m\n", - "\u001b[1;35msource\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: No inventory was parsed, only implicit localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: Could not match supplied host pattern, ignoring: all\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\u001b[1;35m [WARNING]: provided hosts list is empty, only localhost is available\u001b[0m\n", - "\u001b[1;35m\u001b[0m\n", - "\n", - "PLAY [localhost] ***************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "PLAY [localhost] ***************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "PLAY [Use this cell for the exercise] ******************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [localhost]\u001b[0m\n", - "\n", - "TASK [Show the free percentage of the local disk using facts and filters] ******\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/code'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/code\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/code 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/notebooks'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/notebooks\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/notebooks 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/resolv.conf'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/resolv.conf\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/etc/resolv.conf 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/hostname'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hostname\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/etc/hostname 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/etc/hosts'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/etc/hosts\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/etc/hosts 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[0;32mok: [localhost] => (item={u'block_used': 70370259, u'uuid': u'N/A', u'size_total': 290657492992, u'block_total': 70961302, u'inode_available': 4734637, u'block_available': 591043, u'size_available': 2420912128, u'fstype': u'xfs', u'inode_total': 10738168, u'options': u'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind', u'device': u'/dev/mapper/fedora_localhost--live-home', u'inode_used': 6003531, u'block_size': 4096, u'mount': u'/root/.jupyter/custom/custom.css'}) => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"item\": {\u001b[0m\n", - "\u001b[0;32m \"block_available\": 591043, \u001b[0m\n", - "\u001b[0;32m \"block_size\": 4096, \u001b[0m\n", - "\u001b[0;32m \"block_total\": 70961302, \u001b[0m\n", - "\u001b[0;32m \"block_used\": 70370259, \u001b[0m\n", - "\u001b[0;32m \"device\": \"/dev/mapper/fedora_localhost--live-home\", \u001b[0m\n", - "\u001b[0;32m \"fstype\": \"xfs\", \u001b[0m\n", - "\u001b[0;32m \"inode_available\": 4734637, \u001b[0m\n", - "\u001b[0;32m \"inode_total\": 10738168, \u001b[0m\n", - "\u001b[0;32m \"inode_used\": 6003531, \u001b[0m\n", - "\u001b[0;32m \"mount\": \"/root/.jupyter/custom/custom.css\", \u001b[0m\n", - "\u001b[0;32m \"options\": \"rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,bind\", \u001b[0m\n", - "\u001b[0;32m \"size_available\": 2420912128, \u001b[0m\n", - "\u001b[0;32m \"size_total\": 290657492992, \u001b[0m\n", - "\u001b[0;32m \"uuid\": \"N/A\"\u001b[0m\n", - "\u001b[0;32m }, \u001b[0m\n", - "\u001b[0;32m \"msg\": \"/root/.jupyter/custom/custom.css 0%\\n\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\n", - "PLAY RECAP *********************************************************************\n", - "\u001b[0;32mlocalhost\u001b[0m : \u001b[0;32mok=4 \u001b[0m changed=0 unreachable=0 failed=0 \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "!ansible-playbook vars-and-facts.yml --tags exercise" ] }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Filesystem Size Used Avail Use% Mounted on\r\n", - "overlay 271G 269G 2.3G 100% /\r\n", - "tmpfs 64M 0 64M 0% /dev\r\n", - "tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup\r\n", - "shm 64M 0 64M 0% /dev/shm\r\n", - "/dev/mapper/fedora_localhost--live-home 271G 269G 2.3G 100% /code\r\n", - "tmpfs 7.8G 0 7.8G 0% /proc/asound\r\n", - "tmpfs 7.8G 0 7.8G 0% /proc/acpi\r\n", - "tmpfs 7.8G 0 7.8G 0% /proc/scsi\r\n", - "tmpfs 7.8G 0 7.8G 0% /sys/firmware\r\n" - ] - } - ], - "source": [ - "!df -h\n" - ] - }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "# Check the difference between the output of ansible\n", + "# and the one of the OS.\n", + "!df -h" + ] } ], "metadata": { diff --git a/ansible-101/notebooks/04_loops_and_conditions.ipynb b/ansible-101/notebooks/04_loops_and_conditions.ipynb index b23cbbe..af4f282 100644 --- a/ansible-101/notebooks/04_loops_and_conditions.ipynb +++ b/ansible-101/notebooks/04_loops_and_conditions.ipynb @@ -1,10 +1,27 @@ { "cells": [ { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Loops" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /notebooks/exercise-03" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "# Loops\n", "\n", "To repeat a *single task* multiple times, you can use *`with_items`*.\n", "\n", @@ -64,15 +81,7 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cd /notebooks/exercise-03" - ] - }, - { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -138,6 +147,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -168,6 +178,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -191,6 +202,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -217,6 +229,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -238,6 +251,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -287,6 +301,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index ae8602f..02e45e0 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -11,7 +12,7 @@ " - security access eg in cloud environment\n", " - vpn eg via windows hosts\n", " \n", - "The latter case is quite boring as ansible doesn't support windows as a client platform.\n", + "The latter case is quite boring as [ansible doesn't support windows as a client platform](https://docs.ansible.com/ansible/latest/os_guide/windows_faq.html#does-ansible-work-with-windows-xp-or-server-2003).\n", "\n", "A standard approach is:\n", "\n", @@ -42,6 +43,24 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## SSH basics\n", + "\n", + "SSH connections follows this basic schema:\n", + "\n", + "1. client connects to server\n", + "2. server sends its public key\n", + "3. client checks the public key against its known_hosts file\n", + "4. if the key is not found, the client asks the user to confirm the key\n", + "5. if the key is confirmed, the client saves it in known_hosts\n", + "6. client sends its public key\n" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -60,6 +79,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -101,6 +121,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -161,6 +182,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -182,6 +204,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -211,6 +234,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/exercise-01/ansible.cfg b/ansible-101/notebooks/exercise-01/ansible.cfg index 84cb2fe..1254d61 100644 --- a/ansible-101/notebooks/exercise-01/ansible.cfg +++ b/ansible-101/notebooks/exercise-01/ansible.cfg @@ -12,3 +12,8 @@ private_key_file = id_ansible # We want to store root password in an encrypted file # but don't want to be prompted for a password each time vault_password_file = .pin + + +[ssh_connection] +# We will discuss this line later on. +ssh_args = -o UserKnownHostsFile=/dev/null diff --git a/ansible-101/notebooks/exercise-03/ansible.cfg b/ansible-101/notebooks/exercise-03/ansible.cfg index da925d1..9dd8bad 100644 --- a/ansible-101/notebooks/exercise-03/ansible.cfg +++ b/ansible-101/notebooks/exercise-03/ansible.cfg @@ -1,3 +1,6 @@ +# +# Exercise: insert comments for every parameter. +# [defaults] inventory = inventory retry_files_enabled = no diff --git a/ansible-101/notebooks/exercise-03/conditions.yml b/ansible-101/notebooks/exercise-03/conditions.yml index 1eb50e0..5e1bf17 100644 --- a/ansible-101/notebooks/exercise-03/conditions.yml +++ b/ansible-101/notebooks/exercise-03/conditions.yml @@ -10,14 +10,17 @@ - hosts: localhost tags: assert tasks: - - debug: msg="This is Linux!" + - debug: + msg: "This is Linux!" when: ansible_system == 'Linux' - - fail: msg="Stop processing now!" + - fail: + msg: "Stop processing now!" when: ansible_architecture == 'x86_64' - hosts: localhost tags: exercise tasks: - - debug: msg="Replace me" + - debug: + msg: "Replace me" when: true diff --git a/ansible-101/notebooks/exercise-03/environment.yml b/ansible-101/notebooks/exercise-03/environment.yml index 5ef9d13..f0de447 100644 --- a/ansible-101/notebooks/exercise-03/environment.yml +++ b/ansible-101/notebooks/exercise-03/environment.yml @@ -4,6 +4,6 @@ - name: Iterate thru environment debug: var: > - ansible_env.{{item}} + ansible_env.{{ item }} with_items: > - {{ansible_env | map('regex_search', '^PATH') | select('string') | list }} + {{ ansible_env | map('regex_search', '^PATH') | select('string') | list }} diff --git a/ansible-101/notebooks/exercise-03/fileglob.yml b/ansible-101/notebooks/exercise-03/fileglob.yml index a698e06..0721028 100644 --- a/ansible-101/notebooks/exercise-03/fileglob.yml +++ b/ansible-101/notebooks/exercise-03/fileglob.yml @@ -8,9 +8,11 @@ register: fileglob_remote - name: Here we go - debug: msg="{{item}}" + debug: + msg: >- + {{ item }} with_items: > - {{fileglob_remote.stdout_lines}} + {{ fileglob_remote.stdout_lines }} - hosts: web, localhost @@ -23,4 +25,5 @@ echo $WELCOME register: o - name: EuroPython is here - debug: var=o.stdout + debug: + var: o.stdout diff --git a/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml b/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml index c9afb5f..ba9f4e6 100644 --- a/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml +++ b/ansible-101/notebooks/exercise-03/vars-and-facts-solution.yml @@ -7,7 +7,7 @@ tasks: - debug: msg: > - {{ansible_hostname }} {{ one }} + {{ ansible_hostname }} {{ one }} - debug: msg: > The output is {{ one + pi }} @@ -33,6 +33,6 @@ facts and filters. Restricted to unique devices. debug: msg: > - {{item.device}} {{ (100 * item.size_available / item.size_total) | int }}% + {{ item.device }} {{ (100 * item.size_available / item.size_total) | int }}% with_items: >- {{ ansible_mounts}} diff --git a/ansible-101/notebooks/exercise-03/vars-and-facts.yml b/ansible-101/notebooks/exercise-03/vars-and-facts.yml index 4207a8a..42ff0b6 100644 --- a/ansible-101/notebooks/exercise-03/vars-and-facts.yml +++ b/ansible-101/notebooks/exercise-03/vars-and-facts.yml @@ -31,4 +31,5 @@ - name: > Show the free percentage of the local disk using facts and filters - debug: msg="Replace me" + debug: + msg: "Replace me" From 7443d4e2a846ca54b453261ac83e99493630f41b Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Tue, 23 May 2023 16:33:19 +0200 Subject: [PATCH 22/39] Editorial enhancements. --- ansible-101/cloudinit.txt | 4 +-- ansible-101/notebooks/01_architecture.ipynb | 23 +++++++++---- .../notebooks/02_delivery_layout.ipynb | 6 ++-- ansible-101/notebooks/02_vaults.ipynb | 34 ++++++++++++++----- ansible-101/notebooks/exercise-01/ansible.cfg | 5 +-- .../notebooks/exercise-01/copy-key.yml | 7 +++- ansible-101/site-digitalocean.yml | 2 +- docker-101/02-docker.md | 6 ++-- 8 files changed, 61 insertions(+), 26 deletions(-) diff --git a/ansible-101/cloudinit.txt b/ansible-101/cloudinit.txt index 0691fc7..46a9e9a 100644 --- a/ansible-101/cloudinit.txt +++ b/ansible-101/cloudinit.txt @@ -1,12 +1,12 @@ #!/bin/bash # This is NOT a cloud-init file # as https://docs.digitalocean.com/products/droplets/how-to/provide-user-data/ suggests, -# we may insert a payload script. +# we may insert a payload script. # If we had cloud-init file, we could have used this: # package_update: false # package_upgrade: false -# but we are simply rewriting this config file +# but we are simply rewriting this config file echo "APT::Periodic::Update-Package-Lists \"0\";" > /etc/apt/apt.conf.d/20auto-upgrades echo "APT::Periodic::Unattended-Upgrade \"0\";" >> /etc/apt/apt.conf.d/20auto-upgrades diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index fefad3a..7acb994 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -32,15 +32,20 @@ "- managing data centers through machine-readable definition files;\n", "- install, configure, decommission physical and virtual resources;\n", "- avoid manual processes;\n", - "- speed ++, costs --, risk --;\n", + "- speed ++, costs --, risk -- (see [Google SRE Book](https://sre.google/workbook/postmortem-culture/) );\n", "- declarative (describe the expected state) or imperative (describe the steps) approaches;\n", "- push or pull model;\n", "\n", - "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ)\n", - "\n", - "Tricks:\n", + "[![](https://mermaid.ink/img/pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ?type=png)](https://mermaid.live/edit#pako:eNrNVMFu2zAM_RVBhyEB4sB2Yjfxhh7W9RB0RYclp0U9KDaTGLElT5LbuXH-fZQVdw3QATvuYpP0I_keKetIU5kBTajneUyY3BSQkIXYKq6NqlNTKyBckxsEMdFhdopXe_L1OxNMZPA0GDD6QWx09dE9tzzZcq_WoIgzC14ZWb2FsC7xbNPh0Ba-Jq2DWzpeVReFp-BnDdog2rrk7LZoVHI9-INGgA3p3EjVoKNTlVdGo2WgrApuwNp7qY0ePrpeIHa5AKvAWQSVkfYaYQ93Lckv5HdkLaD9hN_vHto-uU8de7LdgSEZN7wli9Xyfm0fZ_k4iKfXWeyAK40cdL1xY3Q11gt-Q25duUsgF7xodK672ZMnXuTYJZfimO4hPZxcOIOqkE0JwlhSmZX12uBSy_pys9ggyxWktiJZfcZBK5mtGf2Gr7qLouJ3ZLzj9Dg7hA3XvY6_uD1agHmW6uA9I4uM_GOM0Ue7Wm2Q6codkP-T43kXRS4OS9MUQCYERy8PkFjEm3jYx3cKADPoiJagSp5n-GMemSCEUbOHEhhN0Mxgy-vCMMrECaF1hZThNrPnnya4WxhRXhu5bETa-w7zJed4KkqKdAuN0YqLH1KWPQhdmhzpL5oE0-l46kdR4E_DyWzuz0e0oUk4j8ZxNI8nYRyH4Sy4Oo3oS5fvj-MgCv0oiGdX4dSP_WBEoSN0726X7pI5_QYwkpLJ)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", - "- use a light development environment\n", + "Trick: use a light development environment based on the introductory session.\n", "\n", "[![](https://mermaid.ink/img/pako:eNp1Uk1v2zAM_SsCD0MCxEVqp67jFru0OwxoL91tVjEoNpMYtSVNH0HdJP99lK1g62EwRJDy4-MjqSPUqkEoIUkSLl3rOizZd7k1wjrja-cNMmHZA4G4HDE7I_SePb1wGb4GD7MZhy9yY_XdZLei3IrEWzRscjuhndL_QviYGH2YzwOT9ZuJ2qBW1QsZ2zplhkgSZJK7Cf6uda_E0BqsXavkKCZk_apmuhPDRqk3OydErxrfoa1m0bnk68HtlQwIlE3sInT3lZ3-Fku077rE4G-P1pHgELIYnkaRUwrKXSvxUwdEh_JQPeKB_h4-TYFq1qqn3rB6UNIJSjWW2KOyRtVv49z-G71GtVF5JGO0mtP9KVRmXMICejS9aBta7JFLxji4PfbIoSS3wa3wnePA5ZmgXjfC4bcmTBtK2jouQHinfgyyvsQT5rEV1GAPpKazdKuF_KlUfwFRCOUR3qG8zourPF2u8tt0nRbrfFUsYKDroriis86DSW-y2-y8gI-RYUn4LE2z6_Rmna3y5ZIycJT0PL3P8Zme_wCRge2O?type=png)](https://mermaid.live/edit#pako:eNp1Uk1v2zAM_SsCD0MCxEVqp67jFru0OwxoL91tVjEoNpMYtSVNH0HdJP99lK1g62EwRJDy4-MjqSPUqkEoIUkSLl3rOizZd7k1wjrja-cNMmHZA4G4HDE7I_SePb1wGb4GD7MZhy9yY_XdZLei3IrEWzRscjuhndL_QviYGH2YzwOT9ZuJ2qBW1QsZ2zplhkgSZJK7Cf6uda_E0BqsXavkKCZk_apmuhPDRqk3OydErxrfoa1m0bnk68HtlQwIlE3sInT3lZ3-Fku077rE4G-P1pHgELIYnkaRUwrKXSvxUwdEh_JQPeKB_h4-TYFq1qqn3rB6UNIJSjWW2KOyRtVv49z-G71GtVF5JGO0mtP9KVRmXMICejS9aBta7JFLxji4PfbIoSS3wa3wnePA5ZmgXjfC4bcmTBtK2jouQHinfgyyvsQT5rEV1GAPpKazdKuF_KlUfwFRCOUR3qG8zourPF2u8tt0nRbrfFUsYKDroriis86DSW-y2-y8gI-RYUn4LE2z6_Rmna3y5ZIycJT0PL3P8Zme_wCRge2O)\n", "\n", @@ -172,7 +177,7 @@ "\n", "**N.B. ansible environment variables are not related with process environment**\n", "\n", - "Exercise:\n", + "#### Exercise:\n", "\n", "- using [the terminal](/terminals/ps) identify the process executing this notebook by the current working directory `/proc/*/cwd`;\n", "- check the environment variables of the process with `cat /proc//environ | od -a`;\n", @@ -267,7 +272,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Exercise" + "#### Exercise\n", + "\n", + "- Read the inventory and try to predict the output of the following command\n", + "- Rename the `staging` inventory file to `foobar`. What happens?\n", + "- Restore the original name." ] }, { diff --git a/ansible-101/notebooks/02_delivery_layout.ipynb b/ansible-101/notebooks/02_delivery_layout.ipynb index 555fff8..52f2115 100644 --- a/ansible-101/notebooks/02_delivery_layout.ipynb +++ b/ansible-101/notebooks/02_delivery_layout.ipynb @@ -15,7 +15,7 @@ " - whether to do privilege escalation (eg. sudo, ...) before running tasks\n", " - if nodes should be accessed via a bastion host, docker, ...\n", " \n", - "Put those informations, together with a brief description of the playbook usage (eg. 2/3 lines) into ansible.cfg\n", + "Put those information, together with a brief description of the playbook usage (eg. 2/3 lines) into `ansible.cfg`\n", "\n", "[![](https://mermaid.ink/img/pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA?type=png)](https://mermaid.live/edit#pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA)" ] @@ -38,7 +38,7 @@ "\n", "When running ansible, the first file read is ansible.cfg, resolved in the following order:\n", "\n", - " - `ANSIBLE_CONFIG` (env var)\n", + " - `ANSIBLE_CONFIG` (process environment variable)\n", " - `./ansible.cfg` (in the current directory)\n", " - `~/ansible.cfg` (in the home directory)\n", " - `/etc/ansible/ansible.cfg`\n", @@ -275,7 +275,7 @@ "A bastion host is the unique management entrypoint for an infrastructure.\n", "\n", "Ansible *leverages ssh functionalities* to manage resources from your local machine thru a bastion.\n", - "With a proper configuration you can run your commands/playbooks without continusly moving files to and fro your bastion.\n", + "With a proper configuration you can run your commands/playbooks **without** continusly moving files to and fro your bastion.\n", "\n", "Those includes:\n", " \n", diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index b75aa6d..1ad3687 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -20,7 +20,7 @@ " - one `inventory` file;\n", " - no host_key_check;\n", " - no retry files;\n", - " - client machine username is `root`. The password will be generated via the ansible `lookup()` plugin;\n", + " - client machines' username is `root`. The password will be generated via the ansible `lookup()` plugin;\n", " - no public key is installed by default.\n", "\n" ] @@ -43,7 +43,7 @@ "\n", "The preparation steps include creating:\n", "\n", - "1. `ansible.cfg` (the deployment descriptor) referencing the files we're going to create;\n", + "1. [`ansible.cfg`](/edit/notebooks/exercise-01/ansible.cfg) (the deployment descriptor) referencing the files we're going to create;\n", "1. all secret files (ssh identity, vault pin file);\n", "1. and the inventory." ] @@ -54,7 +54,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Prepare a deployment descriptor referencing the .pin file\n", + "# Prepare a deployment descriptor referencing the .pin file.\n", + "# Exercise: open ansible.cfg in the editor add the missing comment lines.\n", "!cat ansible.cfg" ] }, @@ -128,6 +129,16 @@ "! cat .pin" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Uncomment the vault_password_file line in ansible.cfg\n", + "! sed -i 's/#vault_password_file/vault_password_file/' ansible.cfg" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -168,10 +179,17 @@ "- use the `copy` module to generate the `vault.yaml` file with the following content\n", "\n", "```yaml\n", - "root_password: \n", + "root_password: \"\"\n", "```" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -180,7 +198,7 @@ "source": [ "# Solution\n", "!ansible localhost -mcopy \\\n", - " -a \"content='root_password: \\\"{{lookup('password','/dev/null')}}\\\"' dest=$PWD/vault.yaml\"" + " -a \"content='root_password: \\\"{{ lookup('password','/dev/null') }}\\\"' dest=$PWD/vault.yaml\"" ] }, { @@ -272,7 +290,7 @@ "outputs": [], "source": [ "# We need to encrypt it. \n", - "!ansible-vault encrypt vault.yml" + "!ansible-vault encrypt vault.yaml" ] }, { @@ -282,9 +300,9 @@ "source": [ "#### Exercise\n", "\n", - " - which secret is used to encrypt vault.yml ?\n", + " - which secret is used to encrypt vault.yaml ?\n", " - where is it specified?\n", - " - what happens if you try to re-encrypt the vault.yml" + " - what happens if you try to re-encrypt the vault.yaml" ] }, { diff --git a/ansible-101/notebooks/exercise-01/ansible.cfg b/ansible-101/notebooks/exercise-01/ansible.cfg index 1254d61..d8e7bdb 100644 --- a/ansible-101/notebooks/exercise-01/ansible.cfg +++ b/ansible-101/notebooks/exercise-01/ansible.cfg @@ -10,8 +10,9 @@ host_key_checking = no private_key_file = id_ansible # We want to store root password in an encrypted file -# but don't want to be prompted for a password each time -vault_password_file = .pin +# but don't want to be prompted for a password each time. +# N.B. If this file is not present, ansible will show an error! +# vault_password_file = .pin [ssh_connection] diff --git a/ansible-101/notebooks/exercise-01/copy-key.yml b/ansible-101/notebooks/exercise-01/copy-key.yml index 13dca46..9a370f1 100644 --- a/ansible-101/notebooks/exercise-01/copy-key.yml +++ b/ansible-101/notebooks/exercise-01/copy-key.yml @@ -2,7 +2,7 @@ # Load variables from the following files - hosts: course vars_files: - - vault.yml + - vault.yaml tasks: - name: Ensure /root/.ssh is present file: @@ -18,3 +18,8 @@ owner: root group: root force: yes +# +# Bonus track: +# search on the Internet an Ansible module to +# manage the authorized_keys. +# diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index 17cdc5b..a398870 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -44,7 +44,7 @@ # # fatal: [localhost]: FAILED! => {"msg": "JMESPathError in json_query filter plugin:\nUnknown function: match()"} loop: "{{ ssh_pubkeys }}" - + - name: Create enough machine for the course. community.digitalocean.digital_ocean_droplet: state: present diff --git a/docker-101/02-docker.md b/docker-101/02-docker.md index 022b2c3..de238a4 100644 --- a/docker-101/02-docker.md +++ b/docker-101/02-docker.md @@ -186,8 +186,10 @@ docker history # list changes of an image. Images are stored in a Docker registry such as [Docker Hub](https://hub.docker.com/) or Github's [Container Registry](). You can also host your own registry. -`docker commit` can create an image from a container. This is similar to the -snapshot feature of Virtual Machines. +`docker commit` can create an image from a container: +this is the process used when building a `Dockerfile`. + +NB. This is similar to the snapshot feature of Virtual Machines. [![](https://mermaid.ink/img/pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC?type=png)](https://mermaid.live/edit#pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC) From a5311c271c4ec8a9ff9d7f0016f895321a23bdd7 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Tue, 23 May 2023 18:18:29 +0200 Subject: [PATCH 23/39] More exercises. Ansible gathering. --- ansible-101/notebooks/02_vaults.ipynb | 26 ++++++++++--------- .../notebooks/03_facts_and_variables.ipynb | 25 ++++++++++++------ .../notebooks/exercise-03/vars-and-facts.yml | 7 +++-- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/ansible-101/notebooks/02_vaults.ipynb b/ansible-101/notebooks/02_vaults.ipynb index 1ad3687..6e381f6 100644 --- a/ansible-101/notebooks/02_vaults.ipynb +++ b/ansible-101/notebooks/02_vaults.ipynb @@ -43,9 +43,9 @@ "\n", "The preparation steps include creating:\n", "\n", - "1. [`ansible.cfg`](/edit/notebooks/exercise-01/ansible.cfg) (the deployment descriptor) referencing the files we're going to create;\n", - "1. all secret files (ssh identity, vault pin file);\n", - "1. and the inventory." + "1. all secret files (ssh keypair, vault pin file)\n", + "1. the inventory\n", + "1. [`ansible.cfg`](/edit/notebooks/exercise-01/ansible.cfg) (the deployment descriptor) referencing the created files" ] }, { @@ -64,7 +64,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now create a new ssh keypair for the project:\n", + "✅ Create a new ssh keypair for the project:\n", "\n", "- cleanup previously existing keys;\n" ] @@ -106,7 +106,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Create the vault password file named `.pin` using the `lookup` plugin. We'll use this password to encrypt the vault later on.\n" + "✅ Create the vault password file named `.pin` using the `lookup` plugin. We'll use this password to encrypt the vault later on.\n", + "**NB: if ansible.cfg references a missing or invalid `vault_password_file`, this task will fail.**\n" ] }, { @@ -129,6 +130,14 @@ "! cat .pin" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "✅ Uncomment the vault_password_file in [ansible.cfg](/edit/notebooks/exercise-01/ansible.cfg)." + ] + }, { "cell_type": "code", "execution_count": null, @@ -183,13 +192,6 @@ "```" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 2e8b7f6..d7b0703 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -43,7 +43,7 @@ " - run the following command\n", " - what does it do?\n", " - where's its output ?\n", - " - use the json python module to make it readable" + " - use the json python module to make it readable. **Hint: you need to `import json` to parse the output**" ] }, { @@ -82,7 +82,7 @@ "source": [ "#### Exercise\n", "\n", - "Gather the following information from the output of the previous command.\n", + "Using python, `print()` the following information from the output of the previous command:\n", "\n", " - hostname\n", " - first ip address\n", @@ -107,8 +107,7 @@ "source": [ "#### Exercise\n", "\n", - "modify [this playbook](/edit/notebooks/exercise-03/get-facts.yml) to print:\n", - "\n", + "modify [this playbook](/edit/notebooks/exercise-03/get-facts.yml) to dump:\n", "\n", " - hostname\n", " - first ip address\n", @@ -168,7 +167,7 @@ "\n", "# template.j2\n", "This is a static line while the following one\n", - "expands the ansible_hostname variable {{ansible_hostname}} \n", + "expands the ansible_hostname variable {{ ansible_hostname }} \n", "\n", "Now we process a simple number {{ 3.1415 | int }}\n", "\n", @@ -210,6 +209,16 @@ "!ansible-playbook vars-and-facts.yml --tags variables" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Extra Exercise\n", + "\n", + "Re-run the above playbook disabling fact gathering setting the process environment variable `ANSIBLE_GATHERING=explicit`." + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -280,12 +289,12 @@ "\n", "Edit [the last section of vars-and-facts.yml](/edit/notebooks/exercise-03/vars-and-facts.yml) so that it shows:\n", " \n", - " - the free percentage of every device\n", + "- the free percentage of every block device\n", "\n", "Hints:\n", " \n", - " - use the playbook as a reference\n", - " - iterate thru server facts" + "- use the playbook as a reference\n", + "- iterate thru server facts" ] }, { diff --git a/ansible-101/notebooks/exercise-03/vars-and-facts.yml b/ansible-101/notebooks/exercise-03/vars-and-facts.yml index 42ff0b6..f35e902 100644 --- a/ansible-101/notebooks/exercise-03/vars-and-facts.yml +++ b/ansible-101/notebooks/exercise-03/vars-and-facts.yml @@ -1,4 +1,7 @@ --- +# +# This playbook has 3 tasklists, each with a different tag. +# - hosts: localhost tags: variables vars: @@ -7,7 +10,7 @@ tasks: - debug: msg: > - {{ansible_hostname }} {{ one }} + {{ ansible_hostname }} {{ one }} - debug: msg: > The output is {{ one + pi }} @@ -22,7 +25,7 @@ - name: Ansible can process expressions using filters debug: msg: > - Floor it {{ ( one + pi ) | int }} + Floor it {{ ( one + pi ) | int }} - hosts: localhost tags: exercise From 879de1d95ce32fd25c28225c91259bd147e670f3 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 24 May 2023 10:33:26 +0200 Subject: [PATCH 24/39] Update docker. --- docker-101/notebooks/02-docker.ipynb | 120 ++++++++++++++------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/docker-101/notebooks/02-docker.ipynb b/docker-101/notebooks/02-docker.ipynb index 9618b54..401fd03 100644 --- a/docker-101/notebooks/02-docker.ipynb +++ b/docker-101/notebooks/02-docker.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "af25ee55", + "id": "eb5b8406", "metadata": {}, "source": [ "## Inspect the Docker host\n", @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": null, - "id": "087a454d", + "id": "4898c92a", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ { "cell_type": "code", "execution_count": null, - "id": "eaf95c65", + "id": "ba0748fc", "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2c3bb55c", + "id": "3bdab09c", "metadata": {}, "outputs": [], "source": [ @@ -45,7 +45,7 @@ }, { "cell_type": "markdown", - "id": "5085d17e", + "id": "0c69d0dd", "metadata": { "slideshow": { "slide_type": "slide" @@ -62,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "abf9ae06", + "id": "d480e5f2", "metadata": {}, "outputs": [], "source": [ @@ -73,7 +73,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3b60a124", + "id": "269567ae", "metadata": {}, "outputs": [], "source": [ @@ -83,7 +83,7 @@ }, { "cell_type": "markdown", - "id": "b16358a4", + "id": "fe7be5d8", "metadata": { "slideshow": { "slide_type": "slide" @@ -104,7 +104,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5f1d0acf", + "id": "6ca14dd5", "metadata": {}, "outputs": [], "source": [ @@ -114,7 +114,7 @@ }, { "cell_type": "markdown", - "id": "9997b2b3", + "id": "3de53199", "metadata": {}, "source": [ "Download an image from the remote registry." @@ -123,7 +123,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3171326c", + "id": "0ea32a09", "metadata": {}, "outputs": [], "source": [ @@ -133,7 +133,7 @@ }, { "cell_type": "markdown", - "id": "23ad6b0a", + "id": "6e6ab248", "metadata": {}, "source": [ "Open a [terminal](/terminals/docker) and run an **interactive shell** (`--interactive`) with a terminal (`--tty`)\n", @@ -145,7 +145,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a5b9317e", + "id": "7d543fe9", "metadata": {}, "outputs": [], "source": [ @@ -155,7 +155,7 @@ }, { "cell_type": "markdown", - "id": "bec24ae4", + "id": "336b13a3", "metadata": {}, "source": [ "Then run the above commands to ensure that you are on another virtual hosts." @@ -164,7 +164,7 @@ { "cell_type": "code", "execution_count": null, - "id": "da9d22e5", + "id": "7ac722e8", "metadata": {}, "outputs": [], "source": [ @@ -177,7 +177,7 @@ }, { "cell_type": "markdown", - "id": "c0637596", + "id": "cf05b683", "metadata": { "slideshow": { "slide_type": "slide" @@ -194,7 +194,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d542d8c4", + "id": "8075910d", "metadata": {}, "outputs": [], "source": [ @@ -204,7 +204,7 @@ }, { "cell_type": "markdown", - "id": "c73e6c52", + "id": "bb09c003", "metadata": {}, "source": [ "Can you retrieve the IP address in another way?\n", @@ -213,7 +213,7 @@ }, { "cell_type": "markdown", - "id": "d5d03d15", + "id": "38f7fd1b", "metadata": { "slideshow": { "slide_type": "slide" @@ -230,7 +230,7 @@ { "cell_type": "code", "execution_count": null, - "id": "aa665e9d", + "id": "cc56d63a", "metadata": {}, "outputs": [], "source": [ @@ -240,7 +240,7 @@ }, { "cell_type": "markdown", - "id": "4b06c007", + "id": "e252e3ee", "metadata": { "slideshow": { "slide_type": "slide" @@ -257,7 +257,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8b59b38e", + "id": "12fb7df7", "metadata": { "attributes": { "classes": [ @@ -282,7 +282,7 @@ }, { "cell_type": "markdown", - "id": "169a6f56", + "id": "419f82ed", "metadata": {}, "source": [ "You can inspect containers" @@ -291,7 +291,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f4ab7ae6", + "id": "bdaaa415", "metadata": { "attributes": { "classes": [ @@ -314,7 +314,7 @@ }, { "cell_type": "markdown", - "id": "f1c1dcef", + "id": "17e88f16", "metadata": {}, "source": [ "#### Exercise\n", @@ -325,7 +325,7 @@ { "cell_type": "code", "execution_count": null, - "id": "67cb7aa4", + "id": "f7eefeab", "metadata": {}, "outputs": [], "source": [ @@ -334,7 +334,7 @@ }, { "cell_type": "markdown", - "id": "1b0cbf90", + "id": "ad3bbc4d", "metadata": {}, "source": [ "1. Inspect the `ansible-101_bastion_1` container.\n", @@ -347,7 +347,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0dcf9458", + "id": "90c84b58", "metadata": {}, "outputs": [], "source": [ @@ -356,7 +356,7 @@ }, { "cell_type": "markdown", - "id": "bbcc0cda", + "id": "d0204b9a", "metadata": {}, "source": [ "💬 Discuss how python treats the `{` character." @@ -364,7 +364,7 @@ }, { "cell_type": "markdown", - "id": "af726bf4", + "id": "5a76021d", "metadata": { "slideshow": { "slide_type": "slide" @@ -394,7 +394,7 @@ }, { "cell_type": "markdown", - "id": "f1449c94", + "id": "5a4f0b77", "metadata": { "slideshow": { "slide_type": "subslide" @@ -410,7 +410,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8c4317cc", + "id": "858ca912", "metadata": { "attributes": { "classes": [ @@ -431,7 +431,7 @@ }, { "cell_type": "markdown", - "id": "d99e9300", + "id": "9883df86", "metadata": { "slideshow": { "slide_type": "subslide" @@ -443,15 +443,17 @@ "Images are stored in a Docker registry such as [Docker Hub](https://hub.docker.com/)\n", "or Github's [Container Registry](). You can also host your own registry.\n", "\n", - "`docker commit` can create an image from a container. This is similar to the\n", - "snapshot feature of Virtual Machines.\n", + "`docker commit` can create an image from a container:\n", + "this is the process used when building a `Dockerfile`.\n", + "\n", + "NB. This is similar to the snapshot feature of Virtual Machines.\n", "\n", "[![](https://mermaid.ink/img/pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC?type=png)](https://mermaid.live/edit#pako:eNqtlV1vmzAUhv-K5WuIwDak4WIXXXcxbd3FVmnS4qpysEmsgImwUcu6_vc5diCQfkxre3fMeY3f8_jj3MO85gJmcN2w3QZcnVNFVV4yrS9EAVYlU1ugTVNvRaZqJYJClqWLRqr1ptbmoAo50xvWNKzLQDJWU6XblV9EVuubdtUq0y4_V1Vr2KoUwH_IEJpFxCrYWoCCZQULyzrfXlPFZSNyI2sFvn6nasW0CFHodDcl60SzXCySBOdzAOLoy_n1QRJPJHOO5jyKAUD4cpBEE0kRpZhhDEAaOYlQ_JF3JW6X38StjXvzL_rdM41Dc2eWVxupgVsH1KrsQF4rw6TSlCqzEaCquSyk4MBiE_p6sm4cekA3eb3r_gNbHDaiWIK-ktNyGrGWduO6U77HLfKxLXmYPJrO7SKiiZcffSG2LvSo9EGMQi71dvmzkd56PkzySLxvzmzW7svJfwBV6FUMnemRh9dhRE9gPKFARhTi5ymQN1Ig70CBvJICefIwPSKBRiTw8yTwG0ngdyCBJyT-eanxy7dpqEBbs_5q9AHqAzJMc28CCMMP08u9P2x7MC6DphlyzJBpBh8zeJo5GNmn_vjY-qwqaSyhvBHMCP2nf9bAYBeEM6tv9Sg5VHCa6x-KYaWn04eOAdyTFLgbFTiggTtXvtkcRaMiggmGYFJgMAHhexFVMICVaComuW1t91QBQKE9DpWgMLMhFwVrS0MhVQ9W2u7sKROfuDR1AzPTtCKArDX1j07l_dhrLiSzW11BeyZKbb_umPpV11UvskOY3cM7mKGEzNJFksYoTlCULlIcwA5mcURmhJAIz9P5GUJnCX4I4G_3h2g2X0QojhYpQvtWhlAAhbN06Tu0a9QPfwEgtsUC)" ] }, { "cell_type": "markdown", - "id": "445cf617", + "id": "d2d7cb30", "metadata": { "slideshow": { "slide_type": "slide" @@ -469,7 +471,7 @@ { "cell_type": "code", "execution_count": null, - "id": "275d6521", + "id": "cafb03b5", "metadata": {}, "outputs": [], "source": [ @@ -478,7 +480,7 @@ }, { "cell_type": "markdown", - "id": "df3c135a", + "id": "97f1b55d", "metadata": {}, "source": [ "Docker will execute all the commands in the Dockerfile and create a new image." @@ -487,7 +489,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f0b183ca", + "id": "eb16a508", "metadata": {}, "outputs": [], "source": [ @@ -496,7 +498,7 @@ }, { "cell_type": "markdown", - "id": "27de786f", + "id": "90a1aff7", "metadata": {}, "source": [ "Open the [terminal](/terminals/docker) and:\n", @@ -508,7 +510,7 @@ { "cell_type": "code", "execution_count": null, - "id": "dd2aa813", + "id": "0faf5382", "metadata": {}, "outputs": [], "source": [ @@ -518,7 +520,7 @@ }, { "cell_type": "markdown", - "id": "219a9077", + "id": "ec99d74c", "metadata": {}, "source": [ "#### Exercise\n", @@ -534,7 +536,7 @@ }, { "cell_type": "markdown", - "id": "71b3cc39", + "id": "beca5e0c", "metadata": { "slideshow": { "slide_type": "slide" @@ -555,7 +557,7 @@ }, { "cell_type": "markdown", - "id": "a40f4cc2", + "id": "6a07e434", "metadata": { "slideshow": { "slide_type": "subslide" @@ -578,7 +580,7 @@ }, { "cell_type": "markdown", - "id": "ae054f71", + "id": "b1d11fd0", "metadata": { "slideshow": { "slide_type": "subslide" @@ -595,7 +597,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5eed9464", + "id": "052b3886", "metadata": { "attributes": { "classes": [ @@ -623,7 +625,7 @@ }, { "cell_type": "markdown", - "id": "411abcfd", + "id": "3a6a7da0", "metadata": {}, "source": [ "Now run docker-compose up and Compose will start and run your entire app.\n", @@ -637,7 +639,7 @@ { "cell_type": "code", "execution_count": null, - "id": "fa27ecd3", + "id": "a042f1ae", "metadata": {}, "outputs": [], "source": [ @@ -647,7 +649,7 @@ }, { "cell_type": "markdown", - "id": "1f230ad4", + "id": "87bcbac1", "metadata": { "slideshow": { "slide_type": "slide" @@ -662,7 +664,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8271bbd4", + "id": "fa756444", "metadata": {}, "outputs": [], "source": [ @@ -676,7 +678,7 @@ }, { "cell_type": "markdown", - "id": "3ad47479", + "id": "b80ee452", "metadata": { "slideshow": { "slide_type": "subslide" @@ -691,7 +693,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e0a5218b", + "id": "4e9e3bf9", "metadata": { "attributes": { "classes": [ @@ -719,7 +721,7 @@ }, { "cell_type": "markdown", - "id": "36beef23", + "id": "9787fa9a", "metadata": { "slideshow": { "slide_type": "subslide" @@ -734,7 +736,7 @@ { "cell_type": "code", "execution_count": null, - "id": "268716d2", + "id": "dce3e371", "metadata": {}, "outputs": [], "source": [ @@ -758,7 +760,7 @@ }, { "cell_type": "markdown", - "id": "4fb67d7a", + "id": "c14d280d", "metadata": { "slideshow": { "slide_type": "subslide" @@ -773,7 +775,7 @@ { "cell_type": "code", "execution_count": null, - "id": "888f959d", + "id": "1eefc329", "metadata": {}, "outputs": [], "source": [ @@ -793,7 +795,7 @@ }, { "cell_type": "markdown", - "id": "3642bdc5", + "id": "6fd5c054", "metadata": { "slideshow": { "slide_type": "slide" @@ -808,7 +810,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3bd00f13", + "id": "e118edc5", "metadata": {}, "outputs": [], "source": [ @@ -817,7 +819,7 @@ }, { "cell_type": "markdown", - "id": "5d4f1cba", + "id": "628ca78e", "metadata": {}, "source": [ "---" From 308f4800fc0023708099ba082a11aff6d294c6c0 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Sun, 28 May 2023 22:51:28 +0200 Subject: [PATCH 25/39] Editorial improvements. --- .../notebooks/04_loops_and_conditions.ipynb | 21 +-- ansible-101/notebooks/05_inventories.ipynb | 178 +++++++++--------- .../notebooks/06_bastion_and_ssh.ipynb | 27 +-- ansible-101/notebooks/exercise-05/inventory | 10 +- .../exercise-05/inventory-docker-solution.py | 42 +++-- .../notebooks/exercise-05/inventory-docker.py | 29 ++- 6 files changed, 164 insertions(+), 143 deletions(-) diff --git a/ansible-101/notebooks/04_loops_and_conditions.ipynb b/ansible-101/notebooks/04_loops_and_conditions.ipynb index af4f282..23b81d1 100644 --- a/ansible-101/notebooks/04_loops_and_conditions.ipynb +++ b/ansible-101/notebooks/04_loops_and_conditions.ipynb @@ -132,7 +132,7 @@ "\n", "Remember on `when` and `with_items`\n", "\n", - "#### `when` statements should not include jinja2 templating delimiters such as {{ }} or {% %}\n", + "#### `when` statements should not include jinja2 templating delimiters such as {{ }} or {% %} because they are evaluated as python code.\n", "\n", "#### `with_items` [requires proper templating and braces](http://docs.ansible.com/ansible/porting_guide_2.0.html#other-caveats). Do it for all expressions everywhere except conditionals (`when`):\n" ] @@ -159,10 +159,12 @@ "- hosts: localhost \n", " tags: assert\n", " tasks: \n", - " - fail: msg=\"This is Linux!\"\n", + " - fail:\n", + " msg: \"This is Linux!\"\n", " when: ansible_system != 'Linux'\n", "\n", - " - fail: msg=\"Stop processing now!\"\n", + " - fail:\n", + " msg: \"Stop processing now!\"\n", " when: ansible_architecture == 'x86_64'\n", "\n", "```" @@ -210,13 +212,10 @@ "\n", "There is a set of predefined variables too:\n", "\n", - " - group_names\n", - " - groups\n", - " - environment \n", - " \n", - "When using playbooks, we'll get this one too:\n", - "\n", - " - hostvars\n" + " - `group_names`\n", + " - `groups`\n", + " - `environment`\n", + " - `hostvars`\n" ] }, { @@ -225,7 +224,7 @@ "metadata": {}, "outputs": [], "source": [ - "!ansible all[0] -i ../web -m debug -a \"var=groups\"" + "!ansible all[0] -i web -m debug -a \"var=groups\"" ] }, { diff --git a/ansible-101/notebooks/05_inventories.ipynb b/ansible-101/notebooks/05_inventories.ipynb index 33286d6..2f7b4a0 100644 --- a/ansible-101/notebooks/05_inventories.ipynb +++ b/ansible-101/notebooks/05_inventories.ipynb @@ -1,97 +1,54 @@ { "cells": [ { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Inventories" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /notebooks/exercise-05" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "# Inventories\n", "\n", "Inventories are a fundamental doc entrypoint for our infrastructures. \n", "\n", "They contain a lot of informations, including:\n", " \n", - " - ansible_user\n", - " - configuration variables in [group_name:vars]\n", - " - host grouping eg. by geographical zones in [group_name:children]\n", + "- `ansible_user`\n", + "- configuration variables in `[group_name:vars]`\n", + "- host grouping eg. by geographical zones in `[group_name:children]`\n", " \n", " \n", "Files:\n", "\n", - "\n", - " - [inventory](/edit/notebooks/exercise-05/inventory)\n", + "- [open the inventory](/edit/notebooks/exercise-05/inventory) file or print it\n", " " ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/notebooks/exercise-05\n" - ] - } - ], - "source": [ - "cd /notebooks/exercise-05" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "# I can group hosts in inventory\r\n", - "\r\n", - "[web:children]\r\n", - "web_rome\r\n", - "web_milan\r\n", - "\r\n", - "[web_rome:children]\r\n", - "web_rome_test\r\n", - "web_rome_prod\r\n", - "\r\n", - "[web_rome_prod]\r\n", - "172.23.0.[3:4]\r\n", - "\r\n", - "[web_milan]\r\n", - "172.24.0.[5:6]\r\n", - "\r\n", - "# further host variables\r\n", - "[web_rome:vars]\r\n", - "ansible_username=root \r\n", - "\r\n", - "\r\n", - "# Connect with docker \r\n", - "[web_rome_test:vars]\r\n", - "ansible_connection=docker\r\n", - "ansible_docker_extra_args=\"-Htcp://172.17.0.1\"\r\n", - "\r\n", - "# The actual host reference\r\n", - "[web_rome_test]\r\n", - "ansible101_web_1\r\n", - "\r\n", - "# \r\n", - "# Don't need to be Ssh \r\n", - "# to be my local machine ;)\r\n", - "#\r\n", - "[course]\r\n", - "localhost ansible_connection=local " - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "!cat inventory" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -108,6 +65,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -115,7 +73,7 @@ "\n", "Use `ansible` to show:\n", " \n", - " - all hosts of the web group." + "- all hosts of the web group." ] }, { @@ -139,10 +97,13 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "## Inventory scripts" + "## Inventory scripts\n", + "\n", + "To create custom inventory scripts just use python ;) and set the script path in `inventory`." ] }, { @@ -151,11 +112,11 @@ "metadata": {}, "outputs": [], "source": [ - "#To create custom inventory scripts just use python ;) and set it in\n", "!grep inventory ansible.cfg # inventory = ./docker-inventory.py" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -164,6 +125,14 @@ "in the official ansible documentation find at least 3 `ansible_connection=docker` parameters " ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An example python inventory script." + ] + }, { "cell_type": "code", "execution_count": null, @@ -188,20 +157,31 @@ "c = Client(base_url=\"http://172.17.0.1:2375/")\n", "\n", "# Define a function to make it clear!\n", - "container_fmt = lambda x: (\n", - " x['Names'][0][1:],\n", - " x['Labels']['com.docker.compose.service'], \n", - " x['NetworkSettings']['Networks']['bridge']['IPAddress'],\n", - ")\n", + "def get_inventory_data(container):\n", + " return {\n", + " \"container_name\": container[\"Names\"][0][1:],\n", + " \"ip_address\": container[\"NetworkSettings\"][\"Networks\"][\"bridge\"][\"IPAddress\"],\n", + " \"group_name\": container[\"Labels\"].get(\"com.docker.compose.service\"),\n", + " }\n", "\n", - "for x in c.containers():\n", + "for container in c.containers():\n", + " # The following exercises will ask you to\n", + " # modify the code in the loop in order to create a correct inventory.\n", " try:\n", - " print(*container_fmt(x), sep='\\t\\t')\n", + " print(get_inventory_data(container))\n", " except KeyError:\n", " # skip non-docker-compose containers\n", " pass" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "JSON inventories" + ] + }, { "cell_type": "code", "execution_count": null, @@ -239,19 +219,21 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise: \n", "\n", - "Reuse the code in [inventory-docker.py](/edit/notebooks/exercise-05/inventory-docker.py) to print a json inventory that:\n", + "Reuse the code in [inventory-docker.py](/edit/notebooks/exercise-05/inventory-docker.py) to print a JSON inventory that:\n", "\n", - " - connects via docker to \"web\" hosts\n", - " - connects via ssh to \"ansible\" hosts \n", + "- connects via docker to \"web\" hosts\n", + "- connects via ssh to \"ansible\" hosts \n", "\n", "Test it in the cell below.\n", "\n", - "** NOTE: there's a [docker inventory](https://github.com/ansible/ansible/blob/devel/contrib/inventory/docker.py) script shipped with ansible **" + "**NOTE: there's a [docker inventory](https://github.com/ansible-community/contrib-scripts/blob/main/inventory/docker.py) script shipped with ansible**\n", + "\n" ] }, { @@ -264,6 +246,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "code_folding": [] @@ -284,15 +267,17 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Configurations\n", "\n", - "You may want to split inventory files and separate prod and test environment." + "You may want to split inventory files and separate production and test environments." ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -316,6 +301,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -337,6 +323,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -358,6 +345,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -374,6 +362,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -384,6 +373,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -391,28 +381,34 @@ "\n", "Host vars can be used in automated or cloud deployments where:\n", "\n", - " - every new host or vm, at boot, populate its own entries in `host_vars` (Eg. via file)\n", - " - ansible is run after that setup and uses `host_vars` to configure the server and expose that values to the other machines." + " - every new host or vm, at boot, populate its own entries in `host_vars` (e.g., via file)\n", + " - ansible is run after that setup, and uses `host_vars` to configure the server and to expose that values to the other machines." ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.14" + "pygments_lexer": "ipython3", + "version": "3.9.9" } }, "nbformat": 4, diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index 02e45e0..2a36284 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -9,26 +9,26 @@ "\n", "There are many reasons for using bastion hosts:\n", "\n", - " - security access eg in cloud environment\n", - " - vpn eg via windows hosts\n", + "- security access eg in cloud environment\n", + "- vpn eg via windows hosts\n", " \n", "The latter case is quite boring as [ansible doesn't support windows as a client platform](https://docs.ansible.com/ansible/latest/os_guide/windows_faq.html#does-ansible-work-with-windows-xp-or-server-2003).\n", "\n", "A standard approach is:\n", "\n", - " - have a ssh server or a proxy installed on the bastion\n", - " - connecto the bastion to the remote network (eg. via vpn)\n", - " - configure ssh options in ansible to connect thru the bastion\n", + "- to have an ssh server or a proxy installed on the bastion\n", + "- connecto the bastion to the remote network (eg. via vpn)\n", + "- configure ssh options in ansible to connect through the bastion\n", " \n", "We'll do this via two configuration files:\n", "\n", - " - a standard ssh_config where we put the passthru configuration\n", - " - a simple ansible.cfg referencing ssh_config\n", + "- a standard `ssh_config` where we put the \"passthru\" configuration\n", + "- a simple `ansible.cfg` referencing `ssh_config`\n", " \n", "This approach allows us:\n", "\n", - " 1. to test the standard ssh connection thru the bastion without messing with ansible\n", - " 2. keep ansible.cfg simple in case we want to reuse them from the intranet (Eg. without traversing the bastion)\n", + "1. to test the standard ssh connection thru the bastion without messing with ansible\n", + "2. keep `ansible.cfg` simple in case we want to reuse them from the intranet (Eg. without traversing the bastion)\n", " \n", " " ] @@ -49,14 +49,15 @@ "source": [ "## SSH basics\n", "\n", - "SSH connections follows this basic schema:\n", + "SSH connections follows roughly this basic schema (more information in [RFC4254](https://www.rfc-editor.org/rfc/rfc4253) and further revisions):\n", "\n", "1. client connects to server\n", "2. server sends its public key\n", - "3. client checks the public key against its known_hosts file\n", + "3. client checks the public key against its `known_hosts` file\n", "4. if the key is not found, the client asks the user to confirm the key\n", - "5. if the key is confirmed, the client saves it in known_hosts\n", - "6. client sends its public key\n" + "5. if the key is confirmed, the client saves it in `known_hosts`\n", + "6. client sends its public key\n", + "\n" ] }, { diff --git a/ansible-101/notebooks/exercise-05/inventory b/ansible-101/notebooks/exercise-05/inventory index 73e3cc2..b133f1e 100644 --- a/ansible-101/notebooks/exercise-05/inventory +++ b/ansible-101/notebooks/exercise-05/inventory @@ -1,4 +1,4 @@ -# I can group hosts in inventory +# I can group hosts in an inventory. [web:children] web_rome @@ -14,22 +14,22 @@ web_rome_prod [web_milan] 172.24.0.[5:6] -# further host variables +# Further host variables. [web_rome:vars] ansible_username=root -# Connect with docker +# Connect with docker. [web_rome_test:vars] ansible_connection=docker ansible_docker_extra_args="-Htcp://172.17.0.1" -# The actual host reference +# The actual host reference. [web_rome_test] ansible101_web_1 # -# Don't need to be Ssh +# Don't need to be ssh # to be my local machine ;) # [course] diff --git a/ansible-101/notebooks/exercise-05/inventory-docker-solution.py b/ansible-101/notebooks/exercise-05/inventory-docker-solution.py index f2ca03b..bf60e7d 100755 --- a/ansible-101/notebooks/exercise-05/inventory-docker-solution.py +++ b/ansible-101/notebooks/exercise-05/inventory-docker-solution.py @@ -6,7 +6,7 @@ from collections import defaultdict # -# Manage different docker libraries +# Support different docker libraries. # try: from docker import Client @@ -19,32 +19,48 @@ logging.basicConfig(level=logging.DEBUG) -def print_hosts(): +def get_inventory_data(container): + return { + "container_name": container["Names"][0][1:], + "ip_address": container["NetworkSettings"]["Networks"]["bridge"]["IPAddress"], + "group_name": container["Labels"].get("com.docker.compose.service"), + } + + +def create_inventory(): + # + # Create a Docker client connecting to the docker daemon port. + # c = Client(base_url="http://172.17.0.1:2375/") - container_fmt = lambda x: ( - x["Names"][0][1:], - x["NetworkSettings"]["Networks"]["bridge"]["IPAddress"], - ) + inventory = {} - inventory = dict() + for container in c.containers(): + # Use str.format to log the container information. + host = get_inventory_data(container) + log.debug("Processing entry: {container_name}\t\t{ip_address}".format(**host)) - for x in c.containers(): - log.debug("Processing entry %r", "\t\t".join(container_fmt(x))) + # Skip parsing errors, and log a warning. try: - group_name = x["Labels"]["com.docker.compose.service"] - ip_address = x["NetworkSettings"]["Networks"]["bridge"]["IPAddress"] + group_name = host["group_name"] + ip_address = host["ip_address"] if group_name not in inventory: inventory[group_name] = defaultdict(list) inventory[group_name]["hosts"].append(ip_address) except KeyError: log.warning("Host not run via docker-compose: skipping") + # + # Replace host_vars on hosts of the "web" group. + # inventory["web"]["host_vars"] = { "ansible_ssh_common_args": " -o StrictHostKeyChecking=no " } ret = json.dumps(inventory, indent=True) return ret - +# +# Execute the script. +# if __name__ == "__main__": - print(print_hosts()) + inventory_text = create_inventory() + print(inventory_text) diff --git a/ansible-101/notebooks/exercise-05/inventory-docker.py b/ansible-101/notebooks/exercise-05/inventory-docker.py index bdcbe5d..8a7cb51 100755 --- a/ansible-101/notebooks/exercise-05/inventory-docker.py +++ b/ansible-101/notebooks/exercise-05/inventory-docker.py @@ -1,5 +1,10 @@ #!/usr/bin/env python -# List our containers. Note: this only works with docker-compose containers. +# +# Exercise: Complete this inventory script. +# +# Note: this only works with docker-compose containers +# setting the "com.docker.compose.service" label. +# from __future__ import print_function import logging @@ -12,16 +17,20 @@ c = Client(base_url="http://172.17.0.1:2375/") -container_fmt = lambda x: ( - x["Names"][0][1:], - x["Labels"]["com.docker.compose.service"], - x["NetworkSettings"]["Networks"]["bridge"]["IPAddress"], -) +def get_inventory_data(container): + return { + "container_name": container["Names"][0][1:], + "ip_address": container["NetworkSettings"]["Networks"]["bridge"]["IPAddress"], + "group_name": container["Labels"].get("com.docker.compose.service"), + } + inventory = defaultdict(list) -for x in c.containers(): - log.debug("Processing entry %r", "\t\t".join(container_fmt(x))) - group_name = x["Labels"]["com.docker.compose.service"] - ip_address = x["NetworkSettings"]["Networks"]["bridge"]["IPAddress"] +for container in c.containers(): + # Use str.format to log the container information. + host = get_inventory_data(container) + log.debug("Processing entry: {container_name}\t\t{ip_address}".format(**host)) + group_name = host["group_name"] + ip_address = host["ip_address"] inventory[group_name].append(ip_address) From d9b544a3c22d1813a5c4a5a53736362f98ae13f9 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 07:57:33 +0200 Subject: [PATCH 26/39] Editorial improvements --- .../notebooks/06_bastion_and_ssh.ipynb | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index 2a36284..8a1cc7d 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -5,7 +5,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Bastion hosts\n", + "# Bastion hosts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /notebooks/exercise-06/" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "There are many reasons for using bastion hosts:\n", "\n", @@ -33,15 +49,6 @@ " " ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cd /notebooks/exercise-06/" - ] - }, { "attachments": {}, "cell_type": "markdown", @@ -106,9 +113,9 @@ "\n", "## Connect to the bastion\n", "\n", - "Test connectivity to the bastion. Check your host ips and modify [`ssh_config`](/edit/notebooks/exercise-06/ssh_config) accordingly.\n", + "Test connectivity to the bastion. Check your host IPs and modify [`ssh_config`](/edit/notebooks/exercise-06/ssh_config) accordingly.\n", "\n", - "** Replace ALL bastion occurrencies, including the one below the BEWARE note**" + "**Replace ALL bastion occurrencies, including the one below the BEWARE note**" ] }, { @@ -131,28 +138,28 @@ "Write the [ssh-copy-id.yml](/edit/notebooks/exercise-06/ssh-copy-id.yml) playbook to install an ssh key to the bastion.\n", "\n", "\n", - "Bastion credentials are:\n", + "Set the bastion credentials to:\n", "\n", - " - user: `root`\n", - " - password `root`\n", + "- user: `root`\n", + "- password `root`\n", " \n", "Try to do it without watching the previous exercises:\n", "\n", - " - modify the empty [`ansible.cfg`](/edit/notebooks/exercise-06/ansible.cfg)\n", - " * referencing a pin file \n", - " * passing [`[ssh_connection]`](http://docs.ansible.com/ansible/intro_configuration.html#openssh-specific-settings) arguments to avoid ssh key mismatches\n", - " * pointing to the local inventory\n", - " - store credentials in the encrypted [`vault.yml`](/edit/notebooks/exercise-06/vault.yml). \n", - " - provide an [`inventory`](/edit/notebooks/exercise-06/inventory) file \n", + "- modify the empty [`ansible.cfg`](/edit/notebooks/exercise-06/ansible.cfg)\n", + " * referencing a pin file \n", + " * passing [`[ssh_connection]`](http://docs.ansible.com/ansible/intro_configuration.html#openssh-specific-settings) arguments to avoid ssh key mismatches\n", + " * pointing to the local inventory\n", + "- store credentials in the encrypted [`vault.yml`](/edit/notebooks/exercise-06/vault.yml). \n", + "- provide an [`inventory`](/edit/notebooks/exercise-06/inventory) file \n", "\n", "You can reuse the old id_ansible key or:\n", "\n", - " - create a new one and adjust the reference in [` ssh_config`](/edit/notebooks/exercise-06/ssh_config) \n", + "- create a new one and adjust the reference in [` ssh_config`](/edit/notebooks/exercise-06/ssh_config) \n", " \n", "Hint:\n", "\n", - " - if you provide an IdentityFile, password authentication won't work on the `bastion` node;\n", - " - you *must* copy ssh id file using password authentication and eventually clean up your known_host file" + "- if you provide an IdentityFile, password authentication won't work on the `bastion` node;\n", + "- you *must* copy ssh id file using password authentication and eventually clean up your known_host file" ] }, { @@ -245,7 +252,7 @@ "\n", " - recycle your dynamic inventory script to access web hosts\n", " - your id_ansible key should already be on your web hosts \n", - " - use ansible -m ping to check host connectivity\n", + " - use `ansible -m ping` to check host connectivity\n", " - run `ps -ef | grep ssh` on your docker host to check all the `ProxyCommand` processes." ] }, From a83402301fe89cc5b828b16651bf48bdcc9b3b10 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 15:27:06 +0200 Subject: [PATCH 27/39] Reference exercise directory in every book. --- .../notebooks/03_facts_and_variables.ipynb | 8 ++++---- ansible-101/notebooks/05_inventories.ipynb | 20 +++++++++++++++---- .../notebooks/06_bastion_and_ssh.ipynb | 5 +++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index d7b0703..878a397 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -40,10 +40,10 @@ "source": [ "#### Exercise\n", "\n", - " - run the following command\n", - " - what does it do?\n", - " - where's its output ?\n", - " - use the json python module to make it readable. **Hint: you need to `import json` to parse the output**" + "Run the following command\n", + "- what does it do?\n", + "- where's its output ?\n", + "- use the json python module to make it readable. **Hint: you need to `import json` to parse the output**" ] }, { diff --git a/ansible-101/notebooks/05_inventories.ipynb b/ansible-101/notebooks/05_inventories.ipynb index 2f7b4a0..797977b 100644 --- a/ansible-101/notebooks/05_inventories.ipynb +++ b/ansible-101/notebooks/05_inventories.ipynb @@ -207,12 +207,24 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'inventories' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[39m# You can pass variables to generated inventories too\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m inventories[\u001b[39m'\u001b[39m\u001b[39mweb\u001b[39m\u001b[39m'\u001b[39m][\u001b[39m'\u001b[39m\u001b[39mvars\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m {\n\u001b[1;32m 3\u001b[0m \u001b[39m'\u001b[39m\u001b[39mansible_ssh_common_args\u001b[39m\u001b[39m'\u001b[39m: \u001b[39m'\u001b[39m\u001b[39m -o GSSApiAuthentication=no\u001b[39m\u001b[39m'\u001b[39m\n\u001b[1;32m 4\u001b[0m }\n\u001b[1;32m 5\u001b[0m \u001b[39mprint\u001b[39m(json\u001b[39m.\u001b[39mdumps(inventories, indent\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m))\n", + "\u001b[0;31mNameError\u001b[0m: name 'inventories' is not defined" + ] + } + ], "source": [ "# You can pass variables to generated inventories too\n", - "inventories['web']['host_vars'] = {\n", + "inventories['web']['vars'] = {\n", " 'ansible_ssh_common_args': ' -o GSSApiAuthentication=no'\n", "}\n", "print(json.dumps(inventories, indent=1))" diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index 8a1cc7d..593c1f4 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -26,9 +26,9 @@ "There are many reasons for using bastion hosts:\n", "\n", "- security access eg in cloud environment\n", - "- vpn eg via windows hosts\n", + "- vpn eg via Windows hosts\n", " \n", - "The latter case is quite boring as [ansible doesn't support windows as a client platform](https://docs.ansible.com/ansible/latest/os_guide/windows_faq.html#does-ansible-work-with-windows-xp-or-server-2003).\n", + "The latter case is not interesting as [ansible doesn't support windows as a client platform](https://docs.ansible.com/ansible/latest/os_guide/windows_faq.html#does-ansible-work-with-windows-xp-or-server-2003).\n", "\n", "A standard approach is:\n", "\n", @@ -46,6 +46,7 @@ "1. to test the standard ssh connection thru the bastion without messing with ansible\n", "2. keep `ansible.cfg` simple in case we want to reuse them from the intranet (Eg. without traversing the bastion)\n", " \n", + "[![](https://mermaid.ink/img/pako:eNptUU1vgzAM_SuRD1MrAYJC6OC8HSZtl-22Zoe0cQsaOFUI6gflvy8UOqnaTvGzn9-z4w42WiHksDNyX7DXd0GCNlWJZGczPFo0JCshqNCNZVuZb6XfNmj8HUoznw9kQU27HrsJ7eqFxp4BHLT5npom5B9Kg-pr1IvYAxvexfTGgpDUnaKqzyvm6GvZ2FJT1wmYQkGjMNrC-aFlURIFizhI4uD4t7ZcDLUwiJw69L0gl_11G9dlvu9fmqa4sMlhSLB_5wQPajS1LJX7uE4QYwKcVY0Cchcq3Mq2sgIE9Y7a7pW0-KxKqw3k1rTogWyt_jjR5oZHzlMp3do1uNmrxmX3kj61rm8kByHv4Ah5nCVBysM0jpachzzNPDhBHiVpEGdpmCUZX_KMx4-9B-erQBhwD_A6wtt47-vZ-x-g3Kuo?type=png)](https://mermaid.live/edit#pako:eNptUU1vgzAM_SuRD1MrAYJC6OC8HSZtl-22Zoe0cQsaOFUI6gflvy8UOqnaTvGzn9-z4w42WiHksDNyX7DXd0GCNlWJZGczPFo0JCshqNCNZVuZb6XfNmj8HUoznw9kQU27HrsJ7eqFxp4BHLT5npom5B9Kg-pr1IvYAxvexfTGgpDUnaKqzyvm6GvZ2FJT1wmYQkGjMNrC-aFlURIFizhI4uD4t7ZcDLUwiJw69L0gl_11G9dlvu9fmqa4sMlhSLB_5wQPajS1LJX7uE4QYwKcVY0Cchcq3Mq2sgIE9Y7a7pW0-KxKqw3k1rTogWyt_jjR5oZHzlMp3do1uNmrxmX3kj61rm8kByHv4Ah5nCVBysM0jpachzzNPDhBHiVpEGdpmCUZX_KMx4-9B-erQBhwD_A6wtt47-vZ-x-g3Kuo)\n", " " ] }, From 74e550c6485db21ec8b1a7a9cd20f4d7efbbd504 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 15:28:06 +0200 Subject: [PATCH 28/39] Fix: host vars. --- ansible-101/notebooks/exercise-05/inventory | 3 ++- .../notebooks/exercise-05/inventory-docker-solution.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ansible-101/notebooks/exercise-05/inventory b/ansible-101/notebooks/exercise-05/inventory index b133f1e..0b65463 100644 --- a/ansible-101/notebooks/exercise-05/inventory +++ b/ansible-101/notebooks/exercise-05/inventory @@ -8,8 +8,9 @@ web_milan web_rome_test web_rome_prod +# Fix IP addresses if they don't match. [web_rome_prod] -172.23.0.[3:4] +172.17.0.[3:4] [web_milan] 172.24.0.[5:6] diff --git a/ansible-101/notebooks/exercise-05/inventory-docker-solution.py b/ansible-101/notebooks/exercise-05/inventory-docker-solution.py index bf60e7d..b7c7cdb 100755 --- a/ansible-101/notebooks/exercise-05/inventory-docker-solution.py +++ b/ansible-101/notebooks/exercise-05/inventory-docker-solution.py @@ -50,9 +50,9 @@ def create_inventory(): log.warning("Host not run via docker-compose: skipping") # - # Replace host_vars on hosts of the "web" group. + # Replace host variables for the "web" group. # - inventory["web"]["host_vars"] = { + inventory["web"]["vars"] = { "ansible_ssh_common_args": " -o StrictHostKeyChecking=no " } ret = json.dumps(inventory, indent=True) From c8a64b67e339a206cf20e605a94f836d663121b8 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 15:31:53 +0200 Subject: [PATCH 29/39] Simplify inventory exercise. --- .../notebooks/exercise-05/inventory-docker.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ansible-101/notebooks/exercise-05/inventory-docker.py b/ansible-101/notebooks/exercise-05/inventory-docker.py index 8a7cb51..36fc133 100755 --- a/ansible-101/notebooks/exercise-05/inventory-docker.py +++ b/ansible-101/notebooks/exercise-05/inventory-docker.py @@ -8,12 +8,13 @@ from __future__ import print_function import logging -from collections import defaultdict log = logging.getLogger() logging.basicConfig(level=logging.DEBUG) - +# +# Run this script in jupyter and fix one issue at a time. +# c = Client(base_url="http://172.17.0.1:2375/") @@ -25,7 +26,7 @@ def get_inventory_data(container): } -inventory = defaultdict(list) +inventory = {} for container in c.containers(): # Use str.format to log the container information. @@ -33,4 +34,9 @@ def get_inventory_data(container): log.debug("Processing entry: {container_name}\t\t{ip_address}".format(**host)) group_name = host["group_name"] ip_address = host["ip_address"] - inventory[group_name].append(ip_address) + + if group_name not in inventory: + inventory[group_name]= {"hosts": []} + + inventory[group_name]["hosts"].append(ip_address) + From cbd9f08a1a1ddf3cf9ac5203b954099a7a29c8e6 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 18:30:38 +0200 Subject: [PATCH 30/39] Editorial improvements + fix YAML. --- ansible-101/notebooks/00_teaser.ipynb | 247 +++--------------- ansible-101/notebooks/01_architecture.ipynb | 50 ++-- .../notebooks/02_delivery_layout.ipynb | 26 +- .../notebooks/03_facts_and_variables.ipynb | 20 +- .../notebooks/04_loops_and_conditions.ipynb | 3 +- ansible-101/notebooks/05_inventories.ipynb | 21 +- .../notebooks/06_bastion_and_ssh.ipynb | 9 +- ansible-101/notebooks/08_yaml_pitfalls.ipynb | 98 ++++--- .../notebooks/exercise-05/inventory-docker.py | 1 - 9 files changed, 168 insertions(+), 307 deletions(-) diff --git a/ansible-101/notebooks/00_teaser.ipynb b/ansible-101/notebooks/00_teaser.ipynb index 98608d9..8341c00 100644 --- a/ansible-101/notebooks/00_teaser.ipynb +++ b/ansible-101/notebooks/00_teaser.ipynb @@ -1,75 +1,48 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Ansible\n", - "\n", - "\n", - "Ansible is a configuration management software.\n", - "\n", - "Connects via ssh or docker to a list of inventory machines and executes a series of tasks eventually grouped in playbooks.\n", - "\n", - "At first, create an inventory file with all your hosts." + "#### ([exercise directory](/tree/notebooks/exercise-00))" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/notebooks/exercise-00\n" - ] - } - ], + "outputs": [], "source": [ "cd /notebooks/exercise-00 " ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "Ansible is a configuration management software.\n", + "\n", + "Connects via ssh or docker to a list of inventory machines and executes a series of tasks eventually grouped in playbooks.\n", + "\n", + "At first, create an inventory file with all your hosts." + ] + }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "#\r\n", - "# This inventory file contains a list of server to\r\n", - "# play with - divided in groups.\r\n", - "#\r\n", - "[course]\r\n", - "# this is the local machine where you run jupyter\r\n", - "# the tutorial just works with this one.\r\n", - "pythonforsysadmin_course_1 ansible_connection=local\r\n", - "\r\n", - "\r\n", - "# Another group of servers\r\n", - "# where we can pass optional arguments\r\n", - "# Homework: you can play with this group of host\r\n", - "# once you exchange ssh-keys between the pythonforsysadmin_course_1\r\n", - "# container and the pythonforsysadmin_ansible_* ones._\r\n", - "[ansible]\r\n", - "172.17.0.[5:7]\r\n", - "\r\n", - "#\r\n", - "# Besides, ansible has two predefined groups:\r\n", - "# - all\r\n", - "# - ungrouped\r\n" - ] - } - ], + "outputs": [], "source": [ "cat inventory" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -78,22 +51,11 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "code_folding": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[0;32mpythonforsysadmin_course_1 | SUCCESS => {\u001b[0m\r\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\r\n", - "\u001b[0;32m \"ping\": \"pong\"\u001b[0m\r\n", - "\u001b[0;32m}\u001b[0m\r\n" - ] - } - ], + "outputs": [], "source": [ "# Check connections versus the local host in the \"course\" group\n", "\n", @@ -102,41 +64,16 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[0;32mpythonforsysadmin_course_1 | SUCCESS => {\u001b[0m\n", - "\u001b[0;32m \"changed\": false, \u001b[0m\n", - "\u001b[0;32m \"ping\": \"pong\"\u001b[0m\n", - "\u001b[0;32m}\u001b[0m\n", - "\u001b[1;31m172.17.0.6 | UNREACHABLE! => {\u001b[0m\n", - "\u001b[1;31m \"changed\": false, \u001b[0m\n", - "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.6 port 22: No route to host\\r\\n\", \u001b[0m\n", - "\u001b[1;31m \"unreachable\": true\u001b[0m\n", - "\u001b[1;31m}\u001b[0m\n", - "\u001b[1;31m172.17.0.5 | UNREACHABLE! => {\u001b[0m\n", - "\u001b[1;31m \"changed\": false, \u001b[0m\n", - "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.5 port 22: No route to host\\r\\n\", \u001b[0m\n", - "\u001b[1;31m \"unreachable\": true\u001b[0m\n", - "\u001b[1;31m}\u001b[0m\n", - "\u001b[1;31m172.17.0.7 | UNREACHABLE! => {\u001b[0m\n", - "\u001b[1;31m \"changed\": false, \u001b[0m\n", - "\u001b[1;31m \"msg\": \"Failed to connect to the host via ssh: ssh: connect to host 172.17.0.7 port 22: No route to host\\r\\n\", \u001b[0m\n", - "\u001b[1;31m \"unreachable\": true\u001b[0m\n", - "\u001b[1;31m}\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ "# Pinging all hosts gives some errors too, due to missing hosts or no ssh-key exchange\n", "!ansible -i inventory -m ping all" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -144,6 +81,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -179,6 +117,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -225,6 +164,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -235,72 +175,24 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "# Run this with\r\n", - "#\r\n", - "# #ansible-playbook -i inventory python-course-test.yml\r\n", - "#\r\n", - "- hosts: course\r\n", - " tasks:\r\n", - " - name: The /notebooks directory should exist\r\n", - " file: path=\"/notebooks\" state=directory\r\n", - "\r\n", - " - name: jupyter is responding on 8888\r\n", - " uri:\r\n", - " url: http://0.0.0.0:8888/notebooks\r\n", - " validate_certs: false\r\n", - " status_code: 200 # modify this line to simulate an error and see the outcome!\r\n", - "\r\n", - " - name: The template.conf is in place\r\n", - " file: path=\"/tmp/template.conf\" state=file\r\n" - ] - } - ], + "outputs": [], "source": [ "!cat python-course-test.yml" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "PLAY [course] ******************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "TASK [The /notebooks directory should exist] ***********************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "TASK [jupyter is responding on 8888] *******************************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "TASK [The template.conf is in place] *******************************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "PLAY RECAP *********************************************************************\n", - "\u001b[0;32mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=4 \u001b[0m changed=0 unreachable=0 failed=0 \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "!ansible-playbook -i inventory python-course-test.yml " ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -313,86 +205,27 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "# Run this with\r\n", - "#\r\n", - "# #ansible-playbook -i inventory site.yml\r\n", - "#\r\n", - "- hosts: course\r\n", - " tasks:\r\n", - "\r\n", - " - name: Create a file from a template\r\n", - " template: src=mytemplate.j2 dest=/tmp/template.conf\r\n", - "\r\n", - " - name: Ensure needed packages are present and eventually install them\r\n", - " apt: name={{item}} state=present\r\n", - " with_items:\r\n", - " - python\r\n", - " - python-dev\r\n", - " ignore_errors: yes # ignore errors during the course (eg. connectivity)\r\n" - ] - } - ], + "outputs": [], "source": [ "!cat site.yml" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "PLAY [course] ******************************************************************\n", - "\n", - "TASK [Gathering Facts] *********************************************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "TASK [Create a file from a template] *******************************************\n", - "\u001b[0;32mok: [pythonforsysadmin_course_1]\u001b[0m\n", - "\n", - "TASK [Ensure needed packages are present and eventually install them] **********\n", - "\u001b[0;31mfailed: [pythonforsysadmin_course_1] (item=[u'python', u'python-dev']) => {\"changed\": false, \"cmd\": \"apt-get update\", \"item\": [\"python\", \"python-dev\"], \"msg\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\", \"rc\": 100, \"stderr\": \"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\\n\\nW: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\\n\\nE: Some index files failed to download. They have been ignored, or old ones used instead.\\n\", \"stderr_lines\": [\"W: Failed to fetch http://security.debian.org/dists/jessie/updates/main/binary-amd64/Packages 404 Not Found [IP: 151.101.130.132 80]\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie/main/binary-amd64/Packages 404 Not Found\", \"\", \"W: Failed to fetch http://deb.debian.org/debian/dists/jessie-updates/main/binary-amd64/Packages 404 Not Found\", \"\", \"E: Some index files failed to download. They have been ignored, or old ones used instead.\"], \"stdout\": \"Ign http://deb.debian.org jessie InRelease\\nIgn http://security.debian.org jessie/updates InRelease\\nIgn http://deb.debian.org jessie-updates InRelease\\nIgn http://security.debian.org jessie/updates Release.gpg\\nIgn http://deb.debian.org jessie Release.gpg\\nIgn http://deb.debian.org jessie-updates Release.gpg\\nIgn http://security.debian.org jessie/updates Release\\nHit https://download.docker.com jessie InRelease\\nIgn http://deb.debian.org jessie Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nIgn http://deb.debian.org jessie-updates Release\\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n \\nErr http://security.debian.org jessie/updates/main amd64 Packages\\n 404 Not Found [IP: 151.101.130.132 80]\\nErr http://deb.debian.org jessie/main amd64 Packages\\n 404 Not Found\\nErr http://deb.debian.org jessie-updates/main amd64 Packages\\n 404 Not Found\\nGet:1 https://download.docker.com jessie/stable amd64 Packages [6099 B]\\nFetched 6099 B in 1s (5411 B/s)\\n\", \"stdout_lines\": [\"Ign http://deb.debian.org jessie InRelease\", \"Ign http://security.debian.org jessie/updates InRelease\", \"Ign http://deb.debian.org jessie-updates InRelease\", \"Ign http://security.debian.org jessie/updates Release.gpg\", \"Ign http://deb.debian.org jessie Release.gpg\", \"Ign http://deb.debian.org jessie-updates Release.gpg\", \"Ign http://security.debian.org jessie/updates Release\", \"Hit https://download.docker.com jessie InRelease\", \"Ign http://deb.debian.org jessie Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Ign http://deb.debian.org jessie-updates Release\", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" \", \"Err http://security.debian.org jessie/updates/main amd64 Packages\", \" 404 Not Found [IP: 151.101.130.132 80]\", \"Err http://deb.debian.org jessie/main amd64 Packages\", \" 404 Not Found\", \"Err http://deb.debian.org jessie-updates/main amd64 Packages\", \" 404 Not Found\", \"Get:1 https://download.docker.com jessie/stable amd64 Packages [6099 B]\", \"Fetched 6099 B in 1s (5411 B/s)\"]}\u001b[0m\n", - "\u001b[0;36m...ignoring\u001b[0m\n", - "\n", - "PLAY RECAP *********************************************************************\n", - "\u001b[0;32mpythonforsysadmin_course_1\u001b[0m : \u001b[0;32mok=3 \u001b[0m changed=0 unreachable=0 failed=0 \n", - "\n" - ] - } - ], + "outputs": [], "source": [ "!ansible-playbook -i inventory site.yml --limit=course # in this case the --limit does not change anything ;)" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ansible 2.4.2.0\r\n", - " config file = /notebooks/exercise-00/ansible.cfg\r\n", - " configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']\r\n", - " ansible python module location = /usr/local/lib/python2.7/site-packages/ansible\r\n", - " executable location = /usr/local/bin/ansible\r\n", - " python version = 2.7.14 (default, Dec 12 2017, 16:55:09) [GCC 4.9.2]\r\n" - ] - } - ], + "outputs": [], "source": [ "!ansible --version" ] diff --git a/ansible-101/notebooks/01_architecture.ipynb b/ansible-101/notebooks/01_architecture.ipynb index 7acb994..6471831 100644 --- a/ansible-101/notebooks/01_architecture.ipynb +++ b/ansible-101/notebooks/01_architecture.ipynb @@ -1,5 +1,25 @@ { "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Architecture\n", + "#### ([exercise directory](/tree/notebooks/exercise-00))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution": "hidden" + }, + "outputs": [], + "source": [ + "cd /notebooks/exercise-00/" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -7,17 +27,14 @@ "source": [ "# Ansible is\n", "\n", - "\n", - " - configuration manager \n", - " - simple \n", - " - extensible via modules\n", - " - written in python\n", - " - broad community\n", - " - many external tools\n", - " - playbook repository\n", - " - used by openstack & tonns of project\n", - " \n", - " \n" + "- configuration manager \n", + "- simple \n", + "- extensible via modules\n", + "- written in python\n", + "- broad community\n", + "- many external tools\n", + "- playbook repository\n", + "- used by openstack & tonns of project" ] }, { @@ -84,17 +101,6 @@ "You have a lot of options! Root logins are not required, you can login as any user, and then su or sudo to any user." ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution": "hidden" - }, - "outputs": [], - "source": [ - "cd /notebooks/exercise-00/" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/ansible-101/notebooks/02_delivery_layout.ipynb b/ansible-101/notebooks/02_delivery_layout.ipynb index 52f2115..ba13836 100644 --- a/ansible-101/notebooks/02_delivery_layout.ipynb +++ b/ansible-101/notebooks/02_delivery_layout.ipynb @@ -6,6 +6,23 @@ "metadata": {}, "source": [ "# Delivery Layout - ansible.cfg\n", + "#### ([exercise directory](/tree/notebooks/exercise-00))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /notebooks/exercise-00" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "When you deliver something you'll probably have a layout:\n", "\n", @@ -20,15 +37,6 @@ "[![](https://mermaid.ink/img/pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA?type=png)](https://mermaid.live/edit#pako:eNplUz2TmzAQ_SuaLVIBARk4m-KqpEyVLuLmRkYLZg4kRgImjs__PZLAn9eIt0-r3fdW4gSVEggFNJoPB1LKUs586kbmV1LzouZhp6qPt1J-4NEwYw7EgXXLQrtjpv1ynkvT7juMqrphd3hNrtsOiU1X4wH12ui9UrJum1LyaTxcA5TCSbnWbeWMclT6yK7ovub3NWg6tUenJ2GDVmJlDeoZtaMpG9GMX-gN84qiKHreetbRaDUN7zPXht3gRYnqBOpHLc5tMy9qPFwU3CrfDykMXz811qhRVmg-b6adIRJGIbGlnIsV0-ttrXNzFYgnHsbpaXdnXxs-deyVmDo05BvRyn6ZXx_svUEAPeqet8I-mlMpCSnBDq_HEgoLBda-P5TybFOnQfARf4rW2oBi1BMGYJWp30dZXeIl50fL7Yh7sK06Y9mByz9K9ZckG0Jxgr9QJGkapXGWJXFKN9tdvAvgCAXdZVGe7fINzXNKt8nLOYB__nwc5UlG4yzJty80jfM4CQC9oF_Ly_c_wPk_d6YQxA)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cd /notebooks/exercise-00" - ] - }, { "attachments": {}, "cell_type": "markdown", diff --git a/ansible-101/notebooks/03_facts_and_variables.ipynb b/ansible-101/notebooks/03_facts_and_variables.ipynb index 878a397..e489012 100644 --- a/ansible-101/notebooks/03_facts_and_variables.ipynb +++ b/ansible-101/notebooks/03_facts_and_variables.ipynb @@ -6,12 +6,7 @@ "metadata": {}, "source": [ "# Facts and variables\n", - "\n", - "When connecting to an host, ansible creates a dictionary with a huge set of useful informations.\n", - "\n", - "This step is named **fact gathering**. \n", - "\n", - "You can inspect facts using the `setup` module." + "#### ([exercise directory](/tree/notebooks/exercise-03))" ] }, { @@ -23,6 +18,19 @@ "cd /notebooks/exercise-03" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "When connecting to an host, ansible creates a dictionary with a huge set of useful informations.\n", + "\n", + "This step is named **fact gathering**. \n", + "\n", + "You can inspect facts using the `setup` module." + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/ansible-101/notebooks/04_loops_and_conditions.ipynb b/ansible-101/notebooks/04_loops_and_conditions.ipynb index 23b81d1..af3476a 100644 --- a/ansible-101/notebooks/04_loops_and_conditions.ipynb +++ b/ansible-101/notebooks/04_loops_and_conditions.ipynb @@ -5,7 +5,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Loops" + "# Loops\n", + "#### ([exercise directory](/tree/notebooks/exercise-03))" ] }, { diff --git a/ansible-101/notebooks/05_inventories.ipynb b/ansible-101/notebooks/05_inventories.ipynb index 797977b..8df02b5 100644 --- a/ansible-101/notebooks/05_inventories.ipynb +++ b/ansible-101/notebooks/05_inventories.ipynb @@ -5,7 +5,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Inventories" + "# Inventories \n", + "#### ([exercise directory](/tree/notebooks/exercise-05))" ] }, { @@ -207,21 +208,9 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'inventories' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[3], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[39m# You can pass variables to generated inventories too\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m inventories[\u001b[39m'\u001b[39m\u001b[39mweb\u001b[39m\u001b[39m'\u001b[39m][\u001b[39m'\u001b[39m\u001b[39mvars\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m {\n\u001b[1;32m 3\u001b[0m \u001b[39m'\u001b[39m\u001b[39mansible_ssh_common_args\u001b[39m\u001b[39m'\u001b[39m: \u001b[39m'\u001b[39m\u001b[39m -o GSSApiAuthentication=no\u001b[39m\u001b[39m'\u001b[39m\n\u001b[1;32m 4\u001b[0m }\n\u001b[1;32m 5\u001b[0m \u001b[39mprint\u001b[39m(json\u001b[39m.\u001b[39mdumps(inventories, indent\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m))\n", - "\u001b[0;31mNameError\u001b[0m: name 'inventories' is not defined" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# You can pass variables to generated inventories too\n", "inventories['web']['vars'] = {\n", diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index 593c1f4..812ddd5 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -5,7 +5,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Bastion hosts" + "# Bastion hosts\n", + "#### ([exercise directory](/tree/notebooks/exercise-06))" ] }, { @@ -126,7 +127,7 @@ "outputs": [], "source": [ "fmt=r'{{.NetworkSettings.IPAddress}}'\n", - "!docker -H tcp://172.17.0.1:2375 inspect ansible101_bastion_1 --format {fmt} # pass variables *before* commands ;)" + "!docker -H tcp://172.17.0.1:2375 inspect ansible-101_bastion_1 --format {fmt} # pass variables *before* commands ;)" ] }, { @@ -230,7 +231,7 @@ "outputs": [], "source": [ "fmt=r'{{.NetworkSettings.IPAddress}}'\n", - "!docker -H tcp://172.17.0.1:2375 inspect ansible101_web_1 --format {fmt} # pass variables *before* commands ;)" + "!docker -H tcp://172.17.0.1:2375 inspect ansible-101_web_1 --format {fmt} # pass variables *before* commands ;)" ] }, { @@ -239,7 +240,7 @@ "metadata": {}, "outputs": [], "source": [ - "!ssh -F ssh_config root@172.17.0.4 ip -4 -o a # get host ip" + "!ssh -F ssh_config root@172.17.0.4 env # get host ip" ] }, { diff --git a/ansible-101/notebooks/08_yaml_pitfalls.ipynb b/ansible-101/notebooks/08_yaml_pitfalls.ipynb index e5192bb..dcb7115 100644 --- a/ansible-101/notebooks/08_yaml_pitfalls.ipynb +++ b/ansible-101/notebooks/08_yaml_pitfalls.ipynb @@ -1,27 +1,12 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "# Yaml\n", - "\n", - "Except for `ansible.cfg` which is an .ini file, all ansible files are in `yaml`, so let's spent some time on YAML.\n", - "\n", - "At the end of [inventories chapter](/notebooks/notebooks/05_inventories.ipynb) we showed how to use yaml to define list and maps variables.\n", - "\n", - "In this chapter we'll go a bit further.\n", - "\n", - "## Goals\n", - "\n", - " - what's yaml\n", - " - parsing and dumping yaml with python\n", - " - strings: quotes and multi-line\n", - " \n", - "## See also\n", - "\n", - " - [Yaml in ansible](http://docs.ansible.com/ansible/YAMLSyntax.html)\n", - " - [Yaml reference](http://www.yaml.org/spec/1.2/spec.html)" + "# YAML Pitfalls\n", + "#### ([exercise directory](/tree/notebooks/exercise-06))" ] }, { @@ -34,10 +19,35 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Except for `ansible.cfg` which is an .ini file, all ansible files are in YAML, so let's spent some time on YAML.\n", + "\n", + "At the end of [inventories chapter](/notebooks/notebooks/05_inventories.ipynb) we showed how to use YAML to define list and maps variables.\n", + "\n", + "In this chapter we'll go a bit further.\n", + "\n", + "## Goals\n", + "\n", + "- what's YAML\n", + "- parsing and dumping yaml with python\n", + "- strings: quotes and multi-line\n", + "\n", + "## See also\n", + "\n", + "- [YAML in ansible](https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html)\n", + "- [YAML reference](http://www.yaml.org/spec/1.2/spec.html)" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "## What's yaml?" + "## What's YAML?" ] }, { @@ -49,9 +59,9 @@ "import yaml\n", "\n", "txt = \"\"\"\n", - "{ \"yaml\": 'is', 'a superset': 'of json'}\n", + "{ \"YAML\": 'is', '~ a superset': 'of JSON'}\n", "\"\"\"\n", - "ret = yaml.load(txt)\n", + "ret = yaml.safe_load(txt)\n", "print(ret)" ] }, @@ -62,7 +72,7 @@ "outputs": [], "source": [ "# Yoda loves dictionaries ;)\n", - "print(yaml.dump(ret))" + "print(yaml.safe_dump(ret))" ] }, { @@ -72,7 +82,7 @@ "outputs": [], "source": [ "# Customized dumper\n", - "print(yaml.dump(ret, default_flow_style=False))" + "print(yaml.safe_dump(ret, default_flow_style=False))" ] }, { @@ -86,8 +96,8 @@ "you: {'can':'use', 'brace':'syntax'}\n", "\"\"\"\n", "\n", - "ret = yaml.load(txt)\n", - "print(yaml.dump(ret))" + "ret = yaml.safe_load(txt)\n", + "print(yaml.safe_dump(ret))" ] }, { @@ -96,7 +106,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(yaml.dump(ret, default_flow_style=False))" + "print(yaml.safe_dump(ret, default_flow_style=False))" ] }, { @@ -106,14 +116,14 @@ "outputs": [], "source": [ "# Yaml can describe list..\n", - "print(yaml.load(\"\"\"\n", + "print(yaml.safe_load(\"\"\"\n", "- tasks:\n", " - contains \n", " - a\n", " - list\n", " - of\n", " - modules\n", - "\"\"\"))\n" + "\"\"\"))" ] }, { @@ -123,7 +133,7 @@ "outputs": [], "source": [ "# .. and maps / dicts\n", - "print(yaml.load(\"\"\"\n", + "print(yaml.safe_load(\"\"\"\n", "- tasks:\n", " - name: \"this dict has two keys: name and debug\"\n", " debug: msg=\"Welcome to Rimini!\"\n", @@ -131,6 +141,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -152,7 +163,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(yaml.load(\"\"\"\n", + "print(yaml.safe_load(\"\"\"\n", "this_works: http://no-spaces-after-colon:8080\n", "\"\"\"))\n" ] @@ -163,7 +174,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(yaml.load(\"\"\"this_no: spaces: after colon\"\"\")) \n" + "print(yaml.safe_load(\"\"\"this_no: spaces: after colon\"\"\")) \n" ] }, { @@ -173,7 +184,7 @@ "outputs": [], "source": [ "# Quoting is important!\n", - "print(yaml.load(\"\"\"\n", + "print(yaml.safe_load(\"\"\"\n", "that: \"works: though\"\n", "\"\"\"))" ] @@ -185,23 +196,24 @@ "outputs": [], "source": [ "# This is fine \n", - "print(yaml.load(\"\"\"\n", + "print(yaml.safe_load(\"\"\"\n", "this_is: fine={{in_yaml}} but\n", "\"\"\"))\n", "\n", "# but with ansible you should\n", - "print(yaml.load(\"\"\"\n", - "always: quote=\"{{moustaches}}\"\n", + "print(yaml.safe_load(\"\"\"\n", + "always: quote=\"{{ moustaches }}\"\n", "\"\"\"))" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Long texts\n", "\n", - "Long texts are easy and clean as long as you *** use `>` and `|` instead of quoting ***." + "Long texts are easy and clean as long as you ***use `>` and `|` instead of quoting***." ] }, { @@ -231,6 +243,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -258,7 +271,7 @@ " Rimini, or the ancient Ariminum, \n", " is an art heritage city with over 22 centuries of history. \n", " \n", - " In 268 B.C., the Roman Senate nsent six thousand settlers \n", + " In 268 B.C., the Roman Senate sent six thousand settlers \n", " who founded the city that was meant to be strategically central \n", " and to develop to this day.\n", "\n", @@ -266,7 +279,7 @@ " Rimini, or the ancient Ariminum, \n", " is an art heritage city with over 22 centuries of history. \n", " \n", - " In 268 B.C., the Roman Senate nsent six thousand settlers \n", + " In 268 B.C., the Roman Senate sent six thousand settlers \n", " who founded the city that was meant to be strategically central \n", " and to develop to this day.\n", "\n", @@ -278,6 +291,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -298,14 +312,15 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "# Yaml and Ansible recap\n", + "# YAML and Ansible recap\n", "\n", - "## Yaml\n", + "## YAML\n", "\n", - " - all files are yaml but inventories (for now) and ansible.cfg\n", + " - all files are yaml but inventories (for now) and `ansible.cfg`\n", " - prefer `>` and `|` over quote hell\n", " - ALWAYS QUOTE `:`\n", "\n", @@ -323,6 +338,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/exercise-05/inventory-docker.py b/ansible-101/notebooks/exercise-05/inventory-docker.py index 36fc133..1455e44 100755 --- a/ansible-101/notebooks/exercise-05/inventory-docker.py +++ b/ansible-101/notebooks/exercise-05/inventory-docker.py @@ -39,4 +39,3 @@ def get_inventory_data(container): inventory[group_name]= {"hosts": []} inventory[group_name]["hosts"].append(ip_address) - From b226b6873b892af33c2c4a6927f715c9988fb129 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Mon, 29 May 2023 18:57:46 +0200 Subject: [PATCH 31/39] better bastion exercise --- .../notebooks/06_bastion_and_ssh.ipynb | 22 +++++++++++++------ ansible-101/notebooks/exercise-06/ansible.cfg | 13 +++++------ .../exercise-06/ansible.cfg-solution | 7 ++++++ ansible-101/notebooks/exercise-06/inventory | 5 +++-- .../notebooks/exercise-06/inventory-solution | 2 ++ ansible-101/notebooks/exercise-06/vault.yml | 3 +++ 6 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 ansible-101/notebooks/exercise-06/ansible.cfg-solution create mode 100644 ansible-101/notebooks/exercise-06/inventory-solution diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index 812ddd5..cdde381 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -47,8 +47,7 @@ "1. to test the standard ssh connection thru the bastion without messing with ansible\n", "2. keep `ansible.cfg` simple in case we want to reuse them from the intranet (Eg. without traversing the bastion)\n", " \n", - "[![](https://mermaid.ink/img/pako:eNptUU1vgzAM_SuRD1MrAYJC6OC8HSZtl-22Zoe0cQsaOFUI6gflvy8UOqnaTvGzn9-z4w42WiHksDNyX7DXd0GCNlWJZGczPFo0JCshqNCNZVuZb6XfNmj8HUoznw9kQU27HrsJ7eqFxp4BHLT5npom5B9Kg-pr1IvYAxvexfTGgpDUnaKqzyvm6GvZ2FJT1wmYQkGjMNrC-aFlURIFizhI4uD4t7ZcDLUwiJw69L0gl_11G9dlvu9fmqa4sMlhSLB_5wQPajS1LJX7uE4QYwKcVY0Cchcq3Mq2sgIE9Y7a7pW0-KxKqw3k1rTogWyt_jjR5oZHzlMp3do1uNmrxmX3kj61rm8kByHv4Ah5nCVBysM0jpachzzNPDhBHiVpEGdpmCUZX_KMx4-9B-erQBhwD_A6wtt47-vZ-x-g3Kuo?type=png)](https://mermaid.live/edit#pako:eNptUU1vgzAM_SuRD1MrAYJC6OC8HSZtl-22Zoe0cQsaOFUI6gflvy8UOqnaTvGzn9-z4w42WiHksDNyX7DXd0GCNlWJZGczPFo0JCshqNCNZVuZb6XfNmj8HUoznw9kQU27HrsJ7eqFxp4BHLT5npom5B9Kg-pr1IvYAxvexfTGgpDUnaKqzyvm6GvZ2FJT1wmYQkGjMNrC-aFlURIFizhI4uD4t7ZcDLUwiJw69L0gl_11G9dlvu9fmqa4sMlhSLB_5wQPajS1LJX7uE4QYwKcVY0Cchcq3Mq2sgIE9Y7a7pW0-KxKqw3k1rTogWyt_jjR5oZHzlMp3do1uNmrxmX3kj61rm8kByHv4Ah5nCVBysM0jpachzzNPDhBHiVpEGdpmCUZX_KMx4-9B-erQBhwD_A6wtt47-vZ-x-g3Kuo)\n", - " " + "[![](https://mermaid.ink/img/pako:eNp1UsuOmzAU_RXrLqoZCSwwCSEsKlVqF5XaTbsrjioHLolVuI7AaDLD8O81wekgjbq6r8N5CI9Qmgohh1OnLmf27YckSWWjkezDA14tdqQaKelsestqldcqHHrswhOq7vFxBivq9bFBXtanYtV7cK0bPEjq-_Pv0lCtT8Vbu4awkIcf2dttZu6H4-LK0xaflnq4O5w_Mmwt-o4FqVoREdriKy2h5uHJdH-8Cz-FT7rD6rAEjtkHNlfha-L5VoxV-1IwBz-q3mpD4yjBt5IWYrRnp4eWxZuYi4RvEn59f9uJ-Rbx2LHDNEly239qPiELw_DVhXtlXmJesP8YhQBa7FqlK_dzR0mMSXBqLUrIXVthrYbGSpA0OehwqZTFL5W2poPcdgMGoAZrfj5TeZ8XzGetXPIWnP2md9uLol_GtHeQGyEf4Qq5yFKeiWifxdtkm0ZZtgngGfI423GRZtF2t0_cLYrFFMDLjSHi6T5O0iTdC5G5GiUB4M3S9-WN3p7q9BcAcurg?type=png)](https://mermaid.live/edit#pako:eNp1UsuOmzAU_RXrLqoZCSwwCSEsKlVqF5XaTbsrjioHLolVuI7AaDLD8O81wekgjbq6r8N5CI9Qmgohh1OnLmf27YckSWWjkezDA14tdqQaKelsestqldcqHHrswhOq7vFxBivq9bFBXtanYtV7cK0bPEjq-_Pv0lCtT8Vbu4awkIcf2dttZu6H4-LK0xaflnq4O5w_Mmwt-o4FqVoREdriKy2h5uHJdH-8Cz-FT7rD6rAEjtkHNlfha-L5VoxV-1IwBz-q3mpD4yjBt5IWYrRnp4eWxZuYi4RvEn59f9uJ-Rbx2LHDNEly239qPiELw_DVhXtlXmJesP8YhQBa7FqlK_dzR0mMSXBqLUrIXVthrYbGSpA0OehwqZTFL5W2poPcdgMGoAZrfj5TeZ8XzGetXPIWnP2md9uLol_GtHeQGyEf4Qq5yFKeiWifxdtkm0ZZtgngGfI423GRZtF2t0_cLYrFFMDLjSHi6T5O0iTdC5G5GiUB4M3S9-WN3p7q9BcAcurg) " ] }, { @@ -66,7 +65,14 @@ "4. if the key is not found, the client asks the user to confirm the key\n", "5. if the key is confirmed, the client saves it in `known_hosts`\n", "6. client sends its public key\n", - "\n" + "\n", + "### SSH Caveats\n", + "\n", + "Host key checking is important. Incorrect validation can lead to:\n", + "\n", + "- persisting an insecure key in your `known_hosts` file\n", + "- connecting to the wrong host, that could be a malicious one, and leak credentials and other sensitive information\n", + "- connecting to the wrong host (e.g., because someone assigned a wrong IP), and execute commands on it" ] }, { @@ -100,15 +106,15 @@ "\n", "Inhibit PKI authentication is insecure by design:\n", "\n", - " - passwords will surely ends in cleartext files\n", - " - people ends doing things like the following\n", + "- passwords will surely end in cleartext files\n", + "- people eventually do things like the following\n", " \n", "```\n", "#\n", "# the password is sent to the bastion via a\n", "# cleartext file.\n", "Match Host 172.25.0.*\n", - " ProxyCommand sshpass -f cleartext-bastion-password ssh -F config jump@bastion -W %h:%p \n", + " ProxyCommand sshpass -f /home/user/.cleartext-bastion-password ssh -F config jump@bastion -W %h:%p \n", "\n", "```\n", "\n", @@ -139,6 +145,8 @@ "\n", "Write the [ssh-copy-id.yml](/edit/notebooks/exercise-06/ssh-copy-id.yml) playbook to install an ssh key to the bastion.\n", "\n", + "NOTE: a cooler version of this exercise includes generating random passwords and vault pin files using the `lookup` plugin,\n", + "like we did in 02_vaults.\n", "\n", "Set the bastion credentials to:\n", "\n", @@ -207,7 +215,7 @@ "ssh_args = -F ssh_config\n", "```\n", "\n", - "Write everything in ssh_config.\n", + "Write everything in `ssh_config`.\n", "\n", "\n", "Connecting via bastion in ansible enforcing multiple references to ssh_config" diff --git a/ansible-101/notebooks/exercise-06/ansible.cfg b/ansible-101/notebooks/exercise-06/ansible.cfg index 8b2c0ff..b983eff 100644 --- a/ansible-101/notebooks/exercise-06/ansible.cfg +++ b/ansible-101/notebooks/exercise-06/ansible.cfg @@ -1,7 +1,6 @@ -[defaults] -inventory = inventory -host_key_checking = False -vault_password_file = pin - -[ssh_connection] -ssh_args = -F ssh_config +# +# Write here your ansible.cfg +# +# * reference a pin file +# * pass [`[ssh_connection]`](http://docs.ansible.com/ansible/intro_configuration.html#openssh-specific-settings) arguments to avoid ssh key mismatches +# * point to the local inventory diff --git a/ansible-101/notebooks/exercise-06/ansible.cfg-solution b/ansible-101/notebooks/exercise-06/ansible.cfg-solution new file mode 100644 index 0000000..8b2c0ff --- /dev/null +++ b/ansible-101/notebooks/exercise-06/ansible.cfg-solution @@ -0,0 +1,7 @@ +[defaults] +inventory = inventory +host_key_checking = False +vault_password_file = pin + +[ssh_connection] +ssh_args = -F ssh_config diff --git a/ansible-101/notebooks/exercise-06/inventory b/ansible-101/notebooks/exercise-06/inventory index 12bf354..e4ef255 100644 --- a/ansible-101/notebooks/exercise-06/inventory +++ b/ansible-101/notebooks/exercise-06/inventory @@ -1,2 +1,3 @@ -[course] -172.17.0.[3:9] ansible_password=root +# +# Inventory file for the 06_bastion exercise. +# diff --git a/ansible-101/notebooks/exercise-06/inventory-solution b/ansible-101/notebooks/exercise-06/inventory-solution new file mode 100644 index 0000000..12bf354 --- /dev/null +++ b/ansible-101/notebooks/exercise-06/inventory-solution @@ -0,0 +1,2 @@ +[course] +172.17.0.[3:9] ansible_password=root diff --git a/ansible-101/notebooks/exercise-06/vault.yml b/ansible-101/notebooks/exercise-06/vault.yml index e69de29..e1e7dc5 100644 --- a/ansible-101/notebooks/exercise-06/vault.yml +++ b/ansible-101/notebooks/exercise-06/vault.yml @@ -0,0 +1,3 @@ +# +# Provide credentials in this vault file. +# From b8293d5b22a1f293253fa1411d917dee4b0d5ef1 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Tue, 30 May 2023 14:58:04 +0200 Subject: [PATCH 32/39] Improve exercise. --- .../notebooks/06_bastion_and_ssh.ipynb | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ansible-101/notebooks/06_bastion_and_ssh.ipynb b/ansible-101/notebooks/06_bastion_and_ssh.ipynb index cdde381..af6db31 100644 --- a/ansible-101/notebooks/06_bastion_and_ssh.ipynb +++ b/ansible-101/notebooks/06_bastion_and_ssh.ipynb @@ -106,10 +106,10 @@ "\n", "Inhibit PKI authentication is insecure by design:\n", "\n", - "- passwords will surely end in cleartext files\n", - "- people eventually do things like the following\n", + "- passwords will end on post-it\n", + "- people will save them in cleartext files, doing things like the following\n", " \n", - "```\n", + "```bash\n", "#\n", "# the password is sent to the bastion via a\n", "# cleartext file.\n", @@ -123,7 +123,7 @@ "\n", "Test connectivity to the bastion. Check your host IPs and modify [`ssh_config`](/edit/notebooks/exercise-06/ssh_config) accordingly.\n", "\n", - "**Replace ALL bastion occurrencies, including the one below the BEWARE note**" + "**Replace ALL bastion IP address occurrencies, including the one below the BEWARE note**" ] }, { @@ -145,7 +145,7 @@ "\n", "Write the [ssh-copy-id.yml](/edit/notebooks/exercise-06/ssh-copy-id.yml) playbook to install an ssh key to the bastion.\n", "\n", - "NOTE: a cooler version of this exercise includes generating random passwords and vault pin files using the `lookup` plugin,\n", + "NOTE: a cooler version of this exercise includes generating random passwords for `root` and for the vault using the `lookup()` plugin,\n", "like we did in 02_vaults.\n", "\n", "Set the bastion credentials to:\n", @@ -156,7 +156,7 @@ "Try to do it without watching the previous exercises:\n", "\n", "- modify the empty [`ansible.cfg`](/edit/notebooks/exercise-06/ansible.cfg)\n", - " * referencing a pin file \n", + " * referencing the vault password file named `pin` \n", " * passing [`[ssh_connection]`](http://docs.ansible.com/ansible/intro_configuration.html#openssh-specific-settings) arguments to avoid ssh key mismatches\n", " * pointing to the local inventory\n", "- store credentials in the encrypted [`vault.yml`](/edit/notebooks/exercise-06/vault.yml). \n", @@ -168,8 +168,8 @@ " \n", "Hint:\n", "\n", - "- if you provide an IdentityFile, password authentication won't work on the `bastion` node;\n", - "- you *must* copy ssh id file using password authentication and eventually clean up your known_host file" + "- if you provide an `IdentityFile`, password authentication won't work on the `bastion` node;\n", + "- you *must* copy ssh id file using password authentication and eventually clean up your `known_host` file" ] }, { @@ -210,7 +210,7 @@ "\n", "We can instead just set\n", "\n", - "```\n", + "```ini\n", "[ssh_connection]\n", "ssh_args = -F ssh_config\n", "```\n", @@ -258,10 +258,10 @@ "source": [ "#### Exercise\n", "\n", - "Configure your `ansible.cfg` so that every web host is accessed via the bastion.\n", + "Configure your [`ansible.cfg`](/edit/notebooks/exercise-06/ansible.cfg) so that every host in the `web` group is accessed via the bastion.\n", "\n", - " - recycle your dynamic inventory script to access web hosts\n", - " - your id_ansible key should already be on your web hosts \n", + " - recycle your dynamic inventory script to access the hosts in the `web` group\n", + " - your id_ansible key should already be on your hosts \n", " - use `ansible -m ping` to check host connectivity\n", " - run `ps -ef | grep ssh` on your docker host to check all the `ProxyCommand` processes." ] From 3ca4aec0b0f9dd34fbee435895154603911ba6c0 Mon Sep 17 00:00:00 2001 From: tucsolo Date: Wed, 31 May 2023 13:15:17 +0200 Subject: [PATCH 33/39] Added automatic Droplet shutdown at night (#63) --- ansible-101/site-digitalocean.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ansible-101/site-digitalocean.yml b/ansible-101/site-digitalocean.yml index a398870..8f4a9cb 100644 --- a/ansible-101/site-digitalocean.yml +++ b/ansible-101/site-digitalocean.yml @@ -101,6 +101,15 @@ tasks: - ping: - block: + - name: Automatic shutdown crontab entry + cron: + name: "shutdown" + hour: 2 # timezone is Etc/UTC + minute: 25 + state: present + disabled: false + job: "/sbin/shutdown -r now" + - name: Docker should listen on localhost. lineinfile: path: /etc/systemd/system/multi-user.target.wants/docker.service From 631decb9d775a7f99eccde4f8c9c7bb0044ac47d Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 31 May 2023 19:19:17 +0200 Subject: [PATCH 34/39] Fix: playbooks. --- ansible-101/notebooks/07_playbooks.ipynb | 145 +++++++++++++----- ansible-101/notebooks/exercise-07/debug.yml | 40 +---- .../notebooks/exercise-07/hostvars.yml | 37 +++++ ansible-101/notebooks/exercise-07/inventory | 4 +- 4 files changed, 147 insertions(+), 79 deletions(-) create mode 100644 ansible-101/notebooks/exercise-07/hostvars.yml diff --git a/ansible-101/notebooks/07_playbooks.ipynb b/ansible-101/notebooks/07_playbooks.ipynb index 3833f94..9e10033 100644 --- a/ansible-101/notebooks/07_playbooks.ipynb +++ b/ansible-101/notebooks/07_playbooks.ipynb @@ -1,30 +1,57 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Playbooks\n", + "#### ([exercise directory](/tree/notebooks/exercise-07))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /notebooks/exercise-07" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "\n", - "As we already learn in the other lessons, playbooks are yaml files where we group tasks.\n", + "As we already learn in the other lessons, playbooks are YAML files where we group **tasks**.\n", "\n", - "A playbook starts with an hosts mark specifying the hosts to run the playbook to.\n", + "A playbook starts with an `hosts` mark specifying the target hosts to run the playbook on.\n", "\n", - "```\n", - "# Yaml files usually start with 3 dashes: ---\n", - "# It's just a separator.\n", + "```yaml\n", + "# Since you can have multiple YAML documents in a single file,\n", + "# YAML files usually start with 3 dashes: ---\n", + "# and may end with 3 dots: ...\n", "---\n", "- hosts: web\n", " tasks: \n", - " ...\n", - "```\n", - "\n", + " ..\n", + "...\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", - "In yaml, a playbook is a *list* of `hosts` entries.\n", + "A playbook is a *list* of `hosts` entries in a single YAML document.\n", "\n", "\n", - "```\n", + "```yaml\n", + "---\n", "- hosts: localhost\n", " tasks:\n", " - name: one or more tasks to be run on localhost\n", @@ -38,7 +65,7 @@ "\n", "We can even pick a single element in an host group, or add `tags` entries to restrict executions\n", "\n", - "```\n", + "```yaml\n", "- hosts: db[0]\n", " tags: beware\n", " tasks:\n", @@ -46,25 +73,33 @@ " ...\n", " - name: run many tasks...\n", "\n", - "```\n", + "```\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", - "You can limit execution of a single task on a single host within a group using `run_once` .\n", - "```\n", + "You can limit execution of a single task on a single host within a group using `run_once`.\n", + "\n", + "```yaml\n", "- hosts: db\n", " tags: beware\n", " tasks:\n", - " - name: Only this task is run on one of the db nodes\n", + " - name: Only this task is run on one of the db nodes.\n", " run_once: yes\n", " \n", " - name: Other tasks are run on all nodes!\n", "```\n", "\n", - "We can even delegate the execution on a given host (eg. the ansible one)\n", + "We can even delegate the execution on a given host (e.g., the ansible one)\n", "\n", - "```\n", + "```yaml\n", "- hosts: db\n", " tasks:\n", - " - name: run this task from the local ansible host\n", + " - name: Run this task from the local ansible host.\n", " run_once: yes\n", " delegate_to: localhost\n", " shell: |\n", @@ -73,15 +108,7 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cd /notebooks/exercise-07" - ] - }, - { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -94,8 +121,6 @@ " - curl\n", " - file, copy & fetch\n", "\n", - "Creating small reports.\n", - "\n", "More fun with:\n", "\n", " - iterations\n", @@ -107,6 +132,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -117,7 +143,7 @@ "\n", "Gathering facts may be time-consuming, so you can [tune it via ansible.cfg](http://docs.ansible.com/ansible/intro_configuration.html#gathering) or disable it\n", "\n", - "```\n", + "```yaml\n", "- hosts: web\n", " gather_facts: no\n", " tasks:\n", @@ -142,6 +168,16 @@ ] }, { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!ansible-playbook debug.yml --tags groups" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -160,6 +196,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -172,6 +209,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -181,9 +219,17 @@ "\n", "Between set variables we have:\n", "\n", - " - hostvars\n", - " - groups\n", - " \n" + "- `groups`\n", + "- `hostvars`\n", + "\n", + "⚠ Fact gathering requires that specific tools are installed on the target host.\n", + "For example, gathering IP addresses requires the `iproute2` package to be installed.\n", + "\n", + "#### Exercise:\n", + "\n", + "1. Run the following playbook and look at the error message: which fact is missing?\n", + "1. Can you gather the missing fact using the `setup` module? Why? **Hint: access the container and try to run `ip addr`.**\n", + "1. Can you fix the playbook to ensure that the `ip` fact is gathered?" ] }, { @@ -192,10 +238,11 @@ "metadata": {}, "outputs": [], "source": [ - "!ansible-playbook debug.yml --tags hostvars" + "!ansible-playbook hostvars.yml" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden", @@ -208,6 +255,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": { "solution": "hidden" @@ -217,24 +265,33 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Filters\n", "\n", - "We can process hostvars using jinja filters (see the facts and variable lesson). \n", + "We can process hostvars using jinja filters (see the \"facts and variables\" lesson). \n", "\n", "Here is a [list of useful filters](http://docs.ansible.com/ansible/latest/playbooks_filters.html)\n", "\n", "\n", "Remember: a filter is essentially a function returning a function, like a [python lambda](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions).\n", "\n", - "```\n", + "```python\n", "int_filter = lambda x: int(x)\n", - "```\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "A more complex filter: \n", - "```\n", + "\n", + "```yaml\n", "- name: This is a getter\n", " debug:\n", " msg: >\n", @@ -244,7 +301,8 @@ "```\n", "\n", "where\n", - "```\n", + "\n", + "```python\n", "hostvars_getter = lambda host: hostvars[host]['key1'][..]['keyN']\n", "```\n", "\n", @@ -261,6 +319,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -268,7 +327,7 @@ "\n", "Creating user and installing packages is easy\n", "\n", - "```\n", + "```yaml\n", " - name: Install apache\n", " apt: item=\"{{item}}\" state=present\n", " with_items:\n", @@ -308,6 +367,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -339,6 +399,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -368,6 +429,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -379,6 +441,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -412,6 +475,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -471,6 +535,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/ansible-101/notebooks/exercise-07/debug.yml b/ansible-101/notebooks/exercise-07/debug.yml index 593a365..a09b27c 100644 --- a/ansible-101/notebooks/exercise-07/debug.yml +++ b/ansible-101/notebooks/exercise-07/debug.yml @@ -4,48 +4,16 @@ tasks: - name: This is the debug module. debug: msg="A string" - - - name: The debug module can print a variable too + - name: The debug module can print a variable too... debug: var=ansible_hostname - hosts: web tags: groups - name: those tasks are run on every web host - tasks: - - name: Iterating over a list - debug: - msg: > - Host: {{item}} - with_items: > - {{ groups['web'] }} - -- hosts: web[0] - tags: hostvars - name: Run only on first host + name: Those tasks are run on every web host tasks: - - name: Iterating over a map yields the keys - debug: - msg: > - Host: {{item}} - with_items: > - {{ hostvars }} - - name: Use subscript to access entries + - name: Iterating over the host in the "web" group. debug: msg: > - address: {{ hostvars[item]['ansible_default_ipv4']['address'] }} + Host: {{ item }} with_items: > {{ groups['web'] }} - - -- hosts: web[0] - tags: filters - name: Get a list of defined host ips. - tasks: - - - name: Using filters - debug: - msg: > - {{ groups['web'] | - map('extract', hostvars, ['ansible_default_ipv4', 'address']) | - reject('undefined') | - list }} diff --git a/ansible-101/notebooks/exercise-07/hostvars.yml b/ansible-101/notebooks/exercise-07/hostvars.yml new file mode 100644 index 0000000..413bda3 --- /dev/null +++ b/ansible-101/notebooks/exercise-07/hostvars.yml @@ -0,0 +1,37 @@ +# - hosts: web +# tasks: +# - name: Ensure iproute2 is installed on every node. +# apt: +# name: iproute2 +# state: present +- hosts: web[0] + tags: hostvars + name: Run only on first host + tasks: + - name: Iterating over a map yields the keys + debug: + msg: > + Host: {{ item }} + with_items: > + {{ hostvars }} + - name: >- + Use subscript to access entries. + NB: This task requires iproute2 installed on the remote host. + debug: + msg: > + address: {{ hostvars[item]['ansible_default_ipv4']['address'] }} + with_items: > + {{ groups['web'] }} + + +- hosts: web[0] + tags: filters + name: Get a list of defined host IPs. + tasks: + - name: Using filters + debug: + msg: > + {{ groups['web'] | + map('extract', hostvars, ['ansible_default_ipv4', 'address']) | + reject('undefined') | + list }} diff --git a/ansible-101/notebooks/exercise-07/inventory b/ansible-101/notebooks/exercise-07/inventory index 38c1bd6..8a992a9 100644 --- a/ansible-101/notebooks/exercise-07/inventory +++ b/ansible-101/notebooks/exercise-07/inventory @@ -2,8 +2,6 @@ ansible_connection=docker ansible_docker_extra_args="-Htcp://172.17.0.1" - - # The actual host reference [web] -ansible101_web_[1:3] +ansible-101_web_[1:2] From a152068d7389f654d0cf6ce4c37d586aa0f5d055 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 31 May 2023 19:30:57 +0200 Subject: [PATCH 35/39] playbooks ++ --- ansible-101/notebooks/07_playbooks.ipynb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/ansible-101/notebooks/07_playbooks.ipynb b/ansible-101/notebooks/07_playbooks.ipynb index 9e10033..d9d0a90 100644 --- a/ansible-101/notebooks/07_playbooks.ipynb +++ b/ansible-101/notebooks/07_playbooks.ipynb @@ -452,7 +452,7 @@ " - every command stdout/stderr is redirected to a given file\n", " - before and after every command output print a header and a footer (eg. the expected output is like\n", " \n", - "```\n", + "```text\n", "--- START COMMAND: cat /etc/resolv.conf --\n", "nameserver 172.17.0.1\n", "-- END COMMAND: cat /etc/resolv.conf\n", @@ -493,7 +493,7 @@ "\n", "Here's a full example!\n", "\n", - "```\n", + "```yaml\n", " - name: This shell task will not modify the system\n", " shell: |\n", " pgrep -fa tomcat\n", @@ -550,7 +550,7 @@ " \n", "*service* manages and enables services\n", "\n", - "```\n", + "```yaml\n", " - name: Restart httpd\n", " service: \n", " name: httpd\n", @@ -561,21 +561,18 @@ "*systemd* manages and enables services with systemd. It can reload systemd configuration too\n", "\n", "\n", - "```\n", - "\n", + "```yaml\n", " - name: Reload docker with new systemd config\n", " systemd:\n", " state: restarted\n", " name: docker\n", " daemon_reload: yes\n", - "\n", - "\n", "```\n", " \n", "*mount* populates entries in /etc/fstab and mounts associate filesystem.\n", "\n", "\n", - "```\n", + "```yaml\n", " - name: Check if mongod LUN is mounted\n", " register: mongod_on_storage\n", " mount:\n", @@ -583,7 +580,6 @@ " src: /dev/sdc\n", " fstype: xfs\n", " state: present # creates an entry in /etc/fstab. `mounted` does the actual mount.\n", - "\n", "```\n", "\n", "#### Exercise\n", From ab368cf6e5d24eea414f2b3c1e9905551ac65d2d Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 7 Jun 2023 01:33:43 +0200 Subject: [PATCH 36/39] Cleanup code. Add exercises. --- ansible-101/notebooks/07_playbooks.ipynb | 73 +++++++++++++++++-- ansible-101/notebooks/07_templates.ipynb | 6 +- .../notebooks/exercise-07/package-user.yml | 9 ++- .../notebooks/exercise-07/process-facts.yml | 4 + .../notebooks/exercise-07/shell-output-01.yml | 6 +- 5 files changed, 87 insertions(+), 11 deletions(-) diff --git a/ansible-101/notebooks/07_playbooks.ipynb b/ansible-101/notebooks/07_playbooks.ipynb index d9d0a90..73e631f 100644 --- a/ansible-101/notebooks/07_playbooks.ipynb +++ b/ansible-101/notebooks/07_playbooks.ipynb @@ -6,7 +6,8 @@ "metadata": {}, "source": [ "# Playbooks\n", - "#### ([exercise directory](/tree/notebooks/exercise-07))" + "#### ([exercise directory](/tree/notebooks/exercise-07))\n", + "#### NB: This lesson requires that the target nodes are reachable via ssh key exchange. Complete lesson 02_vaults (again :) before starting this lesson." ] }, { @@ -203,8 +204,8 @@ "### Hints\n", "\n", " - use `ansible_facts` as possible \n", - " - avoid gathering facts with uname & co\n", - " - test and template your iterations statically instead of continuosly gathering facts\n", + " - avoid gathering facts using system commands like `uname` & co\n", + " - test and template your iterations statically instead of continuosly gathering facts (do you remember lesson 03_facts_and_variables?) )\n", " " ] }, @@ -305,6 +306,65 @@ "```python\n", "hostvars_getter = lambda host: hostvars[host]['key1'][..]['keyN']\n", "```\n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Exercise\n", + "\n", + "Given the data in the cell below, identify the output of the following filter:\n", + "\n", + "```yaml\n", + "debug:\n", + " msg: >-\n", + " hosts | map('extract', hostvars, ['ipv4', 'address'])\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Given the following data, identify the output of\n", + "hosts = [ \"host1\", \"host2\" ]\n", + "hostvars = {\n", + " \"host2\": {\n", + " \"ipv4\": {\n", + " \"address\": \"172.17.0.1\"\n", + " }\n", + " },\n", + " \"host2\": {\n", + " \"ipv4\": {\n", + " \"address\": \"172.17.0.2\"\n", + " }\n", + " }\n", + "}\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Exercise (advanced)\n", + "\n", + "Write a python function fmap associated to the above filter.\n", + "Hints:\n", + "1. `fmap` returns a function that takes a list as input;\n", + "1. `fmap` takes hostvars as a closure." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "You can pipeline filters and test incrementally." ] @@ -329,13 +389,16 @@ "\n", "```yaml\n", " - name: Install apache\n", - " apt: item=\"{{item}}\" state=present\n", + " apt:\n", + " item: \"{{item}}\" state=present\n", " with_items:\n", " - apache2\n", " - curl\n", " \n", " - name: Remove wget\n", - " apt: item=wget state=absent\n", + " apt:\n", + " item: wget \n", + " state: absent\n", "```" ] }, diff --git a/ansible-101/notebooks/07_templates.ipynb b/ansible-101/notebooks/07_templates.ipynb index 1dfcc88..46e0c28 100644 --- a/ansible-101/notebooks/07_templates.ipynb +++ b/ansible-101/notebooks/07_templates.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -21,6 +22,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -91,6 +93,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -127,6 +130,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -140,7 +144,7 @@ "In this recap exercise, write the [add_key.yml](/edit/notebooks/exercises-07/add_key.yml) playbook which:\n", "\n", " - authenticates with `root:root` credentials on remote hosts\n", - " - generate a new ecdsa PK for local `root`\n", + " - generate a new ed25519 PK for local `root`\n", " - creates the fizz user on remote hosts with:\n", " * a keypair\n", " * a password\n", diff --git a/ansible-101/notebooks/exercise-07/package-user.yml b/ansible-101/notebooks/exercise-07/package-user.yml index 38a6434..7b4e992 100644 --- a/ansible-101/notebooks/exercise-07/package-user.yml +++ b/ansible-101/notebooks/exercise-07/package-user.yml @@ -1,13 +1,16 @@ - hosts: web tasks: - name: Install apache and other packages eventually iterating - apt: name="{{item}}" + apt: + name: "{{item}}" with_items: - apache2 - curl - name: Remove wget - apt: name=wget state=absent + apt: + name: wget + state: absent - name: Create user user: @@ -24,7 +27,7 @@ src: package-user.yml dest: "{{ '~foo' | expanduser }}" - - name: > + - name: |- We can fetch files too (eg. logs): - files are dispatched to different directories. - we can avoid enforcing checksum as we're messing with diff --git a/ansible-101/notebooks/exercise-07/process-facts.yml b/ansible-101/notebooks/exercise-07/process-facts.yml index a458516..74998af 100644 --- a/ansible-101/notebooks/exercise-07/process-facts.yml +++ b/ansible-101/notebooks/exercise-07/process-facts.yml @@ -1,3 +1,7 @@ +# +# This playbook shows how to process facts without gathering them, +# e.g., for testing purposes. +# --- - hosts: localhost gather_facts: no diff --git a/ansible-101/notebooks/exercise-07/shell-output-01.yml b/ansible-101/notebooks/exercise-07/shell-output-01.yml index bb58a12..91cc241 100644 --- a/ansible-101/notebooks/exercise-07/shell-output-01.yml +++ b/ansible-101/notebooks/exercise-07/shell-output-01.yml @@ -9,9 +9,11 @@ register: o - name: Show output in a single block... - debug: var=o.stdout + debug: + var: o.stdout - name: ... or one per line - debug: var=item + debug: + var: item with_items: > {{ o.stdout_lines }} From e88943f065d2175030208af65c5748f7ea29163a Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Wed, 7 Jun 2023 11:22:39 +0200 Subject: [PATCH 37/39] Simplify hostvars exercise. --- ansible-101/notebooks/exercise-07/hostvars.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ansible-101/notebooks/exercise-07/hostvars.yml b/ansible-101/notebooks/exercise-07/hostvars.yml index 413bda3..618f5ee 100644 --- a/ansible-101/notebooks/exercise-07/hostvars.yml +++ b/ansible-101/notebooks/exercise-07/hostvars.yml @@ -1,14 +1,19 @@ # - hosts: web # tasks: -# - name: Ensure iproute2 is installed on every node. +# - name: >- +# Ensure iproute2 is installed on every node. +# NB: This may require specific python modules. # apt: # name: iproute2 # state: present -- hosts: web[0] +- hosts: web tags: hostvars - name: Run only on first host + name: Last task runs only on first host tasks: - - name: Iterating over a map yields the keys + - name: hostvars is a dictionary + debug: + var: hostvars + - name: Iterating over a dictionary yields the keys debug: msg: > Host: {{ item }} @@ -17,9 +22,10 @@ - name: >- Use subscript to access entries. NB: This task requires iproute2 installed on the remote host. + run_once: true debug: msg: > - address: {{ hostvars[item]['ansible_default_ipv4']['address'] }} + address: {{ item }} -> {{ hostvars[item]['ansible_default_ipv4']['address'] }} with_items: > {{ groups['web'] }} From fcf601d732857ad4727db08fdb20bb9726981de0 Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Thu, 8 Jun 2023 16:52:32 +0200 Subject: [PATCH 38/39] Add minimal doc tox.ini --- docker-101/tox.ini | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker-101/tox.ini b/docker-101/tox.ini index cee54b2..c8624a4 100644 --- a/docker-101/tox.ini +++ b/docker-101/tox.ini @@ -1,3 +1,10 @@ +# +# When you edit the markdown file, you need to rebuild the .ipynb file +# via tox. +# +# $ pip install tox +# $ tox +# [tox] envlist = py3 skipsdist = True From 226894809453d75abe9f5a57983326e45a617d5d Mon Sep 17 00:00:00 2001 From: Roberto Polli Date: Fri, 9 Jun 2023 08:19:41 +0200 Subject: [PATCH 39/39] cleanup --- ansible-101/notebooks/07_playbooks.ipynb | 65 +++++++++++++++---- ansible-101/notebooks/exercise-07/debug.yml | 7 +- .../notebooks/exercise-07/hostvars.yml | 8 ++- 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/ansible-101/notebooks/07_playbooks.ipynb b/ansible-101/notebooks/07_playbooks.ipynb index 73e631f..5a1155f 100644 --- a/ansible-101/notebooks/07_playbooks.ipynb +++ b/ansible-101/notebooks/07_playbooks.ipynb @@ -62,7 +62,14 @@ " tasks:\n", " - name: followed by tasks to be run on web hostgroup\n", " ...\n", - "```\n", + "```\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "We can even pick a single element in an host group, or add `tags` entries to restrict executions\n", "\n", @@ -93,7 +100,14 @@ " run_once: yes\n", " \n", " - name: Other tasks are run on all nodes!\n", - "```\n", + "```\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "We can even delegate the execution on a given host (e.g., the ansible one)\n", "\n", @@ -142,7 +156,7 @@ "\n", "When run, a playbook gathers facts about hosts (remember the setup module?).\n", "\n", - "Gathering facts may be time-consuming, so you can [tune it via ansible.cfg](http://docs.ansible.com/ansible/intro_configuration.html#gathering) or disable it\n", + "Gathering facts may be time-consuming, so you can [tune it via ansible.cfg](http://docs.ansible.com/ansible/latest/intro_configuration.html#gathering) or disable it\n", "\n", "```yaml\n", "- hosts: web\n", @@ -151,7 +165,7 @@ " ...\n", "```\n", "\n", - "We can use the [predefined variables](http://docs.ansible.com/ansible/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts) too:\n", + "We can use the [predefined variables](http://docs.ansible.com/ansible/latest/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts) too:\n", "\n", " - group_names\n", " - groups\n", @@ -205,7 +219,7 @@ "\n", " - use `ansible_facts` as possible \n", " - avoid gathering facts using system commands like `uname` & co\n", - " - test and template your iterations statically instead of continuosly gathering facts (do you remember lesson 03_facts_and_variables?) )\n", + " - test and template your iterations statically instead of continuosly gathering facts (do you remember lesson [03_facts_and_variables(/notebooks/notebooks/03_facts_and_variables.ipynb)]?) )\n", " " ] }, @@ -226,9 +240,34 @@ "⚠ Fact gathering requires that specific tools are installed on the target host.\n", "For example, gathering IP addresses requires the `iproute2` package to be installed.\n", "\n", - "#### Exercise:\n", + "##### Exercise:\n", "\n", - "1. Run the following playbook and look at the error message: which fact is missing?\n", + "Run the following playbook and look at the output of `hostvars`:\n", + "\n", + "1. which major facts are gathered?\n", + "1. do you see any network related fact?\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!ansible-playbook hostvars.yml --tags debug" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "##### Exercise\n", + "\n", + "Run the following playbook and:\n", + "\n", + "1. look at the error message: which fact is missing?\n", "1. Can you gather the missing fact using the `setup` module? Why? **Hint: access the container and try to run `ip addr`.**\n", "1. Can you fix the playbook to ensure that the `ip` fact is gathered?" ] @@ -239,7 +278,7 @@ "metadata": {}, "outputs": [], "source": [ - "!ansible-playbook hostvars.yml" + "!ansible-playbook hostvars.yml --tags hostvars" ] }, { @@ -272,7 +311,7 @@ "source": [ "## Filters\n", "\n", - "We can process hostvars using jinja filters (see the \"facts and variables\" lesson). \n", + "We can process hostvars using jinja filters (see the [03_facts_and_variables](/notebooks/notebooks/03_facts_and_variables.ipynb) lesson). \n", "\n", "Here is a [list of useful filters](http://docs.ansible.com/ansible/latest/playbooks_filters.html)\n", "\n", @@ -332,9 +371,9 @@ "outputs": [], "source": [ "# Given the following data, identify the output of\n", - "hosts = [ \"host1\", \"host2\" ]\n", + "hosts = [\"host1\", \"host2\"]\n", "hostvars = {\n", - " \"host2\": {\n", + " \"host1\": {\n", " \"ipv4\": {\n", " \"address\": \"172.17.0.1\"\n", " }\n", @@ -344,7 +383,7 @@ " \"address\": \"172.17.0.2\"\n", " }\n", " }\n", - "}\n" + "}" ] }, { @@ -375,7 +414,7 @@ "metadata": {}, "outputs": [], "source": [ - "!ansible-playbook debug.yml --tags filters" + "!ansible-playbook hostvars.yml --tags filters" ] }, { diff --git a/ansible-101/notebooks/exercise-07/debug.yml b/ansible-101/notebooks/exercise-07/debug.yml index a09b27c..870574e 100644 --- a/ansible-101/notebooks/exercise-07/debug.yml +++ b/ansible-101/notebooks/exercise-07/debug.yml @@ -3,9 +3,12 @@ name: those tasks are run on localhost only tasks: - name: This is the debug module. - debug: msg="A string" + debug: + msg: >- + "A string" - name: The debug module can print a variable too... - debug: var=ansible_hostname + debug: + var: ansible_hostname - hosts: web tags: groups diff --git a/ansible-101/notebooks/exercise-07/hostvars.yml b/ansible-101/notebooks/exercise-07/hostvars.yml index 618f5ee..1ad3efc 100644 --- a/ansible-101/notebooks/exercise-07/hostvars.yml +++ b/ansible-101/notebooks/exercise-07/hostvars.yml @@ -7,12 +7,16 @@ # name: iproute2 # state: present - hosts: web - tags: hostvars - name: Last task runs only on first host + tags: debug tasks: - name: hostvars is a dictionary debug: var: hostvars + +- hosts: web + tags: hostvars + name: Last task runs only on first host + tasks: - name: Iterating over a dictionary yields the keys debug: msg: >