├── .devcontainer ├── Dockerfile ├── devcontainer.json └── docker-compose.yml ├── .editorconfig ├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── .releaserc ├── CHANGELOG.md ├── LICENSE ├── MAINTAINERS.md ├── Makefile ├── README.md ├── awx ├── convert_type.go ├── data_source_credential.go ├── data_source_credential_azure_key_vault.go ├── data_source_credential_type.go ├── data_source_credentials.go ├── data_source_execution_environment.go ├── data_source_inventory.go ├── data_source_inventory_group.go ├── data_source_inventory_role.go ├── data_source_job_template.go ├── data_source_notification_template.go ├── data_source_organization.go ├── data_source_organization_role.go ├── data_source_organizations.go ├── data_source_project.go ├── data_source_project_role.go ├── data_source_schedule.go ├── data_source_team.go ├── data_source_workflow_job_template.go ├── helpers.go ├── provider.go ├── resource_credential.go ├── resource_credential_azure_key_vault.go ├── resource_credential_galaxy.go ├── resource_credential_gitlab.go ├── resource_credential_google_compute_engine.go ├── resource_credential_input_source.go ├── resource_credential_machine.go ├── resource_credential_scm.go ├── resource_credential_type.go ├── resource_execution_environment.go ├── resource_host.go ├── resource_instance_group.go ├── resource_inventory.go ├── resource_inventory_group.go ├── resource_inventory_source.go ├── resource_job_template.go ├── resource_job_template_credential.go ├── resource_job_template_launch.go ├── resource_job_template_notification_template_error.go ├── resource_job_template_notification_template_shared.go ├── resource_job_template_notification_template_started.go ├── resource_job_template_notification_template_success.go ├── resource_notification_template.go ├── resource_organization.go ├── resource_organization_galaxy_credential.go ├── resource_organization_instance_group.go ├── resource_project.go ├── resource_schedule.go ├── resource_setting.go ├── resource_settings_ldap_team_map.go ├── resource_team.go ├── resource_user.go ├── resource_workflow_job_template.go ├── resource_workflow_job_template_launch.go ├── resource_workflow_job_template_node.go ├── resource_workflow_job_template_node_always.go ├── resource_workflow_job_template_node_failure.go ├── resource_workflow_job_template_node_shared.go ├── resource_workflow_job_template_node_success.go ├── resource_workflow_job_template_notification_template_error.go ├── resource_workflow_job_template_notification_template_shared.go ├── resource_workflow_job_template_notification_template_started.go ├── resource_workflow_job_template_notification_template_success.go └── resource_workflow_job_template_schedule.go ├── docs ├── data-sources │ ├── credential.md │ ├── credential_azure_key_vault.md │ ├── credential_type.md │ ├── credentials.md │ ├── inventory.md │ ├── inventory_group.md │ ├── inventory_role.md │ ├── job_template.md │ ├── notification_template.md │ ├── organization.md │ ├── project.md │ ├── project_role.md │ ├── schedule.md │ ├── team.md │ └── workflow_job_template.md ├── index.md └── resources │ ├── credential.md │ ├── credential_azure_key_vault.md │ ├── credential_google_compute_engine.md │ ├── credential_input_source.md │ ├── credential_machine.md │ ├── credential_scm.md │ ├── credential_type.md │ ├── host.md │ ├── inventory.md │ ├── inventory_group.md │ ├── inventory_source.md │ ├── job_template.md │ ├── job_template_credential.md │ ├── job_template_notification_template_error.md │ ├── job_template_notification_template_started.md │ ├── job_template_notification_template_success.md │ ├── notification_template.md │ ├── organization.md │ ├── project.md │ ├── schedule.md │ ├── settings_ldap_team_map.md │ ├── team.md │ ├── workflow_job_template.md │ ├── workflow_job_template_node.md │ ├── workflow_job_template_node_always.md │ ├── workflow_job_template_node_failure.md │ ├── workflow_job_template_node_success.md │ └── workflow_job_template_schedule.md ├── examples ├── awx │ └── main.tf └── k8s │ ├── base │ ├── files │ │ ├── id_rsa │ │ └── id_rsa.pub │ ├── main.tf │ ├── provider.tf │ └── versions.tf │ └── data │ ├── main.tf │ ├── provider.tf │ └── versions.tf ├── go.mod ├── go.sum ├── main.go ├── test └── terraform_minimal_acc_test.go └── tools ├── docs.go ├── go.mod ├── go.sum ├── installAwx.sh ├── mage.go ├── magefile.go └── template.go /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.pkg.github.com/nolte/vscode-devcontainers/k8s-operator:latest 2 | 3 | # https://github.com/bflad/tfproviderdocs/releases 4 | ENV TFPROVIDERDOCS_VERSION=0.7.0 5 | 6 | # https://github.com/bats-core/bats-core 7 | ENV BATS_VERSION=1.2.0 8 | 9 | USER root 10 | 11 | COPY --from=docker.pkg.github.com/nolte/vscode-devcontainers/devops:latest /usr/local/bin/swagger /usr/local/bin/swagger 12 | COPY --from=docker.pkg.github.com/nolte/vscode-devcontainers/devops:latest /usr/local/bin/terraform /usr/local/bin/terraform 13 | COPY --from=docker.pkg.github.com/nolte/vscode-devcontainers/devops:latest /usr/local/bin/terraform-doc /usr/local/bin/terraform-doc 14 | COPY --from=docker.pkg.github.com/nolte/vscode-devcontainers/devops:latest /usr/local/bin/shellcheck /usr/local/bin/shellcheck 15 | 16 | RUN curl -sSL -k https://github.com/bflad/tfproviderdocs/releases/download/v${TFPROVIDERDOCS_VERSION}/tfproviderdocs_${TFPROVIDERDOCS_VERSION}_linux_amd64.tar.gz -o /tmp/tfproviderdocs.tgz \ 17 | && tar -zxf /tmp/tfproviderdocs.tgz -C /tmp \ 18 | && mv /tmp/tfproviderdocs /usr/local/bin/ 19 | 20 | RUN apk add --update-cache \ 21 | nodejs npm \ 22 | && rm -rf /var/cache/apk/* 23 | 24 | RUN mkdir -p /go/src && chown -R ${USER_UID}:${USER_GID} /go/src \ 25 | && mkdir -p /go/pkg && chown -R ${USER_UID}:${USER_GID} /go/pkg 26 | 27 | RUN curl -sSL -k https://github.com/goreleaser/goreleaser/releases/download/v0.141.0/goreleaser_Linux_x86_64.tar.gz -o /tmp/goreleaser.tgz \ 28 | && tar -zxf /tmp/goreleaser.tgz -C /tmp \ 29 | && mv /tmp/goreleaser /usr/local/bin/ 30 | 31 | 32 | USER ${USERNAME} 33 | 34 | RUN mkdir -p /home/${USERNAME}/.terraform.d/plugins/linux_amd64 35 | 36 | ENV PATH="/usr/local/share/npm/bin:/usr/local/bin:/usr/local/sbin:~/bin:$PATH" 37 | 38 | RUN mkdir "/home/${USERNAME}/.npm-packages" 39 | RUN npm config set prefix "/home/${USERNAME}/.npm-packages" 40 | 41 | 42 | RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.27.0 43 | 44 | RUN curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.3.0 45 | 46 | RUN npm i markdown-spellcheck -g 47 | 48 | RUN curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash 49 | 50 | RUN npm i madr adr-log -g 51 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "terraform-provider-harbor", 3 | "dockerComposeFile": [ 4 | "docker-compose.yml" 5 | ], 6 | "service": "vscode", 7 | "runServices": [ 8 | "vscode", 9 | ], 10 | "mounts": [ 11 | "source=terraform-awx-vol,target=/home/vscode/.vscode-server/extensions,type=volume", 12 | // And/or for VS Code Insiders 13 | "source=terraform-awx-vol-insiders,target=/home/vscode/.vscode-server-insiders/extensions,type=volume", 14 | ], 15 | "shutdownAction": "stopCompose", 16 | "postCreateCommand": "chmod -R 700 .git", 17 | "workspaceFolder": "/go/src/github.com/denouche/terraform-provider-awx", 18 | // "overrideCommand": "", 19 | "extensions": [ 20 | // General backend 21 | "mohsen1.prettify-json", 22 | "redhat.vscode-yaml", // Kubernetes and Kedge syntax support 23 | // Go 24 | "ms-vscode.go", 25 | "hbenl.vscode-test-explorer", 26 | "ethan-reesor.vscode-go-test-adapter", 27 | // Console 28 | "IBM.output-colorizer", 29 | // Git 30 | "eamodio.gitlens", 31 | "mhutchie.git-graph", 32 | // Other linters 33 | "davidanson.vscode-markdownlint", 34 | "ms-azuretools.vscode-docker", 35 | // Other helpers 36 | "shardulm94.trailing-spaces", 37 | "Gruntfuggly.todo-tree", 38 | "bierner.emojisense", 39 | "stkb.rewrap", // rewrap comments after n characters on one line 40 | // Other 41 | "jrebocho.vscode-random", // generate random values 42 | "alefragnani.Bookmarks", 43 | "quicktype.quicktype", // Paste JSON as code 44 | "spikespaz.vscode-smoothtype", // smooth cursor animation 45 | "vscode-icons-team.vscode-icons", 46 | // markdown 47 | "jebbs.markdown-extended", 48 | "bierner.github-markdown-preview", 49 | "HashiCorp.terraform", 50 | "ms-kubernetes-tools.kind-vscode", 51 | "ms-kubernetes-tools.vscode-kubernetes-tools", 52 | "jetmartin.bats", 53 | "EditorConfig.EditorConfig", 54 | "lonefy.vscode-js-css-html-formatter", 55 | "richie5um2.vscode-statusbar-json-path", 56 | ], 57 | "settings": { 58 | // General settings 59 | "files.eol": "\n", 60 | "files.encoding": "utf8", 61 | "editor.renderWhitespace": "all", 62 | // Docker 63 | "remote.extensionKind": { 64 | "ms-azuretools.vscode-docker": "workspace" 65 | }, 66 | "[makefile]": { 67 | "editor.insertSpaces": false, 68 | "editor.detectIndentation": false 69 | }, 70 | "go.useLanguageServer": true, 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | vscode: 5 | build: . 6 | volumes: 7 | - ../:/go/src/github.com/denouche/terraform-provider-awx 8 | # (only for debug) 9 | #- ../../goawx:/go/src/github.com/denouche/goawx 10 | - ~/.ssh:/home/vscode/.ssh:ro 11 | - ~/.ssh:/root/.ssh:ro 12 | - /var/run/docker.sock:/var/run/docker.sock 13 | ## reuse volumes for extensions 14 | - terraform-awx-vol:/home/vscode/.vscode-server/extensions 15 | # And/or for VS Code Insiders 16 | - terraform-awx-vol-insiders:/home/vscode/.vscode-server-insiders/extensions 17 | environment: 18 | - TZ=Europe/Berlin # $(cat /etc/timezone) 19 | cap_add: 20 | - SYS_PTRACE 21 | security_opt: 22 | - seccomp:unconfined 23 | entrypoint: zsh -c "while sleep 1000; do :; done" 24 | network_mode: "host" 25 | 26 | volumes: 27 | terraform-awx-vol: 28 | terraform-awx-vol-insiders: 29 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [docs/**.md] 13 | # allow line break https://3os.org/markdownCheatSheet/lineBreaks/#line_break_with_2_spaces 14 | trim_trailing_whitespace = false 15 | 16 | [{makefile,Makefile}] 17 | indent_style = tabs 18 | 19 | [{*.yml,*.yaml, *.tf}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | 7 | jobs: 8 | 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo 18 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token 19 | 20 | - name: Set up Go 21 | uses: actions/setup-go@v5 22 | with: 23 | go-version: '1.20' 24 | 25 | - name: Get dependencies 26 | run: | 27 | go mod download 28 | 29 | - name: Build 30 | run: | 31 | go build 32 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This uses an action (crazy-max/ghaction-import-gpg) that assumes you set your 2 | # private key in the `GPG_PRIVATE_KEY` secret and passphrase in the `PASSPHRASE` 3 | # secret. If you would rather own your own GPG handling, please fork this action 4 | # or use an alternative one for key handling. 5 | # 6 | # You will need to pass the `--batch` flag to `gpg` in your signing step 7 | # in `goreleaser` to indicate this is being used in a non-interactive mode. 8 | # 9 | name: Release 10 | 11 | on: 12 | workflow_dispatch: 13 | push: 14 | branches: 15 | - 'main' 16 | tags-ignore: 17 | - '**' 18 | 19 | jobs: 20 | 21 | release: 22 | 23 | runs-on: ubuntu-latest 24 | steps: 25 | 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo 30 | persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token 31 | 32 | - name: Release 33 | id: release 34 | uses: cycjimmy/semantic-release-action@v4 35 | with: 36 | branches: | 37 | [ 38 | 'main' 39 | ] 40 | extra_plugins: | 41 | @semantic-release/commit-analyzer@12.0.0 42 | @semantic-release/release-notes-generator@13.0.0 43 | @semantic-release/changelog@6.0.3 44 | @semantic-release/git@10.0.1 45 | @semantic-release/github@10.0.5 46 | env: 47 | GIT_CREDENTIALS: git:${{ secrets.PAT }} 48 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | 50 | - name: Set up Go 51 | if: steps.release.outputs.new_release_published == 'true' 52 | uses: actions/setup-go@v5 53 | with: 54 | go-version: '1.20' 55 | 56 | - name: Import GPG key 57 | if: steps.release.outputs.new_release_published == 'true' 58 | id: import_gpg 59 | uses: crazy-max/ghaction-import-gpg@v6 60 | with: 61 | # These secrets will need to be configured for the repository: 62 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 63 | passphrase: ${{ secrets.PASSPHRASE }} 64 | 65 | - name: Run GoReleaser 66 | if: steps.release.outputs.new_release_published == 'true' 67 | uses: goreleaser/goreleaser-action@v5 68 | with: 69 | version: '~> v1' 70 | args: release --clean 71 | env: 72 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} 73 | # GitHub sets this automatically 74 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | vendor/ 3 | .idea/ 4 | .DS_Store 5 | terraform-provider-awx 6 | bin 7 | 8 | # Local .terraform directories 9 | **/.terraform/* 10 | 11 | # .tfstate files 12 | *.tfstate 13 | *.tfstate.* 14 | 15 | # Crash log files 16 | crash.log 17 | 18 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 19 | # .tfvars files are managed as part of configuration and so should be included in 20 | # version control. 21 | # 22 | # example.tfvars 23 | 24 | # Ignore override files as they are usually used to override resources locally and so 25 | # are not checked in 26 | override.tf 27 | override.tf.json 28 | *_override.tf 29 | *_override.tf.json 30 | 31 | # Include override files you do wish to add to version control using negated pattern 32 | # 33 | # !example_override.tf 34 | 35 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 36 | # example: *tfplan* 37 | 38 | # Ignore CLI configuration files 39 | .terraformrc 40 | terraform.rc 41 | terraform 42 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | disable-all: true 3 | enable: 4 | - bodyclose 5 | - deadcode 6 | - depguard 7 | - dogsled 8 | - errcheck 9 | - funlen 10 | - gochecknoinits 11 | - goconst 12 | - gocritic 13 | - gocyclo 14 | - gofmt 15 | - goimports 16 | - golint 17 | - gomnd 18 | - goprintffuncname 19 | - gosec 20 | - gosimple 21 | - govet 22 | - ineffassign 23 | - interfacer 24 | - lll 25 | - misspell 26 | - nakedret 27 | - nolintlint 28 | - rowserrcheck 29 | - scopelint 30 | - staticcheck 31 | - structcheck 32 | - stylecheck 33 | - typecheck 34 | - unconvert 35 | - unparam 36 | - unused 37 | - varcheck 38 | - whitespace 39 | - asciicheck 40 | - gochecknoglobals 41 | - gocognit 42 | - godot 43 | - godox 44 | - maligned 45 | - prealloc 46 | - testpackage 47 | - wsl 48 | # don't enable: 49 | #- nestif 50 | #- dupl 51 | #- goerr113 52 | issues: 53 | # Excluding configuration per-path, per-linter, per-text and per-source 54 | exclude-rules: 55 | # Exclude some linters from running on tests files. 56 | - path: _test\.go 57 | linters: 58 | - gochecknoglobals 59 | - gochecknoinits 60 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # Visit https://goreleaser.com for documentation on how to customize this 2 | # behavior. 3 | before: 4 | hooks: 5 | # this is just an example and not a requirement for provider building/publishing 6 | - go mod tidy 7 | builds: 8 | - env: 9 | # goreleaser does not work with CGO, it could also complicate 10 | # usage by users in CI/CD systems like Terraform Cloud where 11 | # they are unable to install libraries. 12 | - CGO_ENABLED=0 13 | mod_timestamp: '{{ .CommitTimestamp }}' 14 | flags: 15 | - -trimpath 16 | ldflags: 17 | - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}' 18 | goos: 19 | - linux 20 | - freebsd 21 | - darwin 22 | - windows 23 | goarch: 24 | - amd64 25 | - '386' 26 | - arm 27 | - arm64 28 | ignore: 29 | - goos: darwin 30 | goarch: '386' 31 | binary: '{{ .ProjectName }}_v{{ .Version }}' 32 | archives: 33 | - format: zip 34 | name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}' 35 | checksum: 36 | name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS' 37 | algorithm: sha256 38 | signs: 39 | - artifacts: checksum 40 | args: 41 | # if you are using this in a GitHub action or some other automated pipeline, you 42 | # need to pass the batch flag to indicate its not interactive. 43 | - "--batch" 44 | - "--local-user" 45 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key 46 | - "--output" 47 | - "${signature}" 48 | - "--detach-sign" 49 | - "${artifact}" 50 | release: 51 | # If you want to manually examine the release before its live, uncomment this line: 52 | draft: false 53 | changelog: 54 | disable: true 55 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "tagFormat": "v${version}", 3 | "plugins": [ 4 | [ 5 | "@semantic-release/commit-analyzer", 6 | { 7 | "preset": "angular", 8 | "releaseRules": [ 9 | { 10 | "type": "refactor", 11 | "release": "patch" 12 | }, 13 | { 14 | "type": "chore", 15 | "release": "patch" 16 | } 17 | ] 18 | } 19 | ], 20 | "@semantic-release/release-notes-generator", 21 | [ 22 | "@semantic-release/changelog", 23 | { 24 | "changelogFile": "CHANGELOG.md" 25 | } 26 | ], 27 | [ 28 | "@semantic-release/git", 29 | { 30 | "assets": [ 31 | "CHANGELOG.md" 32 | ], 33 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 34 | } 35 | ], 36 | "@semantic-release/github" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Antoine Leveugle 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 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | This file describes how this project is maintained. When making changes to the main 4 | branch, this file tells you who needs to review a pull request and who has the right 5 | to merge it. 6 | 7 | ## Project Maintainers 8 | 9 | * [Tioborto](https://github.com/Tioborto) 10 | * [denouche](https://github.com/denouche) 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TEST?=$$(go list ./... | grep -v 'vendor') 2 | HOSTNAME=github.com 3 | NAMESPACE=denouche 4 | NAME=awx 5 | BINARY=terraform-provider-${NAME} 6 | VERSION=0.1 7 | OS_ARCH=linux_amd64 # darwin_amd64 8 | default: install 9 | 10 | build: 11 | go build -o ${BINARY} 12 | 13 | release: 14 | GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64 15 | GOOS=darwin GOARCH=arm64 go build -o ./bin/${BINARY}_${VERSION}_darwin_arm64 16 | GOOS=freebsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_freebsd_386 17 | GOOS=freebsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_freebsd_amd64 18 | GOOS=freebsd GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_freebsd_arm 19 | GOOS=linux GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_linux_386 20 | GOOS=linux GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_linux_amd64 21 | GOOS=linux GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_linux_arm 22 | GOOS=openbsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_openbsd_386 23 | GOOS=openbsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_openbsd_amd64 24 | GOOS=solaris GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_solaris_amd64 25 | GOOS=windows GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_windows_386 26 | GOOS=windows GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_windows_amd64 27 | 28 | install: build 29 | mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 30 | mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 31 | 32 | test: 33 | go test -i $(TEST) || exit 1 34 | echo $(TEST) | xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 35 | 36 | testacc: 37 | TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Provider AWX 2 | 3 | _Fork from [mrcrilly/terraform-provider-awx](https://github.com/mrcrilly/terraform-provider-awx) for develop additional functions. 4 | 5 | Coming soon. 6 | 7 | ## Local Development 8 | 9 | ### 1) Start a Local AWX instance in a kubernetes cluster 10 | A fresh AWX instance is required for automated tests, so they can ensure terraform provider is working by targetting a live AWX instance. 11 | 12 | A new instance can be re-created by invoking the `reCreate` [mage](https://magefile.org/) target defined in `tools/magefile.go`. 13 | Once executed it will deploy an AWX instance to a Kubernetes cluster, using [kind](https://kind.sigs.k8s.io/). 14 | 15 | ```sh 16 | cd ./tools && go run mage.go -v reCreate && cd .. 17 | ``` 18 | 19 | ### 2) Build Provider 20 | 1. Ensure [GoReleaser](https://goreleaser.com/install/) is installed 21 | 2. Run build command: 22 | ```sh 23 | goreleaser build --snapshot --rm-dist 24 | ``` 25 | 26 | ### 3) Copy Provider 27 | Copy the provider to user's `~/.terraform.d` folder. 28 | > Important: if building the provider in an operating system other than Linux x86_64, adjust the paths below replacing `linux_amd64` with the corresponding platform code. E.g.: `darwin_amd64` for macOS. 29 | 30 | ```sh 31 | mkdir -p ~/.terraform.d/plugins/github.com/denouche/awx/0.1/linux_amd64/terraform-provider-awx 32 | find ./dist/terraform-provider-awx_linux_amd64/* -name 'terraform-provider-awx*' -print0 | xargs -0 -I {} mv {} ~/.terraform.d/plugins/github.com/denouche/awx/0.1/linux_amd64/terraform-provider-awx 33 | ``` 34 | 35 | ### 4) Run tests and ensure they're all passing 36 | ```sh 37 | go test ./test -count=1 38 | ``` 39 | 40 | ### Optional: All in one command 41 | For convenience, all the steps above can be achieved by a single command that combines all of them: 42 | ```sh 43 | goreleaser build --snapshot --rm-dist \ 44 | && mkdir -p ~/.terraform.d/plugins/github.com/denouche/awx/0.1/linux_amd64/ \ 45 | && find ./dist/terraform-provider-awx_linux_amd64/* -name 'terraform-provider-awx*' -print0 | xargs -0 -I {} mv {} ~/.terraform.d/plugins/github.com/denouche/awx/0.1/linux_amd64/terraform-provider-awx \ 46 | && go test ./test -count=1 47 | ``` 48 | 49 | ## Update documentation 50 | 51 | The files in `./docs` folder are generated by executing the `genDocumentation` target defined in `tools/magefile.go` file: 52 | ```sh 53 | cd ./tools && go run mage.go -v genDocumentation && cd .. 54 | ``` 55 | -------------------------------------------------------------------------------- /awx/convert_type.go: -------------------------------------------------------------------------------- 1 | package awx 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | // AtoipOr takes a string and a defaultValue. If the string cannot be converted, defaultValue is returned 8 | func AtoipOr(s string, defaultValue *int) *int { 9 | n, err := strconv.Atoi(s) 10 | if err != nil { 11 | return defaultValue 12 | } 13 | return &n 14 | } 15 | -------------------------------------------------------------------------------- /awx/data_source_credential.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use this data source to query Credential by ID. 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "strconv" 16 | 17 | awx "github.com/denouche/goawx/client" 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 20 | ) 21 | 22 | func dataSourceCredentialByID() *schema.Resource { 23 | return &schema.Resource{ 24 | ReadContext: dataSourceCredentialByIDRead, 25 | Schema: map[string]*schema.Schema{ 26 | "id": { 27 | Type: schema.TypeInt, 28 | Required: true, 29 | }, 30 | "tower_id": { 31 | Type: schema.TypeInt, 32 | Computed: true, 33 | }, 34 | "username": { 35 | Type: schema.TypeString, 36 | Computed: true, 37 | }, 38 | "kind": { 39 | Type: schema.TypeString, 40 | Computed: true, 41 | }, 42 | "description": { 43 | Type: schema.TypeString, 44 | Computed: true, 45 | }, 46 | "name": { 47 | Type: schema.TypeString, 48 | Computed: true, 49 | }, 50 | }, 51 | } 52 | } 53 | 54 | func dataSourceCredentialByIDRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 55 | var diags diag.Diagnostics 56 | 57 | client := m.(*awx.AWX) 58 | id := d.Get("id").(int) 59 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 60 | if err != nil { 61 | diags = append(diags, diag.Diagnostic{ 62 | Severity: diag.Error, 63 | Summary: "Unable to fetch credential", 64 | Detail: "The given credential ID is invalid or malformed", 65 | }) 66 | } 67 | 68 | d.Set("username", cred.Inputs["username"]) 69 | d.Set("kind", cred.Kind) 70 | d.Set("tower_id", id) 71 | d.Set("description", cred.Description) 72 | d.Set("name", cred.Name) 73 | d.SetId(strconv.Itoa(id)) 74 | // d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) 75 | 76 | return diags 77 | } 78 | -------------------------------------------------------------------------------- /awx/data_source_credential_azure_key_vault.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | "time" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceCredentialAzure() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceCredentialAzureRead, 27 | Schema: map[string]*schema.Schema{ 28 | "credential_id": { 29 | Type: schema.TypeInt, 30 | Required: true, 31 | }, 32 | "name": { 33 | Type: schema.TypeString, 34 | Computed: true, 35 | }, 36 | "description": { 37 | Type: schema.TypeString, 38 | Computed: true, 39 | }, 40 | "organization_id": { 41 | Type: schema.TypeInt, 42 | Computed: true, 43 | }, 44 | "url": { 45 | Type: schema.TypeString, 46 | Computed: true, 47 | }, 48 | "client": { 49 | Type: schema.TypeString, 50 | Computed: true, 51 | }, 52 | "secret": { 53 | Type: schema.TypeString, 54 | Computed: true, 55 | Sensitive: true, 56 | }, 57 | "tenant": { 58 | Type: schema.TypeString, 59 | Computed: true, 60 | }, 61 | }, 62 | } 63 | } 64 | 65 | func dataSourceCredentialAzureRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 66 | var diags diag.Diagnostics 67 | 68 | client := m.(*awx.AWX) 69 | id, _ := d.Get("credential_id").(int) 70 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 71 | if err != nil { 72 | diags = append(diags, diag.Diagnostic{ 73 | Severity: diag.Error, 74 | Summary: "Unable to fetch credentials", 75 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 76 | }) 77 | return diags 78 | } 79 | 80 | d.Set("name", cred.Name) 81 | d.Set("description", cred.Description) 82 | d.Set("organization_id", cred.OrganizationID) 83 | d.Set("url", cred.Inputs["url"]) 84 | d.Set("client", cred.Inputs["client"]) 85 | d.Set("secret", d.Get("secret").(string)) 86 | d.Set("tenant", cred.Inputs["tenant"]) 87 | d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) 88 | 89 | return diags 90 | } 91 | -------------------------------------------------------------------------------- /awx/data_source_credential_type.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use this data source to query Credential Type by ID. 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func dataSourceCredentialTypeByID() *schema.Resource { 24 | return &schema.Resource{ 25 | ReadContext: dataSourceCredentialTypeByIDRead, 26 | Schema: map[string]*schema.Schema{ 27 | "id": { 28 | Type: schema.TypeInt, 29 | Required: true, 30 | }, 31 | "name": { 32 | Type: schema.TypeString, 33 | Computed: true, 34 | }, 35 | "description": { 36 | Type: schema.TypeString, 37 | Computed: true, 38 | }, 39 | "kind": { 40 | Type: schema.TypeString, 41 | Computed: true, 42 | }, 43 | "inputs": { 44 | Type: schema.TypeString, 45 | Computed: true, 46 | }, 47 | "injectors": { 48 | Type: schema.TypeString, 49 | Computed: true, 50 | }, 51 | }, 52 | } 53 | } 54 | 55 | func dataSourceCredentialTypeByIDRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 56 | var diags diag.Diagnostics 57 | 58 | client := m.(*awx.AWX) 59 | id := d.Get("id").(int) 60 | credType, err := client.CredentialTypeService.GetCredentialTypeByID(id, map[string]string{}) 61 | if err != nil { 62 | diags = append(diags, diag.Diagnostic{ 63 | Severity: diag.Error, 64 | Summary: "Unable to fetch credential type", 65 | Detail: fmt.Sprintf("Unable to fetch credential type with ID: %d. Error: %s", id, err.Error()), 66 | }) 67 | } 68 | 69 | d.Set("name", credType.Name) 70 | d.Set("description", credType.Description) 71 | d.Set("kind", credType.Kind) 72 | d.Set("inputs", credType.Inputs) 73 | d.Set("injectors", credType.Injectors) 74 | d.SetId(strconv.Itoa(id)) 75 | 76 | return diags 77 | } 78 | -------------------------------------------------------------------------------- /awx/data_source_credentials.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use this data source to query Credential by ID. 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "strconv" 16 | "time" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func dataSourceCredentials() *schema.Resource { 24 | return &schema.Resource{ 25 | ReadContext: dataSourceCredentialsRead, 26 | Schema: map[string]*schema.Schema{ 27 | "credentials": { 28 | Type: schema.TypeList, 29 | Computed: true, 30 | Elem: &schema.Resource{ 31 | Schema: map[string]*schema.Schema{ 32 | "id": { 33 | Type: schema.TypeInt, 34 | Computed: true, 35 | }, 36 | "username": { 37 | Type: schema.TypeString, 38 | Computed: true, 39 | }, 40 | "kind": { 41 | Type: schema.TypeString, 42 | Computed: true, 43 | }, 44 | "description": { 45 | Type: schema.TypeString, 46 | Computed: true, 47 | }, 48 | "name": { 49 | Type: schema.TypeString, 50 | Computed: true, 51 | }, 52 | }, 53 | }, 54 | }, 55 | }, 56 | } 57 | } 58 | 59 | func dataSourceCredentialsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 60 | var diags diag.Diagnostics 61 | client := m.(*awx.AWX) 62 | 63 | creds, err := client.CredentialsService.ListCredentials(map[string]string{}) 64 | if err != nil { 65 | diags = append(diags, diag.Diagnostic{ 66 | Severity: diag.Error, 67 | Summary: "Unable to fetch credentials", 68 | Detail: "Unable to fetch credentials from AWX API", 69 | }) 70 | return diags 71 | } 72 | 73 | parsedCreds := make([]map[string]interface{}, 0) 74 | for _, c := range creds { 75 | parsedCreds = append(parsedCreds, map[string]interface{}{ 76 | "id": c.ID, 77 | "username": c.Inputs["username"], 78 | "kind": c.Kind, 79 | "description": c.Description, 80 | "name": c.Name, 81 | }) 82 | } 83 | 84 | err = d.Set("credentials", parsedCreds) 85 | if err != nil { 86 | return diag.FromErr(err) 87 | } 88 | 89 | d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) 90 | 91 | return diags 92 | } 93 | -------------------------------------------------------------------------------- /awx/data_source_execution_environment.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_execution_environment" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceExecutionEnvironment() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceExecutionEnvironmentsRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceExecutionEnvironmentsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or group_id)", 58 | ) 59 | } 60 | executionEnvironments, _, err := client.ExecutionEnvironmentsService.ListExecutionEnvironments(params) 61 | if err != nil { 62 | return buildDiagnosticsMessage( 63 | "Get: Fail to fetch execution environment", 64 | "Fail to find the execution environment got: %s", 65 | err.Error(), 66 | ) 67 | } 68 | if len(executionEnvironments) > 1 { 69 | return buildDiagnosticsMessage( 70 | "Get: find more than one element", 71 | "The query returns more than one execution environment, %d", 72 | len(executionEnvironments), 73 | ) 74 | } 75 | if len(executionEnvironments) == 0 { 76 | return buildDiagnosticsMessage( 77 | "Get: Execution Environment does not exist", 78 | "The Query Returns no Execution Environment matching filter %v", 79 | params, 80 | ) 81 | } 82 | 83 | executionEnvironment := executionEnvironments[0] 84 | d = setExecutionEnvironmentsResourceData(d, executionEnvironment) 85 | return diags 86 | } 87 | -------------------------------------------------------------------------------- /awx/data_source_inventory.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_inventory" "default" { 8 | name = "private_services" 9 | organization_id = data.awx_organization.default.id 10 | } 11 | ``` 12 | 13 | */ 14 | package awx 15 | 16 | import ( 17 | "context" 18 | "strconv" 19 | 20 | awx "github.com/denouche/goawx/client" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 22 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 23 | ) 24 | 25 | func dataSourceInventory() *schema.Resource { 26 | return &schema.Resource{ 27 | ReadContext: dataSourceInventoriesRead, 28 | Schema: map[string]*schema.Schema{ 29 | "id": { 30 | Type: schema.TypeInt, 31 | Optional: true, 32 | Computed: true, 33 | }, 34 | "name": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | Computed: true, 38 | }, 39 | "organization_id": { 40 | Type: schema.TypeInt, 41 | Optional: true, 42 | Computed: true, 43 | }, 44 | }, 45 | } 46 | } 47 | 48 | func dataSourceInventoriesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 49 | var diags diag.Diagnostics 50 | client := m.(*awx.AWX) 51 | params := make(map[string]string) 52 | if groupName, okName := d.GetOk("name"); okName { 53 | params["name"] = groupName.(string) 54 | } 55 | 56 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 57 | params["id"] = strconv.Itoa(groupID.(int)) 58 | } 59 | 60 | if organizationID, okIOrgID := d.GetOk("organization_id"); okIOrgID { 61 | params["organization"] = strconv.Itoa(organizationID.(int)) 62 | } 63 | if len(params) == 0 { 64 | return buildDiagnosticsMessage( 65 | "Get: Missing Parameters", 66 | "Please use one of the selectors (name or id)", 67 | ) 68 | } 69 | inventories, _, err := client.InventoriesService.ListInventories(params) 70 | if err != nil { 71 | return buildDiagnosticsMessage( 72 | "Get: Fail to fetch Inventory", 73 | "Fail to find the inventory got: %s", 74 | err.Error(), 75 | ) 76 | } 77 | if len(inventories) > 1 { 78 | return buildDiagnosticsMessage( 79 | "Get: find more than one Element", 80 | "The Query Returns more than one Inventory, %d", 81 | len(inventories), 82 | ) 83 | } 84 | 85 | if len(inventories) == 0 { 86 | return buildDiagnosticsMessage( 87 | "Get: Inventory does not exist", 88 | "The Query Returns no Inventory matching filter %v", 89 | params, 90 | ) 91 | } 92 | 93 | inventory := inventories[0] 94 | d = setInventoryResourceData(d, inventory) 95 | return diags 96 | } 97 | -------------------------------------------------------------------------------- /awx/data_source_inventory_group.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_inventory_group" "default" { 8 | name = "k3sPrimary" 9 | inventory_id = data.awx_inventory.default.id 10 | } 11 | ``` 12 | 13 | */ 14 | package awx 15 | 16 | import ( 17 | "context" 18 | "strconv" 19 | 20 | awx "github.com/denouche/goawx/client" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 22 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 23 | ) 24 | 25 | func dataSourceInventoryGroup() *schema.Resource { 26 | return &schema.Resource{ 27 | ReadContext: dataSourceInventoryGroupRead, 28 | Schema: map[string]*schema.Schema{ 29 | "id": { 30 | Type: schema.TypeInt, 31 | Optional: true, 32 | Computed: true, 33 | }, 34 | "name": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | Computed: true, 38 | }, 39 | "inventory_id": { 40 | Type: schema.TypeInt, 41 | Required: true, 42 | }, 43 | }, 44 | } 45 | } 46 | 47 | func dataSourceInventoryGroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 48 | var diags diag.Diagnostics 49 | client := m.(*awx.AWX) 50 | params := make(map[string]string) 51 | if groupName, okName := d.GetOk("name"); okName { 52 | params["name"] = groupName.(string) 53 | } 54 | 55 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 56 | params["id"] = strconv.Itoa(groupID.(int)) 57 | } 58 | 59 | if len(params) == 0 { 60 | return buildDiagnosticsMessage( 61 | "Get: Missing Parameters", 62 | "Please use one of the selectors (name or id)", 63 | ) 64 | } 65 | inventoryID := d.Get("inventory_id").(int) 66 | groups, _, err := client.InventoryGroupService.ListInventoryGroups(inventoryID, params) 67 | if err != nil { 68 | return buildDiagnosticsMessage( 69 | "Get: Fail to fetch Inventory Group", 70 | "Fail to find the group got: %s", 71 | err.Error(), 72 | ) 73 | } 74 | if len(groups) > 1 { 75 | return buildDiagnosticsMessage( 76 | "Get: find more than one Element", 77 | "The Query Returns more than one Inventory Group, %d", 78 | len(groups), 79 | ) 80 | } 81 | if len(groups) == 0 { 82 | return buildDiagnosticsMessage( 83 | "Get: Inventory Group does not exist", 84 | "The Query Returns no Inventory Group matching filter %v", 85 | params, 86 | ) 87 | } 88 | 89 | group := groups[0] 90 | d = setInventoryGroupResourceData(d, group) 91 | return diags 92 | } 93 | -------------------------------------------------------------------------------- /awx/data_source_inventory_role.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | resource "awx_inventory" "myinv" { 8 | name = "My Inventory" 9 | ... 10 | } 11 | 12 | data "awx_inventory_role" "inv_admin_role" { 13 | name = "Admin" 14 | inventory_id = data.awx_inventory.myinv.id 15 | } 16 | ``` 17 | 18 | */ 19 | package awx 20 | 21 | import ( 22 | "context" 23 | "strconv" 24 | 25 | awx "github.com/denouche/goawx/client" 26 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 27 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 28 | ) 29 | 30 | func dataSourceInventoryRole() *schema.Resource { 31 | return &schema.Resource{ 32 | ReadContext: dataSourceInventoryRoleRead, 33 | Schema: map[string]*schema.Schema{ 34 | "id": { 35 | Type: schema.TypeInt, 36 | Optional: true, 37 | Computed: true, 38 | }, 39 | "name": { 40 | Type: schema.TypeString, 41 | Optional: true, 42 | Computed: true, 43 | }, 44 | "inventory_id": { 45 | Type: schema.TypeInt, 46 | Required: true, 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | func dataSourceInventoryRoleRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 53 | var diags diag.Diagnostics 54 | client := m.(*awx.AWX) 55 | params := make(map[string]string) 56 | 57 | inv_id := d.Get("inventory_id").(int) 58 | inventory, err := client.InventoriesService.GetInventoryByID(inv_id, params) 59 | if err != nil { 60 | return buildDiagnosticsMessage( 61 | "Get: Fail to fetch Inventory", 62 | "Fail to find the inventory, got: %s", 63 | err.Error(), 64 | ) 65 | } 66 | 67 | roleslist := []*awx.ApplyRole{ 68 | inventory.SummaryFields.ObjectRoles.UseRole, 69 | inventory.SummaryFields.ObjectRoles.AdminRole, 70 | inventory.SummaryFields.ObjectRoles.AdhocRole, 71 | inventory.SummaryFields.ObjectRoles.UpdateRole, 72 | inventory.SummaryFields.ObjectRoles.ReadRole, 73 | inventory.SummaryFields.ObjectRoles.ExecuteRole, 74 | } 75 | 76 | if roleID, okID := d.GetOk("id"); okID { 77 | id := roleID.(int) 78 | for _, v := range roleslist { 79 | if v != nil && id == v.ID { 80 | d = setInventoryRoleData(d, v) 81 | return diags 82 | } 83 | } 84 | } 85 | 86 | if roleName, okName := d.GetOk("name"); okName { 87 | name := roleName.(string) 88 | 89 | for _, v := range roleslist { 90 | if v != nil && name == v.Name { 91 | d = setInventoryRoleData(d, v) 92 | return diags 93 | } 94 | } 95 | } 96 | 97 | return buildDiagnosticsMessage( 98 | "Failed to fetch inventory role - Not Found", 99 | "The project role was not found", 100 | ) 101 | } 102 | 103 | func setInventoryRoleData(d *schema.ResourceData, r *awx.ApplyRole) *schema.ResourceData { 104 | d.Set("name", r.Name) 105 | d.SetId(strconv.Itoa(r.ID)) 106 | return d 107 | } 108 | -------------------------------------------------------------------------------- /awx/data_source_job_template.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_job_template" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | "log" 20 | 21 | awx "github.com/denouche/goawx/client" 22 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 23 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 24 | ) 25 | 26 | func dataSourceJobTemplate() *schema.Resource { 27 | return &schema.Resource{ 28 | ReadContext: dataSourceJobTemplateRead, 29 | Schema: map[string]*schema.Schema{ 30 | "id": { 31 | Type: schema.TypeInt, 32 | Optional: true, 33 | Computed: true, 34 | }, 35 | "name": { 36 | Type: schema.TypeString, 37 | Optional: true, 38 | Computed: true, 39 | }, 40 | }, 41 | } 42 | } 43 | 44 | func dataSourceJobTemplateRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 45 | var diags diag.Diagnostics 46 | client := m.(*awx.AWX) 47 | params := make(map[string]string) 48 | if groupName, okName := d.GetOk("name"); okName { 49 | params["name"] = groupName.(string) 50 | } 51 | 52 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 53 | params["id"] = strconv.Itoa(groupID.(int)) 54 | } 55 | 56 | if len(params) == 0 { 57 | return buildDiagnosticsMessage( 58 | "Get: Missing Parameters", 59 | "Please use one of the selectors (name or group_id)", 60 | ) 61 | } 62 | 63 | jobTemplate, _, err := client.JobTemplateService.ListJobTemplates(params) 64 | 65 | if err != nil { 66 | return buildDiagnosticsMessage( 67 | "Get: Fail to fetch Inventory Group", 68 | "Fail to find the group got: %s", 69 | err.Error(), 70 | ) 71 | } 72 | 73 | for _, template := range jobTemplate { 74 | log.Printf("loop %v", template.Name) 75 | if template.Name == params["name"] { 76 | d = setJobTemplateResourceData(d, template) 77 | return diags 78 | } 79 | } 80 | 81 | if _, okGroupID := d.GetOk("id"); okGroupID { 82 | log.Printf("byid %v", len(jobTemplate)) 83 | if len(jobTemplate) > 1 { 84 | return buildDiagnosticsMessage( 85 | "Get: find more than one Element", 86 | "The Query Returns more than one Group, %d", 87 | len(jobTemplate), 88 | ) 89 | } 90 | if len(jobTemplate) == 0 { 91 | return buildDiagnosticsMessage( 92 | "Get: Job Template does not exist", 93 | "The Query Returns no Job Template matching filter %v", 94 | params, 95 | ) 96 | } 97 | d = setJobTemplateResourceData(d, jobTemplate[0]) 98 | return diags 99 | } 100 | return buildDiagnosticsMessage( 101 | "Get: find more than one Element", 102 | "The Query Returns more than one Group, %d", 103 | len(jobTemplate), 104 | ) 105 | } 106 | -------------------------------------------------------------------------------- /awx/data_source_notification_template.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_notification_template" "default" { 8 | name = "private_services" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceNotificationTemplate() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceNotificationTemplatesRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceNotificationTemplatesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okID := d.GetOk("id"); okID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or id)", 58 | ) 59 | } 60 | 61 | notificationTemplates, _, err := client.NotificationTemplatesService.List(params) 62 | if err != nil { 63 | return buildDiagnosticsMessage( 64 | "Get: Fail to fetch NotificationTemplate", 65 | "Fail to find the group got: %s", 66 | err.Error(), 67 | ) 68 | } 69 | if len(notificationTemplates) > 1 { 70 | return buildDiagnosticsMessage( 71 | "Get: find more than one Element", 72 | "The Query Returns more than one Group, %d", 73 | len(notificationTemplates), 74 | ) 75 | } 76 | if len(notificationTemplates) == 0 { 77 | return buildDiagnosticsMessage( 78 | "Get: Notification Template does not exist", 79 | "The Query Returns no Notification Template matching filter %v", 80 | params, 81 | ) 82 | } 83 | 84 | notificationTemplate := notificationTemplates[0] 85 | d = setNotificationTemplateResourceData(d, notificationTemplate) 86 | return diags 87 | } 88 | -------------------------------------------------------------------------------- /awx/data_source_organization.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_organization" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceOrganization() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceOrganizationRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceOrganizationRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or group_id)", 58 | ) 59 | } 60 | organizations, err := client.OrganizationsService.ListOrganizations(params) 61 | if err != nil { 62 | return buildDiagnosticsMessage( 63 | "Get: Fail to fetch organization", 64 | "Fail to find the organization got: %s", 65 | err.Error(), 66 | ) 67 | } 68 | if len(organizations) > 1 { 69 | return buildDiagnosticsMessage( 70 | "Get: find more than one Element", 71 | "The Query Returns more than one organization, %d", 72 | len(organizations), 73 | ) 74 | } 75 | if len(organizations) == 0 { 76 | return buildDiagnosticsMessage( 77 | "Get: Organization does not exist", 78 | "The Query Returns no Organization matching filter %v", 79 | params, 80 | ) 81 | } 82 | 83 | organization := organizations[0] 84 | d = setOrganizationsResourceData(d, organization) 85 | return diags 86 | } 87 | -------------------------------------------------------------------------------- /awx/data_source_organization_role.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | resource "awx_organization" "myorg" { 8 | name = "My AWX Org" 9 | ... 10 | } 11 | 12 | data "awx_organization_role" "org_admins" { 13 | name = "Admin" 14 | organization_id = resource.awx_organization.myorg.id 15 | } 16 | ``` 17 | 18 | */ 19 | package awx 20 | 21 | import ( 22 | "context" 23 | "strconv" 24 | 25 | awx "github.com/denouche/goawx/client" 26 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 27 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 28 | ) 29 | 30 | func dataSourceOrganizationRole() *schema.Resource { 31 | return &schema.Resource{ 32 | ReadContext: dataSourceOrganizationRolesRead, 33 | Schema: map[string]*schema.Schema{ 34 | "id": { 35 | Type: schema.TypeInt, 36 | Optional: true, 37 | Computed: true, 38 | }, 39 | "name": { 40 | Type: schema.TypeString, 41 | Optional: true, 42 | Computed: true, 43 | }, 44 | "organization_id": { 45 | Type: schema.TypeInt, 46 | Required: true, 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | func dataSourceOrganizationRolesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 53 | var diags diag.Diagnostics 54 | client := m.(*awx.AWX) 55 | params := make(map[string]string) 56 | 57 | org_id := d.Get("organization_id").(int) 58 | 59 | organization, err := client.OrganizationsService.GetOrganizationsByID(org_id, params) 60 | if err != nil { 61 | return buildDiagnosticsMessage( 62 | "Get: Fail to fetch organization role", 63 | "Fail to find the organization role got: %s", 64 | err.Error(), 65 | ) 66 | } 67 | 68 | roleslist := []*awx.ApplyRole{ 69 | organization.SummaryFields.ObjectRoles.AdhocRole, 70 | organization.SummaryFields.ObjectRoles.AdminRole, 71 | organization.SummaryFields.ObjectRoles.ApprovalRole, 72 | organization.SummaryFields.ObjectRoles.AuditorRole, 73 | organization.SummaryFields.ObjectRoles.CredentialAdminRole, 74 | organization.SummaryFields.ObjectRoles.ExecuteRole, 75 | organization.SummaryFields.ObjectRoles.InventoryAdminRole, 76 | organization.SummaryFields.ObjectRoles.JobTemplateAdminRole, 77 | organization.SummaryFields.ObjectRoles.MemberRole, 78 | organization.SummaryFields.ObjectRoles.NotificationAdminRole, 79 | organization.SummaryFields.ObjectRoles.ProjectAdminRole, 80 | organization.SummaryFields.ObjectRoles.ReadRole, 81 | organization.SummaryFields.ObjectRoles.UpdateRole, 82 | organization.SummaryFields.ObjectRoles.UseRole, 83 | organization.SummaryFields.ObjectRoles.WorkflowAdminRole, 84 | } 85 | 86 | if roleID, okID := d.GetOk("id"); okID { 87 | id := roleID.(int) 88 | for _, v := range roleslist { 89 | if v != nil && id == v.ID { 90 | d = setOrganizationRoleData(d, v) 91 | return diags 92 | } 93 | } 94 | } 95 | 96 | if roleName, okName := d.GetOk("name"); okName { 97 | name := roleName.(string) 98 | 99 | for _, v := range roleslist { 100 | if v != nil && name == v.Name { 101 | d = setOrganizationRoleData(d, v) 102 | return diags 103 | } 104 | } 105 | } 106 | 107 | return buildDiagnosticsMessage( 108 | "Failed to fetch organization role - Not Found", 109 | "The organization role was not found", 110 | ) 111 | } 112 | 113 | func setOrganizationRoleData(d *schema.ResourceData, r *awx.ApplyRole) *schema.ResourceData { 114 | d.Set("name", r.Name) 115 | d.SetId(strconv.Itoa(r.ID)) 116 | return d 117 | } 118 | -------------------------------------------------------------------------------- /awx/data_source_organizations.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use this data source to query Organizations. 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_organizations" "all_orgs" {} 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "strconv" 16 | "time" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func dataSourceOrganizations() *schema.Resource { 24 | return &schema.Resource{ 25 | ReadContext: dataSourceOrganizationsRead, 26 | Schema: map[string]*schema.Schema{ 27 | "organizations": { 28 | Type: schema.TypeList, 29 | Computed: true, 30 | Elem: &schema.Resource{ 31 | Schema: map[string]*schema.Schema{ 32 | "id": { 33 | Type: schema.TypeInt, 34 | Computed: true, 35 | }, 36 | "name": { 37 | Type: schema.TypeString, 38 | Computed: true, 39 | }, 40 | }, 41 | }, 42 | }, 43 | }, 44 | } 45 | } 46 | 47 | func dataSourceOrganizationsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 48 | var diags diag.Diagnostics 49 | client := m.(*awx.AWX) 50 | 51 | parsedOrgs := make([]map[string]interface{}, 0) 52 | 53 | orgs, err := client.OrganizationsService.ListOrganizations(map[string]string{}) 54 | if err != nil { 55 | diags = append(diags, diag.Diagnostic{ 56 | Severity: diag.Error, 57 | Summary: "Unable to fetch organizations", 58 | Detail: "Unable to fetch organizations from AWX API", 59 | }) 60 | return diags 61 | } 62 | for _, c := range orgs { 63 | parsedOrgs = append(parsedOrgs, map[string]interface{}{ 64 | "id": c.ID, 65 | "name": c.Name, 66 | }) 67 | } 68 | 69 | err = d.Set("organizations", parsedOrgs) 70 | if err != nil { 71 | return diag.FromErr(err) 72 | } 73 | 74 | d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) 75 | 76 | return diags 77 | } 78 | -------------------------------------------------------------------------------- /awx/data_source_project.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_project" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceProject() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceProjectsRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceProjectsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or group_id)", 58 | ) 59 | } 60 | projects, _, err := client.ProjectService.ListProjects(params) 61 | if err != nil { 62 | return buildDiagnosticsMessage( 63 | "Get: Fail to fetch Inventory Group", 64 | "Fail to find the group got: %s", 65 | err.Error(), 66 | ) 67 | } 68 | if len(projects) > 1 { 69 | return buildDiagnosticsMessage( 70 | "Get: find more than one Element", 71 | "The Query Returns more than one Group, %d", 72 | len(projects), 73 | ) 74 | } 75 | if len(projects) == 0 { 76 | return buildDiagnosticsMessage( 77 | "Get: Project does not exist", 78 | "The Query Returns no Project matching filter %v", 79 | params, 80 | ) 81 | } 82 | 83 | project := projects[0] 84 | d = setProjectResourceData(d, project) 85 | return diags 86 | } 87 | -------------------------------------------------------------------------------- /awx/data_source_project_role.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | resource "awx_project" "myproj" { 8 | name = "My AWX Project" 9 | ... 10 | } 11 | 12 | data "awx_project_role" "proj_admins" { 13 | name = "Admin" 14 | project_id = resource.awx_project.myproj.id 15 | } 16 | ``` 17 | 18 | */ 19 | package awx 20 | 21 | import ( 22 | "context" 23 | "strconv" 24 | 25 | awx "github.com/denouche/goawx/client" 26 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 27 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 28 | ) 29 | 30 | func dataSourceProjectRole() *schema.Resource { 31 | return &schema.Resource{ 32 | ReadContext: dataSourceProjectRolesRead, 33 | Schema: map[string]*schema.Schema{ 34 | "id": { 35 | Type: schema.TypeInt, 36 | Optional: true, 37 | Computed: true, 38 | }, 39 | "name": { 40 | Type: schema.TypeString, 41 | Optional: true, 42 | Computed: true, 43 | }, 44 | "project_id": { 45 | Type: schema.TypeInt, 46 | Required: true, 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | func dataSourceProjectRolesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 53 | var diags diag.Diagnostics 54 | client := m.(*awx.AWX) 55 | params := make(map[string]string) 56 | 57 | proj_id := d.Get("project_id").(int) 58 | 59 | Project, err := client.ProjectService.GetProjectByID(proj_id, params) 60 | if err != nil { 61 | return buildDiagnosticsMessage( 62 | "Get: Fail to fetch Project", 63 | "Fail to find the project got: %s", 64 | err.Error(), 65 | ) 66 | } 67 | 68 | roleslist := []*awx.ApplyRole{ 69 | Project.SummaryFields.ObjectRoles.UseRole, 70 | Project.SummaryFields.ObjectRoles.AdminRole, 71 | Project.SummaryFields.ObjectRoles.UpdateRole, 72 | Project.SummaryFields.ObjectRoles.ReadRole, 73 | } 74 | 75 | if roleID, okID := d.GetOk("id"); okID { 76 | id := roleID.(int) 77 | for _, v := range roleslist { 78 | if v != nil && id == v.ID { 79 | d = setProjectRoleData(d, v) 80 | return diags 81 | } 82 | } 83 | } 84 | 85 | if roleName, okName := d.GetOk("name"); okName { 86 | name := roleName.(string) 87 | 88 | for _, v := range roleslist { 89 | if v != nil && name == v.Name { 90 | d = setProjectRoleData(d, v) 91 | return diags 92 | } 93 | } 94 | } 95 | 96 | return buildDiagnosticsMessage( 97 | "Failed to fetch project role - Not Found", 98 | "The project role was not found", 99 | ) 100 | } 101 | 102 | func setProjectRoleData(d *schema.ResourceData, r *awx.ApplyRole) *schema.ResourceData { 103 | d.Set("name", r.Name) 104 | d.SetId(strconv.Itoa(r.ID)) 105 | return d 106 | } 107 | -------------------------------------------------------------------------------- /awx/data_source_schedule.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_schedule" "default" { 8 | name = "private_services" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceSchedule() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceSchedulesRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceSchedulesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okID := d.GetOk("id"); okID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or id)", 58 | ) 59 | } 60 | 61 | schedules, _, err := client.ScheduleService.List(params) 62 | if err != nil { 63 | return buildDiagnosticsMessage( 64 | "Get: Fail to fetch Schedule Group", 65 | "Fail to find the group got: %s", 66 | err.Error(), 67 | ) 68 | } 69 | if len(schedules) > 1 { 70 | return buildDiagnosticsMessage( 71 | "Get: find more than one Element", 72 | "The Query Returns more than one Group, %d", 73 | len(schedules), 74 | ) 75 | } 76 | if len(schedules) == 0 { 77 | return buildDiagnosticsMessage( 78 | "Get: Schedule does not exist", 79 | "The Query Returns no Schedule matching filter %v", 80 | params, 81 | ) 82 | } 83 | 84 | schedule := schedules[0] 85 | d = setScheduleResourceData(d, schedule) 86 | return diags 87 | } 88 | -------------------------------------------------------------------------------- /awx/data_source_team.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_team" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceTeam() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceTeamsRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceTeamsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if teamName, okName := d.GetOk("name"); okName { 47 | params["name"] = teamName.(string) 48 | } 49 | 50 | if teamID, okTeamID := d.GetOk("id"); okTeamID { 51 | params["id"] = strconv.Itoa(teamID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or id)", 58 | ) 59 | } 60 | Teams, _, err := client.TeamService.ListTeams(params) 61 | if err != nil { 62 | return buildDiagnosticsMessage( 63 | "Get: Fail to fetch Team", 64 | "Fail to find the team got: %s", 65 | err.Error(), 66 | ) 67 | } 68 | 69 | if len(Teams) > 1 { 70 | return buildDiagnosticsMessage( 71 | "Get: find more than one Element", 72 | "The Query Returns more than one team, %d", 73 | len(Teams), 74 | ) 75 | } 76 | 77 | if len(Teams) == 0 { 78 | return buildDiagnosticsMessage( 79 | "Get: Team does not exist", 80 | "The Query Returns no Team matching filter %v", 81 | params, 82 | ) 83 | } 84 | 85 | Team := Teams[0] 86 | Entitlements, _, err := client.TeamService.ListTeamRoleEntitlements(Team.ID, make(map[string]string)) 87 | if err != nil { 88 | return buildDiagnosticsMessage( 89 | "Get: Failed to fetch team role entitlements", 90 | "Fail to retrieve team role entitlements got: %s", 91 | err.Error(), 92 | ) 93 | } 94 | 95 | d = setTeamResourceData(d, Team, Entitlements) 96 | return diags 97 | } 98 | -------------------------------------------------------------------------------- /awx/data_source_workflow_job_template.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_workflow_job_template" "default" { 8 | name = "Default" 9 | } 10 | ``` 11 | 12 | */ 13 | package awx 14 | 15 | import ( 16 | "context" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func dataSourceWorkflowJobTemplate() *schema.Resource { 25 | return &schema.Resource{ 26 | ReadContext: dataSourceWorkflowJobTemplateRead, 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeInt, 30 | Optional: true, 31 | Computed: true, 32 | }, 33 | "name": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | Computed: true, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | func dataSourceWorkflowJobTemplateRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 43 | var diags diag.Diagnostics 44 | client := m.(*awx.AWX) 45 | params := make(map[string]string) 46 | if groupName, okName := d.GetOk("name"); okName { 47 | params["name"] = groupName.(string) 48 | } 49 | 50 | if groupID, okGroupID := d.GetOk("id"); okGroupID { 51 | params["id"] = strconv.Itoa(groupID.(int)) 52 | } 53 | 54 | if len(params) == 0 { 55 | return buildDiagnosticsMessage( 56 | "Get: Missing Parameters", 57 | "Please use one of the selectors (name or group_id)", 58 | ) 59 | } 60 | workflowJobTemplate, _, err := client.WorkflowJobTemplateService.ListWorkflowJobTemplates(params) 61 | if err != nil { 62 | return buildDiagnosticsMessage( 63 | "Get: Fail to fetch Inventory Group", 64 | "Fail to find the group got: %s", 65 | err.Error(), 66 | ) 67 | } 68 | if groupName, okName := d.GetOk("name"); okName { 69 | for _, template := range workflowJobTemplate { 70 | if template.Name == groupName { 71 | d = setWorkflowJobTemplateResourceData(d, template) 72 | return diags 73 | } 74 | } 75 | } 76 | if _, okGroupID := d.GetOk("id"); okGroupID { 77 | if len(workflowJobTemplate) > 1 { 78 | return buildDiagnosticsMessage( 79 | "Get: find more than one Element", 80 | "The Query Returns more than one Group, %d", 81 | len(workflowJobTemplate), 82 | ) 83 | } 84 | if len(workflowJobTemplate) == 0 { 85 | return buildDiagnosticsMessage( 86 | "Get: Workflow template does not exist", 87 | "The Query Returns no Workflow template matching filter %v", 88 | params, 89 | ) 90 | } 91 | d = setWorkflowJobTemplateResourceData(d, workflowJobTemplate[0]) 92 | return diags 93 | } 94 | return buildDiagnosticsMessage( 95 | "Get: find more than one Element", 96 | "The Query Returns more than one Group, %d", 97 | len(workflowJobTemplate), 98 | ) 99 | } 100 | -------------------------------------------------------------------------------- /awx/resource_credential.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "encoding/json" 16 | "fmt" 17 | "strconv" 18 | 19 | awx "github.com/denouche/goawx/client" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 21 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 22 | ) 23 | 24 | func resourceCredential() *schema.Resource { 25 | return &schema.Resource{ 26 | CreateContext: resourceCredentialCreate, 27 | ReadContext: resourceCredentialRead, 28 | UpdateContext: resourceCredentialUpdate, 29 | DeleteContext: CredentialsServiceDeleteByID, 30 | Schema: map[string]*schema.Schema{ 31 | "name": { 32 | Type: schema.TypeString, 33 | Required: true, 34 | }, 35 | "description": { 36 | Type: schema.TypeString, 37 | Optional: true, 38 | }, 39 | "organization_id": { 40 | Type: schema.TypeInt, 41 | Required: true, 42 | }, 43 | "credential_type_id": { 44 | Type: schema.TypeInt, 45 | Required: true, 46 | Description: "Specify the type of credential you want to create. Refer to the Ansible Tower documentation for details on each type", 47 | }, 48 | "inputs": { 49 | Type: schema.TypeString, 50 | Required: true, 51 | Sensitive: true, 52 | }, 53 | }, 54 | } 55 | } 56 | 57 | func resourceCredentialCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 58 | var diags diag.Diagnostics 59 | var err error 60 | 61 | inputs := d.Get("inputs").(string) 62 | inputs_map := make(map[string]interface{}) 63 | jsonerr := json.Unmarshal([]byte(inputs), &inputs_map) 64 | 65 | if jsonerr != nil { 66 | diags = append(diags, diag.Diagnostic{ 67 | Severity: diag.Error, 68 | Summary: "Unable to create new credential", 69 | Detail: fmt.Sprintf("Unable to create new credential: %s", jsonerr.Error()), 70 | }) 71 | return diags 72 | } 73 | 74 | newCredential := map[string]interface{}{ 75 | "name": d.Get("name").(string), 76 | "description": d.Get("description").(string), 77 | "organization": d.Get("organization_id").(int), 78 | "credential_type": d.Get("credential_type_id").(int), 79 | "inputs": inputs_map, 80 | } 81 | 82 | client := m.(*awx.AWX) 83 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 84 | if err != nil { 85 | diags = append(diags, diag.Diagnostic{ 86 | Severity: diag.Error, 87 | Summary: "Unable to create new credential", 88 | Detail: fmt.Sprintf("Unable to create new credential: %s", err.Error()), 89 | }) 90 | return diags 91 | } 92 | 93 | d.SetId(strconv.Itoa(cred.ID)) 94 | resourceCredentialRead(ctx, d, m) 95 | 96 | return diags 97 | } 98 | 99 | func resourceCredentialRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 100 | var diags diag.Diagnostics 101 | 102 | client := m.(*awx.AWX) 103 | id, _ := strconv.Atoi(d.Id()) 104 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 105 | if err != nil { 106 | diags = append(diags, diag.Diagnostic{ 107 | Severity: diag.Error, 108 | Summary: "Unable to fetch credential", 109 | Detail: fmt.Sprintf("Unable to credential with id %d: %s", id, err.Error()), 110 | }) 111 | return diags 112 | } 113 | 114 | d.Set("name", cred.Name) 115 | d.Set("description", cred.Description) 116 | d.Set("organization_id", cred.OrganizationID) 117 | d.Set("inputs", cred.Inputs) 118 | 119 | return diags 120 | } 121 | 122 | func resourceCredentialUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 123 | var diags diag.Diagnostics 124 | 125 | keys := []string{ 126 | "name", 127 | "description", 128 | "organization_id", 129 | "inputs", 130 | } 131 | 132 | if d.HasChanges(keys...) { 133 | var err error 134 | 135 | inputs := d.Get("inputs").(string) 136 | inputs_map := make(map[string]interface{}) 137 | jsonerr := json.Unmarshal([]byte(inputs), &inputs_map) 138 | 139 | if jsonerr != nil { 140 | diags = append(diags, diag.Diagnostic{ 141 | Severity: diag.Error, 142 | Summary: "Unable to create new credential", 143 | Detail: fmt.Sprintf("Unable to create new credential: %s", jsonerr.Error()), 144 | }) 145 | return diags 146 | } 147 | 148 | id, _ := strconv.Atoi(d.Id()) 149 | updatedCredential := map[string]interface{}{ 150 | "name": d.Get("name").(string), 151 | "description": d.Get("description").(string), 152 | "organization": d.Get("organization_id").(int), 153 | "credential_type": d.Get("credential_type_id"), 154 | "inputs": inputs_map, 155 | } 156 | 157 | client := m.(*awx.AWX) 158 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 159 | if err != nil { 160 | diags = append(diags, diag.Diagnostic{ 161 | Severity: diag.Error, 162 | Summary: "Unable to update existing credentials", 163 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 164 | }) 165 | return diags 166 | } 167 | } 168 | 169 | return resourceCredentialSCMRead(ctx, d, m) 170 | } 171 | -------------------------------------------------------------------------------- /awx/resource_credential_azure_key_vault.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceCredentialAzureKeyVault() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceCredentialAzureKeyVaultCreate, 26 | ReadContext: resourceCredentialAzureKeyVaultRead, 27 | UpdateContext: resourceCredentialAzureKeyVaultUpdate, 28 | DeleteContext: CredentialsServiceDeleteByID, 29 | Schema: map[string]*schema.Schema{ 30 | "name": { 31 | Type: schema.TypeString, 32 | Required: true, 33 | }, 34 | "description": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | }, 38 | "organization_id": { 39 | Type: schema.TypeInt, 40 | Required: true, 41 | }, 42 | "url": { 43 | Type: schema.TypeString, 44 | Required: true, 45 | }, 46 | "client": { 47 | Type: schema.TypeString, 48 | Required: true, 49 | }, 50 | "secret": { 51 | Type: schema.TypeString, 52 | Required: true, 53 | Sensitive: true, 54 | }, 55 | "tenant": { 56 | Type: schema.TypeString, 57 | Required: true, 58 | }, 59 | }, 60 | } 61 | } 62 | 63 | func resourceCredentialAzureKeyVaultCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 64 | var diags diag.Diagnostics 65 | var err error 66 | 67 | newCredential := map[string]interface{}{ 68 | "name": d.Get("name").(string), 69 | "description": d.Get("description").(string), 70 | "organization": d.Get("organization_id").(int), 71 | "credential_type": 19, // Azure Key Vault 72 | "inputs": map[string]interface{}{ 73 | "url": d.Get("url").(string), 74 | "client": d.Get("client").(string), 75 | "secret": d.Get("secret").(string), 76 | "tenant": d.Get("tenant").(string), 77 | }, 78 | } 79 | 80 | client := m.(*awx.AWX) 81 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 82 | if err != nil { 83 | diags = append(diags, diag.Diagnostic{ 84 | Severity: diag.Error, 85 | Summary: "Unable to create new credentials", 86 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 87 | }) 88 | return diags 89 | } 90 | 91 | d.SetId(strconv.Itoa(cred.ID)) 92 | resourceCredentialAzureKeyVaultRead(ctx, d, m) 93 | 94 | return diags 95 | } 96 | 97 | func resourceCredentialAzureKeyVaultRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 98 | var diags diag.Diagnostics 99 | 100 | client := m.(*awx.AWX) 101 | id, _ := strconv.Atoi(d.Id()) 102 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 103 | if err != nil { 104 | diags = append(diags, diag.Diagnostic{ 105 | Severity: diag.Error, 106 | Summary: "Unable to fetch credentials", 107 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 108 | }) 109 | return diags 110 | } 111 | 112 | d.Set("name", cred.Name) 113 | d.Set("description", cred.Description) 114 | d.Set("organization_id", cred.OrganizationID) 115 | d.Set("url", cred.Inputs["url"]) 116 | d.Set("client", cred.Inputs["client"]) 117 | d.Set("secret", d.Get("secret").(string)) 118 | d.Set("tenant", cred.Inputs["tenant"]) 119 | 120 | return diags 121 | } 122 | 123 | func resourceCredentialAzureKeyVaultUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 124 | var diags diag.Diagnostics 125 | 126 | keys := []string{ 127 | "name", 128 | "description", 129 | "url", 130 | "client", 131 | //"secret", 132 | "tenant", 133 | } 134 | 135 | if d.HasChanges(keys...) { 136 | var err error 137 | 138 | id, _ := strconv.Atoi(d.Id()) 139 | updatedCredential := map[string]interface{}{ 140 | "name": d.Get("name").(string), 141 | "description": d.Get("description").(string), 142 | "organization": d.Get("organization_id").(int), 143 | "credential_type": 19, // Azure Key Vault 144 | "inputs": map[string]interface{}{ 145 | "url": d.Get("url").(string), 146 | "client": d.Get("client").(string), 147 | "secret": d.Get("secret").(string), 148 | "tenant": d.Get("tenant").(string), 149 | }, 150 | } 151 | 152 | client := m.(*awx.AWX) 153 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 154 | if err != nil { 155 | diags = append(diags, diag.Diagnostic{ 156 | Severity: diag.Error, 157 | Summary: "Unable to update existing credentials", 158 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 159 | }) 160 | return diags 161 | } 162 | } 163 | 164 | return resourceCredentialAzureKeyVaultRead(ctx, d, m) 165 | } 166 | -------------------------------------------------------------------------------- /awx/resource_credential_galaxy.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceCredentialGalaxy() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceCredentialGalaxyCreate, 26 | ReadContext: resourceCredentialGalaxyRead, 27 | UpdateContext: resourceCredentialGalaxyUpdate, 28 | DeleteContext: CredentialsServiceDeleteByID, 29 | Schema: map[string]*schema.Schema{ 30 | "name": { 31 | Type: schema.TypeString, 32 | Required: true, 33 | }, 34 | "description": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | }, 38 | "organization_id": { 39 | Type: schema.TypeInt, 40 | Required: true, 41 | }, 42 | "url": { 43 | Type: schema.TypeString, 44 | Required: true, 45 | }, 46 | "auth_url": { 47 | Type: schema.TypeString, 48 | Optional: true, 49 | }, 50 | "token": { 51 | Type: schema.TypeString, 52 | Optional: true, 53 | Sensitive: true, 54 | }, 55 | }, 56 | } 57 | } 58 | 59 | func resourceCredentialGalaxyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 60 | var diags diag.Diagnostics 61 | var err error 62 | 63 | newCredential := map[string]interface{}{ 64 | "name": d.Get("name").(string), 65 | "description": d.Get("description").(string), 66 | "organization": d.Get("organization_id").(int), 67 | "credential_type": 18, // Ansible Galaxy/Automation Hub API Token 68 | "inputs": map[string]interface{}{ 69 | "url": d.Get("url").(string), 70 | "auth_url": d.Get("auth_url").(string), 71 | "token": d.Get("token").(string), 72 | }, 73 | } 74 | 75 | client := m.(*awx.AWX) 76 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 77 | if err != nil { 78 | diags = append(diags, diag.Diagnostic{ 79 | Severity: diag.Error, 80 | Summary: "Unable to create new credentials", 81 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 82 | }) 83 | return diags 84 | } 85 | 86 | d.SetId(strconv.Itoa(cred.ID)) 87 | resourceCredentialGalaxyRead(ctx, d, m) 88 | 89 | return diags 90 | } 91 | 92 | func resourceCredentialGalaxyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 93 | var diags diag.Diagnostics 94 | 95 | client := m.(*awx.AWX) 96 | id, _ := strconv.Atoi(d.Id()) 97 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 98 | if err != nil { 99 | diags = append(diags, diag.Diagnostic{ 100 | Severity: diag.Error, 101 | Summary: "Unable to fetch credentials", 102 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 103 | }) 104 | return diags 105 | } 106 | 107 | d.Set("name", cred.Name) 108 | d.Set("description", cred.Description) 109 | d.Set("url", cred.Inputs["url"]) 110 | d.Set("auth_url", cred.Inputs["auth_url"]) 111 | d.Set("token", cred.Inputs["token"]) 112 | d.Set("organization_id", cred.OrganizationID) 113 | 114 | return diags 115 | } 116 | 117 | func resourceCredentialGalaxyUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 118 | var diags diag.Diagnostics 119 | 120 | keys := []string{ 121 | "name", 122 | "description", 123 | "url", 124 | "auth_url", 125 | "token", 126 | "organization_id", 127 | "team_id", 128 | "owner_id", 129 | } 130 | 131 | if d.HasChanges(keys...) { 132 | var err error 133 | 134 | id, _ := strconv.Atoi(d.Id()) 135 | updatedCredential := map[string]interface{}{ 136 | "name": d.Get("name").(string), 137 | "description": d.Get("description").(string), 138 | "organization": d.Get("organization_id").(int), 139 | "credential_type": 18, // Ansible Galaxy/Automation Hub API Token 140 | "inputs": map[string]interface{}{ 141 | "url": d.Get("url").(string), 142 | "auth_url": d.Get("auth_url").(string), 143 | "token": d.Get("token").(string), 144 | }, 145 | } 146 | 147 | client := m.(*awx.AWX) 148 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 149 | if err != nil { 150 | diags = append(diags, diag.Diagnostic{ 151 | Severity: diag.Error, 152 | Summary: "Unable to update existing credentials", 153 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 154 | }) 155 | return diags 156 | } 157 | } 158 | 159 | return resourceCredentialGalaxyRead(ctx, d, m) 160 | } 161 | -------------------------------------------------------------------------------- /awx/resource_credential_gitlab.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | resource "awx_credential_gitlab" "credential" { 8 | organization_id = awx_organization.default.id 9 | name = "awx-scm-credential" 10 | description = "test" 11 | token = "My_TOKEN" 12 | } 13 | ``` 14 | 15 | */ 16 | package awx 17 | 18 | import ( 19 | "context" 20 | "fmt" 21 | "strconv" 22 | 23 | awx "github.com/denouche/goawx/client" 24 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 25 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 26 | ) 27 | 28 | func resourceCredentialGitlab() *schema.Resource { 29 | return &schema.Resource{ 30 | CreateContext: resourceCredentialGitlabCreate, 31 | ReadContext: resourceCredentialGitlabRead, 32 | UpdateContext: resourceCredentialGitlabUpdate, 33 | DeleteContext: CredentialsServiceDeleteByID, 34 | Schema: map[string]*schema.Schema{ 35 | "name": { 36 | Type: schema.TypeString, 37 | Required: true, 38 | }, 39 | "organization_id": { 40 | Type: schema.TypeInt, 41 | Optional: true, 42 | }, 43 | "description": { 44 | Type: schema.TypeString, 45 | Optional: true, 46 | }, 47 | "token": { 48 | Type: schema.TypeString, 49 | Required: true, 50 | Sensitive: true, 51 | }, 52 | }, 53 | } 54 | } 55 | 56 | func resourceCredentialGitlabCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 57 | var diags diag.Diagnostics 58 | var err error 59 | 60 | newCredential := map[string]interface{}{ 61 | "name": d.Get("name").(string), 62 | "description": d.Get("description").(string), 63 | "organization": d.Get("organization_id").(int), 64 | "credential_type": 12, // GitLab Personal Access Token 65 | "inputs": map[string]interface{}{ 66 | "token": d.Get("token").(string), 67 | }, 68 | } 69 | 70 | client := m.(*awx.AWX) 71 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 72 | if err != nil { 73 | diags = append(diags, diag.Diagnostic{ 74 | Severity: diag.Error, 75 | Summary: "Unable to create new credentials", 76 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 77 | }) 78 | return diags 79 | } 80 | 81 | d.SetId(strconv.Itoa(cred.ID)) 82 | resourceCredentialGitlabRead(ctx, d, m) 83 | 84 | return diags 85 | } 86 | 87 | func resourceCredentialGitlabRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 88 | var diags diag.Diagnostics 89 | 90 | client := m.(*awx.AWX) 91 | id, _ := strconv.Atoi(d.Id()) 92 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 93 | if err != nil { 94 | diags = append(diags, diag.Diagnostic{ 95 | Severity: diag.Error, 96 | Summary: "Unable to fetch credentials", 97 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 98 | }) 99 | return diags 100 | } 101 | 102 | d.Set("name", cred.Name) 103 | d.Set("description", cred.Description) 104 | d.Set("token", cred.Inputs["token"]) 105 | d.Set("organization_id", cred.OrganizationID) 106 | 107 | return diags 108 | } 109 | 110 | func resourceCredentialGitlabUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 111 | var diags diag.Diagnostics 112 | 113 | keys := []string{ 114 | "name", 115 | "description", 116 | "token", 117 | "organization_id", 118 | } 119 | 120 | if d.HasChanges(keys...) { 121 | var err error 122 | 123 | id, _ := strconv.Atoi(d.Id()) 124 | updatedCredential := map[string]interface{}{ 125 | "name": d.Get("name").(string), 126 | "description": d.Get("description").(string), 127 | "organization": d.Get("organization_id").(int), 128 | "credential_type": 12, // GitLab Personal Access Token 129 | "inputs": map[string]interface{}{ 130 | "token": d.Get("token").(string), 131 | }, 132 | } 133 | 134 | client := m.(*awx.AWX) 135 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 136 | if err != nil { 137 | diags = append(diags, diag.Diagnostic{ 138 | Severity: diag.Error, 139 | Summary: "Unable to update existing credentials", 140 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 141 | }) 142 | return diags 143 | } 144 | } 145 | 146 | return resourceCredentialGitlabRead(ctx, d, m) 147 | } 148 | -------------------------------------------------------------------------------- /awx/resource_credential_google_compute_engine.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceCredentialGoogleComputeEngine() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceCredentialGoogleComputeEngineCreate, 26 | ReadContext: resourceCredentialGoogleComputeEngineRead, 27 | UpdateContext: resourceCredentialGoogleComputeEngineUpdate, 28 | DeleteContext: CredentialsServiceDeleteByID, 29 | Schema: map[string]*schema.Schema{ 30 | "name": { 31 | Type: schema.TypeString, 32 | Required: true, 33 | }, 34 | "description": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | }, 38 | "organization_id": { 39 | Type: schema.TypeInt, 40 | Required: true, 41 | }, 42 | "username": { 43 | Type: schema.TypeString, 44 | Required: true, 45 | }, 46 | "project": { 47 | Type: schema.TypeString, 48 | Required: true, 49 | }, 50 | "ssh_key_data": { 51 | Type: schema.TypeString, 52 | Required: true, 53 | Sensitive: true, 54 | }, 55 | }, 56 | } 57 | } 58 | 59 | func resourceCredentialGoogleComputeEngineCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 60 | var diags diag.Diagnostics 61 | var err error 62 | 63 | newCredential := map[string]interface{}{ 64 | "name": d.Get("name").(string), 65 | "description": d.Get("description").(string), 66 | "organization": d.Get("organization_id").(int), 67 | "credential_type": 10, // Google Compute Engine 68 | "inputs": map[string]interface{}{ 69 | "username": d.Get("username").(string), 70 | "project": d.Get("project").(string), 71 | "ssh_key_data": d.Get("ssh_key_data").(string), 72 | }, 73 | } 74 | 75 | client := m.(*awx.AWX) 76 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 77 | if err != nil { 78 | diags = append(diags, diag.Diagnostic{ 79 | Severity: diag.Error, 80 | Summary: "Unable to create new credentials", 81 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 82 | }) 83 | return diags 84 | } 85 | 86 | d.SetId(strconv.Itoa(cred.ID)) 87 | resourceCredentialGoogleComputeEngineRead(ctx, d, m) 88 | 89 | return diags 90 | } 91 | 92 | func resourceCredentialGoogleComputeEngineRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 93 | var diags diag.Diagnostics 94 | 95 | client := m.(*awx.AWX) 96 | id, _ := strconv.Atoi(d.Id()) 97 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 98 | if err != nil { 99 | diags = append(diags, diag.Diagnostic{ 100 | Severity: diag.Error, 101 | Summary: "Unable to fetch credentials", 102 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 103 | }) 104 | return diags 105 | } 106 | 107 | d.Set("name", cred.Name) 108 | d.Set("description", cred.Description) 109 | d.Set("organization_id", cred.OrganizationID) 110 | d.Set("username", cred.Inputs["username"]) 111 | d.Set("project", cred.Inputs["project"]) 112 | 113 | return diags 114 | } 115 | 116 | func resourceCredentialGoogleComputeEngineUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 117 | var diags diag.Diagnostics 118 | 119 | keys := []string{ 120 | "name", 121 | "description", 122 | "username", 123 | "project", 124 | 125 | "ssh_key_data", 126 | } 127 | 128 | if d.HasChanges(keys...) { 129 | var err error 130 | 131 | id, _ := strconv.Atoi(d.Id()) 132 | updatedCredential := map[string]interface{}{ 133 | "name": d.Get("name").(string), 134 | "description": d.Get("description").(string), 135 | "organization": d.Get("organization_id").(int), 136 | "credential_type": 10, // Google Compute Engine 137 | "inputs": map[string]interface{}{ 138 | "username": d.Get("username").(string), 139 | "project": d.Get("project").(string), 140 | "ssh_key_data": d.Get("ssh_key_data").(string), 141 | }, 142 | } 143 | 144 | client := m.(*awx.AWX) 145 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 146 | if err != nil { 147 | diags = append(diags, diag.Diagnostic{ 148 | Severity: diag.Error, 149 | Summary: "Unable to update existing credentials", 150 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 151 | }) 152 | return diags 153 | } 154 | } 155 | 156 | return resourceCredentialGoogleComputeEngineRead(ctx, d, m) 157 | } 158 | -------------------------------------------------------------------------------- /awx/resource_credential_input_source.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceCredentialInputSource() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceCredentialInputSourceCreate, 26 | ReadContext: resourceCredentialInputSourceRead, 27 | UpdateContext: resourceCredentialInputSourceUpdate, 28 | DeleteContext: resourceCredentialInputSourceDelete, 29 | Schema: map[string]*schema.Schema{ 30 | "description": { 31 | Type: schema.TypeString, 32 | Optional: true, 33 | }, 34 | "input_field_name": { 35 | Type: schema.TypeString, 36 | Required: true, 37 | }, 38 | "target": { 39 | Type: schema.TypeInt, 40 | Required: true, 41 | }, 42 | "source": { 43 | Type: schema.TypeInt, 44 | Required: true, 45 | }, 46 | "metadata": { 47 | Type: schema.TypeMap, 48 | Elem: &schema.Schema{ 49 | Type: schema.TypeString, 50 | }, 51 | Optional: true, 52 | }, 53 | }, 54 | } 55 | } 56 | 57 | func resourceCredentialInputSourceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 58 | var diags diag.Diagnostics 59 | var err error 60 | 61 | newSourceInput := map[string]interface{}{ 62 | "description": d.Get("description").(string), 63 | "input_field_name": d.Get("input_field_name").(string), 64 | "target_credential": d.Get("target").(int), 65 | "source_credential": d.Get("source").(int), 66 | "metadata": d.Get("metadata").(map[string]interface{}), 67 | } 68 | 69 | client := m.(*awx.AWX) 70 | cred, err := client.CredentialInputSourceService.CreateCredentialInputSource(newSourceInput, map[string]string{}) 71 | if err != nil { 72 | diags = append(diags, diag.Diagnostic{ 73 | Severity: diag.Error, 74 | Summary: "Unable to create new credentials", 75 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 76 | }) 77 | return diags 78 | } 79 | 80 | d.SetId(strconv.Itoa(cred.ID)) 81 | resourceCredentialInputSourceRead(ctx, d, m) 82 | 83 | return diags 84 | } 85 | 86 | func resourceCredentialInputSourceRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 87 | var diags diag.Diagnostics 88 | 89 | client := m.(*awx.AWX) 90 | id, _ := strconv.Atoi(d.Id()) 91 | inputSource, err := client.CredentialInputSourceService.GetCredentialInputSourceByID(id, map[string]string{}) 92 | if err != nil { 93 | diags = append(diags, diag.Diagnostic{ 94 | Severity: diag.Error, 95 | Summary: "Unable to fetch credentials", 96 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 97 | }) 98 | return diags 99 | } 100 | 101 | d.Set("description", inputSource.Description) 102 | d.Set("input_field_name", inputSource.InputFieldName) 103 | d.Set("target", inputSource.TargetCredential) 104 | d.Set("source", inputSource.SourceCredential) 105 | d.Set("metadata", inputSource.Metadata) 106 | 107 | return diags 108 | } 109 | 110 | func resourceCredentialInputSourceUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 111 | var diags diag.Diagnostics 112 | 113 | keys := []string{ 114 | "description", 115 | "input_field_name", 116 | "target", 117 | "source", 118 | "metadata", 119 | } 120 | 121 | if d.HasChanges(keys...) { 122 | var err error 123 | 124 | id, _ := strconv.Atoi(d.Id()) 125 | updatedSourceInput := map[string]interface{}{ 126 | "description": d.Get("description").(string), 127 | "input_field_name": d.Get("input_field_name").(string), 128 | "target_credential": d.Get("target").(int), 129 | "source_credential": d.Get("source").(int), 130 | "metadata": d.Get("metadata").(map[string]interface{}), 131 | } 132 | 133 | client := m.(*awx.AWX) 134 | _, err = client.CredentialInputSourceService.UpdateCredentialInputSourceByID(id, updatedSourceInput, map[string]string{}) 135 | if err != nil { 136 | diags = append(diags, diag.Diagnostic{ 137 | Severity: diag.Error, 138 | Summary: "Unable to update existing credentials", 139 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 140 | }) 141 | return diags 142 | } 143 | } 144 | 145 | return resourceCredentialInputSourceRead(ctx, d, m) 146 | } 147 | 148 | func resourceCredentialInputSourceDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 149 | var diags diag.Diagnostics 150 | 151 | id, _ := strconv.Atoi(d.Id()) 152 | client := m.(*awx.AWX) 153 | err := client.CredentialInputSourceService.DeleteCredentialInputSourceByID(id, map[string]string{}) 154 | if err != nil { 155 | diags = append(diags, diag.Diagnostic{ 156 | Severity: diag.Error, 157 | Summary: "Unable to delete existing credentials", 158 | Detail: fmt.Sprintf("Unable to delete existing credentials with id %d: %s", id, err.Error()), 159 | }) 160 | } 161 | 162 | return diags 163 | } 164 | -------------------------------------------------------------------------------- /awx/resource_credential_scm.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceCredentialSCM() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceCredentialSCMCreate, 26 | ReadContext: resourceCredentialSCMRead, 27 | UpdateContext: resourceCredentialSCMUpdate, 28 | DeleteContext: CredentialsServiceDeleteByID, 29 | Schema: map[string]*schema.Schema{ 30 | "name": { 31 | Type: schema.TypeString, 32 | Required: true, 33 | }, 34 | "description": { 35 | Type: schema.TypeString, 36 | Optional: true, 37 | }, 38 | "organization_id": { 39 | Type: schema.TypeInt, 40 | Required: true, 41 | }, 42 | "username": { 43 | Type: schema.TypeString, 44 | Optional: true, 45 | }, 46 | "password": { 47 | Type: schema.TypeString, 48 | Optional: true, 49 | Sensitive: true, 50 | }, 51 | "ssh_key_data": { 52 | Type: schema.TypeString, 53 | Optional: true, 54 | Sensitive: true, 55 | }, 56 | "ssh_key_unlock": { 57 | Type: schema.TypeString, 58 | Optional: true, 59 | Sensitive: true, 60 | }, 61 | }, 62 | } 63 | } 64 | 65 | func resourceCredentialSCMCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 66 | var diags diag.Diagnostics 67 | var err error 68 | 69 | newCredential := map[string]interface{}{ 70 | "name": d.Get("name").(string), 71 | "description": d.Get("description").(string), 72 | "organization": d.Get("organization_id").(int), 73 | "credential_type": 2, // Source Controll 74 | "inputs": map[string]interface{}{ 75 | "username": d.Get("username").(string), 76 | "password": d.Get("password").(string), 77 | "ssh_key_data": d.Get("ssh_key_data").(string), 78 | "ssh_key_unlock": d.Get("ssh_key_unlock").(string), 79 | }, 80 | } 81 | 82 | client := m.(*awx.AWX) 83 | cred, err := client.CredentialsService.CreateCredentials(newCredential, map[string]string{}) 84 | if err != nil { 85 | diags = append(diags, diag.Diagnostic{ 86 | Severity: diag.Error, 87 | Summary: "Unable to create new credentials", 88 | Detail: fmt.Sprintf("Unable to create new credentials: %s", err.Error()), 89 | }) 90 | return diags 91 | } 92 | 93 | d.SetId(strconv.Itoa(cred.ID)) 94 | resourceCredentialSCMRead(ctx, d, m) 95 | 96 | return diags 97 | } 98 | 99 | func resourceCredentialSCMRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 100 | var diags diag.Diagnostics 101 | 102 | client := m.(*awx.AWX) 103 | id, _ := strconv.Atoi(d.Id()) 104 | cred, err := client.CredentialsService.GetCredentialsByID(id, map[string]string{}) 105 | if err != nil { 106 | diags = append(diags, diag.Diagnostic{ 107 | Severity: diag.Error, 108 | Summary: "Unable to fetch credentials", 109 | Detail: fmt.Sprintf("Unable to credentials with id %d: %s", id, err.Error()), 110 | }) 111 | return diags 112 | } 113 | 114 | d.Set("name", cred.Name) 115 | d.Set("description", cred.Description) 116 | d.Set("username", cred.Inputs["username"]) 117 | d.Set("password", cred.Inputs["password"]) 118 | d.Set("ssh_key_data", cred.Inputs["ssh_key_data"]) 119 | d.Set("ssh_key_unlock", cred.Inputs["ssh_key_unlock"]) 120 | d.Set("organization_id", cred.OrganizationID) 121 | 122 | return diags 123 | } 124 | 125 | func resourceCredentialSCMUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 126 | var diags diag.Diagnostics 127 | 128 | keys := []string{ 129 | "name", 130 | "description", 131 | "username", 132 | "password", 133 | "ssh_key_data", 134 | "ssh_key_unlock", 135 | "organization_id", 136 | } 137 | 138 | if d.HasChanges(keys...) { 139 | var err error 140 | 141 | id, _ := strconv.Atoi(d.Id()) 142 | updatedCredential := map[string]interface{}{ 143 | "name": d.Get("name").(string), 144 | "description": d.Get("description").(string), 145 | "organization": d.Get("organization_id").(int), 146 | "credential_type": 2, // Source Controll 147 | "inputs": map[string]interface{}{ 148 | "username": d.Get("username").(string), 149 | "password": d.Get("password").(string), 150 | "ssh_key_data": d.Get("ssh_key_data").(string), 151 | "ssh_key_unlock": d.Get("ssh_key_unlock").(string), 152 | }, 153 | } 154 | 155 | client := m.(*awx.AWX) 156 | _, err = client.CredentialsService.UpdateCredentialsByID(id, updatedCredential, map[string]string{}) 157 | if err != nil { 158 | diags = append(diags, diag.Diagnostic{ 159 | Severity: diag.Error, 160 | Summary: "Unable to update existing credentials", 161 | Detail: fmt.Sprintf("Unable to update existing credentials with id %d: %s", id, err.Error()), 162 | }) 163 | return diags 164 | } 165 | } 166 | 167 | return resourceCredentialSCMRead(ctx, d, m) 168 | } 169 | -------------------------------------------------------------------------------- /awx/resource_instance_group.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | *TBD* 8 | ``` 9 | 10 | */ 11 | package awx 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "strconv" 17 | 18 | awx "github.com/denouche/goawx/client" 19 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 20 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 21 | ) 22 | 23 | func resourceInstanceGroup() *schema.Resource { 24 | return &schema.Resource{ 25 | CreateContext: resourceInstanceGroupCreate, 26 | ReadContext: resourceInstanceGroupRead, 27 | UpdateContext: resourceInstanceGroupUpdate, 28 | DeleteContext: resourceInstanceGroupDelete, 29 | 30 | Schema: map[string]*schema.Schema{ 31 | "name": { 32 | Type: schema.TypeString, 33 | Required: true, 34 | }, 35 | "is_container_group": { 36 | Type: schema.TypeBool, 37 | Optional: true, 38 | Default: true, 39 | }, 40 | "policy_instance_minimum": { 41 | Type: schema.TypeInt, 42 | Optional: true, 43 | Default: 0, 44 | }, 45 | "policy_instance_percentage": { 46 | Type: schema.TypeInt, 47 | Optional: true, 48 | Default: 0, 49 | }, 50 | "pod_spec_override": { 51 | Type: schema.TypeString, 52 | Optional: true, 53 | Default: "", 54 | StateFunc: normalizeJsonYaml, 55 | }, 56 | }, 57 | Importer: &schema.ResourceImporter{ 58 | State: schema.ImportStatePassthrough, 59 | }, 60 | } 61 | } 62 | 63 | func resourceInstanceGroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 64 | 65 | client := m.(*awx.AWX) 66 | awxService := client.InstanceGroupsService 67 | 68 | result, err := awxService.CreateInstanceGroup(map[string]interface{}{ 69 | "name": d.Get("name").(string), 70 | "policy_instance_minimum": d.Get("policy_instance_minimum").(int), 71 | "is_container_group": d.Get("is_container_group").(bool), 72 | "policy_instance_percentage": d.Get("policy_instance_percentage").(int), 73 | "pod_spec_override": d.Get("pod_spec_override").(string), 74 | }, map[string]string{}) 75 | if err != nil { 76 | return buildDiagCreateFail(diagElementInstanceGroupTitle, err) 77 | } 78 | 79 | d.SetId(strconv.Itoa(result.ID)) 80 | return resourceInstanceGroupRead(ctx, d, m) 81 | 82 | } 83 | 84 | func resourceInstanceGroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 85 | client := m.(*awx.AWX) 86 | awxService := client.InstanceGroupsService 87 | id, diags := convertStateIDToNummeric(diagElementInstanceGroupTitle, d) 88 | if diags.HasError() { 89 | return diags 90 | } 91 | 92 | _, err := awxService.UpdateInstanceGroup(id, map[string]interface{}{ 93 | "name": d.Get("name").(string), 94 | "policy_instance_minimum": d.Get("policy_instance_minimum").(int), 95 | "is_container_group": d.Get("is_container_group").(bool), 96 | "policy_instance_percentage": d.Get("policy_instance_percentage").(int), 97 | "pod_spec_override": d.Get("pod_spec_override").(string), 98 | }, nil) 99 | if err != nil { 100 | return buildDiagUpdateFail(diagElementInstanceGroupTitle, id, err) 101 | } 102 | 103 | return resourceInstanceGroupRead(ctx, d, m) 104 | 105 | } 106 | 107 | func resourceInstanceGroupDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 108 | client := m.(*awx.AWX) 109 | awxService := client.InstanceGroupsService 110 | 111 | id, diags := convertStateIDToNummeric(diagElementInstanceGroupTitle, d) 112 | if diags.HasError() { 113 | return diags 114 | } 115 | 116 | if _, err := awxService.DeleteInstanceGroup(id); err != nil { 117 | return buildDiagDeleteFail( 118 | diagElementInstanceGroupTitle, 119 | fmt.Sprintf("ID: %v, got %s ", 120 | id, err.Error())) 121 | } 122 | d.SetId("") 123 | return nil 124 | } 125 | 126 | func resourceInstanceGroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { 127 | var diags diag.Diagnostics 128 | client := m.(*awx.AWX) 129 | awxService := client.InstanceGroupsService 130 | 131 | id, diags := convertStateIDToNummeric(diagElementInstanceGroupTitle, d) 132 | if diags.HasError() { 133 | return diags 134 | } 135 | 136 | res, err := awxService.GetInstanceGroupByID(id, make(map[string]string)) 137 | if err != nil { 138 | return buildDiagNotFoundFail(diagElementInstanceGroupTitle, id, err) 139 | } 140 | d = setInstanceGroupResourceData(d, res) 141 | return diags 142 | } 143 | 144 | func setInstanceGroupResourceData(d *schema.ResourceData, r *awx.InstanceGroup) *schema.ResourceData { 145 | d.Set("name", r.Name) 146 | d.Set("is_container_group", r.IsContainerGroup) 147 | d.Set("pod_spec_override", normalizeJsonYaml(r.PodSpecOverride)) 148 | 149 | d.SetId(strconv.Itoa(r.ID)) 150 | return d 151 | } 152 | -------------------------------------------------------------------------------- /awx/resource_inventory.go: -------------------------------------------------------------------------------- 1 | /* 2 | *TBD* 3 | 4 | Example Usage 5 | 6 | ```hcl 7 | data "awx_organization" "default" { 8 | name = "Default" 9 | } 10 | 11 | resource "awx_inventory" "default" { 12 | name = "acc-test" 13 | organization_id = data.awx_organization.default.id 14 | variables = < ⚠️ Be careful, if you set both token and username/password the token will have the precedence. 26 | 27 | ## Argument Reference 28 | 29 | The following arguments are supported: 30 | 31 | * `hostname` - (Optional) The API endpoint for AWX. Defaults to `"http://localhost"`. 32 | * `username` - (Optional) The username for API access. Defaults to `"admin"`. 33 | * `password` - (Optional) The password for API access. Defaults to `"password"`. 34 | * `token` - (Optional) The AWX token for API access. Defaults to empty. 35 | * `insecure` - (Optional) Whether to check the TLS certificate. Defaults to `false`. 36 | -------------------------------------------------------------------------------- /docs/resources/credential.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential" 4 | sidebar_current: "docs-awx-resource-credential" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `credential_type_id` - (Required) Specify the type of credential you want to create. Refer to the Ansible Tower documentation for details on each type 24 | * `inputs` - (Required) 25 | * `name` - (Required) 26 | * `organization_id` - (Required) 27 | * `description` - (Optional) 28 | 29 | -------------------------------------------------------------------------------- /docs/resources/credential_azure_key_vault.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_azure_key_vault" 4 | sidebar_current: "docs-awx-resource-credential_azure_key_vault" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_azure_key_vault 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `client` - (Required) 24 | * `name` - (Required) 25 | * `organization_id` - (Required) 26 | * `secret` - (Required) 27 | * `tenant` - (Required) 28 | * `url` - (Required) 29 | * `description` - (Optional) 30 | 31 | -------------------------------------------------------------------------------- /docs/resources/credential_google_compute_engine.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_google_compute_engine" 4 | sidebar_current: "docs-awx-resource-credential_google_compute_engine" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_google_compute_engine 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `name` - (Required) 24 | * `organization_id` - (Required) 25 | * `project` - (Required) 26 | * `ssh_key_data` - (Required) 27 | * `username` - (Required) 28 | * `description` - (Optional) 29 | 30 | -------------------------------------------------------------------------------- /docs/resources/credential_input_source.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_input_source" 4 | sidebar_current: "docs-awx-resource-credential_input_source" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_input_source 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `input_field_name` - (Required) 24 | * `source` - (Required) 25 | * `target` - (Required) 26 | * `description` - (Optional) 27 | * `metadata` - (Optional) 28 | 29 | -------------------------------------------------------------------------------- /docs/resources/credential_machine.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_machine" 4 | sidebar_current: "docs-awx-resource-credential_machine" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_machine 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `name` - (Required) 24 | * `organization_id` - (Required) 25 | * `become_method` - (Optional) 26 | * `become_password` - (Optional) 27 | * `become_username` - (Optional) 28 | * `description` - (Optional) 29 | * `password` - (Optional) 30 | * `ssh_key_data` - (Optional) 31 | * `ssh_key_unlock` - (Optional) 32 | * `ssh_public_key_data` - (Optional) 33 | * `username` - (Optional) 34 | 35 | -------------------------------------------------------------------------------- /docs/resources/credential_scm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_scm" 4 | sidebar_current: "docs-awx-resource-credential_scm" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_scm 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `name` - (Required) 24 | * `organization_id` - (Required) 25 | * `description` - (Optional) 26 | * `password` - (Optional) 27 | * `ssh_key_data` - (Optional) 28 | * `ssh_key_unlock` - (Optional) 29 | * `username` - (Optional) 30 | 31 | -------------------------------------------------------------------------------- /docs/resources/credential_type.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_credential_type" 4 | sidebar_current: "docs-awx-resource-credential_type" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_credential_type 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | *TBD* 17 | ``` 18 | 19 | ## Argument Reference 20 | 21 | The following arguments are supported: 22 | 23 | * `injectors` - (Required) 24 | * `inputs` - (Required) 25 | * `name` - (Required) Name of this credential type. 26 | * `description` - (Optional) Optional description of this credential type. 27 | * `kind` - (Optional) Choices cloud or net 28 | 29 | -------------------------------------------------------------------------------- /docs/resources/host.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "awx" 3 | page_title: "AWX: awx_host" 4 | sidebar_current: "docs-awx-resource-host" 5 | description: |- 6 | *TBD* 7 | --- 8 | 9 | # awx_host 10 | 11 | *TBD* 12 | 13 | ## Example Usage 14 | 15 | ```hcl 16 | resource "awx_host" "k3snode1" { 17 | name = "k3snode1" 18 | description = "pi node 1" 19 | inventory_id = data.awx_inventory.default.id 20 | group_ids = [ 21 | data.awx_inventory_group.default.id, 22 | data.awx_inventory_group.pinodes.id, 23 | ] 24 | enabled = true 25 | variables = < ../. 47 | -------------------------------------------------------------------------------- /tools/installAwx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "==> Install Operator..." 3 | kubectl apply -f https://raw.githubusercontent.com/ansible/awx-operator/devel/deploy/awx-operator.yaml 4 | 5 | echo "==> Wait Operator started..." 6 | kubectl wait --for=condition=ready pod -l name=awx-operator 7 | 8 | echo "==> Starting AWX Test installation..." 9 | kubectl create ns ansible-awx 10 | # kubectl delete AWX awx -n ansible-awx 11 | KUBENODE_IP=$(kubectl get node -ojson | jq '.items[0].status.addresses[0].address' -r) 12 | INGRESS_DOMAIN="${KUBENODE_IP}.sslip.io" 13 | 14 | cat < Waiting Operator Started the AWX Deployment..." 31 | sleep 45 32 | 33 | echo "==> Waiting AWX full Started..." 34 | kubectl wait --for=condition=ready pod -l app=awx -n ansible-awx --timeout=800s 35 | -------------------------------------------------------------------------------- /tools/mage.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | 8 | "github.com/magefile/mage/mage" 9 | ) 10 | 11 | func main() { os.Exit(mage.Main()) } 12 | -------------------------------------------------------------------------------- /tools/magefile.go: -------------------------------------------------------------------------------- 1 | //go:build mage 2 | // +build mage 3 | 4 | package main 5 | 6 | import ( 7 | "context" 8 | "log" 9 | 10 | "github.com/magefile/mage/mg" 11 | "github.com/magefile/mage/sh" 12 | 13 | tools "github.com/denouche/terraform-provider-awx/tools" 14 | 15 | // mage:import 16 | "github.com/nolte/plumbing/cmd/kind" 17 | _ "github.com/nolte/plumbing/cmd/kind" 18 | ) 19 | 20 | func check(e error) { 21 | if e != nil { 22 | panic(e) 23 | } 24 | } 25 | 26 | // Delete the cluster. 27 | func InstallAWX() error { 28 | log.Printf("InstallAWX to Kind Cluster") 29 | 30 | return sh.Run( 31 | "sh", "./installAwx.sh") 32 | } 33 | func GenDocumentation() error { 34 | return tools.GenerateProviderCoumentation() 35 | } 36 | 37 | // ReCreate a kind Cluster with Awx support. 38 | func ReCreate(ctx context.Context) { 39 | log.Printf("Create Kind Cluster with AWX") 40 | mg.CtxDeps(ctx, kind.Kind.Recreate) 41 | mg.CtxDeps(ctx, InstallAWX) 42 | } 43 | -------------------------------------------------------------------------------- /tools/template.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | const ( 4 | docTPL = `--- 5 | layout: "{{.cloud_mark}}" 6 | page_title: "{{.cloud_title}}: {{.name}}" 7 | sidebar_current: "docs-{{.cloud_mark}}-{{.dtype}}-{{.resource}}" 8 | description: |- 9 | {{.description_short}} 10 | --- 11 | 12 | # {{.name}} 13 | 14 | {{.description}} 15 | 16 | ## Example Usage 17 | 18 | {{.example}} 19 | 20 | ## Argument Reference 21 | 22 | The following arguments are supported: 23 | 24 | {{.arguments}} 25 | {{ if ne .attributes ""}} 26 | ## Attributes Reference 27 | 28 | In addition to all arguments above, the following attributes are exported: 29 | 30 | {{.attributes}} 31 | {{- end}} 32 | {{- if ne .import ""}} 33 | ## Import 34 | 35 | {{.import}} 36 | {{- end}} 37 | ` 38 | idxTPL = ` 39 | <% wrap_layout :inner do %> 40 | <% content_for :sidebar do %> 41 | 62 | <% end %> 63 | <%= yield %> 64 | <% end %> 65 | ` 66 | ) 67 | --------------------------------------------------------------------------------