{"id":17108755,"url":"https://github.com/robertoaloi/ansible-nodetool","last_synced_at":"2025-10-11T23:13:21.992Z","repository":{"id":17130302,"uuid":"19896573","full_name":"robertoaloi/ansible-nodetool","owner":"robertoaloi","description":"An Ansible module to interact with Erlang nodes via Erlang RPC","archived":false,"fork":false,"pushed_at":"2017-12-04T07:27:11.000Z","size":25,"stargazers_count":27,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-13T02:58:36.397Z","etag":null,"topics":["ansible","erlang"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robertoaloi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-17T21:19:45.000Z","updated_at":"2024-05-25T09:26:13.000Z","dependencies_parsed_at":"2022-08-24T11:10:06.159Z","dependency_job_id":null,"html_url":"https://github.com/robertoaloi/ansible-nodetool","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertoaloi%2Fansible-nodetool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertoaloi%2Fansible-nodetool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertoaloi%2Fansible-nodetool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robertoaloi%2Fansible-nodetool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robertoaloi","download_url":"https://codeload.github.com/robertoaloi/ansible-nodetool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248657872,"owners_count":21140844,"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","erlang"],"created_at":"2024-10-14T16:06:11.054Z","updated_at":"2025-10-11T23:13:21.911Z","avatar_url":"https://github.com/robertoaloi.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# README\n\nAn Ansible module to interact with Erlang nodes via Erlang RPC.\n\n## Overview\n\nIf your architecture includes one or more Erlang nodes and you use\nAnsible to orchestrate them, you may find this Ansible module helpful.\n\n## Minimum Requirements\n\n- Ansible 2.0.0.2\n- Erlang/OTP 17.0\n\n## Installation\n\nClone the ansible-nodetool repository:\n\n    git clone https://github.com/robertoaloi/ansible-nodetool.git /path/to/ansible-nodetool\n\nThen, you need to tell Ansible where to find the new module.\nYou can do this by\nappending the repository path to the `library` value in your\n`~/.ansible.cfg` file. You can find the `library` value under the\n`defaults` group. If you do not have a `defaults` group in your\n`~/.ansible.cfg` file (or if you do not have a `~/.ansible.cfg` file\nat all)\nadd one. You can find more information about configuring Ansible\n[here](http://docs.ansible.com/ansible/intro_configuration.html).\n\n    [defaults]\n    library = CURRENT_PATH:/path/to/ansible-nodetool\n\nAlternatively, you can specify the `-M` option when invoking a\nplaybook. Example:\n\n    $ ansible-playbook -M /path/to/ansible-nodetool my_playbook.yml\n\nOr when running an [ad-hoc\ncommand](http://docs.ansible.com/ansible/intro_adhoc.html). Example:\n\n    $ ansible -m nodetool \\\n             -M /path/to/ansible-nodetool \\\n             -a 'node=alice@localhost cookie=secret action=ping' \\\n             localhost\n\n## Parameters\n\n     node:\n         description: The remote Erlang node\n         required:    true\n     action:\n         description: The action to be performed\n         choices:     [getpid, ping, stop, restart, reboot, eval]\n         required:    true\n     nametype:\n         description: Nametype to be used\n         choices:     [longnames, shortnames]\n         required:    false\n         default:     shortnames\n     cookie:\n         description: Erlang Cookie to be used for the connection\n         required:    false\n     timeout:\n         description: Timeout (in ms) for the actions\n         required:    false\n         default:     60000\n\n## Usage\n\nThe ansible-nodetool module is typically used from an Ansible\nplaybook.\n\nTo try things out, start a sample Erlang node named\n'alice' and with a 'secret' cookie:\n\n    $ erl -sname alice@localhost -setcookie secret\n\nYou can now ping the node using the following playbook:\n\n    ---\n\n    - hosts: localhost\n      tasks:\n      - name: \"Ping the 'alice' Erlang node\"\n        nodetool:\n          action: ping\n          cookie: secret\n          node:   alice@{{ inventory_hostname_short }}\n\nExample:\n\n    $ ansible-playbook ping.yml\n\n    PLAY\n    ***************************************************************************\n\n    TASK [setup]\n    *******************************************************************\n    ok: [localhost]\n\n    TASK [Ping the 'alice' Erlang node]\n    ********************************************\n    changed: [localhost]\n\n    PLAY RECAP\n    *********************************************************************\n    localhost                  : ok=2    changed=1    unreachable=0\n    failed=0\n\nBut the ansible-nodetool module is not only about pinging nodes.\nYou can also evaluate custom Erlang expressions on a remote Erlang\nnode using the `eval` action.\n\nThe following playbook gets the list of running applications in an\nErlang node, registers the result into an Ansible variable and prints\nthe result:\n\n    ---\n\n    - hosts: localhost\n      tasks:\n      - name: \"Return a list of running applications\"\n        nodetool:\n          action:  eval\n          command: application:which_applications()\n          cookie:  secret\n          node:    alice@{{ inventory_hostname_short }}\n        register: applications\n      - debug:\n          msg: \"{{ applications.stdout_lines }}\"\n\nLet's see it in action:\n\n    $ ansible-playbook applications.yml\n\n    PLAY\n    ***************************************************************************\n\n    TASK [setup]\n    *******************************************************************\n    ok: [localhost]\n\n    TASK [Return a list of running applications]\n    ***********************************\n    changed: [localhost]\n\n    TASK [debug]\n    *******************************************************************\n    ok: [localhost] =\u003e {\n      \"msg\": [\n        \"[{sasl,\\\"SASL  CXC 138 11\\\",\\\"2.4.1\\\"},\",\n        \" {stdlib,\\\"ERTS  CXC 138 10\\\",\\\"2.4\\\"},\",\n        \" {kernel,\\\"ERTS  CXC 138 10\\\",\\\"3.2.0.1\\\"}]\"\n      ]\n    }\n\n    PLAY RECAP\n    *********************************************************************\n    localhost                  : ok=3    changed=1    unreachable=0\n    failed=0\n\nAnother available action is `getpid`, which returns the process\nidentifier of the current Erlang emulator:\n\n    ---\n\n    - hosts: localhost\n      tasks:\n      - name: \"Return the process identifier of the current Erlang emulator\"\n        nodetool:\n          action: getpid\n          cookie: secret\n          node:   alice@{{ inventory_hostname_short }}\n        register: pid\n      - debug:\n          msg: \"{{ pid.stdout }}\"\n\nThere are also other available actions, such as `stop`, `restart` or\n`reboot` to control a remote Erlang node.\n\n## Result\n\nAs part of the Ansible result, the ansible-nodetool provides a JSON structure\nwhich contains the following fields:\n\n FIELD        | DESCRIPTION\n--------------|-----------------------------------------------------------------\nrc            | The Erlang RPC _return code_ (0 =\u003e success, 1 =\u003e failure)\nstdout        | The return value of the Erlang RPC\nstdout_lines  | The return value of the Erlang RPC call, split in lines\nremote_output | The stdout on the remote Erlang node, captured via [group leader](http://erlang.org/doc/man/erlang.html#group_leader-0)\n\nI have seen many people trying to assert the return value of the\nErlang RPC in complicated ways. Remember that, if you want to verify\nthat the return value of a given Erlang expression corresponds to a\nspecific value you can simply use the [pattern matching\noperator](http://erlang.org/doc/reference_manual/patterns.html) for\nthis. No need to find complicated Ansible-based solutions!\n\nExample:\n\n    ---\n\n    - hosts: localhost\n      tasks:\n      - name: \"Ensure that the reverse of 'foo' is 'oof'\"\n        nodetool:\n          action:  eval\n          command: \"\\\"oof\\\"=lists:reverse(\\\"foo\\\")\"\n          cookie:  secret\n          node:    alice@{{ inventory_hostname_short }}\n\nNotice the usage of the pattern matching operator (=) above and the\npresence of backslashes to escape the double quotes.\n\n## Idempotence\n\nIdempotence is a crucial principle in Ansible. Given the nature of the\nAnsible nodetool module, which allow the operator to perform custom\nErlang expressions via the `eval` action, idempotence **cannot** be\nguaranteed by the module. It is up to the user to avoid violating it.\n\nLet's consider the following example:\n\n    ---\n\n    # THIS PLAYBOOK IS NOT IDEMPOTENT!!!\n    # RUNNING IT TWICE WOULD CAUSE A FAILURE!!!\n    - hosts: localhost\n      tasks:\n      - name: \"Start the SASL application\"\n        nodetool:\n          action:  eval\n          command: ok=application:start(sasl).\n          cookie:  secret\n          node:    alice@{{ inventory_hostname_short }}\n\nThe above playbook expects the `application:start/1` function to\nreturn `ok`. This will only happen if the application is not already started.\nThe following is a much better approach:\n\n    ---\n\n    - hosts: localhost\n      tasks:\n      - name: \"Start the SASL application\"\n        nodetool:\n          action:  eval\n          command: ok=application:ensure_started(sasl)\n          cookie:  secret\n          node:    alice@{{ inventory_hostname_short }}\n\nThe `application:ensure_started/1` function will only start the\napplication if it is not already started. Much better!\n\n## Credits\n\nThe work is based on the `nodetool` escript from the Yaws project:\n\nhttps://github.com/klacke/yaws\n\n## Contributors\n\nA big thanks to:\n\n- Amir Moulavi\n- Fabricio Leotti\n\nFor their precious contributions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobertoaloi%2Fansible-nodetool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobertoaloi%2Fansible-nodetool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobertoaloi%2Fansible-nodetool/lists"}