{"id":20703660,"url":"https://github.com/cppmx/dynamic_hosts","last_synced_at":"2025-07-20T16:34:41.762Z","repository":{"id":177319336,"uuid":"169640509","full_name":"cppmx/dynamic_hosts","owner":"cppmx","description":"A tool for ansible that manages and lists a dynamic host inventory.","archived":false,"fork":false,"pushed_at":"2019-03-28T16:38:48.000Z","size":956,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-11T04:32:42.976Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cppmx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-07T20:50:08.000Z","updated_at":"2019-03-28T16:38:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"54d7fca4-b010-4b7d-9842-74c66c05d35c","html_url":"https://github.com/cppmx/dynamic_hosts","commit_stats":null,"previous_names":["cppmx/dynamic_hosts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cppmx/dynamic_hosts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cppmx%2Fdynamic_hosts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cppmx%2Fdynamic_hosts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cppmx%2Fdynamic_hosts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cppmx%2Fdynamic_hosts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cppmx","download_url":"https://codeload.github.com/cppmx/dynamic_hosts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cppmx%2Fdynamic_hosts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266160866,"owners_count":23885886,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T01:08:56.754Z","updated_at":"2025-07-20T16:34:41.699Z","avatar_url":"https://github.com/cppmx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dynamic Hosts Inventory\n\nA tool for ansible that manages and lists a dynamic host inventory.\n\nAs DevOps engineers it is common that we have to perform administration and maintenance tasks on a large number of servers. These servers can be grouped by different categories, and the same tasks are not applied for all servers, but are specific tasks for each group of servers.\n\nThe purpose of this project is to manage a list of servers using JSON files as a database, and to generate a dynamic inventory that can be used by Ansible scripts.\n\n## Usage\n\nClone this project\n\n```bash\n git clone git@github.com:cppmx/dynamic_hosts.git\n```\n\nNow you can use the scripts [play.sh](#script-play) and [hosts.py](#script-hosts) to manage your list of servers and your Ansible scripts.\n\n### Script hosts\n\nYou can register servers with the following data:\n\n- Client: Each client will have their own data file, in this way you will be able to manage servers of different clients\n- Environment: Refers to the development environment, can be any of the following values:\n    - dev: If the server is in a development environment\n    - itg: If the server is in an integration environment\n    - pro: If the server is in a production environment\n- Role: Refers to the role for which this server is used. It's possible values are:\n    - app: If it is an application server\n    - db: If it is a database server\n    - web: If it is a web server\n    - zoo: If it is a zookeeper server\n- Location: This is a free field, here you can use any value to specify the location of your server, example: MEX for Mexico, IND for India, GER for Germany, etc.\n\nThe script recognizes the following parameters in the command line:\n\n```bash\noptional arguments:\n  -h, --help            show this help message and exit\n  --client CLIENT       A valid client\n  --config              Display current configuration\n  --env {dev,test,prod}\n                        Execution environment of this script. By default it is\n                        executed in production.\n  --list                Returns all hosts that meet the criteria.\n  --new-server          Add new server record.\n  --test                Run tests\n  --update-server       Update information of a server.\n  --verbose, -v         Displays extra data in the console output. It should\n                        not be used in production.\n  --version             show program's version number and exit\n```\n\n* __IMPORTANT NOTE__: One thing is the server environment, and another the execution environment of this script. The env flag refers to the environment of the script, not the environment of the servers in the database.\n\nSo, how is this script used? Continue reading.\n\n#### Show the configuration\n\nThree possible scenarios or environments are considered to use this script:\n\n- A testing environment: Normally used to run unit tests on this code.\n    - The name of the client is *test_test*\n    - The test database is stored in dynamic_hosts/db/test/test_prod/\n\n- A development environment: This environment is useful for testing during the development of this code and its improvements.\n    - The name of the client is *test_dev*\n    - The test database is stored in dynamic_hosts/db/dev/test_dev/\n \n - A production environment: This environment is useful for testing during the development of this code and its improvements.\n     - The name of the client is *test_prod*\n     - The test database is stored in dynamic_hosts/db/dev/test_prod/\n\nBelow we can see how to view the current configuration that the script is using:\n\n```bash\n $ ./hosts.py --config -v\n \n ***** D Y N A M I C   H O S T S *****\n             CONFIGURATION\n *************************************\n  - Client..............: test_prod\n  - Environment.........: None\n  - Role................: None\n  - Location............: None\n  - Database............: /home/user/dynamic_hosts/dynamic_hosts/db/prod/test_prod/data.json\n  *************************************\n```\n\nFrom the previous example we can observe the following:\n\n- It is a production environment, this can be deduced by the place where the database is stored:\n    - /db/prod/client_name\n- Since no name was specified for the client, then *test_prod* is used.\n- No environment, role or location was specified for the servers, so if we requested the generation of an inventory for Ansible, it would return everything the database has at that moment.\n\nIf we want to change the environment we will use the ```--env``` parameter as follows:\n\n```bash\n $ ./hosts.py --env dev --config -v\n \n ***** D Y N A M I C   H O S T S *****\n             CONFIGURATION\n *************************************\n  - Client..............: test_dev\n  - Environment.........: None\n  - Role................: None\n  - Location............: None\n  - Database............: /home/user/dynamic_hosts/dynamic_hosts/db/dev/test_dev/dev_data.json\n  *************************************\n```\n\nIf we want to use a different client name we will use the --client parameter:\n\n```bash\n $ ./hosts.py --env dev --client MyClient --config -v\n \n ***** D Y N A M I C   H O S T S *****\n             CONFIGURATION\n *************************************\n  - Client..............: MyClient\n  - Environment.........: None\n  - Role................: None\n  - Location............: None\n  - Database............: /home/user/dynamic_hosts/dynamic_hosts/db/dev/MyClient/dev_data.json\n  *************************************\n```\n\nThe values for the environment, role and location fields are assigned by environment variables. The script looks for the following environment variables to assign these values:\n\n- THE_CLIENT: If the script does not receive the name of the client as a parameter, then it will look for this environment variable. If this environment variable does not exist either, then it will use an arbitrary name by default.\n- THE_ENVIRONMENT: The possible values for this environment variable are:\n    - dev\n    - itg\n    - pro\n- THE_ROLE: The possible values for this environment variable are:\n    - app\n    - db\n    - web\n    - zoo\n- THE_LOCATION: It is expected that the value of this environment variable matches the values that you used in the database when registering your servers.\n\n```bash\n $ THE_ENVIRONMENT=itg ./hosts.py --env dev --client MyClient --config -v\n \n ***** D Y N A M I C   H O S T S *****\n             CONFIGURATION\n *************************************\n  - Client..............: MyClient\n  - Environment.........: itg\n  - Role................: None\n  - Location............: None\n  - Database............: /home/user/dynamic_hosts/dynamic_hosts/db/dev/MyClient/dev_data.json\n  *************************************\n```\n\n#### Add new server\n\nRegistering a new server is as simple as using the --new-server parameter as follows:\n\n```bash\n $ ./hosts.py --new-server\n Please enter the following information:\n  - Host................: demo.domain.net\n  - Environment.........: itg\n  - Role................: web\n  - Location............: mex\n Do you want to add variables for this host (y/N)? y\n Variable name: shell\n Value for \"shell\" variable: bash\n Do you want to add another variable for this host (y/N)? n\n```\n\nIf there are no errors in the data capture then the script will end normally returning a zero error code.\n\nThe possible errors that you can face are:\n- Capture the same record twice. A duplicate registration is considered when the hostname is repeated, that is, there can not be two servers with the same hostname.\n- Use an incorrect value for the environment or the role fields. In previous lines, the only possible values for these fields are specified.\n- Create two variables for the host with the same name. This is obvious, there can not be two variables that are called the same for the same host.\n\nTo verify the server that you just registered, you can see the section on how to [obtain a dynamic inventory](#get-a-dynamic-inventory).\n\n#### Update A Server Data\n\nUpdate a server data is as simple as using the --update-server parameter as follows:\n\n```bash\n $ ./hosts.py --update-server\n Please enter the following information:\n  - Host................: demo.domain.net\n  Current Host................: demo.domain.net\n  Change it to..................:\n  Current Environment.........: itg\n  Change it to..................: dev\n  Current Role................: web\n  Change it to..................:\n  Current Location............: mex\n  Change it to..................: usa\n This host has variables\n Do you want to keep the current variables Y/n?\n```\n\nAs we can see in the previous example, the first data requested is the name of the host. The script will search for this record and will show us one by one the current values and will ask us if we want to make any changes in them. If we only press enter then it will be considered that we do not want to make changes in that field.\n\nIf there are no errors in the data capture then the script will end normally returning a zero error code.\n\nThe possible errors that you can face are:\n- Try changing the registry of a host that does not exist in the database.\n- Capture the same record twice. A duplicate registration is considered when the hostname is repeated, that is, there can not be two servers with the same hostname.\n- Use an incorrect value for the environment or the role fields. In previous lines, the only possible values for these fields are specified.\n- Create two variables for the host with the same name. This is obvious, there can not be two variables that are called the same for the same host.\n\nTo verify the server that you just updated, you can see the section on how to [obtain a dynamic inventory](#get-a-dynamic-inventory).\n\n\n#### Get A Dynamic Inventory\n\nAnsible uses the --list parameter to obtain a dynamic inventory of a script. You can see that dynamic inventory also using this parameter as shown below:\n\n```bash\n $ ./hosts.py --list\n {\"_meta\": {\"hostvars\": {}}, \"all\": {\"hosts\": [], \"vars\": {}}}\n```\n\nWhen there is no data in the database, or the database file has not yet been created, then it will return an empty inventory like the one shown in the previous example.\n\nIf there is already data in the database then we can see an output like the following:\n\n```bash\n $ ./hosts.py --list\n {\"_meta\": {\"hostvars\": {\"demo.domain.net\": {\"shell\": \"bash\"}}}, \"all\": {\"hosts\": [\"demo.domain.net\"], \"vars\": {}}}\n```\n\n### Script play\n\nThis script uses a Docker container to run an Ansible playbook, the playbook will use the [hosts.py](#script-hosts) script to obtain the server inventory.\n\nThe script receives the following parameters:\n\n```bash\n$ ./play.sh --help\n|--------------------------------------------------------------------------------|\n|     A N S I B L E   W I T H   D Y N A M I C   H O S T S            |\n|--------------------------------------------------------------------------------|\n| Current environment ...                                                        |\n|      Script Version ... 0.0.1                                                  |\n|        Bash Version ... 4.4.19(2)-release                                      |\n|         Description ... This script allows you to run a playbook in a container using a dynamic host list.|\n|--------------------------------------------------------------------------------|\n\n Usage:\n  play.sh CLIENT [ENVIRONMENT] [GROUP] [ROLES]\n\n Client:\n        MyClient\n Environment:\n   -e|--env        It sets the environment of the hosts.\n                   If omitted, all environments will be used.\n The available environments are:\n        all\n        pro\n        itg\n        dev\n Groups:\n   -g|--group       It sets the group of the hosts.\n                    If omitted, a group called all will be used.\n The available groups are:\n        all\n        self\n Roles:\n   -e|--env         It sets the role of the hosts.\n                   If omitted, all roles will be used.\n The available roles are:\n        all\n        app\n        db\n        web\n        zoo\n\n Expamples:\n  play.sh MyClient\n  It will execute the playbbok on all the hosts of the client . The hosts will be grouped into a group called all.\n  {\n      \"all\": {\n          \"hosts\": [\n              \"hosta.domain.net\",\n              \"hostb.domain.net\"\n          ],\n          \"vars\": {}\n      }\n  }\n\n  play.sh MyClient -e pro\n  Execute playbbok on all hosts of client  that belong to environment pro. The hosts will be grouped into a group called all.\n  {\n      \"all\": {\n          \"hosts\": [\n              \"hostc.domain.net\",\n              \"hostd.domain.net\"\n          ],\n          \"vars\": {}\n      }\n  }\n\n  play.sh MyClient -g self\n  It will execute the playbbok on all hosts of client  and they will be grouped in the group to which they belong.\n  {\n      \"PRO\": {\n          \"hosts\": [\n              \"hosta.domain.net\",\n              \"hostb.domain.net\"\n          ],\n          \"vars\": {}\n      }\n      \"DEV\": {\n          \"hosts\": [\n              \"hostc.domain.net\",\n              \"hostd.domain.net\"\n          ],\n          \"vars\": {}\n      }\n  }\n```\n\nBefore deploying this help the script will verify that there is already at least one client captured in the production environment. If you do not find any client for production then the script will show an error message like the following:\n\n```bash\n$ ./play.sh --help\n[ERROR] No client has yet been defined\n[ERROR] Please first capture some servers for some client\n[ERROR] Test clients are not valid\n[ERROR] To add a server use one of the following commands:\n[ERROR]   hosts.py --client \u003cCLIENT_NAME\u003e --new-server\n[ERROR]   python3 hosts.py --client \u003cCLIENT_NAME\u003e --new-server\n```\n\nOnce you have captured at least one server for a client in the production database, this script will allow you to continue with the execution of the playbook.\n\nBy default, the playbook will ping the list of servers that generate the dynamic inventory.\n\nThis works in the following way, suppose we have captured the following servers:\n\n| Host | Client | Environment | Role | Location |\n| --- | --- | --- | --- | --- |\n| app1.client1.domain.net | Client1 | pro | app | usa |\n| app2.client1.domain.net | Client1 | itg | app | mex |\n| db1.client1.domain.net | Client1 | pro | db | usa |\n| db2.client1.domain.net | Client1 | dev | db | ind |\n| web1.client1.domain.net | Client1 | pro | web | ger |\n| web2.client1.domain.net | Client1 | pro | web | fra |\n| zoo1.client1.domain.net | Client1 | pro | zoo | usa |\n| zoo2.client1.domain.net | Client1 | itg | zoo | arg |\n| app1.client2.domain.net | Client2 | pro | app | usa |\n| app2.client2.domain.net | Client2 | pro | app | mex |\n| db1.client2.domain.net | Client2 | pro | db | usa |\n| db2.client2.domain.net | Client2 | pro | db | ind |\n| web1.client2.domain.net | Client2 | pro | web | ger |\n| web2.client2.domain.net | Client2 | pro | web | fra |\n| zoo1.client2.domain.net | Client2 | pro | zoo | usa |\n| zoo2.client2.domain.net | Client2 | pro | zoo | arg |\n\nNow, with the above information, suppose we want to ping all the web servers of client 2, then we will do the following:\n\n```bash\n$ ./play.sh Client2 --role web\n```\n\nTo run the playbook on all servers that are in use we do the following:\n\n```bash\n$ ./play.sh Client2 --location web\n```\n\nIf we want to do the same thing now, but with the servers of client 1 that are in an ITG environment, we do the following:\n\n```bash\n$ ./play.sh Client1 --env itg\n```\n\nObviously you can combine these parameters and make the filter that suits your needs.\n\n# TODO\nThis script was created and tested in a secure environment where folder sharing is not allowed, for this reason it is necessary to use a volume for the container and make changes dynamically.\n\nCurrently if you want to make changes in the BD and then execute your scripts it is necessary to recreate the image.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcppmx%2Fdynamic_hosts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcppmx%2Fdynamic_hosts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcppmx%2Fdynamic_hosts/lists"}