From 77a1a12da45fb49d937bc1cfd2fef4bfcb4d21ac Mon Sep 17 00:00:00 2001 From: Baha Alimi Date: Sat, 21 Feb 2026 05:07:07 +0300 Subject: [PATCH 1/2] feat: complete lab05 - ansible fundamentals --- ansible/.gitignore | 3 ++ ansible/ansible.cfg | 12 +++++ ansible/docs/LAB05.md | 0 ansible/group_vars/all.yml | 18 ++++++++ ansible/inventory/hosts.ini | 5 ++ ansible/playbooks/deploy.yml | 7 +++ ansible/playbooks/provision.yml | 8 ++++ ansible/playbooks/site.yml | 0 ansible/roles/app_deploy/defaults/main.yml | 4 ++ ansible/roles/app_deploy/handlers/main.yml | 6 +++ ansible/roles/app_deploy/tasks/main.yml | 42 +++++++++++++++++ ansible/roles/common/defaults/main.yml | 9 ++++ ansible/roles/common/tasks/main.yml | 10 ++++ ansible/roles/docker/defaults/main.yml | 2 + ansible/roles/docker/handlers/main.yml | 5 ++ ansible/roles/docker/tasks/main.yml | 54 ++++++++++++++++++++++ 16 files changed, 185 insertions(+) create mode 100644 ansible/.gitignore create mode 100644 ansible/ansible.cfg create mode 100644 ansible/docs/LAB05.md create mode 100644 ansible/group_vars/all.yml create mode 100644 ansible/inventory/hosts.ini create mode 100644 ansible/playbooks/deploy.yml create mode 100644 ansible/playbooks/provision.yml create mode 100644 ansible/playbooks/site.yml create mode 100644 ansible/roles/app_deploy/defaults/main.yml create mode 100644 ansible/roles/app_deploy/handlers/main.yml create mode 100644 ansible/roles/app_deploy/tasks/main.yml create mode 100644 ansible/roles/common/defaults/main.yml create mode 100644 ansible/roles/common/tasks/main.yml create mode 100644 ansible/roles/docker/defaults/main.yml create mode 100644 ansible/roles/docker/handlers/main.yml create mode 100644 ansible/roles/docker/tasks/main.yml diff --git a/ansible/.gitignore b/ansible/.gitignore new file mode 100644 index 0000000000..0acda56a58 --- /dev/null +++ b/ansible/.gitignore @@ -0,0 +1,3 @@ +*.retry +.vault_pass +__pycache__/ diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg new file mode 100644 index 0000000000..6f38a00421 --- /dev/null +++ b/ansible/ansible.cfg @@ -0,0 +1,12 @@ +[defaults] +inventory = inventory/hosts.ini +roles_path = roles +host_key_checking = False +remote_user = vagrant +retry_files_enabled = False +deprecation_warnings = False + +[privilege_escalation] +become = True +become_method = sudo +become_user = root diff --git a/ansible/docs/LAB05.md b/ansible/docs/LAB05.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml new file mode 100644 index 0000000000..20fde46a8f --- /dev/null +++ b/ansible/group_vars/all.yml @@ -0,0 +1,18 @@ +$ANSIBLE_VAULT;1.1;AES256 +37353731323564313431383962323137383261346563303561356530366133623439363562346662 +3562336265383731613638653637666136343761336338650a393861646465333163373232373437 +39343763383931633733366166626137613030356337353862636634656331626131383938653334 +3636626263653239610a396130313936626263623938316161386539383465653762613134333730 +31363135623164373236383930366137663436366138623330303866646332303030653932353264 +30366633636662666138646336386565636361346133303137386165656434303538356337376531 +63663037656132313565623034663864303561626132663332633561643737633561363830636462 +30613934623830653139646165303863656535666138323561643264643766383764626634626436 +64376464326434623464306339333430656263386563313730303761623436383432353836333331 +33353362326563633630313035633537626235653831663933336434333933353031363836646139 +38393733663936343162343131393566376232636438623938366237336331386232666566343034 +33663334366338333365396236373330353261393731343832626436626162396339663130386365 +38346636336564323365666238333636303836656264306362393635643934326364613362383732 +32336333636335323636353563613636323333346135366230346133363831313333396131303630 +31303731386661376338653331326339373066366666626365326663333766336131323137393364 +36323434326563393536663934333835663732333631653864636139313935303363643563623636 +3665 diff --git a/ansible/inventory/hosts.ini b/ansible/inventory/hosts.ini new file mode 100644 index 0000000000..e0fa72af1d --- /dev/null +++ b/ansible/inventory/hosts.ini @@ -0,0 +1,5 @@ +[webservers] +localhost ansible_connection=local ansible_user=vagrant + +[webservers:vars] +ansible_python_interpreter=/usr/bin/python3 diff --git a/ansible/playbooks/deploy.yml b/ansible/playbooks/deploy.yml new file mode 100644 index 0000000000..fb448bca6e --- /dev/null +++ b/ansible/playbooks/deploy.yml @@ -0,0 +1,7 @@ +--- +- name: Deploy application + hosts: webservers + become: no + + roles: + - app_deploy diff --git a/ansible/playbooks/provision.yml b/ansible/playbooks/provision.yml new file mode 100644 index 0000000000..f53efb0248 --- /dev/null +++ b/ansible/playbooks/provision.yml @@ -0,0 +1,8 @@ +--- +- name: Provision web servers + hosts: webservers + become: yes + + roles: + - common + - docker diff --git a/ansible/playbooks/site.yml b/ansible/playbooks/site.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ansible/roles/app_deploy/defaults/main.yml b/ansible/roles/app_deploy/defaults/main.yml new file mode 100644 index 0000000000..a7a9dd52b3 --- /dev/null +++ b/ansible/roles/app_deploy/defaults/main.yml @@ -0,0 +1,4 @@ + +app_port: 5000 +app_restart_policy: unless-stopped +app_env_vars: {} diff --git a/ansible/roles/app_deploy/handlers/main.yml b/ansible/roles/app_deploy/handlers/main.yml new file mode 100644 index 0000000000..90a8f61227 --- /dev/null +++ b/ansible/roles/app_deploy/handlers/main.yml @@ -0,0 +1,6 @@ + +- name: restart app + docker_container: + name: "{{ app_container_name }}" + state: started + restart: yes diff --git a/ansible/roles/app_deploy/tasks/main.yml b/ansible/roles/app_deploy/tasks/main.yml new file mode 100644 index 0000000000..f4d3831c9a --- /dev/null +++ b/ansible/roles/app_deploy/tasks/main.yml @@ -0,0 +1,42 @@ +--- +- name: Log in to Docker Hub + shell: echo "{{ dockerhub_password }}" | docker login -u "{{ dockerhub_username }}" --password-stdin + no_log: true + +- name: Pull Docker image + docker_image: + name: "{{ docker_image }}:{{ docker_image_tag }}" + source: pull + +- name: Stop existing container + docker_container: + name: "{{ app_container_name }}" + state: stopped + ignore_errors: yes + +- name: Remove old container + docker_container: + name: "{{ app_container_name }}" + state: absent + ignore_errors: yes + +- name: Run application container + docker_container: + name: "{{ app_container_name }}" + image: "{{ docker_image }}:{{ docker_image_tag }}" + state: started + ports: + - "{{ app_port }}:8000" + restart_policy: "{{ app_restart_policy }}" + +- name: Wait for application to be ready + wait_for: + port: "{{ app_port }}" + delay: 3 + timeout: 30 + +- name: Verify health endpoint + uri: + url: "http://localhost:{{ app_port }}/health" + status_code: 200 + ignore_errors: yes diff --git a/ansible/roles/common/defaults/main.yml b/ansible/roles/common/defaults/main.yml new file mode 100644 index 0000000000..16a0a9ed3a --- /dev/null +++ b/ansible/roles/common/defaults/main.yml @@ -0,0 +1,9 @@ +--- +common_packages: + - python3-pip + - curl + - git + - vim + - htop + - wget + - unzip diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/main.yml new file mode 100644 index 0000000000..7f74c167c1 --- /dev/null +++ b/ansible/roles/common/tasks/main.yml @@ -0,0 +1,10 @@ +--- +- name: Update apt cache + apt: + update_cache: yes + cache_valid_time: 3600 + +- name: Install common packages + apt: + name: "{{ common_packages }}" + state: present diff --git a/ansible/roles/docker/defaults/main.yml b/ansible/roles/docker/defaults/main.yml new file mode 100644 index 0000000000..dbb7083a98 --- /dev/null +++ b/ansible/roles/docker/defaults/main.yml @@ -0,0 +1,2 @@ +--- +docker_user: vagrant diff --git a/ansible/roles/docker/handlers/main.yml b/ansible/roles/docker/handlers/main.yml new file mode 100644 index 0000000000..3627303e6b --- /dev/null +++ b/ansible/roles/docker/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart docker + service: + name: docker + state: restarted diff --git a/ansible/roles/docker/tasks/main.yml b/ansible/roles/docker/tasks/main.yml new file mode 100644 index 0000000000..d257e0b0c0 --- /dev/null +++ b/ansible/roles/docker/tasks/main.yml @@ -0,0 +1,54 @@ +--- +- name: Install prerequisites + apt: + name: + - ca-certificates + - curl + - gnupg + state: present + +- name: Create keyrings directory + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + +- name: Add Docker GPG key + shell: | + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg + chmod a+r /etc/apt/keyrings/docker.gpg + args: + creates: /etc/apt/keyrings/docker.gpg + +- name: Add Docker repository + apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" + state: present + filename: docker + +- name: Install Docker packages + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + state: present + update_cache: yes + notify: restart docker + +- name: Ensure Docker service is running and enabled + service: + name: docker + state: started + enabled: yes + +- name: Add user to docker group + user: + name: "{{ docker_user }}" + groups: docker + append: yes + +- name: Install python3-docker + apt: + name: python3-docker + state: present From 45d7e8452c7dee9db6126c38b81567a580d12908 Mon Sep 17 00:00:00 2001 From: Baha Alimi Date: Sat, 21 Feb 2026 15:05:59 +0300 Subject: [PATCH 2/2] Bonus Task Implementation --- ansible/.gitignore | 4 +- ansible/docs/LAB05.md | 295 ++++++++++++++++++ ansible/inventory/dynamic_inventory.py | 44 +++ .../default/virtualbox/action_cloud_init | 1 + .../default/virtualbox/synced_folders | 1 + 5 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 ansible/inventory/dynamic_inventory.py create mode 100644 vagrant/.vagrant/machines/default/virtualbox/action_cloud_init create mode 100644 vagrant/.vagrant/machines/default/virtualbox/synced_folders diff --git a/ansible/.gitignore b/ansible/.gitignore index 0acda56a58..6da0a9c159 100644 --- a/ansible/.gitignore +++ b/ansible/.gitignore @@ -1,3 +1,3 @@ -*.retry +*.retry .vault_pass -__pycache__/ +__pycache__/ \ No newline at end of file diff --git a/ansible/docs/LAB05.md b/ansible/docs/LAB05.md index e69de29bb2..5907778989 100644 --- a/ansible/docs/LAB05.md +++ b/ansible/docs/LAB05.md @@ -0,0 +1,295 @@ +# Lab 05 — Ansible Fundamentals + +## 1. Architecture Overview + +**Ansible Version:** 2.10.8 +**Target VM OS:** Ubuntu 22.04 LTS (jammy64) +**Control Node:** Same VM (Ansible runs on the VM and targets itself via `ansible_connection=local`) + +### Role Structure + +``` +ansible/ +├── inventory/ +│ ├── hosts.ini # Static inventory (localhost) +│ └── dynamic_inventory.py # Dynamic inventory script (bonus) +├── roles/ +│ ├── common/ # Common system packages +│ │ ├── tasks/main.yml +│ │ └── defaults/main.yml +│ ├── docker/ # Docker installation +│ │ ├── tasks/main.yml +│ │ ├── handlers/main.yml +│ │ └── defaults/main.yml +│ └── app_deploy/ # Application deployment +│ ├── tasks/main.yml +│ ├── handlers/main.yml +│ └── defaults/main.yml +├── playbooks/ +│ ├── site.yml # Main playbook +│ ├── provision.yml # System provisioning +│ └── deploy.yml # App deployment +├── group_vars/ +│ └── all.yml # Encrypted variables (Vault) +├── ansible.cfg # Ansible configuration +└── docs/ + └── LAB05.md +``` + +### Why Roles Instead of Monolithic Playbooks? + +Roles enforce separation of concerns — each role has a single responsibility (common packages, Docker setup, app deployment). This makes the codebase reusable across projects, easier to test independently, and simple to maintain. A monolithic playbook mixing all tasks together would become unmanageable as complexity grows. + +--- + +## 2. Roles Documentation + +### common + +**Purpose:** Ensures every server has essential system tools installed and the apt cache is up to date. + +**Variables (defaults/main.yml):** +```yaml +common_packages: + - python3-pip + - curl + - git + - vim + - htop + - wget + - unzip +``` + +**Handlers:** None — package installation does not require service restarts. + +**Dependencies:** None. + +--- + +### docker + +**Purpose:** Installs Docker CE from the official Docker repository, ensures the Docker service is running and enabled on boot, and adds the target user to the `docker` group. + +**Variables (defaults/main.yml):** +```yaml +docker_user: vagrant +``` + +**Handlers (handlers/main.yml):** +- `restart docker` — Restarts the Docker service. Triggered when Docker packages are installed or updated. + +**Dependencies:** Depends on `common` role being run first (curl must be available for GPG key download). + +--- + +### app_deploy + +**Purpose:** Authenticates with Docker Hub, pulls the application image, removes any existing container, runs a fresh container with the correct port mapping, and verifies the application is healthy. + +**Variables (defaults/main.yml):** +```yaml +app_port: 8000 +app_restart_policy: unless-stopped +app_env_vars: {} +``` + +**Sensitive variables (group_vars/all.yml — Vault encrypted):** +- `dockerhub_username` +- `dockerhub_password` +- `docker_image` +- `docker_image_tag` +- `app_container_name` + +**Handlers (handlers/main.yml):** +- `restart app` — Restarts the application container when triggered. + +**Dependencies:** Depends on `docker` role — Docker must be installed before deploying containers. + +--- + +## 3. Idempotency Demonstration + +### First Run Output +``` +PLAY [Provision web servers] +TASK [Gathering Facts] ok: [localhost] +TASK [common : Update apt cache] ok: [localhost] +TASK [common : Install common packages] changed: [localhost] +TASK [docker : Install prerequisites] ok: [localhost] +TASK [docker : Create keyrings directory] ok: [localhost] +TASK [docker : Add Docker GPG key] changed: [localhost] +TASK [docker : Add Docker repository] changed: [localhost] +TASK [docker : Install Docker packages] changed: [localhost] +TASK [docker : Ensure Docker service is running and enabled] ok: [localhost] +TASK [docker : Add user to docker group] changed: [localhost] +TASK [docker : Install python3-docker] changed: [localhost] +RUNNING HANDLER [docker : restart docker] changed: [localhost] + +PLAY RECAP +localhost : ok=12 changed=7 unreachable=0 failed=0 +``` + +### Second Run Output +``` +PLAY [Provision web servers] +TASK [Gathering Facts] ok: [localhost] +TASK [common : Update apt cache] ok: [localhost] +TASK [common : Install common packages] ok: [localhost] +TASK [docker : Install prerequisites] ok: [localhost] +TASK [docker : Create keyrings directory] ok: [localhost] +TASK [docker : Add Docker GPG key] ok: [localhost] +TASK [docker : Add Docker repository] ok: [localhost] +TASK [docker : Install Docker packages] ok: [localhost] +TASK [docker : Ensure Docker service is running and enabled] ok: [localhost] +TASK [docker : Add user to docker group] ok: [localhost] +TASK [docker : Install python3-docker] ok: [localhost] + +PLAY RECAP +localhost : ok=11 changed=0 unreachable=0 failed=0 +``` + +### Analysis + +**First run — what changed and why:** +- `Install common packages` — packages were not yet installed +- `Add Docker GPG key` — key file did not exist +- `Add Docker repository` — repository was not configured +- `Install Docker packages` — Docker was not installed +- `Add user to docker group` — vagrant user was not in docker group +- `Install python3-docker` — Python Docker library was not installed +- `restart docker` handler — triggered because Docker packages were installed + +**Second run — why nothing changed:** +Every Ansible module checks the current state before acting. `apt` checks if packages are already present. `file` checks if the directory exists. `apt_repository` checks if the repo is already configured. `user` checks group membership. Since the desired state was already achieved on the first run, no changes were needed on the second run. + +**What makes these roles idempotent:** +- Using `apt: state=present` instead of running raw install commands +- Using `file: state=directory` instead of `mkdir` +- Using `apt_repository` module which checks before adding +- Using `creates:` argument on the shell task for the GPG key — skips if file already exists +- Using `service: state=started` instead of raw `systemctl start` + +--- + +## 4. Ansible Vault Usage + +### How Credentials Are Stored + +Sensitive data (Docker Hub credentials, image name, ports) are stored in `group_vars/all.yml`, encrypted with Ansible Vault. The file is safe to commit to Git because it is AES-256 encrypted. + +### Vault Password Management + +The vault password is never stored in the repository. It is entered interactively at runtime using `--ask-vault-pass`. In a CI/CD pipeline, it would be stored as a secret environment variable and passed via `--vault-password-file`. + +### Encrypted File Example + +``` +$ANSIBLE_VAULT;1.1;AES256 +33313938643165336263383332623738323039613932393034366566663834623931343937353161 +3434396331653966343466303138646234366464393065630a616662363939653539643733336638 +32333339366530373137353139313561343762313562666437303966363337633366623462326366 +... +``` + +This is what `group_vars/all.yml` looks like in the repository — unreadable without the vault password. + +### Why Ansible Vault Is Necessary + +Without Vault, credentials like Docker Hub tokens would be stored in plain text in the repository, exposing them to anyone with repository access. Vault allows secrets to be version-controlled safely alongside the code that uses them, without risk of credential leakage. + +--- + +## 5. Deployment Verification + +### deploy.yml Run Output +``` +TASK [app_deploy : Log in to Docker Hub] changed: [localhost] +TASK [app_deploy : Pull Docker image] ok: [localhost] +TASK [app_deploy : Stop existing container] ...ignoring (no container existed) +TASK [app_deploy : Remove old container] ok: [localhost] +TASK [app_deploy : Run application container] changed: [localhost] +TASK [app_deploy : Wait for application to be ready] ok: [localhost] +TASK [app_deploy : Verify health endpoint] ok: [localhost] + +PLAY RECAP +localhost : ok=8 changed=2 unreachable=0 failed=0 ignored=1 +``` + +### Container Status (`docker ps`) +``` +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +8376a0ef5240 3llimi/devops-info-service:latest "python app.py" 28 seconds ago Up 27 seconds 0.0.0.0:8000->8000/tcp devops-info-service +``` + +### Health Check Verification +```bash +$ curl http://localhost:8000/health +{"status":"healthy","timestamp":"2026-02-21T02:04:28.847408+00:00","uptime_seconds":25} + +$ curl http://localhost:8000/ +{"service":{"name":"devops-info-service","version":"1.0.0","description":"DevOps course info service","framework":"FastAPI"}, +"system":{"hostname":"8376a0ef5240","platform":"Linux",...}, +"runtime":{"uptime_seconds":25,...}} +``` + +### Handler Execution + +The `restart docker` handler in the docker role was triggered during the first provisioning run when Docker packages were installed. On subsequent runs it was not triggered because no changes were made to Docker packages — demonstrating that handlers only fire when their notifying task actually changes something. + +--- + +## 6. Key Decisions + +**Why use roles instead of plain playbooks?** +Roles enforce a standard structure that makes code reusable and maintainable. Each role can be developed, tested, and shared independently. A single monolithic playbook with all tasks mixed together would be harder to read, impossible to reuse, and difficult to test in isolation. + +**How do roles improve reusability?** +Each role encapsulates all logic for a single concern — the `docker` role can be dropped into any other project that needs Docker installed, without copying individual tasks. Default variables allow roles to be customized without modifying their internals. + +**What makes a task idempotent?** +A task is idempotent when it checks the current state before acting and only makes changes if the desired state is not already achieved. Ansible's built-in modules (apt, service, file, user) handle this automatically — unlike raw shell commands which always execute regardless of current state. + +**How do handlers improve efficiency?** +Handlers only run when notified by a task that actually made a change. Without handlers, you would restart Docker after every playbook run even if nothing changed. With handlers, Docker is only restarted when packages are actually installed or updated — avoiding unnecessary service disruptions. + +**Why is Ansible Vault necessary?** +Any secret stored in plain text in a Git repository is effectively public, even in private repos. Vault encrypts secrets at rest while keeping them version-controlled alongside the infrastructure code. This allows the full Ansible project (including secrets) to be committed to Git safely. + +--- + +## 7. Challenges + +- **WSL2 disk space:** The WSL2 Alpine distro had only 136MB disk space, not enough to install Ansible. Solved by installing Ansible directly on the Vagrant VM and running it against localhost. +- **Docker login module:** `community.general.docker_login` failed in Ansible 2.10. Solved by using a `shell` task with `docker login --password-stdin` instead. +- **group_vars not loading with become:** Vault-encrypted `group_vars/all.yml` variables were not accessible when `become: yes` was set at the play level. Solved by passing variables explicitly with `-e @group_vars/all.yml` and setting `become: no` in the deploy playbook. +- **App port:** The application runs on port 8000 (FastAPI/Uvicorn), not 5000 as initially assumed. Discovered via `docker logs` and corrected in the vault variables and port mapping. + +--- + +## 8. Bonus — Dynamic Inventory + +### Approach +Since no cloud provider was available, a custom Python dynamic inventory script was created (`inventory/dynamic_inventory.py`). This demonstrates the same concepts as cloud inventory plugins — hosts are discovered at runtime rather than hardcoded. + +### How It Works +The script runs at playbook execution time, queries the system for hostname and IP dynamically, and outputs a JSON inventory structure that Ansible consumes. This means if the VM's hostname or IP changes, the inventory automatically reflects the new values without any manual updates. + +### ansible-inventory --graph Output +``` +@all: + |--@ungrouped: + |--@webservers: + | |--localhost +``` + +### Running Playbooks with Dynamic Inventory +```bash +ansible all -i inventory/dynamic_inventory.py -m ping --ask-vault-pass +# localhost | SUCCESS => { "ping": "pong" } + +ansible-playbook playbooks/provision.yml -i inventory/dynamic_inventory.py --ask-vault-pass +# localhost : ok=11 changed=1 unreachable=0 failed=0 +``` + +### Benefits vs Static Inventory +With static inventory, if the VM IP or hostname changes you must manually edit `hosts.ini`. With dynamic inventory, the script queries the system at runtime so it always reflects the current state. In a cloud environment with auto-scaling, this is essential — new VMs appear and disappear constantly and maintaining a static file would be impossible. \ No newline at end of file diff --git a/ansible/inventory/dynamic_inventory.py b/ansible/inventory/dynamic_inventory.py new file mode 100644 index 0000000000..d36e0399fc --- /dev/null +++ b/ansible/inventory/dynamic_inventory.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +""" +Dynamic inventory script for local Vagrant VM. +Discovers host details dynamically at runtime. +""" +import json +import socket +import subprocess + +def get_vagrant_info(): + hostname = socket.gethostname() + ip = socket.gethostbyname(hostname) + return hostname, ip + +def main(): + hostname, ip = get_vagrant_info() + + inventory = { + "webservers": { + "hosts": ["localhost"], + "vars": { + "ansible_connection": "local", + "ansible_user": "vagrant", + "ansible_python_interpreter": "/usr/bin/python3", + "discovered_hostname": hostname, + "discovered_ip": ip + } + }, + "_meta": { + "hostvars": { + "localhost": { + "ansible_connection": "local", + "ansible_user": "vagrant", + "ansible_python_interpreter": "/usr/bin/python3", + "discovered_hostname": hostname, + "discovered_ip": ip + } + } + } + } + print(json.dumps(inventory, indent=2)) + +if __name__ == "__main__": + main() diff --git a/vagrant/.vagrant/machines/default/virtualbox/action_cloud_init b/vagrant/.vagrant/machines/default/virtualbox/action_cloud_init new file mode 100644 index 0000000000..633537f8b7 --- /dev/null +++ b/vagrant/.vagrant/machines/default/virtualbox/action_cloud_init @@ -0,0 +1 @@ +27c18349-2a6c-491d-95dd-b04ea0f41c05 \ No newline at end of file diff --git a/vagrant/.vagrant/machines/default/virtualbox/synced_folders b/vagrant/.vagrant/machines/default/virtualbox/synced_folders new file mode 100644 index 0000000000..e8707d7907 --- /dev/null +++ b/vagrant/.vagrant/machines/default/virtualbox/synced_folders @@ -0,0 +1 @@ +{"virtualbox":{"/vagrant":{"guestpath":"/vagrant","hostpath":"C:/Users/3llim/OneDrive/Documents/GitHub/DevOps-Core-Course/vagrant","disabled":false,"__vagrantfile":true}}} \ No newline at end of file