{"id":13572876,"url":"https://github.com/teslamotors/ansible_puller","last_synced_at":"2026-03-08T10:36:57.484Z","repository":{"id":36673409,"uuid":"162504372","full_name":"teslamotors/ansible_puller","owner":"teslamotors","description":"Ansible daemon for massively-scaleable Ansible","archived":false,"fork":false,"pushed_at":"2025-07-21T21:24:47.000Z","size":222,"stargazers_count":142,"open_issues_count":6,"forks_count":37,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-07-21T22:25:50.652Z","etag":null,"topics":["ansible","devops-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/teslamotors.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,"zenodo":null}},"created_at":"2018-12-20T00:09:17.000Z","updated_at":"2025-06-24T19:54:01.000Z","dependencies_parsed_at":"2024-01-22T06:40:01.510Z","dependency_job_id":"78221df3-f09d-4dcf-8730-fddbc4c0e599","html_url":"https://github.com/teslamotors/ansible_puller","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/teslamotors/ansible_puller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teslamotors%2Fansible_puller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teslamotors%2Fansible_puller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teslamotors%2Fansible_puller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teslamotors%2Fansible_puller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teslamotors","download_url":"https://codeload.github.com/teslamotors/ansible_puller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teslamotors%2Fansible_puller/sbom","scorecard":{"id":874900,"data":{"date":"2025-08-11","repo":{"name":"github.com/teslamotors/ansible_puller","commit":"1cef3eac60e5795725b067beaff53b407c7d5567"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":3,"reason":"3 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:8: update your workflow using https://app.stepsecurity.io/secureworkflow/teslamotors/ansible_puller/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/teslamotors/ansible_puller/ci.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T05:36:41.651Z","repository_id":36673409,"created_at":"2025-08-24T05:36:41.651Z","updated_at":"2025-08-24T05:36:41.651Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278686638,"owners_count":26028325,"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","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","devops-tools"],"created_at":"2024-08-01T15:00:22.926Z","updated_at":"2026-03-08T10:36:57.478Z","avatar_url":"https://github.com/teslamotors.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# ansible-puller\n\nThis daemon extends the `ansible-pull` method of running Ansible.\nIt uses S3 or HTTP file transmission instead of Git to manage distribution (easy to cache), and integrates with Prometheus monitoring.\n\n## Why ansible-puller?\n\n`ansible-pull` assumes that you are checking out an Ansible repository from git.\nThis wasn't an option for us at the scale that we needed, so we turned to HTTP file distribution.\nOn top of scaling, we've integrated monitoring (via Prometheus) to retain the centralized view of all of our Ansible\nruns and a simple REST API to enable/disable the puller and trigger a run to give more fine-grained control of rollouts.\n\n# How to use it\n\nAnsible puller expects an HTTP endpoint, or an S3 ARN that points to a tarball with Ansible playbooks, inventories, etc.\n\nThe minimal configuration would just be a config file supplying `http-url` (see below).\nWhile the defaults have been set assuming [Ansible's \"Alternative Directory Layout\"](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#alternative-directory-layout)\nit should be configurable enough to support alternative setups.\n\nInside of the tarball, at a minimum you'll need an inventory, playbook, and a `requirements.txt` file.\nThe requirements file will be used to populate the Python virtual environment that Ansible will run in locally.\nAt a minimum it needs to contain `ansible` so that Ansible will be installed in the virtualenv. A pinned version is even better.\nThe playbook is what will be actually run.\nThe inventory needs to contain the hostname of the node that Ansible puller is installed on.\n\n## Ansible Inventory\n\nTo support our use of an Infrastructure monorepo, Ansible-puller will loop through an entire directory looking for inventories.\nIt will test each of these inventories for a matching hostname and run the given playbook in the first found inventory.\n\nGiven the structure:\n\n```\n.\n├── ansible.cfg\n├── inventories/\n│   ├── production/\n│   └── staging/\n├── roles/\n└── site.yml\n```\n\nAnd the config file:\n\n```json\n{\n  \"http-url\": \"https://example.com/infra.tgz\",\n  \"ansible-inventory\": [\"inventories/production\", \"inventories/staging\"],\n  \"playbook\": \"site.yml\"\n}\n```\n\nSetting `ansible-inventory` to `[\"inventories/production\", \"inventories/staging\"]` and `playbook` to `site.yml`\nwould mean that the puller would search for the correct host in `production` and `staging`, provided that the hosts were\na part of `site.yml`'s run. Use the `debug` option to get more insight to the process while it is running.\n\n## Configuration and Metrics\n\nConfig file should be in: `/etc/ansible-puller/config.json`, `$HOME/.ansible-puller.json`, `./ansible-puller.json`\n\n**Note:** This application supports hot-reloading of config file. So any changes to the configuration file would take immediate effect on the subsequent ansible runs.\nAny command line flag takes precedence over config file vars.\n\n| Config Option            | Default                               | Description                                                                             |\n|--------------------------|---------------------------------------|-----------------------------------------------------------------------------------------|\n| `http-listen-string`     | `\"0.0.0.0:31836\"`                     | Address/port the service will listen on. Use `127.0.0.1:31386` to lock down the UI.     |\n| `http-proto`             | `https`                               | Modify to \"http\" if necessary                                                           |\n| `http-user`              | `\"\"`                                  | Username for HTTP Basic Auth                                                            |\n| `http-pass`              | `\"\"`                                  | Password for HTTP basic Auth                                                            |\n| `http-url`               | `\"\"`                                  | HTTP Url to find the Ansible tarball. Required if s3-arn is not set                     |\n| `http-checksum-url`      | `\"\"`                                  | HTTP Url to find the Ansible tarball md5 hash. Defaults to http-url + `.md5`.           |\n| `log-dir`                | `\"/var/log/ansible-puller\"`           | Log directory (must exist)                                                              |\n| `ansible-dir`            | `\"\"`                                  | Path in the pulled tarball to cd into before ansible commands - usually ansible.cfg dir |\n| `ansible-playbook`       | `\"site.yml\"`                          | The playbook that will be run  - relative to ansible-dir                                |\n| `ansible-inventory`      | `[]`                                  | List of inventories to operate on - relative to ansible-dir                             |\n| `venv-python`            | `\"/usr/bin/python3\"`                  | Path to the python version you are using for Ansible                                    |\n| `venv-path`              | `\"/root/.virtualenvs/ansible_puller\"` | Path to where the virtualenv will be created                                            |\n| `venv-requirements-file` | `\"requirements.txt\"`                  | Path to the python requirements file to populate the virtual environment                |\n| `sleep`                  | `30`                                  | How often to trigger run events in minutes                                              |\n| `start-disabled`         | `false`                               | Whether or not to start with Ansbile disabled (good for debugging)                      |\n| `s3-arn`                 | `\"\"`                                  | S3 location to find the Ansible tarball. Required if http-url is not set                |\n| `s3-conn-region`         | `\"\"`                                  | S3 connection region to use. Uses the aws-sdk-go-v2 default providers if not set        |\n| `debug`                  | `false`                               | Whether or not to start in debug mode                                                   |\n| `once`                   | `false`                               | Only run the configured playbook once and then stop                                     |\n\n### Monitoring with prometheus\n\nThis daemon uses Ansible's `json` STDOUT callback to parse the results of this run for this host.\nIt currently produces the number of tasks that are ok, skipped, changed, failed, or unreachable.\n\n| Metric                            | Description                                                  |\n|-----------------------------------|--------------------------------------------------------------|\n| `ansible_puller_debug`            | Whether or not debug mode is enabled                         |\n| `ansible_puller_disabled`         | Whether or not the puller is disabled                        |\n| `ansible_puller_last_success`     | Last timestamp of a successful run                           |\n| `ansible_puller_last_exit_code`   | Last ansible run exit code                                   |\n| `ansible_puller_play_summary`     | Ansible metrics: changed, failures, ok, skipped, unreachable |\n| `ansible_puller_run_time_seconds` | How long Ansible took to run to completion                   |\n| `ansible_puller_running`          | Whether or not the puller is currently running               |\n| `ansible_puller_runs`             | How many times the puller has run                            |\n| `ansible_puller_version`          | Version (git sha) of the puller                              |\n\n#### Exit code mapping\n\nFollowing are some of internal ansible-puller errors and corresponding exit codes \n\n| Exit code  | Error explained               | \n|------------|-------------------------------|\n| 2          | virtualenv creation failed    |\n| 5          | virtual env update failed     |\n| 6          | inventory fetch failed        |\n|125         | Remote repository pull failed |\n\n\n### MD5 checksum support\n\nEnabling MD5 checksumming will prevent extraneous calls to download the ansible tarball from the\nremote.\n\nBy design, ansible_puller will look at the remote path `\u003cresource_path\u003e.md5` to discover the live\nMD5 checksum. If, for example, your resource is located at `https://example.com/some/file.tgz` then\nansible_puller will look for the MD5 hash at `https://example.com/some/file.tgz.md5`. A custom remote\npath can be specified with the `http-checksum-url` option.\nThe following conditions will lead to a (re-)download of the ansible tarball:\n- There is no current ansible tarball at the specified local path\n- The current hash of the local ansible tarball not match the remote checksum\n- The remote checksum does not exist\n\nIf a remote checksum exists then the downloaded tarball will be hashed and the resulting output will\nbe compared to the remote checksum to validate artifact integrity.\n\n## Runtime Dependencies\n\nThis program expects the following to be true about its runtime environment:\n* It is running as root (unless you don't need `--become`)\n* `virtualenv` is installed on the server\n\n## Development Notes\n\nThis project uses Go Modules. Go 1.19+ should be able to handle this transparently.\n\n### Doing Things\n\n#### Running Locally\n\n`bazelisk run //:ansible_puller`\n\nor, without bazel\n\n`go run .`\n\n#### Updating Dependencies\n\nUpdate go.mod and regenerate deps.bzl:\n\n`go mod tidy \u0026\u0026 bazelisk run //:update-deps`\n\n#### Running tests\n\n`bazelisk test //...`\n\n#### Building a Production Release\n\n`bazelisk build --config=release --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //...`\n\n#### Building Production Packages\n\n* `bazelisk build --config=release //:ansible_puller_deb`\n* `bazelisk build --config=release //:ansible_puller_rpm`\n\n#### Debugging an Ansible Run\n\nFor debugging the application, use the `--debug` flag, or the `debug` option in the config file.\nThis streams the Ansible output to the console so that you can follow along in the run.\n\nAlso consider using the `--once` flag to run the process just once and then exit without spinning up the webserver.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteslamotors%2Fansible_puller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteslamotors%2Fansible_puller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteslamotors%2Fansible_puller/lists"}