├── .env ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .goreleaser.yml ├── CHANGELOG.md ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── RELEASE_NOTES.md ├── docker-compose.yml ├── docs ├── logo │ ├── go-ansible_logo.png │ └── go-ansible_logo.svg ├── upgrade_guide_to_1.x.md └── upgrade_guide_to_2.x.md ├── examples ├── ansibleadhoc-command-module │ ├── .env │ ├── Makefile │ ├── ansibleadhoc-command-module.go │ ├── docker-compose.yaml │ └── docker │ │ └── ansible │ │ └── Dockerfile ├── ansibleadhoc-simple │ ├── .env │ ├── Makefile │ ├── ansibleadhoc-simple.go │ ├── docker-compose.yaml │ └── docker │ │ └── ansible │ │ └── Dockerfile ├── ansibleinventory-graph │ ├── .env │ ├── Makefile │ ├── ansibleinventory-graph.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── inventory.yml ├── ansibleinventory-simple │ ├── .env │ ├── Makefile │ ├── ansibleinventory-simple.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── inventory.yml ├── ansibleinventory-vaulted-vars │ ├── .env │ ├── Makefile │ ├── ansibleinventory-vaulted-vars.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── inventory.yml │ └── vault_password.cfg ├── ansibleplaybook-become │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-become.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-cobra-cmd │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-cobra-cmd.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-custom-transformer │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-custom-transformer.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-embed-python │ ├── .env │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-embed-python.go │ ├── docker-compose.yml │ ├── go.mod │ ├── go.sum │ ├── internal │ │ └── ansibleplaybook-embed-python │ │ │ ├── dummy.go │ │ │ ├── generate │ │ │ └── main.go │ │ │ └── requirements.txt │ └── resources │ │ └── ansible │ │ ├── requirements.yml │ │ └── site.yml ├── ansibleplaybook-extravars-file │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-extravars-file.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site.yml │ ├── vars-file1.yml │ └── vars-file2.yml ├── ansibleplaybook-extravars │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-extravars.go │ ├── docker-compose.yaml │ ├── docker │ │ ├── ansible │ │ │ └── Dockerfile │ │ ├── openssh-client │ │ │ └── Dockerfile │ │ └── server │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ ├── inventory.yml │ └── site.yml ├── ansibleplaybook-json-stdout │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-json-stdout.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site1.yml │ ├── site2.yml │ └── site3.yml ├── ansibleplaybook-myexecutor │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-myexecutor.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-posix-jsonl-stdout-persistence │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-posix-jsonl-stdout-persistence.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site1.yml │ ├── site2.yml │ └── site3.yml ├── ansibleplaybook-posix-jsonl-stdout │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-posix-jsonl-stdout.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site1.yml │ ├── site2.yml │ └── site3.yml ├── ansibleplaybook-signals-and-cancellation │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-signals-and-cancellation.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-simple-embedfs │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-simple-embedfs.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── embedfs │ │ ├── inventory.ini │ │ ├── site.yml │ │ └── site2.yml ├── ansibleplaybook-simple-with-prompt │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-simple-with-prompt.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── input.yml ├── ansibleplaybook-simple │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-simple.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site.yml │ └── site2.yml ├── ansibleplaybook-skipping-failing │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-skipping-failing.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site1.yml │ └── site2.yml ├── ansibleplaybook-ssh-become-root-with-password │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-ssh-become-root-with-password.go │ ├── docker-compose.yaml │ ├── docker │ │ ├── ansible │ │ │ └── Dockerfile │ │ ├── openssh-client │ │ │ └── Dockerfile │ │ └── server │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ ├── inventory.yml │ └── site.yml ├── ansibleplaybook-ssh │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-ssh.go │ ├── docker-compose.yaml │ ├── docker │ │ ├── ansible │ │ │ └── Dockerfile │ │ ├── openssh-client │ │ │ └── Dockerfile │ │ └── server │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ ├── inventory.yml │ └── site.yml ├── ansibleplaybook-time-measurement │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-time-measurement.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-walk-through-json-output │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-walk-through-json-output.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site1.yml │ └── site2.yml ├── ansibleplaybook-with-executor-time-measurament │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-with-executor-time-measurament.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-with-timeout │ ├── .env │ ├── Makefile │ ├── README.md │ ├── ansibleplaybook-with-timeout.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ └── site.yml ├── ansibleplaybook-with-vaulted-extravar │ ├── .env │ ├── Makefile │ ├── ansibleplaybook-with-vaulted-extravar.go │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── site.yml │ └── vault_password.cfg ├── workflowexecute-ansibleplaybook-with-galaxy-install-collection │ ├── .env │ ├── Makefile │ ├── docker-compose.yaml │ ├── docker │ │ ├── ansible │ │ │ └── Dockerfile │ │ ├── openssh-client │ │ │ └── Dockerfile │ │ └── server │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ ├── inventory.yml │ ├── requirements.yml │ ├── site.yml │ └── workflowexecute-ansibleplaybook-with-galaxy-install-collection.go ├── workflowexecute-ansibleplaybook-with-galaxy-install-role │ ├── .env │ ├── Makefile │ ├── docker-compose.yaml │ ├── docker │ │ ├── ansible │ │ │ └── Dockerfile │ │ ├── openssh-client │ │ │ └── Dockerfile │ │ └── server │ │ │ ├── Dockerfile │ │ │ └── entrypoint.sh │ ├── inventory.yml │ ├── requirements.yml │ ├── site.yml │ └── workflowexecute-ansibleplaybook-with-galaxy-install-role.go ├── workflowexecute-simple │ ├── .env │ ├── Makefile │ ├── docker-compose.yaml │ ├── docker │ │ └── ansible │ │ │ └── Dockerfile │ ├── first.yml │ ├── second.yml │ └── workflowexecute-simple.go └── workflowexecute-time-measurament │ ├── .env │ ├── Makefile │ ├── docker-compose.yaml │ ├── docker │ └── ansible │ │ └── Dockerfile │ ├── first.yml │ ├── second.yml │ └── workflowexecute-time-measurament.go ├── go.mod ├── go.sum ├── mocks ├── mockAnsibleCmd.go ├── mockExitCodeErr.go ├── mockIOReader.go └── mockIOWriter.go ├── pkg ├── adhoc │ ├── ansibleAdhocCmd.go │ ├── ansibleAdhocCmd_test.go │ ├── ansibleAdhocExecute.go │ ├── ansibleAdhocExecute_test.go │ ├── ansibleAdhocOptions.go │ └── ansibleAdhocOptions_test.go ├── execute │ ├── configuration │ │ ├── ansibleConfiguration.go │ │ ├── ansibleWithConfigurationSettingsExecute.go │ │ ├── ansibleWithConfigurationSettingsExecute_test.go │ │ └── interface.go │ ├── defaultExecute.go │ ├── defaultExecuteOptions.go │ ├── defaultExecuteOptions_test.go │ ├── defaultExecute_test.go │ ├── exec │ │ ├── cmd.go │ │ ├── exec.go │ │ ├── interface.go │ │ ├── mockCmd.go │ │ └── mockExec.go │ ├── interface.go │ ├── measure │ │ └── executorTimeMeasurement.go │ ├── mockExecute.go │ ├── result │ │ ├── default │ │ │ ├── defaultResult.go │ │ │ └── defaultResult_test.go │ │ ├── interface.go │ │ ├── json │ │ │ ├── JSONLEventStdoutCallbackResults.go │ │ │ ├── JSONLEventStdoutCallbackResults_test.go │ │ │ ├── JSONStdoutCallbackResults.go │ │ │ ├── JSONStdoutCallbackResults_test.go │ │ │ ├── ansiblePlaybookJSONLEventResults.go │ │ │ ├── ansiblePlaybookJSONLEventResults_test.go │ │ │ ├── ansiblePlaybookJSONResults.go │ │ │ └── ansiblePlaybookJSONResults_test.go │ │ └── transformer │ │ │ ├── transformer.go │ │ │ └── transformer_test.go │ ├── stdoutcallback │ │ ├── ansiblePosixJsonl.go │ │ ├── ansiblePosixJsonl_test.go │ │ ├── debug.go │ │ ├── debug_test.go │ │ ├── default.go │ │ ├── default_test.go │ │ ├── dense.go │ │ ├── dense_test.go │ │ ├── interface.go │ │ ├── json.go │ │ ├── json_test.go │ │ ├── minimal.go │ │ ├── minimal_test.go │ │ ├── null.go │ │ ├── null_test.go │ │ ├── oneline.go │ │ ├── oneline_test.go │ │ ├── stderr.go │ │ ├── stderr_test.go │ │ ├── timer.go │ │ ├── timer_test.go │ │ ├── yaml.go │ │ └── yaml_test.go │ └── workflow │ │ ├── workflowExecute.go │ │ └── workflowExecute_test.go ├── galaxy │ ├── collection │ │ ├── collection.go │ │ └── install │ │ │ ├── ansibleGalaxyCollectionInstallCmd.go │ │ │ ├── ansibleGalaxyCollectionInstallCmd_test.go │ │ │ ├── ansibleGalaxyCollectionInstallOptions.go │ │ │ └── ansibleGalaxyCollectionInstallOptions_test.go │ ├── galaxy.go │ └── role │ │ ├── install │ │ ├── ansibleGalaxyRoleInstallCmd.go │ │ ├── ansibleGalaxyRoleInstallCmd_test.go │ │ ├── ansibleGalaxyRoleInstallOptions.go │ │ └── ansibleGalaxyRoleInstallOptions_test.go │ │ └── role.go ├── inventory │ ├── ansibleInventoryCmd.go │ ├── ansibleInventoryCmd_test.go │ ├── ansibleInventoryExecute.go │ └── ansibleInventoryExecute_test.go ├── playbook │ ├── ansiblePlaybookCmd.go │ ├── ansiblePlaybookCmd_test.go │ ├── ansiblePlaybookErrorEnrich.go │ ├── ansiblePlaybookErrorEnrich_test.go │ ├── ansiblePlaybookExecute.go │ ├── ansiblePlaybookExecute_test.go │ ├── ansiblePlaybookOptions.go │ ├── ansiblePlaybookOptions_test.go │ ├── interface.go │ └── test │ │ ├── all │ │ └── test_site.yml └── vault │ ├── encrypt │ ├── encryptString.go │ ├── encryptString_test.go │ ├── instance.go │ └── mocEncryptStringk.go │ ├── interface.go │ ├── mockVariableVaulter.go │ ├── password │ ├── envvars │ │ ├── readPasswordFromEnvVar.go │ │ └── readPasswordFromEnvVar_test.go │ ├── file │ │ ├── readPasswordFromFile.go │ │ └── readPasswordFromFile_test.go │ ├── mock │ │ └── mock.go │ ├── resolve │ │ ├── interface.go │ │ ├── readPasswordResolve.go │ │ └── readPasswordResolve_test.go │ └── text │ │ ├── readPasswordFromText.go │ │ └── readPasswordFromText_test.go │ ├── variableVaulter.go │ ├── variableVaulter_test.go │ ├── vaultVariableValue.go │ └── vaultVariableValue_test.go ├── test ├── all └── test_site.yml └── utils └── cmd └── configGenerator.go /.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 2 | GOLANGCI_LINT_VERSION=v1.64.7 -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: testing 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - fix/* 8 | - feat/* 9 | pull_request: 10 | branches: 11 | - master 12 | 13 | jobs: 14 | static-analysis: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v4 19 | 20 | - name: Execute go vet 21 | run: | 22 | make vet 23 | 24 | - name: Execute golangci-lint 25 | run: | 26 | make golangci-lint 27 | 28 | testing: 29 | runs-on: ubuntu-latest 30 | needs: static-analysis 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v4 34 | with: 35 | fetch-depth: 0 36 | - run: git fetch --force --tags 37 | 38 | - name: Execute unit tests 39 | run: | 40 | make unit-test 41 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - "v*.*.*" 6 | 7 | jobs: 8 | goreleaser: 9 | runs-on: ubuntu-latest 10 | steps: 11 | 12 | - name: Checkout repository 13 | uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | - run: git fetch --force --tags 17 | 18 | - uses: actions/setup-go@v4 19 | with: 20 | go-version: ^1.22 21 | cache: true 22 | 23 | - name: Run GoReleaser 24 | uses: goreleaser/goreleaser-action@v5 25 | with: 26 | version: latest 27 | args: release --rm-dist --release-notes RELEASE_NOTES.md 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/* 2 | *.lock 3 | .vscode 4 | *.exe 5 | 6 | .idea/* 7 | .DS_Store 8 | 9 | # CMake 10 | cmake-build-*/ 11 | 12 | # JIRA plugin 13 | atlassian-ide-plugin.xml 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example .goreleaser.yml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | before: 4 | hooks: 5 | - go mod tidy 6 | builds: 7 | - skip: true 8 | changelog: 9 | sort: asc 10 | filters: 11 | exclude: 12 | - '^docs:' 13 | - '^test:' 14 | - '^Merge branch' 15 | - '^Merge pull request' 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Aleix Penella 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | ## [undefined] (yyyy-mm-dd) 4 | 5 | ## Changed 6 | 7 | - Bump golang.org/x/net from 0.36.0 to 0.38.0 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | golang-ci: 3 | image: golang:${GOLANG_VERSION:-1.19}-alpine 4 | volumes: 5 | - .:/app 6 | working_dir: /app 7 | command: ["go", "version"] 8 | 9 | golangci-lint: 10 | image: golangci/golangci-lint:${GOLANGCI_LINT_VERSION:-v1.57.2}-alpine 11 | volumes: 12 | - .:/app 13 | working_dir: /app 14 | entrypoint: ["golangci-lint"] 15 | command: ["--version"] 16 | -------------------------------------------------------------------------------- /docs/logo/go-ansible_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apenella/go-ansible/a22b40c03c5cd4358e8e692c2edc76133701464b/docs/logo/go-ansible_logo.png -------------------------------------------------------------------------------- /examples/ansibleadhoc-command-module/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleadhoc-command-module/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-command-module/ansibleadhoc-command-module.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/adhoc" 8 | "github.com/apenella/go-ansible/v2/pkg/execute" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback" 10 | ) 11 | 12 | func main() { 13 | 14 | ansibleAdhocOptions := &adhoc.AnsibleAdhocOptions{ 15 | Args: "ping 127.0.0.1 -c 2", 16 | Connection: "local", 17 | Inventory: " 127.0.0.1,", 18 | ModuleName: "command", 19 | } 20 | 21 | adhocCmd := adhoc.NewAnsibleAdhocCmd( 22 | adhoc.WithPattern("all"), 23 | adhoc.WithAdhocOptions(ansibleAdhocOptions), 24 | ) 25 | 26 | fmt.Println("Command: ", adhocCmd.String()) 27 | 28 | onelineExecute := stdoutcallback.NewOnelineStdoutCallbackExecute( 29 | execute.NewDefaultExecute( 30 | execute.WithCmd(adhocCmd), 31 | ), 32 | ) 33 | 34 | err := onelineExecute.Execute(context.TODO()) 35 | if err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-command-module/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-command-module/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-simple/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleadhoc-simple/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-simple/ansibleadhoc-simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/adhoc" 9 | ) 10 | 11 | func main() { 12 | 13 | ansibleAdhocOptions := &adhoc.AnsibleAdhocOptions{ 14 | Args: `msg=" 15 | {{ arg1 }} 16 | {{ arg2 }} 17 | {{ arg3 }} 18 | "`, 19 | Connection: "local", 20 | ExtraVars: map[string]interface{}{ 21 | "arg1": map[string]interface{}{"subargument": "subargument_value"}, 22 | "arg2": "arg2_value", 23 | "arg3": "arg3_value", 24 | }, 25 | Inventory: "127.0.0.1,", 26 | ModuleName: "debug", 27 | } 28 | 29 | err := adhoc.NewAnsibleAdhocExecute("all"). 30 | WithAdhocOptions(ansibleAdhocOptions). 31 | Execute(context.TODO()) 32 | 33 | if err != nil { 34 | fmt.Println(err.Error()) 35 | os.Exit(1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-simple/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleadhoc-simple/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/ansibleinventory-graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/inventory" 9 | ) 10 | 11 | func main() { 12 | ansibleInventoryOptions := inventory.AnsibleInventoryOptions{ 13 | Graph: true, 14 | Inventory: "inventory.yml", 15 | Vars: true, 16 | Yaml: true, 17 | } 18 | 19 | inventoryCmd := inventory.NewAnsibleInventoryCmd( 20 | inventory.WithPattern("all"), 21 | inventory.WithInventoryOptions(&ansibleInventoryOptions), 22 | ) 23 | 24 | fmt.Println("Test strings:", inventoryCmd.String()) 25 | 26 | exec := execute.NewDefaultExecute( 27 | execute.WithCmd(inventoryCmd), 28 | ) 29 | 30 | err := exec.Execute(context.TODO()) 31 | if err != nil { 32 | panic(err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleinventory-graph/inventory.yml: -------------------------------------------------------------------------------- 1 | all: 2 | children: 3 | webserver: 4 | hosts: 5 | web1: 6 | ansible_host: 192.168.1.101 7 | http_port: 80 8 | max_clients: 200 9 | web2: 10 | ansible_host: 192.168.1.102 11 | http_port: 80 12 | max_clients: 150 13 | 14 | database: 15 | hosts: 16 | db1: 17 | ansible_host: 192.168.1.103 18 | db_port: 5432 19 | db_name: 'mydb' 20 | 21 | vars: 22 | ansible_user: 'admin' 23 | -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/ansibleinventory-simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/inventory" 9 | ) 10 | 11 | func main() { 12 | ansibleInventoryOptions := inventory.AnsibleInventoryOptions{ 13 | Inventory: "inventory.yml", 14 | List: true, 15 | Yaml: true, 16 | } 17 | 18 | err := inventory.NewAnsibleInventoryExecute(). 19 | WithInventoryOptions(&ansibleInventoryOptions). 20 | WithPattern("all"). 21 | Execute(context.TODO()) 22 | 23 | if err != nil { 24 | fmt.Println(err.Error()) 25 | os.Exit(1) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleinventory-simple/inventory.yml: -------------------------------------------------------------------------------- 1 | all: 2 | children: 3 | webserver: 4 | hosts: 5 | web1: 6 | ansible_host: 192.168.1.101 7 | http_port: 80 8 | max_clients: 200 9 | web2: 10 | ansible_host: 192.168.1.102 11 | http_port: 80 12 | max_clients: 150 13 | 14 | database: 15 | hosts: 16 | db1: 17 | ansible_host: 192.168.1.103 18 | db_port: 5432 19 | db_name: 'mydb' 20 | 21 | vars: 22 | ansible_user: 'admin' 23 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/ansibleinventory-vaulted-vars.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/inventory" 9 | ) 10 | 11 | func main() { 12 | ansibleInventoryOptions := inventory.AnsibleInventoryOptions{ 13 | Graph: true, 14 | Inventory: "inventory.yml", 15 | Vars: true, 16 | Yaml: true, 17 | VaultPasswordFile: "vault_password.cfg", 18 | } 19 | 20 | inventoryCmd := inventory.NewAnsibleInventoryCmd( 21 | inventory.WithPattern("all"), 22 | inventory.WithInventoryOptions(&ansibleInventoryOptions), 23 | ) 24 | 25 | fmt.Println("Test strings:", inventoryCmd.String()) 26 | 27 | exec := execute.NewDefaultExecute( 28 | execute.WithCmd(inventoryCmd), 29 | ) 30 | 31 | err := exec.Execute(context.TODO()) 32 | if err != nil { 33 | panic(err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/inventory.yml: -------------------------------------------------------------------------------- 1 | all: 2 | children: 3 | database_servers: 4 | hosts: 5 | db1.example.com: 6 | db2.example.com: 7 | vars: 8 | ansible_ssh_user: dbadmin 9 | ansible_ssh_pass: !vault | 10 | $ANSIBLE_VAULT;1.1;AES256 11 | 35666433353234313161636238653633313264383230316233656236313935313465666533646164 12 | 3039353461343961616134653164666663646362646336360a383332663562396237613264386636 13 | 66663233616235396662383434343966333665383937653839326633333861366162616365353533 14 | 6237653031613664340a383736643130303935633164366536363561663334643763343661666138 15 | 62343234643536663061316666626466343265353065333439643065313134633132 16 | db_port: 5432 17 | -------------------------------------------------------------------------------- /examples/ansibleinventory-vaulted-vars/vault_password.cfg: -------------------------------------------------------------------------------- 1 | ThatIsAPassword -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/ansibleplaybook-become.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute" 7 | "github.com/apenella/go-ansible/v2/pkg/execute/result/transformer" 8 | "github.com/apenella/go-ansible/v2/pkg/playbook" 9 | ) 10 | 11 | func main() { 12 | 13 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 14 | User: "apenella", 15 | Inventory: "127.0.0.1,", 16 | Become: true, 17 | AskBecomePass: true, 18 | } 19 | 20 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 21 | playbook.WithPlaybooks("site.yml"), 22 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 23 | ) 24 | 25 | exec := execute.NewDefaultExecute( 26 | execute.WithCmd(playbookCmd), 27 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 28 | execute.WithEnvVars( 29 | map[string]string{ 30 | "ANSIBLE_FORCE_COLOR": "true", 31 | }, 32 | ), 33 | execute.WithTransformers( 34 | transformer.Prepend("Go-ansible example with become"), 35 | ), 36 | ) 37 | 38 | err := exec.Execute(context.TODO()) 39 | if err != nil { 40 | panic(err) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-become/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | 7 | - name: commands 8 | shell: | 9 | hostname && whoami 10 | register: output 11 | 12 | - name: output commands 13 | debug: 14 | var: output.stdout_lines 15 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-cobra-cmd/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-cobra-cmd/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-cobra-cmd 2 | 3 | ```sh 4 | $ go run ansibleplaybook-cobra-cmd.go --connection-local --playbook site.yml --inventory 127.0.0.1, --extra-var example="Hi! There" 5 | cobra-cmd-ansibleplaybook example ── 6 | cobra-cmd-ansibleplaybook example ── PLAY [all] ********************************************************************* 7 | cobra-cmd-ansibleplaybook example ── 8 | cobra-cmd-ansibleplaybook example ── TASK [Gathering Facts] ********************************************************* 9 | cobra-cmd-ansibleplaybook example ── ok: [127.0.0.1] 10 | cobra-cmd-ansibleplaybook example ── 11 | cobra-cmd-ansibleplaybook example ── TASK [ansibleplaybook-cobra-cmd] *********************************************** 12 | cobra-cmd-ansibleplaybook example ── ok: [127.0.0.1] => { 13 | cobra-cmd-ansibleplaybook example ── "msg": "Your are running 'ansibleplaybook-cobra-cmd' example" 14 | cobra-cmd-ansibleplaybook example ── } 15 | cobra-cmd-ansibleplaybook example ── 16 | cobra-cmd-ansibleplaybook example ── TASK [Print extra variable 'example'] ****************************************** 17 | cobra-cmd-ansibleplaybook example ── ok: [127.0.0.1] => { 18 | cobra-cmd-ansibleplaybook example ── "msg": "Example value is Hi! There" 19 | cobra-cmd-ansibleplaybook example ── } 20 | cobra-cmd-ansibleplaybook example ── 21 | cobra-cmd-ansibleplaybook example ── PLAY RECAP ********************************************************************* 22 | cobra-cmd-ansibleplaybook example ── 127.0.0.1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 23 | cobra-cmd-ansibleplaybook example ── 24 | ``` -------------------------------------------------------------------------------- /examples/ansibleplaybook-cobra-cmd/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-cobra-cmd/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-cobra-cmd/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-cobra-cmd 7 | debug: 8 | msg: Your are running 'ansibleplaybook-cobra-cmd' example 9 | 10 | - name: Print extra variable 'example' 11 | debug: 12 | msg: "Example value is {{ example }}" 13 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-custom-transformer 2 | 3 | ```sh 4 | ❯ go run ansibleplaybook-custom-transformer.go 5 | 2023-07-27 08:24:30 Go-ansible example ── 6 | 2023-07-27 08:24:30 Go-ansible example ── PLAY [all] ********************************************************************* 7 | 2023-07-27 08:24:30 Go-ansible example ── 8 | 2023-07-27 08:24:30 Go-ansible example ── TASK [Gathering Facts] ********************************************************* 9 | 2023-07-27 08:24:33 Go-ansible example ── ok: [127.0.0.1] 10 | 2023-07-27 08:24:33 Go-ansible example ── 11 | 2023-07-27 08:24:33 Go-ansible example ── TASK [ansibleplaybook-custom-transformer] ************************************** 12 | 2023-07-27 08:24:33 Go-ansible example ── ok: [127.0.0.1] => { 13 | 2023-07-27 08:24:33 Go-ansible example ── "msg": "Your are running 'ansibleplaybook-custom-transformer' example" 14 | 2023-07-27 08:24:33 Go-ansible example ── } 15 | 2023-07-27 08:24:33 Go-ansible example ── 16 | 2023-07-27 08:24:33 Go-ansible example ── PLAY RECAP ********************************************************************* 17 | 2023-07-27 08:24:33 Go-ansible example ── 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 18 | 2023-07-27 08:24:33 Go-ansible example ── 19 | ``` -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-custom-transformer/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-custom-transformer 7 | debug: 8 | msg: Your are running 'ansibleplaybook-custom-transformer' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # The repository does not contains the data directory content, so you need to generate it by running the command: go generate ./... 3 | internal/ansibleplaybook-embed-python/data 4 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-bookworm as builder 6 | 7 | RUN apt-get update \ 8 | && apt-get install -y \ 9 | openssh-client \ 10 | git \ 11 | && rm -rf /var/lib/apt/lists/* 12 | 13 | COPY --from=golang /usr/local/go /usr/local/go 14 | 15 | # Configure Go 16 | ENV GOROOT /usr/local/go 17 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 18 | 19 | WORKDIR /app 20 | 21 | # Copy the Go module files and download dependencies 22 | COPY go.mod go.sum ./ 23 | RUN go mod download 24 | 25 | COPY . . 26 | 27 | ## go generate is used to install go-embed-python 28 | RUN go generate ./... 29 | 30 | RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /usr/local/bin/app ansibleplaybook-embed-python.go 31 | 32 | FROM debian:bookworm-slim 33 | 34 | COPY --from=builder /usr/local/bin/app /usr/local/bin/app 35 | 36 | CMD ["/usr/local/bin/app"] 37 | 38 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 2 | 3 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 4 | 5 | # dafault target 6 | .DEFAULT_GOAL: help 7 | 8 | help: ## Lists available targets 9 | @echo 10 | @echo "Makefile usage:" 11 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 12 | @echo 13 | 14 | run: ## Run the example 15 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build app 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | app: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/apenella/go-ansible/v2/examples/ansibleplaybook-embed-python 2 | 3 | go 1.22 4 | 5 | toolchain go1.23.0 6 | 7 | require ( 8 | github.com/apenella/go-ansible/v2 v2.0.2-0.20241114073458-df85b88b0587 9 | github.com/kluctl/go-embed-python v0.0.0-3.12.2-20240224-1 10 | ) 11 | 12 | require ( 13 | github.com/apenella/go-common-utils/data v0.0.0-20220913191136-86daaa87e7df // indirect 14 | github.com/apenella/go-common-utils/error v0.0.0-20220913191136-86daaa87e7df // indirect 15 | github.com/cyphar/filepath-securejoin v0.2.4 // indirect 16 | github.com/davecgh/go-spew v1.1.1 // indirect 17 | github.com/gobwas/glob v0.2.3 // indirect 18 | github.com/pkg/errors v0.9.1 // indirect 19 | github.com/pmezard/go-difflib v1.0.0 // indirect 20 | github.com/rogpeppe/go-internal v1.12.0 // indirect 21 | github.com/sirupsen/logrus v1.9.3 // indirect 22 | github.com/stretchr/objx v0.5.2 // indirect 23 | github.com/stretchr/testify v1.9.0 // indirect 24 | golang.org/x/sync v0.6.0 // indirect 25 | golang.org/x/sys v0.19.0 // indirect 26 | gopkg.in/yaml.v2 v2.4.0 // indirect 27 | gopkg.in/yaml.v3 v3.0.1 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/internal/ansibleplaybook-embed-python/dummy.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | //go:generate go run ./generate 4 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/internal/ansibleplaybook-embed-python/generate/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/kluctl/go-embed-python/pip" 5 | ) 6 | 7 | func main() { 8 | err := pip.CreateEmbeddedPipPackagesForKnownPlatforms("requirements.txt", "./data/") 9 | if err != nil { 10 | panic(err) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/internal/ansibleplaybook-embed-python/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible-core 2 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/resources/ansible/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | collections: 4 | - name: community.general -------------------------------------------------------------------------------- /examples/ansibleplaybook-embed-python/resources/ansible/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: no 5 | 6 | tasks: 7 | - name: ansibleplaybook-simple 8 | ansible.builtin.debug: 9 | msg: Your are running 'ansibleplaybook-embed-python' example 10 | 11 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/ansibleplaybook-extravars-file.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute" 7 | "github.com/apenella/go-ansible/v2/pkg/playbook" 8 | ) 9 | 10 | func main() { 11 | 12 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 13 | Connection: "local", 14 | User: "aleix", 15 | Inventory: "127.0.0.1,", 16 | ExtraVarsFile: []string{ 17 | "@vars-file1.yml", 18 | "@vars-file2.yml", 19 | }, 20 | } 21 | 22 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 23 | playbook.WithPlaybooks("site.yml"), 24 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 25 | ) 26 | 27 | exec := execute.NewDefaultExecute( 28 | execute.WithCmd(playbookCmd), 29 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 30 | ) 31 | 32 | err := exec.Execute(context.TODO()) 33 | if err != nil { 34 | panic(err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | connection: local 5 | vars: 6 | f1_var1: na 7 | f1_var2: na 8 | f2_var1: na 9 | f2_var2: na 10 | 11 | tasks: 12 | - name: show values 13 | debug: 14 | msg: | 15 | {{ f1_var1 }} 16 | {{ f1_var2 }} 17 | {{ f2_var1 }} 18 | {{ f2_var2 }} 19 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/vars-file1.yml: -------------------------------------------------------------------------------- 1 | f1_var1: value11 2 | f1_var2: value12 -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars-file/vars-file2.yml: -------------------------------------------------------------------------------- 1 | f2_var1: value21 2 | f2_var2: value22 -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-ssh 2 | 3 | This example demonstrates how to use `go-ansible` to run an Ansible playbook on a remote host using SSH. 4 | 5 | The example provides a `Makefile` to build and run the example. The `Makefile` includes the following targets: 6 | 7 | - `build`: Builds the containers to run the example 8 | - `run`: Runs the example 9 | - `up`: Starts the environment 10 | - `down`: Stops the environment 11 | - `restart`: Restarts the environment 12 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/ansibleplaybook-extravars.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback" 9 | "github.com/apenella/go-ansible/v2/pkg/playbook" 10 | ) 11 | 12 | func main() { 13 | 14 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 15 | ExtraVars: map[string]interface{}{ 16 | "extravar1": "value11", 17 | "extravar2": "value12", 18 | "ansible_port": "22225", 19 | }, 20 | Inventory: "inventory.yml", 21 | SSHCommonArgs: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null", 22 | } 23 | 24 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 25 | playbook.WithPlaybooks("site.yml"), 26 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 27 | ) 28 | 29 | fmt.Println("Command: ", playbookCmd.String()) 30 | 31 | yamlexec := stdoutcallback.NewYAMLStdoutCallbackExecute( 32 | execute.NewDefaultExecute( 33 | execute.WithCmd(playbookCmd), 34 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 35 | ), 36 | ) 37 | 38 | err := yamlexec.Execute(context.TODO()) 39 | if err != nil { 40 | panic(err) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ssh:/ssh 13 | - ../..:/code 14 | working_dir: /code 15 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 16 | init: true 17 | depends_on: 18 | - server 19 | 20 | server: 21 | build: 22 | context: docker/server 23 | args: 24 | - sshd_port=${SSHD_PORT:-22225} 25 | # command: ["cat", "/etc/ssh/sshd_config"] 26 | volumes: 27 | - ssh:/ssh 28 | depends_on: 29 | - openssh-client 30 | ports: 31 | - "22220:${SSHD_PORT:-22225}" 32 | 33 | openssh-client: 34 | build: 35 | context: docker/openssh-client 36 | working_dir: /ssh 37 | volumes: 38 | - ssh:/ssh 39 | deploy: 40 | resources: 41 | limits: 42 | memory: 10M 43 | 44 | volumes: 45 | ssh: -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/docker/openssh-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-client \ 5 | git \ 6 | && rm -rf /var/cache/apk/* 7 | 8 | ENTRYPOINT [ "/usr/bin/ssh-keygen" ] 9 | CMD [ "--help" ] -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine3.18 2 | 3 | ARG sshd_port=2222 4 | 5 | RUN apk add --update --no-cache \ 6 | openssh-server \ 7 | # create a user 8 | && adduser -D ansible \ 9 | && rm -rf /var/cache/apk/* \ 10 | && ssh-keygen -A 11 | 12 | RUN echo "Port ${sshd_port}" >> /etc/ssh/sshd_config 13 | 14 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh 15 | RUN chmod +x /usr/local/bin/entrypoint.sh 16 | 17 | # Expose the SSH port 18 | EXPOSE ${sshd_port} 19 | 20 | CMD ["/usr/local/bin/entrypoint.sh"] 21 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | home=$(getent passwd "$(whoami)" | cut -d: -f6) 4 | 5 | mkdir -p "${home}/.ssh" 6 | cat /ssh/id_rsa.pub > "${home}/.ssh/authorized_keys" 7 | 8 | /usr/sbin/sshd -D -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/inventory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | all: 4 | hosts: 5 | server: 6 | ansible_host: server 7 | ansible_user: root 8 | ansible_ssh_private_key_file: /ssh/id_rsa 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-extravars/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: server 4 | vars: 5 | extravar1: na 6 | extravar2: na 7 | 8 | tasks: 9 | - name: Gather facts 10 | ansible.builtin.setup: 11 | gather_subset: 12 | - all_ipv4_addresses 13 | 14 | - name: show values 15 | debug: 16 | msg: | 17 | {{ hostvars['server']['ansible_hostname'] }}[{{ hostvars['server']['ansible_default_ipv4']['address'] }}] (port: {{ hostvars['server']['ansible_port'] }}) 18 | - {{ extravar1 }} 19 | - {{ extravar2 }} -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/ansibleplaybook-json-stdout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io" 8 | 9 | "github.com/apenella/go-ansible/v2/pkg/execute" 10 | "github.com/apenella/go-ansible/v2/pkg/execute/measure" 11 | results "github.com/apenella/go-ansible/v2/pkg/execute/result/json" 12 | "github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback" 13 | "github.com/apenella/go-ansible/v2/pkg/playbook" 14 | ) 15 | 16 | func main() { 17 | 18 | var err error 19 | var res *results.AnsiblePlaybookJSONResults 20 | 21 | buff := new(bytes.Buffer) 22 | 23 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 24 | Connection: "local", 25 | Inventory: "127.0.0.1,", 26 | } 27 | 28 | playbooksList := []string{"site1.yml", "site2.yml", "site3.yml"} 29 | 30 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 31 | playbook.WithPlaybooks(playbooksList...), 32 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 33 | ) 34 | 35 | exec := measure.NewExecutorTimeMeasurement( 36 | stdoutcallback.NewJSONStdoutCallbackExecute( 37 | execute.NewDefaultExecute( 38 | execute.WithCmd(playbookCmd), 39 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 40 | execute.WithWrite(io.Writer(buff)), 41 | ), 42 | ), 43 | ) 44 | 45 | err = exec.Execute(context.TODO()) 46 | if err != nil { 47 | fmt.Println(err.Error()) 48 | } 49 | 50 | res, err = results.ParseJSONResultsStream(io.Reader(buff)) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | fmt.Println(res.String()) 56 | fmt.Println("Duration: ", exec.Duration().String()) 57 | 58 | } 59 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/site1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-json-stdout' 9 | - first example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-json-stdout 13 | outro: first example 14 | 15 | tasks: 16 | - name: ansibleplaybook-json-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-json-stdout' 21 | first example 22 | 23 | - name: ansibleplaybook-json-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-json-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-json-stdout' 9 | - second example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-json-stdout 13 | outro: second example 14 | 15 | tasks: 16 | - name: ansibleplaybook-json-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-json-stdout' 21 | second example 22 | 23 | - name: ansibleplaybook-json-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-json-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-json-stdout/site3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-json-stdout' 9 | - third example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-json-stdout 13 | outro: third example 14 | 15 | tasks: 16 | - name: ansibleplaybook-json-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-json-stdout' 21 | third example 22 | 23 | - name: ansibleplaybook-json-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-json-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-myexecutor 2 | 3 | ```sh 4 | ❯ go run ansibleplaybook-myexecutor.go 5 | [Go ansible example] I am MyExecutor and I am doing nothing 6 | 7 | ``` 8 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/ansibleplaybook-myexecutor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/playbook" 9 | ) 10 | 11 | type MyExecutor struct { 12 | Prefix string 13 | Cmd execute.Commander 14 | } 15 | 16 | func NewMyExecutor(cmd execute.Commander) *MyExecutor { 17 | return &MyExecutor{ 18 | Cmd: cmd, 19 | } 20 | } 21 | 22 | func (e *MyExecutor) WithPrefix(prefix string) { 23 | e.Prefix = prefix 24 | } 25 | 26 | func (e *MyExecutor) Execute(ctx context.Context) error { 27 | fmt.Println(fmt.Sprintf("%s %s\n", e.Prefix, "I am MyExecutor and I am doing nothing")) 28 | 29 | return nil 30 | } 31 | 32 | func main() { 33 | 34 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 35 | Connection: "local", 36 | Inventory: "127.0.0.1,", 37 | } 38 | 39 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 40 | playbook.WithPlaybooks("site.yml"), 41 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 42 | ) 43 | 44 | exec := NewMyExecutor(playbookCmd) 45 | exec.WithPrefix("[Go ansible example]") 46 | 47 | err := exec.Execute(context.TODO()) 48 | if err != nil { 49 | panic(err) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-myexecutor/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-myexecutor 7 | debug: 8 | msg: Your are running 'ansibleplaybook-myexecutor' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/site1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - first example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: first example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | first example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - second example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: second example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | second example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout-persistence/site3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - third example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: third example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | third example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/site1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - first example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: first example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | first example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - second example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: second example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | second example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-posix-jsonl-stdout/site3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | vars: 6 | array: 7 | - Your are running 8 | - 'ansibleplaybook-posix-jsonl-stdout' 9 | - third example 10 | map: 11 | intro: Your are running 12 | what: ansibleplaybook-posix-jsonl-stdout 13 | outro: third example 14 | 15 | tasks: 16 | - name: ansibleplaybook-posix-jsonl-stdout 17 | debug: 18 | msg: | 19 | Your are running 20 | 'ansibleplaybook-posix-jsonl-stdout' 21 | third example 22 | 23 | - name: ansibleplaybook-posix-jsonl-stdout from array 24 | debug: 25 | msg: "{{ array }}" 26 | 27 | - name: ansibleplaybook-posix-jsonl-stdout from map 28 | debug: 29 | msg: "{{ map }}" 30 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-signals-and-cancellation 2 | 3 | ```sh 4 | ❯ go run ansibleplaybook-signals-and-cancellation.go 5 | Go-ansible example ── 6 | Go-ansible example ── PLAY [all] ********************************************************************* 7 | Go-ansible example ── 8 | Go-ansible example ── TASK [Gathering Facts] ********************************************************* 9 | Go-ansible example ── ok: [127.0.0.1] 10 | Go-ansible example ── 11 | Go-ansible example ── TASK [ansibleplaybook-signals-and-cancellation] ******************************** 12 | Go-ansible example ── ok: [127.0.0.1] => { 13 | Go-ansible example ── "msg": "Your are running 'ansibleplaybook-signals-and-cancellation' example" 14 | Go-ansible example ── } 15 | Go-ansible example ── 16 | Go-ansible example ── PLAY RECAP ********************************************************************* 17 | Go-ansible example ── 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 18 | Go-ansible example ── 19 | ``` -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/ansibleplaybook-signals-and-cancellation.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | 9 | "github.com/apenella/go-ansible/v2/pkg/execute" 10 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 11 | "github.com/apenella/go-ansible/v2/pkg/execute/result/transformer" 12 | "github.com/apenella/go-ansible/v2/pkg/playbook" 13 | ) 14 | 15 | func main() { 16 | 17 | signalChan := make(chan os.Signal, 1) 18 | ctx, cancel := context.WithCancel(context.Background()) 19 | 20 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 21 | Connection: "local", 22 | User: "aleix", 23 | Inventory: "127.0.0.1,", 24 | } 25 | 26 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 27 | playbook.WithPlaybooks("site.yml"), 28 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 29 | ) 30 | 31 | exec := configuration.NewAnsibleWithConfigurationSettingsExecute( 32 | execute.NewDefaultExecute( 33 | execute.WithCmd(playbookCmd), 34 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 35 | execute.WithTransformers( 36 | transformer.Prepend("[ansibleplaybook-signals-and-cancellation]"), 37 | ), 38 | ), 39 | configuration.WithAnsibleForceColor(), 40 | ) 41 | 42 | signal.Notify(signalChan, os.Interrupt) 43 | defer func() { 44 | signal.Stop(signalChan) 45 | cancel() 46 | }() 47 | 48 | go func() { 49 | select { 50 | case <-signalChan: 51 | cancel() 52 | case <-ctx.Done(): 53 | } 54 | }() 55 | 56 | err := exec.Execute(ctx) 57 | if err != nil { 58 | fmt.Println(err.Error()) 59 | os.Exit(1) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-signals-and-cancellation/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-signals-and-cancellation 7 | debug: 8 | msg: Your are running 'ansibleplaybook-signals-and-cancellation' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/embedfs/inventory.ini: -------------------------------------------------------------------------------- 1 | [localhost] 2 | 127.0.0.1 ansible_connection=local -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/embedfs/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-simple 7 | debug: 8 | msg: Your are running 'ansibleplaybook-simple-embedfs' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-embedfs/embedfs/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-simple 7 | debug: 8 | msg: Your are running 'ansibleplaybook-simple-embedfs' example on site2.yml 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/ansibleplaybook-simple-with-prompt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 9 | "github.com/apenella/go-ansible/v2/pkg/playbook" 10 | ) 11 | 12 | func main() { 13 | 14 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 15 | Connection: "local", 16 | Inventory: "127.0.0.1,", 17 | // Verbose: true, 18 | } 19 | 20 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 21 | playbook.WithPlaybooks("input.yml"), 22 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 23 | ) 24 | 25 | exec := configuration.NewAnsibleWithConfigurationSettingsExecute( 26 | execute.NewDefaultExecute( 27 | execute.WithCmd(playbookCmd), 28 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 29 | execute.WithWriteError(os.Stdout), 30 | ), 31 | configuration.WithAnsibleForceColor(), 32 | ) 33 | 34 | err := exec.Execute(context.TODO()) 35 | if err != nil { 36 | panic(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple-with-prompt/input.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Test playbook for user input 4 | hosts: localhost 5 | gather_facts: false 6 | 7 | vars_prompt: 8 | - name: input_this 9 | prompt: Type in anything 10 | - name: input_that 11 | prompt: Type in another thing 12 | tasks: 13 | 14 | - name: echo user input this 15 | debug: 16 | msg: "You typed this: '{{ input_this }}'" 17 | 18 | - name: echo user input that 19 | debug: 20 | msg: "You typed that: '{{ input_that }}'" 21 | 22 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/ansibleplaybook-simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/playbook" 9 | ) 10 | 11 | func main() { 12 | 13 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 14 | Connection: "local", 15 | Inventory: "127.0.0.1,", 16 | } 17 | 18 | err := playbook.NewAnsiblePlaybookExecute("site.yml", "site2.yml"). 19 | WithPlaybookOptions(ansiblePlaybookOptions). 20 | Execute(context.TODO()) 21 | 22 | if err != nil { 23 | fmt.Println(err.Error()) 24 | os.Exit(1) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-simple 7 | debug: 8 | msg: Your are running 'ansibleplaybook-simple' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-simple/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-simple 7 | debug: 8 | msg: Your are running 'ansibleplaybook-simple' example on site2.yml 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/site1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | tasks: 6 | - name: ok-task 7 | ansible.builtin.shell: /usr/bin/true 8 | 9 | - name: skipping-task 10 | ansible.builtin.shell: echo "'{{ foo }}'" 11 | when: foo is defined 12 | 13 | - name: failing-task 14 | ansible.builtin.shell: exit -1 15 | ignore_errors: true 16 | 17 | - name: failing-task-when 18 | ansible.builtin.command: /usr/bin/ls /tmp/foobar.baz 19 | register: command_result 20 | failed_when: "'No such file or directory' in command_result.stderr" 21 | 22 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-skipping-failing/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | tasks: 6 | - name: ok-task 7 | ansible.builtin.shell: /usr/bin/true 8 | 9 | - name: skipping-task 10 | ansible.builtin.shell: echo "'{{ foo }}'" 11 | when: foo is defined 12 | 13 | - name: failing-task 14 | ansible.builtin.shell: exit -1 15 | ignore_errors: true 16 | 17 | - name: failing-task-when 18 | ansible.builtin.command: /usr/bin/ls /tmp/foobar.baz 19 | register: command_result 20 | failed_when: "'No such file or directory' in command_result.stderr" 21 | 22 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 2 | ANSIBLE_CORE_VERSION=2.16.9 -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-ssh 2 | 3 | This example demonstrates how to use `go-ansible` to run an Ansible playbook on a remote host using SSH and using _sudo_ to become root user. 4 | 5 | The example provides a `Makefile` to build and run the example. The `Makefile` includes the following targets: 6 | 7 | - `build`: Builds the containers to run the example 8 | - `run`: Runs the example 9 | - `up`: Starts the environment 10 | - `down`: Stops the environment 11 | - `restart`: Restarts the environment 12 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/ansibleplaybook-ssh-become-root-with-password.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 10 | "github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback" 11 | "github.com/apenella/go-ansible/v2/pkg/playbook" 12 | ) 13 | 14 | func main() { 15 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 16 | Become: true, 17 | BecomeMethod: "sudo", 18 | BecomeUser: "root", 19 | ExtraVars: map[string]interface{}{ 20 | "ansible_ssh_private_key_file": "/ssh/id_rsa", 21 | "ansible_sudo_pass": "12345", 22 | }, 23 | Inventory: "inventory.yml", 24 | SSHCommonArgs: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null", 25 | Timeout: 300, 26 | User: "aleix", 27 | } 28 | 29 | cmd := playbook.NewAnsiblePlaybookCmd( 30 | playbook.WithPlaybooks("site.yml"), 31 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 32 | ) 33 | 34 | exec := configuration.NewAnsibleWithConfigurationSettingsExecute( 35 | execute.NewDefaultExecute( 36 | execute.WithCmd(cmd), 37 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 38 | ), 39 | configuration.WithAnsibleForceColor(), 40 | configuration.WithAnsibleStdoutCallback(stdoutcallback.YAMLStdoutCallback), 41 | ) 42 | 43 | fmt.Printf("Executing command: '%s'", cmd.String()) 44 | 45 | err := exec.Execute(context.TODO()) 46 | if err != nil { 47 | fmt.Println(err) 48 | os.Exit(1) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | - ansible_core_version=${ANSIBLE_CORE_VERSION} 10 | command: ["tail", "-f", "/dev/null"] 11 | volumes: 12 | - ssh:/ssh 13 | - ../..:/code 14 | working_dir: /code 15 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 16 | init: true 17 | depends_on: 18 | - server 19 | 20 | server: 21 | build: 22 | context: docker/server 23 | volumes: 24 | - ssh:/ssh 25 | depends_on: 26 | - openssh-client 27 | ports: 28 | - "22220:22" 29 | 30 | openssh-client: 31 | build: 32 | context: docker/openssh-client 33 | working_dir: /ssh 34 | volumes: 35 | - ssh:/ssh 36 | deploy: 37 | resources: 38 | limits: 39 | memory: 10M 40 | 41 | volumes: 42 | ssh: -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | ARG ansible_core_version=2.17.5 8 | 9 | RUN apk add --update --no-cache \ 10 | openssh-client \ 11 | git \ 12 | && rm -rf /var/cache/apk/* 13 | 14 | RUN pip3 install -U pip setuptools \ 15 | && pip3 install --no-cache-dir \ 16 | setuptools-rust \ 17 | cryptography \ 18 | # Required library to execute ansible community.general.dig plugin 19 | dnspython \ 20 | ansible-core==${ansible_core_version} \ 21 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook \ 22 | && ansible-galaxy collection install community.general 23 | 24 | COPY --from=golang /usr/local/go /usr/local/go 25 | 26 | # Configure Go 27 | ENV GOROOT /usr/local/go 28 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 29 | 30 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 31 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/docker/openssh-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-client \ 5 | git \ 6 | && rm -rf /var/cache/apk/* 7 | 8 | ENTRYPOINT [ "/usr/bin/ssh-keygen" ] 9 | CMD [ "--help" ] -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine3.18 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-server \ 5 | # create a user 6 | && adduser -D ansible \ 7 | && rm -rf /var/cache/apk/* \ 8 | && ssh-keygen -A 9 | 10 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh 11 | RUN chmod +x /usr/local/bin/entrypoint.sh 12 | 13 | # Expose the SSH port 14 | EXPOSE 22 15 | 16 | CMD ["/usr/local/bin/entrypoint.sh"] 17 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | home=$(getent passwd "$(whoami)" | cut -d: -f6) 4 | 5 | mkdir -p "${home}/.ssh" 6 | cat /ssh/id_rsa.pub > "${home}/.ssh/authorized_keys" 7 | 8 | { 9 | echo "PasswordAuthentication no" 10 | echo "PubkeyAuthentication yes" 11 | echo "AllowUsers aleix" 12 | } >> /etc/ssh/sshd_config 13 | 14 | adduser aleix -D 15 | cp -r ~/.ssh /home/aleix/ 16 | chown -R aleix:aleix /home/aleix/.ssh 17 | echo 'aleix:12345' | chpasswd; 18 | 19 | apk update 20 | apk add sudo 21 | 22 | echo "aleix ALL=(ALL:ALL) ALL" >> /etc/sudoers 23 | 24 | ## -e option will print the logs to the console 25 | /usr/sbin/sshd -D -e 26 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/inventory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | all: 4 | hosts: 5 | server: 6 | ansible_host: server 7 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh-become-root-with-password/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: server 4 | gather_facts: true 5 | become: true 6 | 7 | tasks: 8 | - name: ansibleplaybook-ssh 9 | ansible.builtin.debug: 10 | msg: | 11 | Your are running 'ansibleplaybook-ssh-become-root-with-password' example 12 | 13 | Remote server IP is: {{ hostvars['server']['ansible_facts']['eth0']['ipv4']['address'] }} 14 | 15 | - name: update apk cache 16 | ansible.builtin.apk: 17 | update_cache: yes -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-ssh 2 | 3 | This example demonstrates how to use `go-ansible` to run an Ansible playbook on a remote host using SSH. 4 | 5 | The example provides a `Makefile` to build and run the example. The `Makefile` includes the following targets: 6 | 7 | - `build`: Builds the containers to run the example 8 | - `run`: Runs the example 9 | - `up`: Starts the environment 10 | - `down`: Stops the environment 11 | - `restart`: Restarts the environment 12 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/ansibleplaybook-ssh.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute" 9 | "github.com/apenella/go-ansible/v2/pkg/playbook" 10 | ) 11 | 12 | func main() { 13 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 14 | Inventory: "inventory.yml", 15 | SSHCommonArgs: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null", 16 | } 17 | 18 | cmd := playbook.NewAnsiblePlaybookCmd( 19 | playbook.WithPlaybooks("site.yml"), 20 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 21 | ) 22 | 23 | exec := execute.NewDefaultExecute( 24 | execute.WithCmd(cmd), 25 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 26 | ) 27 | 28 | fmt.Println("Executing command: ", cmd.String()) 29 | 30 | err := exec.Execute(context.TODO()) 31 | if err != nil { 32 | fmt.Println(err) 33 | os.Exit(1) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ssh:/ssh 13 | - ../..:/code 14 | working_dir: /code 15 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 16 | init: true 17 | depends_on: 18 | - server 19 | 20 | server: 21 | build: 22 | context: docker/server 23 | # command: ["cat", "/etc/ssh/sshd_config"] 24 | volumes: 25 | - ssh:/ssh 26 | depends_on: 27 | - openssh-client 28 | ports: 29 | - "22220:22" 30 | 31 | openssh-client: 32 | build: 33 | context: docker/openssh-client 34 | working_dir: /ssh 35 | volumes: 36 | - ssh:/ssh 37 | deploy: 38 | resources: 39 | limits: 40 | memory: 10M 41 | 42 | volumes: 43 | ssh: -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/docker/openssh-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-client \ 5 | git \ 6 | && rm -rf /var/cache/apk/* 7 | 8 | ENTRYPOINT [ "/usr/bin/ssh-keygen" ] 9 | CMD [ "--help" ] -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine3.18 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-server \ 5 | # create a user 6 | && adduser -D ansible \ 7 | && rm -rf /var/cache/apk/* \ 8 | && ssh-keygen -A 9 | 10 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh 11 | RUN chmod +x /usr/local/bin/entrypoint.sh 12 | 13 | # Expose the SSH port 14 | EXPOSE 22 15 | 16 | CMD ["/usr/local/bin/entrypoint.sh"] 17 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | home=$(getent passwd "$(whoami)" | cut -d: -f6) 4 | 5 | mkdir -p "${home}/.ssh" 6 | cat /ssh/id_rsa.pub > "${home}/.ssh/authorized_keys" 7 | 8 | /usr/sbin/sshd -D -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/inventory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | all: 4 | hosts: 5 | server: 6 | ansible_host: server 7 | ansible_user: root 8 | ansible_ssh_private_key_file: /ssh/id_rsa 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-ssh/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: server 4 | 5 | tasks: 6 | - name: ansibleplaybook-ssh 7 | ansible.builtin.debug: 8 | msg: Your are running 'ansibleplaybook-ssh' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/ansibleplaybook-time-measurement.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute" 8 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/measure" 10 | "github.com/apenella/go-ansible/v2/pkg/playbook" 11 | ) 12 | 13 | func main() { 14 | 15 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 16 | Connection: "local", 17 | Inventory: "127.0.0.1,", 18 | } 19 | 20 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 21 | playbook.WithPlaybooks("site.yml"), 22 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 23 | ) 24 | 25 | exec := measure.NewExecutorTimeMeasurement( 26 | configuration.NewAnsibleWithConfigurationSettingsExecute( 27 | execute.NewDefaultExecute( 28 | execute.WithCmd(playbookCmd), 29 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 30 | ), 31 | configuration.WithAnsibleForceColor(), 32 | ), 33 | ) 34 | 35 | err := exec.Execute(context.TODO()) 36 | if err != nil { 37 | fmt.Println(err.Error()) 38 | } 39 | 40 | fmt.Println("Duration: ", exec.Duration().String()) 41 | } 42 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-time-measurement/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-time-measurement 7 | debug: 8 | msg: Your are running 'ansibleplaybook-time-measurement' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-walk-through-json-output/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-walk-through-json-output/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-walk-through-json-output/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-walk-through-json-output/site1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: False 5 | 6 | tasks: 7 | - name: ansibleplaybook-walk-through-json-output 8 | ansible.builtin.shell: | 9 | printf '{"host": "%s", "message": "%s"}' "{{ inventory_hostname }}" "that is just an example" 10 | args: 11 | executable: /bin/sh 12 | register: output 13 | 14 | - name: ansibleplaybook-walk-through-json-output output 15 | debug: 16 | msg: "{{ output.stdout }}" 17 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-walk-through-json-output/site2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: False 5 | 6 | tasks: 7 | - name: ansibleplaybook-walk-through-json-output 8 | ansible.builtin.shell: | 9 | printf '{"host": "%s", "message": "%s"}' "{{ inventory_hostname }}" "that is another example" 10 | args: 11 | executable: /bin/sh 12 | register: output 13 | 14 | - name: ansibleplaybook-walk-through-json-output output 15 | debug: 16 | msg: "{{ output.stdout }}" 17 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-with-executor-time-measurament 2 | 3 | ```sh 4 | ❯ go run ansibleplaybook-with-executor-time-measurament.go 5 | 2023-07-27 08:27:45 Go-ansible example ── 6 | 2023-07-27 08:27:45 Go-ansible example ── PLAY [all] ********************************************************************* 7 | 2023-07-27 08:27:45 Go-ansible example ── 8 | 2023-07-27 08:27:45 Go-ansible example ── TASK [Gathering Facts] ********************************************************* 9 | 2023-07-27 08:27:48 Go-ansible example ── ok: [127.0.0.1] 10 | 2023-07-27 08:27:48 Go-ansible example ── 11 | 2023-07-27 08:27:48 Go-ansible example ── TASK [ansibleplaybook-wit-executor-time-measurement] *************************** 12 | 2023-07-27 08:27:48 Go-ansible example ── ok: [127.0.0.1] => { 13 | 2023-07-27 08:27:48 Go-ansible example ── "msg": "Your are running 'ansibleplaybook-wit-executor-time-measurement' example" 14 | 2023-07-27 08:27:48 Go-ansible example ── } 15 | 2023-07-27 08:27:48 Go-ansible example ── 16 | 2023-07-27 08:27:48 Go-ansible example ── PLAY RECAP ********************************************************************* 17 | 2023-07-27 08:27:48 Go-ansible example ── 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 18 | 2023-07-27 08:27:48 Go-ansible example ── 19 | 20 | Duration: 3.397462474s 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/ansibleplaybook-with-executor-time-measurament.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute" 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | "github.com/apenella/go-ansible/v2/pkg/execute/measure" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/result/transformer" 10 | "github.com/apenella/go-ansible/v2/pkg/playbook" 11 | "github.com/fatih/color" 12 | ) 13 | 14 | func main() { 15 | 16 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 17 | Connection: "local", 18 | Inventory: "127.0.0.1,", 19 | } 20 | 21 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 22 | playbook.WithPlaybooks("site.yml"), 23 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 24 | ) 25 | 26 | exec := measure.NewExecutorTimeMeasurement( 27 | configuration.NewAnsibleWithConfigurationSettingsExecute( 28 | execute.NewDefaultExecute( 29 | execute.WithCmd(playbookCmd), 30 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 31 | execute.WithTransformers( 32 | transformer.Prepend("Go-ansible example"), 33 | transformer.LogFormat(transformer.DefaultLogFormatLayout, transformer.Now), 34 | ), 35 | ), 36 | configuration.WithAnsibleForceColor(), 37 | ), 38 | ) 39 | 40 | err := exec.Execute(context.TODO()) 41 | if err != nil { 42 | panic(err) 43 | } 44 | 45 | color.Cyan("\n\tDuration: %s\n\n", exec.Duration()) 46 | } 47 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-executor-time-measurament/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-wit-executor-time-measurement 7 | debug: 8 | msg: Your are running 'ansibleplaybook-wit-executor-time-measurement' example 9 | 10 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/README.md: -------------------------------------------------------------------------------- 1 | # Example ansibleplaybook-with-timeout 2 | 3 | ```sh 4 | ❯ go run ansibleplaybook-with-timeout.go 5 | Timeout: 15 seconds 6 | Go-ansible example ── 7 | Go-ansible example ── PLAY [all] ********************************************************************* 8 | Go-ansible example ── 9 | Go-ansible example ── TASK [Gathering Facts] ********************************************************* 10 | Go-ansible example ── ok: [127.0.0.1] 11 | Go-ansible example ── 12 | Go-ansible example ── TASK [ansibleplaybook-with-timeout] ******************************************** 13 | Go-ansible example ── ok: [127.0.0.1] => { 14 | Go-ansible example ── "msg": "Your are running 'ansibleplaybook-with-timeout' example" 15 | Go-ansible example ── } 16 | Go-ansible example ── 17 | Go-ansible example ── PLAY RECAP ********************************************************************* 18 | Go-ansible example ── 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 19 | Go-ansible example ── 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/ansibleplaybook-with-timeout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "time" 8 | 9 | "github.com/apenella/go-ansible/v2/pkg/execute" 10 | "github.com/apenella/go-ansible/v2/pkg/execute/result/transformer" 11 | "github.com/apenella/go-ansible/v2/pkg/playbook" 12 | ) 13 | 14 | func main() { 15 | 16 | var timeout int 17 | flag.IntVar(&timeout, "timeout", 10, "Timeout in seconds") 18 | flag.Parse() 19 | 20 | fmt.Printf("Timeout: %d seconds\n", timeout) 21 | 22 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) 23 | defer cancel() 24 | 25 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 26 | User: "apenella", 27 | Connection: "local", 28 | Inventory: "127.0.0.1,", 29 | } 30 | 31 | playbookCmd := playbook.NewAnsiblePlaybookCmd( 32 | playbook.WithPlaybooks("site.yml"), 33 | playbook.WithPlaybookOptions(ansiblePlaybookOptions), 34 | ) 35 | 36 | exec := execute.NewDefaultExecute( 37 | execute.WithCmd(playbookCmd), 38 | execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()), 39 | execute.WithTransformers( 40 | transformer.Prepend("Go-ansible example"), 41 | ), 42 | ) 43 | 44 | err := exec.Execute(ctx) 45 | if err != nil { 46 | panic(err) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-timeout/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: sleep 7 | pause: 8 | seconds: 15 9 | 10 | - name: ansibleplaybook-with-timeout 11 | debug: 12 | msg: Your are running 'ansibleplaybook-with-timeout' example 13 | 14 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: ansibleplaybook-with-vaulted-extravar 7 | debug: 8 | msg: Your are reading a vaulted variable provided as an extra-vars '{{ vaulted_extra_var }}' 9 | -------------------------------------------------------------------------------- /examples/ansibleplaybook-with-vaulted-extravar/vault_password.cfg: -------------------------------------------------------------------------------- 1 | ThatIsAPassword -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ssh:/ssh 13 | - ../..:/code 14 | working_dir: /code 15 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 16 | init: true 17 | depends_on: 18 | - server 19 | 20 | server: 21 | build: 22 | context: docker/server 23 | # command: ["cat", "/etc/ssh/sshd_config"] 24 | volumes: 25 | - ssh:/ssh 26 | depends_on: 27 | - openssh-client 28 | # ports: 29 | # - "22220:22" 30 | 31 | openssh-client: 32 | build: 33 | context: docker/openssh-client 34 | working_dir: /ssh 35 | volumes: 36 | - ssh:/ssh 37 | deploy: 38 | resources: 39 | limits: 40 | memory: 10M 41 | 42 | volumes: 43 | ssh: -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/docker/openssh-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-client \ 5 | git \ 6 | && rm -rf /var/cache/apk/* 7 | 8 | ENTRYPOINT [ "/usr/bin/ssh-keygen" ] 9 | CMD [ "--help" ] -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:bookworm 2 | 3 | 4 | RUN adduser --disabled-password --gecos "" ansible 5 | 6 | RUN apt-get update \ 7 | && apt-get install -y \ 8 | openssh-server \ 9 | && rm -rf /var/lib/apt/lists/* 10 | 11 | RUN mkdir /var/run/sshd \ 12 | && ssh-keygen -A 13 | 14 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh 15 | RUN chmod +x /usr/local/bin/entrypoint.sh 16 | 17 | # Expose the SSH port 18 | EXPOSE 22 19 | 20 | CMD ["/usr/local/bin/entrypoint.sh"] 21 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | home=$(getent passwd "$(whoami)" | cut -d: -f6) 4 | 5 | mkdir -p "${home}/.ssh" 6 | cat /ssh/id_rsa.pub > "${home}/.ssh/authorized_keys" 7 | 8 | /usr/sbin/sshd -D -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/inventory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | all: 4 | hosts: 5 | server: 6 | ansible_host: server 7 | ansible_user: root 8 | ansible_ssh_private_key_file: /ssh/id_rsa 9 | 10 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | collections: 4 | - name: community.general -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: server 4 | 5 | tasks: 6 | 7 | - name: Check version of community.general 8 | ansible.builtin.debug: 9 | msg: "community.general version {{ lookup('community.general.collection_version', 'community.general') }}" 10 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-collection/workflowexecute-ansibleplaybook-with-galaxy-install-collection.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/workflow" 10 | galaxy "github.com/apenella/go-ansible/v2/pkg/galaxy/collection/install" 11 | "github.com/apenella/go-ansible/v2/pkg/playbook" 12 | ) 13 | 14 | func main() { 15 | 16 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 17 | Inventory: "inventory.yml", 18 | SSHCommonArgs: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null", 19 | } 20 | 21 | galaxyInstallCollectionCmd := galaxy.NewAnsibleGalaxyCollectionInstallCmd( 22 | galaxy.WithGalaxyCollectionInstallOptions(&galaxy.AnsibleGalaxyCollectionInstallOptions{ 23 | Force: true, 24 | Upgrade: true, 25 | RequirementsFile: "requirements.yml", 26 | }), 27 | ) 28 | 29 | galaxyInstallCollectionExec := execute.NewDefaultExecute( 30 | execute.WithCmd(galaxyInstallCollectionCmd), 31 | ) 32 | 33 | playbookCmd := playbook.NewAnsiblePlaybookExecute("site.yml"). 34 | WithPlaybookOptions(ansiblePlaybookOptions) 35 | 36 | err := workflow.NewWorkflowExecute(galaxyInstallCollectionExec, playbookCmd). 37 | WithTrace(). 38 | Execute(context.TODO()) 39 | if err != nil { 40 | fmt.Println(err.Error()) 41 | os.Exit(1) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ssh:/ssh 13 | - ../..:/code 14 | working_dir: /code 15 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 16 | init: true 17 | depends_on: 18 | - server 19 | 20 | server: 21 | build: 22 | context: docker/server 23 | # command: ["cat", "/etc/ssh/sshd_config"] 24 | volumes: 25 | - ssh:/ssh 26 | depends_on: 27 | - openssh-client 28 | # ports: 29 | # - "22220:22" 30 | 31 | openssh-client: 32 | build: 33 | context: docker/openssh-client 34 | working_dir: /ssh 35 | volumes: 36 | - ssh:/ssh 37 | deploy: 38 | resources: 39 | limits: 40 | memory: 10M 41 | 42 | volumes: 43 | ssh: -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | 22 | COPY --from=golang /usr/local/go /usr/local/go 23 | 24 | # Configure Go 25 | ENV GOROOT /usr/local/go 26 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 27 | 28 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 29 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/docker/openssh-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | RUN apk add --update --no-cache \ 4 | openssh-client \ 5 | git \ 6 | && rm -rf /var/cache/apk/* 7 | 8 | ENTRYPOINT [ "/usr/bin/ssh-keygen" ] 9 | CMD [ "--help" ] -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:bookworm 2 | 3 | 4 | RUN adduser --disabled-password --gecos "" ansible 5 | 6 | RUN apt-get update \ 7 | && apt-get install -y \ 8 | openssh-server \ 9 | && rm -rf /var/lib/apt/lists/* 10 | 11 | RUN mkdir /var/run/sshd \ 12 | && ssh-keygen -A 13 | 14 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh 15 | RUN chmod +x /usr/local/bin/entrypoint.sh 16 | 17 | # Expose the SSH port 18 | EXPOSE 22 19 | 20 | CMD ["/usr/local/bin/entrypoint.sh"] 21 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/docker/server/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | home=$(getent passwd "$(whoami)" | cut -d: -f6) 4 | 5 | mkdir -p "${home}/.ssh" 6 | cat /ssh/id_rsa.pub > "${home}/.ssh/authorized_keys" 7 | 8 | /usr/sbin/sshd -D -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/inventory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | all: 4 | hosts: 5 | server: 6 | ansible_host: server 7 | ansible_user: root 8 | ansible_ssh_private_key_file: /ssh/id_rsa 9 | 10 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # ansible requirements.yml file include role go to install 4 | - src: geerlingguy.go 5 | version: 1.1.0 -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: server 4 | 5 | tasks: 6 | - name: Install nginx 7 | ansible.builtin.import_role: 8 | name: geerlingguy.go 9 | -------------------------------------------------------------------------------- /examples/workflowexecute-ansibleplaybook-with-galaxy-install-role/workflowexecute-ansibleplaybook-with-galaxy-install-role.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/workflow" 10 | galaxy "github.com/apenella/go-ansible/v2/pkg/galaxy/role/install" 11 | "github.com/apenella/go-ansible/v2/pkg/playbook" 12 | ) 13 | 14 | func main() { 15 | 16 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 17 | Inventory: "inventory.yml", 18 | SSHCommonArgs: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null", 19 | } 20 | 21 | galaxyInstallRolesCmd := galaxy.NewAnsibleGalaxyRoleInstallCmd( 22 | // galaxy.WithRoleNames("geerlingguy.go"), 23 | galaxy.WithGalaxyRoleInstallOptions(&galaxy.AnsibleGalaxyRoleInstallOptions{ 24 | Force: true, 25 | RoleFile: "requirements.yml", 26 | }), 27 | ) 28 | 29 | galaxyInstallRolesExec := execute.NewDefaultExecute( 30 | execute.WithCmd(galaxyInstallRolesCmd), 31 | ) 32 | 33 | playbookCmd := playbook.NewAnsiblePlaybookExecute("site.yml"). 34 | WithPlaybookOptions(ansiblePlaybookOptions) 35 | 36 | err := workflow.NewWorkflowExecute(galaxyInstallRolesExec, playbookCmd). 37 | WithTrace(). 38 | Execute(context.TODO()) 39 | if err != nil { 40 | fmt.Println(err.Error()) 41 | os.Exit(1) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/workflowexecute-simple/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/first.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: Workflow Execute first playbook 7 | debug: 8 | msg: Your are running 'workflowexecute-simple' example 9 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/second.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: Workflow Execute second playbook 7 | debug: 8 | msg: Your are running 'workflowexecute-simple' example 9 | -------------------------------------------------------------------------------- /examples/workflowexecute-simple/workflowexecute-simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute/workflow" 9 | "github.com/apenella/go-ansible/v2/pkg/playbook" 10 | ) 11 | 12 | func main() { 13 | 14 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 15 | Connection: "local", 16 | Inventory: "127.0.0.1,", 17 | } 18 | 19 | first := playbook.NewAnsiblePlaybookExecute("first.yml"). 20 | WithPlaybookOptions(ansiblePlaybookOptions) 21 | 22 | second := playbook.NewAnsiblePlaybookExecute("second.yml"). 23 | WithPlaybookOptions(ansiblePlaybookOptions) 24 | 25 | err := workflow.NewWorkflowExecute(first, second).Execute(context.TODO()) 26 | if err != nil { 27 | fmt.Println(err.Error()) 28 | os.Exit(1) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/.env: -------------------------------------------------------------------------------- 1 | GOLANG_VERSION=1.23 -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/Makefile: -------------------------------------------------------------------------------- 1 | 2 | DOCKER_COMPOSE_BINARY := $(shell docker compose version > /dev/null 2>&1 && echo "docker compose" || (which docker-compose > /dev/null 2>&1 && echo "docker-compose" || (echo "docker compose not found. Aborting." >&2; exit 1))) 3 | 4 | PROJECT_NAME := go-ansible-$(shell basename ${PWD}) 5 | 6 | # dafault target 7 | .DEFAULT_GOAL: help 8 | 9 | help: ## Lists available targets 10 | @echo 11 | @echo "Makefile usage:" 12 | @grep -E '^[a-zA-Z1-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[1;32m%-20s\033[0m %s\n", $$1, $$2}' 13 | @echo 14 | 15 | build: ## Build the Docker compose environment 16 | @$(DOCKER_COMPOSE_BINARY) build 17 | 18 | up: ## Create and start containers 19 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) up --detach --build 20 | 21 | down: ## Stop and remove containers, networks, and volumes 22 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) down --volumes --remove-orphans --timeout 3 23 | 24 | restart: down up ## Restart the containers 25 | 26 | ps: ## List containers 27 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) ps 28 | 29 | logs: ## Show all logs 30 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) logs 31 | 32 | attach-ansible: ## Attach to the ansible container 33 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) exec --workdir /code/examples/$$(basename $$(pwd)) ansible /bin/sh 34 | 35 | project-name: ## Show the project name 36 | @echo $(PROJECT_NAME) 37 | 38 | run: ## Run the playbook 39 | @$(DOCKER_COMPOSE_BINARY) --project-name $(PROJECT_NAME) run --build --rm --workdir /code/examples/$$(basename $$(pwd)) ansible go run $$(basename $$(pwd)).go 40 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | ansible: 5 | build: 6 | context: docker/ansible 7 | args: 8 | - golang_version=${GOLANG_VERSION} 9 | command: ["tail", "-f", "/dev/null"] 10 | # command: ["ansible-playbook", "--help"] 11 | volumes: 12 | - ../..:/code 13 | working_dir: /code 14 | ## Set the init flag to true lets the process 1 to reap all the zombie processes 15 | init: true 16 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/docker/ansible/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG golang_version=1.23 2 | 3 | FROM golang:${golang_version}-bookworm AS golang 4 | 5 | FROM python:3.12-alpine3.19 6 | 7 | RUN apk add --update --no-cache \ 8 | openssh-client \ 9 | git \ 10 | && rm -rf /var/cache/apk/* 11 | 12 | RUN pip3 install -U pip setuptools \ 13 | && pip3 install --no-cache-dir \ 14 | setuptools-rust \ 15 | cryptography \ 16 | # Required library to execute ansible community.general.dig plugin 17 | dnspython \ 18 | ansible \ 19 | && ln /usr/local/bin/ansible-playbook /usr/bin/ansible-playbook 20 | 21 | COPY --from=golang /usr/local/go /usr/local/go 22 | 23 | # Configure Go 24 | ENV GOROOT /usr/local/go 25 | ENV PATH /usr/local/go/bin:/go/bin:$PATH 26 | 27 | RUN mkdir -p ${GOPATH}/src ${GOPATH}/bin 28 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/first.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: Workflow Execute first playbook 7 | debug: 8 | msg: Your are running 'workflowexecute-simple' example 9 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/second.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | 5 | tasks: 6 | - name: Workflow Execute second playbook 7 | debug: 8 | msg: Your are running 'workflowexecute-simple' example 9 | -------------------------------------------------------------------------------- /examples/workflowexecute-time-measurament/workflowexecute-time-measurament.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/apenella/go-ansible/v2/pkg/execute/measure" 9 | "github.com/apenella/go-ansible/v2/pkg/execute/workflow" 10 | "github.com/apenella/go-ansible/v2/pkg/playbook" 11 | ) 12 | 13 | func main() { 14 | 15 | ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{ 16 | Connection: "local", 17 | Inventory: "127.0.0.1,", 18 | } 19 | 20 | first := playbook.NewAnsiblePlaybookExecute("first.yml"). 21 | WithPlaybookOptions(ansiblePlaybookOptions) 22 | 23 | second := playbook.NewAnsiblePlaybookExecute("second.yml"). 24 | WithPlaybookOptions(ansiblePlaybookOptions) 25 | 26 | exec := measure.NewExecutorTimeMeasurement( 27 | workflow.NewWorkflowExecute(first, second), 28 | ) 29 | err := exec.Execute(context.TODO()) 30 | if err != nil { 31 | fmt.Println(err.Error()) 32 | os.Exit(1) 33 | } 34 | 35 | fmt.Println("Duration: ", exec.Duration().String()) 36 | } 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/apenella/go-ansible/v2 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/PuerkitoBio/goquery v1.9.1 7 | github.com/apenella/go-common-utils/data v0.0.0-20220913191136-86daaa87e7df 8 | github.com/apenella/go-common-utils/error v0.0.0-20220913191136-86daaa87e7df 9 | github.com/fatih/color v1.16.0 10 | github.com/go-errors/errors v1.5.1 11 | github.com/iancoleman/strcase v0.3.0 12 | github.com/pkg/errors v0.9.1 13 | github.com/sosedoff/ansible-vault-go v0.2.0 14 | github.com/spf13/afero v1.11.0 15 | github.com/spf13/cobra v1.8.0 16 | github.com/stretchr/testify v1.9.0 17 | ) 18 | 19 | require ( 20 | github.com/andybalholm/cascadia v1.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 23 | github.com/mattn/go-colorable v0.1.13 // indirect 24 | github.com/mattn/go-isatty v0.0.20 // indirect 25 | github.com/pmezard/go-difflib v1.0.0 // indirect 26 | github.com/spf13/pflag v1.0.5 // indirect 27 | github.com/stretchr/objx v0.5.2 // indirect 28 | golang.org/x/crypto v0.36.0 // indirect 29 | golang.org/x/net v0.38.0 // indirect 30 | golang.org/x/sys v0.31.0 // indirect 31 | golang.org/x/text v0.23.0 // indirect 32 | gopkg.in/yaml.v2 v2.4.0 // indirect 33 | gopkg.in/yaml.v3 v3.0.1 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /mocks/mockAnsibleCmd.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | type MockAnsibleCmd struct { 4 | cmd []string 5 | err error 6 | } 7 | 8 | func NewMockAnsibleCmd(cmd []string, err error) *MockAnsibleCmd { 9 | return &MockAnsibleCmd{ 10 | cmd: cmd, 11 | } 12 | } 13 | 14 | func (c *MockAnsibleCmd) Command() ([]string, error) { 15 | return c.cmd, c.err 16 | } 17 | 18 | func (c *MockAnsibleCmd) String() string { 19 | return "" 20 | } 21 | -------------------------------------------------------------------------------- /mocks/mockExitCodeErr.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | type MockExitCodeErr struct { 4 | error //nolint:golint,unused 5 | Code int 6 | Message string 7 | } 8 | 9 | func (e *MockExitCodeErr) Error() string { 10 | return e.Message 11 | } 12 | 13 | func (e *MockExitCodeErr) ExitCode() int { 14 | return e.Code 15 | } 16 | -------------------------------------------------------------------------------- /mocks/mockIOReader.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | import ( 4 | "github.com/stretchr/testify/mock" 5 | ) 6 | 7 | type MockIOReader struct { 8 | mock.Mock 9 | } 10 | 11 | func NewMockIOReader() *MockIOReader { 12 | return &MockIOReader{} 13 | } 14 | 15 | func (m *MockIOReader) Read(p []byte) (n int, err error) { 16 | args := m.Called(p) 17 | return args.Get(0).(int), args.Get(1).(error) 18 | } 19 | -------------------------------------------------------------------------------- /mocks/mockIOWriter.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | import ( 4 | "github.com/stretchr/testify/mock" 5 | ) 6 | 7 | type MockIOWriter struct { 8 | mock.Mock 9 | } 10 | 11 | func NewMockIOWriter() *MockIOWriter { 12 | return &MockIOWriter{} 13 | } 14 | 15 | func (m *MockIOWriter) Write(p []byte) (n int, err error) { 16 | args := m.Called(p) 17 | return args.Get(0).(int), args.Get(1).(error) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/adhoc/ansibleAdhocExecute.go: -------------------------------------------------------------------------------- 1 | package adhoc 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute" 7 | ) 8 | 9 | // AnsibleAdhocExecute is an executor for ansible command that runs the command using a DefaultExecute with default options 10 | type AnsibleAdhocExecute struct { 11 | cmd *AnsibleAdhocCmd 12 | } 13 | 14 | // NewAnsibleAdhocExecute returns a new AnsibleAdhocExecute. It receives host pattern to be executed 15 | func NewAnsibleAdhocExecute(pattern string) *AnsibleAdhocExecute { 16 | 17 | ansiblePlaybookCmd := &AnsibleAdhocCmd{ 18 | Pattern: pattern, 19 | } 20 | 21 | exec := &AnsibleAdhocExecute{ 22 | cmd: ansiblePlaybookCmd, 23 | } 24 | 25 | return exec 26 | } 27 | 28 | // WithBinary return a AnsibleAdhocExecute with the binary file set 29 | func (e *AnsibleAdhocExecute) WithBinary(binary string) *AnsibleAdhocExecute { 30 | e.cmd.Binary = binary 31 | 32 | return e 33 | } 34 | 35 | // WithAdhocOptions returns an AnsibleAdhocExecute with the ansible's playbook options set 36 | func (e *AnsibleAdhocExecute) WithAdhocOptions(options *AnsibleAdhocOptions) *AnsibleAdhocExecute { 37 | e.cmd.AdhocOptions = options 38 | 39 | return e 40 | } 41 | 42 | // Execute method runs the ansible command using a DefaultExecute with default options 43 | func (e *AnsibleAdhocExecute) Execute(ctx context.Context) error { 44 | 45 | exec := execute.NewDefaultExecute( 46 | execute.WithCmd(e.cmd), 47 | ) 48 | 49 | err := exec.Execute(ctx) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/execute/configuration/interface.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import "github.com/apenella/go-ansible/v2/pkg/execute" 4 | 5 | type ExecutorEnvVarSetter interface { 6 | execute.Executor 7 | AddEnvVar(key, value string) 8 | } 9 | -------------------------------------------------------------------------------- /pkg/execute/exec/cmd.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import ( 4 | "io" 5 | "os/exec" 6 | ) 7 | 8 | // Cmd struct is a wrapper of exec.Cmd 9 | type Cmd struct { 10 | cmd *exec.Cmd 11 | } 12 | 13 | // NewCmd return a wa 14 | func NewCmd(cmd *exec.Cmd) *Cmd { 15 | return &Cmd{cmd} 16 | } 17 | 18 | // CombinedOutput is a wrapper of exec.Cmd CombinedOutput method 19 | func (c *Cmd) CombinedOutput() ([]byte, error) { 20 | return c.cmd.CombinedOutput() 21 | } 22 | 23 | // Environ is a wrapper of exec.Cmd Environ method 24 | func (c *Cmd) Environ() []string { 25 | return c.cmd.Environ() 26 | } 27 | 28 | // Output is a wrapper of exec.Cmd Output method 29 | func (c *Cmd) Output() ([]byte, error) { 30 | return c.cmd.Output() 31 | } 32 | 33 | // Run is a wrapper of exec.Cmd Run method 34 | func (c *Cmd) Run() error { 35 | return c.cmd.Run() 36 | } 37 | 38 | // Start is a wrapper of exec.Cmd Start method 39 | func (c *Cmd) Start() error { 40 | return c.cmd.Start() 41 | } 42 | 43 | // StderrPipe is a wrapper of exec.Cmd StderrPipe method 44 | func (c *Cmd) StderrPipe() (io.ReadCloser, error) { 45 | return c.cmd.StderrPipe() 46 | } 47 | 48 | // StdinPipe is a wrapper of exec.Cmd StdinPipe method 49 | func (c *Cmd) StdinPipe() (io.WriteCloser, error) { 50 | return c.cmd.StdinPipe() 51 | } 52 | 53 | // StdoutPipe is a wrapper of exec.Cmd StdoutPipe method 54 | func (c *Cmd) StdoutPipe() (io.ReadCloser, error) { 55 | return c.cmd.StdoutPipe() 56 | } 57 | 58 | // String is a wrapper of exec.Cmd String method 59 | func (c *Cmd) String() string { 60 | return c.cmd.String() 61 | } 62 | 63 | // Wait is a wrapper of exec.Cmd Wait method 64 | func (c *Cmd) Wait() error { 65 | return c.cmd.Wait() 66 | } 67 | -------------------------------------------------------------------------------- /pkg/execute/exec/exec.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import ( 4 | "context" 5 | "os/exec" 6 | ) 7 | 8 | // OsExec struct wrapps the OS Exec package 9 | type OsExec struct{} 10 | 11 | func NewOsExec() *OsExec { 12 | return &OsExec{} 13 | } 14 | 15 | // Command is a wrapper of exec.Command 16 | func (e *OsExec) Command(name string, arg ...string) Cmder { 17 | return exec.Command(name, arg...) 18 | } 19 | 20 | // CommandContext is a wrapper of exec.CommandContext 21 | func (e *OsExec) CommandContext(ctx context.Context, name string, arg ...string) Cmder { 22 | return exec.CommandContext(ctx, name, arg...) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/execute/exec/interface.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import "io" 4 | 5 | // Cmder is an interface to run a command 6 | type Cmder interface { 7 | CombinedOutput() ([]byte, error) 8 | Environ() []string 9 | Output() ([]byte, error) 10 | Run() error 11 | Start() error 12 | StderrPipe() (io.ReadCloser, error) 13 | StdinPipe() (io.WriteCloser, error) 14 | StdoutPipe() (io.ReadCloser, error) 15 | String() string 16 | Wait() error 17 | } 18 | -------------------------------------------------------------------------------- /pkg/execute/exec/mockExec.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/stretchr/testify/mock" 7 | ) 8 | 9 | // MockExec struct is wrapper of os.Exec that enable you to mock os.Cmd 10 | type MockExec struct { 11 | mock.Mock 12 | } 13 | 14 | // NewMockExec returns a MockExec to mock to Cmd 15 | func NewMockExec() *MockExec { 16 | return &MockExec{} 17 | } 18 | 19 | // Command is a wrapper of exec.Command 20 | func (e *MockExec) Command(name string, arg ...string) Cmder { 21 | ret := e.Mock.Called(name, append([]string{}, arg...)) 22 | return ret.Get(0).(*MockCmd) 23 | } 24 | 25 | // CommandContext is a wrapper of exec.CommandContext 26 | func (e *MockExec) CommandContext(ctx context.Context, name string, arg ...string) Cmder { 27 | ret := e.Mock.Called(ctx, name, append([]string{}, arg...)) 28 | return ret.Get(0).(*MockCmd) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/execute/interface.go: -------------------------------------------------------------------------------- 1 | package execute 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute/exec" 7 | ) 8 | 9 | // Executor interface to execute commands 10 | type Executor interface { 11 | Execute(ctx context.Context) error 12 | } 13 | 14 | // Executabler is an interface to run commands 15 | type Executabler interface { 16 | Command(name string, arg ...string) exec.Cmder 17 | CommandContext(ctx context.Context, name string, arg ...string) exec.Cmder 18 | } 19 | 20 | // Commander generates commands to be executed 21 | type Commander interface { 22 | Command() ([]string, error) 23 | String() string 24 | } 25 | 26 | // ErrorEnricher interface to enrich and customize errors 27 | type ErrorEnricher interface { 28 | Enrich(err error) error 29 | } 30 | -------------------------------------------------------------------------------- /pkg/execute/mockExecute.go: -------------------------------------------------------------------------------- 1 | package execute 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/apenella/go-ansible/v2/pkg/execute/result" 7 | "github.com/stretchr/testify/mock" 8 | ) 9 | 10 | // MockExecute is a mock of Execute interface 11 | type MockExecute struct { 12 | mock.Mock 13 | } 14 | 15 | // NewMockExecute returns a new instance of MockExecute 16 | func NewMockExecute() *MockExecute { 17 | return &MockExecute{} 18 | } 19 | 20 | // Quiet is a mock 21 | func (e *MockExecute) Quiet() { 22 | e.Called() 23 | } 24 | 25 | // Execute is a mock 26 | func (e *MockExecute) Execute(ctx context.Context) error { 27 | args := e.Called(ctx) 28 | return args.Error(0) 29 | } 30 | 31 | // AddEnvVar is a mock 32 | func (e *MockExecute) AddEnvVar(key, value string) { 33 | e.Called(key, value) 34 | } 35 | 36 | // WithOutput is a mock 37 | func (e *MockExecute) WithOutput(output result.ResultsOutputer) { 38 | e.Called(output) 39 | } 40 | -------------------------------------------------------------------------------- /pkg/execute/result/interface.go: -------------------------------------------------------------------------------- 1 | package result 2 | 3 | import ( 4 | "context" 5 | "io" 6 | ) 7 | 8 | // OptionsFunc is a function that can be used to configure a ResultsOutputer struct 9 | type OptionsFunc func(ResultsOutputer) 10 | 11 | // ResultsOutputer is the interface that must implements an struct to print the execution results 12 | type ResultsOutputer interface { 13 | Print(ctx context.Context, reader io.Reader, writer io.Writer, options ...OptionsFunc) error 14 | } 15 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/debug.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // DebugStdoutCallback formatted stdout/stderr output 13 | DebugStdoutCallback = "debug" 14 | ) 15 | 16 | // DebugStdoutCallbackExecute defines an executor to run an ansible command with a debug stdout callback 17 | type DebugStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewDebugStdoutCallbackExecute creates a DebugStdoutCallbackExecute 22 | func NewDebugStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *DebugStdoutCallbackExecute { 23 | return &DebugStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the DebugStdoutCallbackExecute 27 | func (e *DebugStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *DebugStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *DebugStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("DebugStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(DebugStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/default.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // DefaultStdoutCallback default ansible screen output 13 | DefaultStdoutCallback = "default" 14 | ) 15 | 16 | // DefaultStdoutCallbackExecute defines an executor to run an ansible command with a default stdout callback 17 | type DefaultStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewDefaultStdoutCallbackExecute creates a DefaultStdoutCallbackExecute 22 | func NewDefaultStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *DefaultStdoutCallbackExecute { 23 | return &DefaultStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the DefaultStdoutCallbackExecute 27 | func (e *DefaultStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *DefaultStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *DefaultStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("DefaultStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(DefaultStdoutCallback), 43 | ).Execute(ctx) 44 | 45 | } 46 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/dense.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // DenseStdoutCallback dense stdout output 13 | DenseStdoutCallback = "dense" 14 | ) 15 | 16 | // DenseStdoutCallbackExecute defines an executor to run an ansible command with a dense stdout callback 17 | type DenseStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewDenseStdoutCallbackExecute creates a DenseStdoutCallbackExecute 22 | func NewDenseStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *DenseStdoutCallbackExecute { 23 | return &DenseStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the DenseStdoutCallbackExecute 27 | func (e *DenseStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *DenseStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *DenseStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("DenseStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(DenseStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/interface.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "github.com/apenella/go-ansible/v2/pkg/execute" 5 | "github.com/apenella/go-ansible/v2/pkg/execute/result" 6 | ) 7 | 8 | // ExecutorStdoutCallbackSetter extends the executor interface by adding methods to configure the Stdout Callback configuration 9 | type ExecutorStdoutCallbackSetter interface { 10 | execute.Executor 11 | AddEnvVar(key, value string) 12 | WithOutput(output result.ResultsOutputer) 13 | } 14 | 15 | // ExecutorQuietStdoutCallbackSetter extends the ExecutorStdoutCallbackSetter interface by adding a method to force the non-verbose mode in the Stdout Callback configuration 16 | type ExecutorQuietStdoutCallbackSetter interface { 17 | ExecutorStdoutCallbackSetter 18 | Quiet() 19 | } 20 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/json.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | jsonresults "github.com/apenella/go-ansible/v2/pkg/execute/result/json" 9 | ) 10 | 11 | const ( 12 | // JSONStdoutCallback ansible screen output as json 13 | JSONStdoutCallback = "json" 14 | ) 15 | 16 | // JSONStdoutCallbackExecute defines an executor to run an ansible command with a json stdout callback 17 | type JSONStdoutCallbackExecute struct { 18 | executor ExecutorQuietStdoutCallbackSetter 19 | } 20 | 21 | // NewJSONStdoutCallbackExecute creates a JSONStdoutCallbackExecute 22 | func NewJSONStdoutCallbackExecute(executor ExecutorQuietStdoutCallbackSetter) *JSONStdoutCallbackExecute { 23 | return &JSONStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the JSONStdoutCallbackExecute 27 | func (e *JSONStdoutCallbackExecute) WithExecutor(exec ExecutorQuietStdoutCallbackSetter) *JSONStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *JSONStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("JSONStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.Quiet() 40 | e.executor.WithOutput(jsonresults.NewJSONStdoutCallbackResults()) 41 | 42 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 43 | configuration.WithAnsibleStdoutCallback(JSONStdoutCallback), 44 | ).Execute(ctx) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/minimal.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // MinimalStdoutCallback minmal ansible screen output 13 | MinimalStdoutCallback = "minimal" 14 | ) 15 | 16 | // MinimalStdoutCallbackExecute defines an executor to run an ansible command with a minimal stdout callback 17 | type MinimalStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewMinimalStdoutCallbackExecute creates a MinimalStdoutCallbackExecute 22 | func NewMinimalStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *MinimalStdoutCallbackExecute { 23 | return &MinimalStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the MinimalStdoutCallbackExecute 27 | func (e *MinimalStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *MinimalStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *MinimalStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("MinimalStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(MinimalStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/null.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // NullStdoutCallback don't display stuff to screen 13 | NullStdoutCallback = "null" 14 | ) 15 | 16 | // NullStdoutCallbackExecute defines an executor to run an ansible command with a null stdout callback 17 | type NullStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewNullStdoutCallbackExecute creates a NullStdoutCallbackExecute 22 | func NewNullStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *NullStdoutCallbackExecute { 23 | return &NullStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the NullStdoutCallbackExecute 27 | func (e *NullStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *NullStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *NullStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("NullStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(NullStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/oneline.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // OnelineStdoutCallback oneline ansible screen output 13 | OnelineStdoutCallback = "oneline" 14 | ) 15 | 16 | // OnelineStdoutCallbackExecute defines an executor to run an ansible command with a oneline stdout callback 17 | type OnelineStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewOnelineStdoutCallbackExecute creates a OnelineStdoutCallbackExecute 22 | func NewOnelineStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *OnelineStdoutCallbackExecute { 23 | return &OnelineStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the OnelineStdoutCallbackExecute 27 | func (e *OnelineStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *OnelineStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *OnelineStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("OnelineStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(OnelineStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/stderr.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // StderrStdoutCallback splits output, sending failed tasks to stderr 13 | StderrStdoutCallback = "stderr" 14 | ) 15 | 16 | // StderrStdoutCallbackExecute defines an executor to run an ansible command with a stderr stdout callback 17 | type StderrStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewStderrStdoutCallbackExecute creates a StderrStdoutCallbackExecute 22 | func NewStderrStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *StderrStdoutCallbackExecute { 23 | return &StderrStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the StderrStdoutCallbackExecute 27 | func (e *StderrStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *StderrStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *StderrStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("StderrStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(StderrStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/timer.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // TimerStdoutCallback adds time to play stats 13 | TimerStdoutCallback = "timer" 14 | ) 15 | 16 | // TimerStdoutCallbackExecute defines an executor to run an ansible command with a timer stdout callback 17 | type TimerStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewTimerStdoutCallbackExecute creates a TimerStdoutCallbackExecute 22 | func NewTimerStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *TimerStdoutCallbackExecute { 23 | return &TimerStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the TimerStdoutCallbackExecute 27 | func (e *TimerStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *TimerStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *TimerStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("TimerStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(TimerStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/execute/stdoutcallback/yaml.go: -------------------------------------------------------------------------------- 1 | package stdoutcallback 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/execute/configuration" 8 | defaultresult "github.com/apenella/go-ansible/v2/pkg/execute/result/default" 9 | ) 10 | 11 | const ( 12 | // YAMLStdoutCallback yamlized ansible screen output 13 | YAMLStdoutCallback = "yaml" 14 | ) 15 | 16 | // YAMLStdoutCallbackExecute defines an executor to run an ansible command with a yaml stdout callback 17 | type YAMLStdoutCallbackExecute struct { 18 | executor ExecutorStdoutCallbackSetter 19 | } 20 | 21 | // NewYAMLStdoutCallbackExecute creates a YAMLStdoutCallbackExecute 22 | func NewYAMLStdoutCallbackExecute(executor ExecutorStdoutCallbackSetter) *YAMLStdoutCallbackExecute { 23 | return &YAMLStdoutCallbackExecute{executor: executor} 24 | } 25 | 26 | // WithExecutor sets the executor for the YAMLStdoutCallbackExecute 27 | func (e *YAMLStdoutCallbackExecute) WithExecutor(exec ExecutorStdoutCallbackSetter) *YAMLStdoutCallbackExecute { 28 | e.executor = exec 29 | return e 30 | } 31 | 32 | // Execute takes a command and args and runs it, streaming output to stdout 33 | func (e *YAMLStdoutCallbackExecute) Execute(ctx context.Context) error { 34 | 35 | if e.executor == nil { 36 | return fmt.Errorf("YAMLStdoutCallbackExecute executor requires an executor") 37 | } 38 | 39 | e.executor.WithOutput(defaultresult.NewDefaultResults()) 40 | 41 | return configuration.NewAnsibleWithConfigurationSettingsExecute(e.executor, 42 | configuration.WithAnsibleStdoutCallback(YAMLStdoutCallback), 43 | ).Execute(ctx) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/galaxy/collection/collection.go: -------------------------------------------------------------------------------- 1 | package galaxycollection 2 | 3 | // AnsibleGalaxyCollectionSubCommand is the ansible-galaxy collection subcommand 4 | const AnsibleGalaxyCollectionSubCommand = "collection" 5 | -------------------------------------------------------------------------------- /pkg/galaxy/galaxy.go: -------------------------------------------------------------------------------- 1 | package galaxy 2 | 3 | // DefaultAnsibleGalaxyBinary is the ansible-galaxy binary file default value 4 | const DefaultAnsibleGalaxyBinary = "ansible-galaxy" 5 | -------------------------------------------------------------------------------- /pkg/galaxy/role/role.go: -------------------------------------------------------------------------------- 1 | package galaxyrole 2 | 3 | // AnsibleGalaxyRoleSubCommand is the ansible-galaxy role subcommand 4 | const AnsibleGalaxyRoleSubCommand = "role" 5 | -------------------------------------------------------------------------------- /pkg/playbook/interface.go: -------------------------------------------------------------------------------- 1 | package playbook 2 | 3 | import "github.com/apenella/go-ansible/v2/pkg/vault" 4 | 5 | type Vaulter interface { 6 | Vault(value string) (*vault.VaultVariableValue, error) 7 | } 8 | 9 | type ExitCodeErrorer interface { 10 | ExitCode() int 11 | } 12 | -------------------------------------------------------------------------------- /pkg/playbook/test/all: -------------------------------------------------------------------------------- 1 | [local] 2 | 127.0.0.1 3 | -------------------------------------------------------------------------------- /pkg/playbook/test/test_site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: local 4 | gather_facts: false 5 | 6 | tasks: 7 | - name: Print test message 8 | ansible.builtin.debug: 9 | msg: That's a message to test 10 | -------------------------------------------------------------------------------- /pkg/vault/encrypt/encryptString.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | vault "github.com/sosedoff/ansible-vault-go" 6 | ) 7 | 8 | // OptionsFunc is a function used to configure EncryptString 9 | type OptionsFunc func(*EncryptString) 10 | 11 | type EncryptString struct { 12 | reader PasswordReader 13 | } 14 | 15 | func NewEncryptString(options ...OptionsFunc) *EncryptString { 16 | EncryptString := &EncryptString{} 17 | EncryptString.Options(options...) 18 | 19 | return EncryptString 20 | } 21 | 22 | func WithReader(reader PasswordReader) OptionsFunc { 23 | return func(c *EncryptString) { 24 | c.reader = reader 25 | } 26 | } 27 | 28 | // Options configure the ReadSecretFromEnvVar 29 | func (c *EncryptString) Options(opts ...OptionsFunc) { 30 | for _, opt := range opts { 31 | opt(c) 32 | } 33 | } 34 | 35 | func (c *EncryptString) Encrypt(plainText string) (string, error) { 36 | var pass, encryptedText string 37 | var err error 38 | 39 | pass, err = c.reader.Read() 40 | if err != nil { 41 | return "", errors.Wrap(err, "Error reading the password") 42 | } 43 | 44 | encryptedText, err = vault.Encrypt(plainText, pass) 45 | if err != nil { 46 | return "", errors.Wrap(err, "Error encrypting the password") 47 | } 48 | 49 | return encryptedText, nil 50 | } 51 | -------------------------------------------------------------------------------- /pkg/vault/encrypt/encryptString_test.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "regexp" 5 | "testing" 6 | 7 | "github.com/apenella/go-ansible/v2/pkg/vault/password/text" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestEncrypt(t *testing.T) { 12 | tests := []struct { 13 | desc string 14 | text string 15 | encrypt *EncryptString 16 | expectedRegexp string 17 | expectedLen uint 18 | err error 19 | }{ 20 | { 21 | desc: "Testing encrypting a message", 22 | text: "ThatIsASecretMessage", 23 | encrypt: NewEncryptString( 24 | WithReader( 25 | text.NewReadPasswordFromText( 26 | text.WithText("secret"), 27 | ), 28 | ), 29 | ), 30 | expectedRegexp: "\\$ANSIBLE_VAULT;1.1;AES256", 31 | expectedLen: 418, 32 | }, 33 | } 34 | 35 | for _, test := range tests { 36 | t.Run(test.desc, func(t *testing.T) { 37 | res, err := test.encrypt.Encrypt(test.text) 38 | if err != nil { 39 | assert.EqualError(t, err, test.err.Error()) 40 | } else { 41 | assert.Regexp(t, regexp.MustCompile(test.expectedRegexp), res) 42 | assert.Len(t, res, int(test.expectedLen)) 43 | } 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pkg/vault/encrypt/instance.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | type PasswordReader interface { 4 | Read() (string, error) 5 | } 6 | -------------------------------------------------------------------------------- /pkg/vault/encrypt/mocEncryptStringk.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | type MockEncryptString struct { 6 | mock.Mock 7 | } 8 | 9 | func NewMockEncryptString() *MockEncryptString { 10 | return &MockEncryptString{} 11 | } 12 | 13 | func (e *MockEncryptString) Encrypt(plainText string) (string, error) { 14 | args := e.Called(plainText) 15 | 16 | return args.String(0), args.Error(1) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/vault/interface.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | type Encrypter interface { 4 | Encrypt(plainText string) (string, error) 5 | } 6 | -------------------------------------------------------------------------------- /pkg/vault/mockVariableVaulter.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | // MockVariableVaulter is a mock for VariableVaulter 6 | type MockVariableVaulter struct { 7 | mock.Mock 8 | } 9 | 10 | // NewMockVariableVaulter returns a new MockVariableVaulter 11 | func NewMockVariableVaulter() *MockVariableVaulter { 12 | return &MockVariableVaulter{} 13 | } 14 | 15 | func (v *MockVariableVaulter) Vault(value string) (*VaultVariableValue, error) { 16 | args := v.Called(value) 17 | return args.Get(0).(*VaultVariableValue), args.Error(1) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/vault/password/envvars/readPasswordFromEnvVar.go: -------------------------------------------------------------------------------- 1 | package envvars 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/pkg/errors" 8 | ) 9 | 10 | // OptionsFunc is a function used to configure ReadPasswordFromEnvVar 11 | type OptionsFunc func(*ReadPasswordFromEnvVar) 12 | 13 | // ReadPasswordFromEnvVar returns a password set in an environment variable 14 | type ReadPasswordFromEnvVar struct { 15 | envvar string 16 | } 17 | 18 | // NewReadPasswordFromEnvVar returns a ReadPasswordFromEnvVar 19 | func NewReadPasswordFromEnvVar(options ...OptionsFunc) *ReadPasswordFromEnvVar { 20 | secret := &ReadPasswordFromEnvVar{} 21 | secret.Options(options...) 22 | 23 | return secret 24 | } 25 | 26 | // WithEnvVar set the environment variable that contains the password defined on it 27 | func WithEnvVar(envvar string) OptionsFunc { 28 | return func(s *ReadPasswordFromEnvVar) { 29 | s.envvar = envvar 30 | } 31 | } 32 | 33 | // Options configure the ReadPasswordFromEnvVar 34 | func (s *ReadPasswordFromEnvVar) Options(opts ...OptionsFunc) { 35 | for _, opt := range opts { 36 | opt(s) 37 | } 38 | } 39 | 40 | // Read returns the password that is set in the environment variable defined on the envvar attribute 41 | func (s *ReadPasswordFromEnvVar) Read() (string, error) { 42 | if s == nil { 43 | return "", errors.New("Read password from an environment variable component has not been initialized.") 44 | } 45 | 46 | secret := os.Getenv(s.envvar) 47 | if len(secret) <= 0 { 48 | log.Printf("The environment variable '%s' is not set.", s.envvar) 49 | } 50 | 51 | return secret, nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/vault/password/envvars/readPasswordFromEnvVar_test.go: -------------------------------------------------------------------------------- 1 | package envvars 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/pkg/errors" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestRead(t *testing.T) { 11 | 12 | t.Setenv("VAULT_PASSWORD", "ThatIsAPassword") 13 | 14 | tests := []struct { 15 | desc string 16 | reader *ReadPasswordFromEnvVar 17 | expected string 18 | err error 19 | }{ 20 | { 21 | desc: "Testing reading a secret from an environment variable", 22 | reader: NewReadPasswordFromEnvVar( 23 | WithEnvVar("VAULT_PASSWORD"), 24 | ), 25 | expected: "ThatIsAPassword", 26 | err: nil, 27 | }, 28 | { 29 | desc: "Testing error reading a secret from environment variable when ReadPasswordFromEnvVar is not initialized", 30 | reader: nil, 31 | err: errors.New("Read password from an environment variable component has not been initialized."), 32 | }, 33 | { 34 | desc: "Testing error reading a secret from an environment variable when it is not set", 35 | reader: NewReadPasswordFromEnvVar( 36 | WithEnvVar("UNSET_VARIALBE"), 37 | ), 38 | err: errors.New("The environment variable 'UNSET_VARIALBE' is not set"), 39 | }, 40 | } 41 | 42 | for _, test := range tests { 43 | 44 | t.Run(test.desc, func(t *testing.T) { 45 | secret, err := test.reader.Read() 46 | if err != nil { 47 | assert.EqualError(t, err, test.err.Error()) 48 | } else { 49 | assert.Equal(t, test.expected, secret) 50 | } 51 | }) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/vault/password/mock/mock.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import ( 4 | "github.com/stretchr/testify/mock" 5 | ) 6 | 7 | // MockReadPassword mocks the PasswordReader 8 | type MockReadPassword struct { 9 | mock.Mock 10 | } 11 | 12 | // NewMockReadPassword return a MockReadPassword 13 | func NewMockReadPassword() *MockReadPassword { 14 | return &MockReadPassword{} 15 | } 16 | 17 | // Read returns a mocked password 18 | func (s *MockReadPassword) Read() (string, error) { 19 | args := s.Called() 20 | 21 | return args.String(0), args.Error(1) 22 | } 23 | -------------------------------------------------------------------------------- /pkg/vault/password/resolve/interface.go: -------------------------------------------------------------------------------- 1 | package resolve 2 | 3 | // PasswordReader defines the implementation of a password reader 4 | type PasswordReader interface { 5 | Read() (string, error) 6 | } 7 | -------------------------------------------------------------------------------- /pkg/vault/password/resolve/readPasswordResolve.go: -------------------------------------------------------------------------------- 1 | package resolve 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // OptionsFunc is a function used to configure ReadPasswordResolve 8 | type OptionsFunc func(*ReadPasswordResolve) 9 | 10 | // ReadPasswordResolve contains multiple methods that can resolve a password 11 | type ReadPasswordResolve struct { 12 | reader []PasswordReader 13 | } 14 | 15 | // NewReadPasswordResolve return a ReadPasswordResolve 16 | func NewReadPasswordResolve(options ...OptionsFunc) *ReadPasswordResolve { 17 | secret := &ReadPasswordResolve{} 18 | secret.Options(options...) 19 | 20 | return secret 21 | } 22 | 23 | // WithReader allow you to set a list of readers that you can use to resolve a password 24 | func WithReader(reader ...PasswordReader) OptionsFunc { 25 | return func(s *ReadPasswordResolve) { 26 | if s.reader == nil { 27 | s.reader = []PasswordReader{} 28 | } 29 | 30 | s.reader = append(s.reader, reader...) 31 | } 32 | } 33 | 34 | // Options configure the ReadPasswordResolve 35 | func (s *ReadPasswordResolve) Options(opts ...OptionsFunc) { 36 | for _, opt := range opts { 37 | opt(s) 38 | } 39 | } 40 | 41 | // Read looks for the first reader defined into the reader attribute which returns a password 42 | func (s *ReadPasswordResolve) Read() (string, error) { 43 | if s == nil { 44 | return "", errors.New("The component to resolve read password mechanism has not been initialized.") 45 | } 46 | 47 | for _, reader := range s.reader { 48 | secret, err := reader.Read() 49 | if err == nil { 50 | return secret, nil 51 | } 52 | } 53 | 54 | return "", errors.New("The component to resolve read password does not found a password.") 55 | } 56 | -------------------------------------------------------------------------------- /pkg/vault/password/text/readPasswordFromText.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // OptionsFunc is a function used to configure ReadPasswordFromText 8 | type OptionsFunc func(*ReadPasswordFromText) 9 | 10 | // ReadPasswordFromText allow to read a password as a plain text 11 | type ReadPasswordFromText struct { 12 | text string 13 | } 14 | 15 | // NewReadPasswordFromText generates a ReadPasswordFromText struct 16 | func NewReadPasswordFromText(options ...OptionsFunc) *ReadPasswordFromText { 17 | secret := &ReadPasswordFromText{} 18 | secret.Options(options...) 19 | 20 | return secret 21 | } 22 | 23 | // WithText set the text (password) into the ReadPasswordFromText 24 | func WithText(text string) OptionsFunc { 25 | return func(s *ReadPasswordFromText) { 26 | s.text = text 27 | } 28 | } 29 | 30 | // Options configure the ReadPasswordFromText 31 | func (s *ReadPasswordFromText) Options(opts ...OptionsFunc) { 32 | for _, opt := range opts { 33 | opt(s) 34 | } 35 | } 36 | 37 | // Read returns a password save the text attribute from the ReadPasswordFromText struct 38 | func (s *ReadPasswordFromText) Read() (string, error) { 39 | if s == nil { 40 | return "", errors.New("Password input from text has not been initialized.") 41 | } 42 | 43 | if len(s.text) <= 0 { 44 | return "", errors.New("Text must be specified to use the password input from text.") 45 | } 46 | 47 | return s.text, nil 48 | } 49 | -------------------------------------------------------------------------------- /pkg/vault/password/text/readPasswordFromText_test.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestRead(t *testing.T) { 11 | tests := []struct { 12 | desc string 13 | reader *ReadPasswordFromText 14 | expected string 15 | err error 16 | }{ 17 | { 18 | desc: "Testing reading a password from text", 19 | reader: NewReadPasswordFromText( 20 | WithText("ThatIsAPassword"), 21 | ), 22 | expected: "ThatIsAPassword", 23 | err: nil, 24 | }, 25 | { 26 | desc: "Testing error reading a password from text when text is an empty string", 27 | reader: NewReadPasswordFromText(), 28 | err: errors.New("Text must be specified to use the password input from text."), 29 | }, 30 | { 31 | desc: "Testing error reading a password from text when ReadPasswordFromText has not been initialized", 32 | reader: nil, 33 | err: errors.New("Password input from text has not been initialized."), 34 | }, 35 | } 36 | 37 | for _, test := range tests { 38 | t.Run(test.desc, func(t *testing.T) { 39 | t.Run(test.desc, func(t *testing.T) { 40 | secret, err := test.reader.Read() 41 | if err != nil { 42 | assert.EqualError(t, err, test.err.Error()) 43 | } else { 44 | assert.Equal(t, test.expected, secret) 45 | } 46 | }) 47 | }) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pkg/vault/variableVaulter.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | // OptionsFunc is a function used to configure ReadPasswordFromEnvVar 8 | type OptionsFunc func(*VariableVaulter) 9 | 10 | type VariableVaulter struct { 11 | encrypt Encrypter 12 | } 13 | 14 | func NewVariableVaulter(options ...OptionsFunc) *VariableVaulter { 15 | vault := &VariableVaulter{} 16 | vault.Options(options...) 17 | 18 | return vault 19 | } 20 | 21 | func WithEncrypt(e Encrypter) OptionsFunc { 22 | return func(v *VariableVaulter) { 23 | v.encrypt = e 24 | } 25 | } 26 | 27 | func (v *VariableVaulter) Options(opts ...OptionsFunc) { 28 | for _, opt := range opts { 29 | opt(v) 30 | } 31 | } 32 | 33 | func (v *VariableVaulter) Vault(value string) (*VaultVariableValue, error) { 34 | var err error 35 | var encryptedValue string 36 | 37 | if v == nil { 38 | return nil, errors.New("VariableVaulter must be initialized before vaulting a variable.") 39 | } 40 | 41 | if v.encrypt == nil { 42 | return nil, errors.New("Encrypter must be provided to encrypt a variable.") 43 | } 44 | 45 | encryptedValue, err = v.encrypt.Encrypt(value) 46 | if err != nil { 47 | return nil, errors.Wrap(err, "Error encrypting variable value.") 48 | } 49 | 50 | VariableVaulterValue := NewVaultVariableValue(encryptedValue) 51 | // encryptedValueJSON, err = VariableVaulterValue.ToJSON() 52 | // if err != nil { 53 | // return "", errors.Wrap(err, "Vault variable could not be converted to JSON.") 54 | // } 55 | 56 | return VariableVaulterValue, nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/vault/vaultVariableValue.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | import ( 4 | common "github.com/apenella/go-common-utils/data" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | type VaultVariableValue struct { 9 | Value interface{} `json:"__ansible_vault"` 10 | } 11 | 12 | func NewVaultVariableValue(value interface{}) *VaultVariableValue { 13 | return &VaultVariableValue{ 14 | Value: value, 15 | } 16 | } 17 | 18 | func (v *VaultVariableValue) ToJSON() (string, error) { 19 | 20 | // jsonValue, err := json.Marshal(v) 21 | jsonValue, err := common.ObjectToJSONString(v) 22 | if err != nil { 23 | return "", errors.Wrap(err, "Error converting the vault variable value to JSON.") 24 | } 25 | 26 | return string(jsonValue), nil 27 | } 28 | -------------------------------------------------------------------------------- /pkg/vault/vaultVariableValue_test.go: -------------------------------------------------------------------------------- 1 | package vault 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestToJSON(t *testing.T) { 10 | tests := []struct { 11 | desc string 12 | variable *VaultVariableValue 13 | expected string 14 | err error 15 | }{ 16 | { 17 | desc: "Testing converting vaulted variable value to JSON", 18 | variable: NewVaultVariableValue("encrypted_variable_value"), 19 | expected: "{\"__ansible_vault\":\"encrypted_variable_value\"}", 20 | err: nil, 21 | }, 22 | } 23 | 24 | for _, test := range tests { 25 | t.Run(test.desc, func(t *testing.T) { 26 | res, err := test.variable.ToJSON() 27 | if err != nil { 28 | assert.EqualError(t, err, test.err.Error()) 29 | } else { 30 | assert.Equal(t, test.expected, res) 31 | } 32 | }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/all: -------------------------------------------------------------------------------- 1 | [local] 2 | 127.0.0.1 3 | -------------------------------------------------------------------------------- /test/test_site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | gather_facts: false 5 | 6 | tasks: 7 | - name: Print test message 8 | ansible.builtin.debug: 9 | msg: That's a message to test 10 | --------------------------------------------------------------------------------