{"id":15685671,"url":"https://github.com/tristancacqueray/haxible","last_synced_at":"2025-05-07T17:29:22.345Z","repository":{"id":138665325,"uuid":"497633830","full_name":"TristanCacqueray/Haxible","owner":"TristanCacqueray","description":"Ansible interpreter powered by Haxl","archived":false,"fork":false,"pushed_at":"2022-06-13T16:12:14.000Z","size":587,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-07T17:29:17.083Z","etag":null,"topics":["ansible","haskell","haxl"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TristanCacqueray.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":"2022-05-29T15:42:19.000Z","updated_at":"2023-06-27T08:05:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"8cd6a38d-a4ea-4728-9769-24de5c0b34f3","html_url":"https://github.com/TristanCacqueray/Haxible","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TristanCacqueray%2FHaxible","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TristanCacqueray%2FHaxible/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TristanCacqueray%2FHaxible/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TristanCacqueray%2FHaxible/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TristanCacqueray","download_url":"https://codeload.github.com/TristanCacqueray/Haxible/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252926164,"owners_count":21826256,"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":["ansible","haskell","haxl"],"created_at":"2024-10-03T17:28:39.572Z","updated_at":"2025-05-07T17:29:22.320Z","avatar_url":"https://github.com/TristanCacqueray.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Haxible - Ansible interpreter powered by Haxl\n\nThis project is a proof concept Ansible interpreter that leverages\nthe [Haxl](https://github.com/facebook/Haxl) library to evaluate\nthe playbook tasks concurrently.\n\n\n## Why Haxl?\n\nPros:\n\n- Haxl is a big hammer for solving problems involving I/O and concurrency: it flips the default from sequential to concurrent.\n- Haxl comes with testing and debugging facilities.\n\nCons:\n\n- The implementation is not written in Python.\n\n\u003e Learn more about Haxl in this short video: https://www.youtube.com/watch?v=sT6VJkkhy0o\n\nWhy Haskell?\n\n- Suitable for large scale system.\n- Statically typed with type inference.\n- Fearless concurrency, without async/await, but with managed effects (IO and STM).\n\n\n## Overview\n\nHaxible does the following:\n\n- Parse the playbook into a syntax tree.\n- Annotate the tasks dependencies.\n- Generate a Haxl program.\n- Compile the generated code with the Glasgow Haskell Compiler.\n- Perform the tasks through the `ansible-playbook` command.\n\nLimitations:\n\n- Variable inheritance is simpler: local scope takes priority over global scope (as expected), therefore `include_vars` no longer overrides locally defined variables.\n  In other words, the closer a variable is defined, the higher its priority: Task vars \u003e Include vars \u003e Play vars \u003e Inventory vars \u003e Role defaults \u003e Extra vars.\n- Template in `include` path is not currently supported: the full playbook need to be loaded statically.\n- Tasks run concurrently by default, thus adding extra register/vars pairs may be required to force sequencial evaluation.\n  Though Haxible may be improved to detect common pattern such as running `package` modules before `service` modules.\n\n\n## Demo\n\nGiven this playbook:\n\n```yaml\n- hosts: localhost\n  tasks:\n    - name: Create network\n      create_network:\n        name: \"private\"\n      register: network\n\n    - name: Create instances\n      create_instance:\n        network: \"{{ network.uid }}\"\n        name: \"{{ item }}\"\n      loop:\n        - backend\n        - frontend\n        - monitoring\n\n    - name: Create storage\n      create_volume:\n        name: \"db\"\n      register: storage\n\n    - name: Create database\n      create_instance:\n        network: \"{{ network.uid }}\"\n        name: \"database\"\n        volume: \"{{ storage.uid }}\"\n\n    - name: Create object\n      create_object:\n        name: \"standalone-object\"\n\n    - name: Create network object\n      create_object:\n        name: \"network-{{ network.uid }}\"\n\n    - name: Start local service\n      include_role:\n        name: \"container-service\"\n```\n\nHaxible runs three batches:\n\n```\nPLAY [concurrent] ***********************************************************************\n\nTASK \u003c17631\u003e [Create network] ***********************************************************\nok: [localhost] \u003c17631\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"6b280cb6\"}\n\nTASK \u003c17631\u003e [Create network object] ****************************************************\nTASK \u003c17662\u003e [Create object] ************************************************************\nTASK \u003c17663\u003e [Create storage] ***********************************************************\nTASK \u003c17666\u003e [Create instances] *********************************************************\nTASK \u003c17665\u003e [Create instances] *********************************************************\nok: [localhost] \u003c17631\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"f8db2cc0\"}\n\nTASK \u003c17631\u003e [Create instances] *********************************************************\nok: [localhost] \u003c17663\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"b060e6d3\"}\n\nTASK \u003c17663\u003e [Create database] **********************************************************\nok: [localhost] \u003c17666\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"3ab9d5a3\"}\nok: [localhost] \u003c17662\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"8c0e3f35\"}\nok: [localhost] \u003c17665\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"1e4fa090\"}\nok: [localhost] \u003c17631\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"d7adee85\"}\nok: [localhost] \u003c17663\u003e =\u003e {\"changed\":false,\"delay\":null,\"success\":\"ok\",\"uid\":\"6977e877\"}\n```\n\nThanks to the Haxl library, the order of the operations is automatically arranged to maximize concurrency.\n\n![demo timing](./test/playbooks/demo.png)\n\nHere is a production zuul-jobs pre run report that demonstrates almost 2x improvement:\n\n![zuul-jobs](./doc/zuul-jobs.png)\n\n\n## Usage\n\nInstall the toolchain using [ghcup](https://www.haskell.org/ghcup/).\n\n```ShellSession\n$ cabal run haxible -- --help\nHaxible - Ansible interpreter powered by Haxl\n\nUsage: haxible --playbook FILE [--dry]\n\nAvailable options:\n  --help                   Show this help text\n  --playbook FILE          YAML file to interpret\n  --inventory FILE         Inventory path\n  --dry                    Don't run the playbook, just compile it\n```\n\nRun the tests with `cabal test`.\n\nBuild the command line with `cabal build`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristancacqueray%2Fhaxible","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftristancacqueray%2Fhaxible","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristancacqueray%2Fhaxible/lists"}