mirror of
https://github.com/ansible/awx.git
synced 2026-02-05 03:24:50 -03:30
Compare commits
178 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fdf491c05 | ||
|
|
ef1563283e | ||
|
|
a206d79851 | ||
|
|
42c9c0a06b | ||
|
|
f0ede01017 | ||
|
|
d67007f777 | ||
|
|
83d81e3788 | ||
|
|
e789e16289 | ||
|
|
61c9683aa6 | ||
|
|
ee9d1356b2 | ||
|
|
f92a49fda9 | ||
|
|
3dc6a055ac | ||
|
|
229f0d97f9 | ||
|
|
7cc530f950 | ||
|
|
2ef840ce12 | ||
|
|
a372d8d1d5 | ||
|
|
be13a11dd5 | ||
|
|
59c6f35b0b | ||
|
|
37e45c5e7c | ||
|
|
aec7ac6ebd | ||
|
|
f6e63d0917 | ||
|
|
0ae67edaba | ||
|
|
481f6435ee | ||
|
|
d0c5c3d3cf | ||
|
|
9f8250bd47 | ||
|
|
3a3fffb2dd | ||
|
|
4cfa4eaf8e | ||
|
|
abb1125a2c | ||
|
|
a2acbe9fe6 | ||
|
|
cab8c690d2 | ||
|
|
0d1f8a06ce | ||
|
|
d42fe921db | ||
|
|
db7fb81855 | ||
|
|
d3c695b853 | ||
|
|
010c3ab0b8 | ||
|
|
58cdbca5cf | ||
|
|
8275082896 | ||
|
|
d79da1ef9f | ||
|
|
a9636426b8 | ||
|
|
329caad681 | ||
|
|
ecb84e090c | ||
|
|
8e9fc14b0e | ||
|
|
0f77ca605d | ||
|
|
231fcc8178 | ||
|
|
2839091b22 | ||
|
|
47e67481b3 | ||
|
|
55059b015f | ||
|
|
eb6c58682d | ||
|
|
26055de772 | ||
|
|
ebb4581595 | ||
|
|
d1fecc11c9 | ||
|
|
056247a34a | ||
|
|
7010015e8a | ||
|
|
62d50d27be | ||
|
|
1e5231d68b | ||
|
|
e04efad3c0 | ||
|
|
e54db3ce50 | ||
|
|
77076dbd67 | ||
|
|
6f20a798ab | ||
|
|
0d3a22bbc3 | ||
|
|
f34c96ecf5 | ||
|
|
206c85778e | ||
|
|
d6b4b9f973 | ||
|
|
3065e29deb | ||
|
|
481047bed8 | ||
|
|
f72292cce2 | ||
|
|
7b35902d33 | ||
|
|
1660900914 | ||
|
|
a7be25ce8b | ||
|
|
54b5ba08b8 | ||
|
|
0fb8d48074 | ||
|
|
b5fac4157d | ||
|
|
9e61949f9f | ||
|
|
6c5640798f | ||
|
|
03222197a3 | ||
|
|
12f417d0a3 | ||
|
|
c77aaece1d | ||
|
|
25140c9072 | ||
|
|
3a636c29ab | ||
|
|
a11d5ccd37 | ||
|
|
f6e7937f74 | ||
|
|
e447b667e5 | ||
|
|
24c635e9bc | ||
|
|
2ad4dcd741 | ||
|
|
f5cd9e0799 | ||
|
|
e7064868b4 | ||
|
|
65cbbf15c9 | ||
|
|
a325509e1e | ||
|
|
69ae731898 | ||
|
|
3452dee1b0 | ||
|
|
64b337e3c6 | ||
|
|
5df9655fe3 | ||
|
|
f3669f3be6 | ||
|
|
61eb99c46d | ||
|
|
f74a14e34f | ||
|
|
517f1d7991 | ||
|
|
25e69885d0 | ||
|
|
60a357eda1 | ||
|
|
d74679a5f9 | ||
|
|
73a865073d | ||
|
|
4ff8c28fe4 | ||
|
|
4ab2539c8a | ||
|
|
459eb3903e | ||
|
|
611a537b55 | ||
|
|
3a74cc5a74 | ||
|
|
f1520e1a70 | ||
|
|
727b4668c2 | ||
|
|
1287e001d8 | ||
|
|
c9b53cf975 | ||
|
|
64811d0b6b | ||
|
|
74af187568 | ||
|
|
a28c023cf1 | ||
|
|
cdf7fd64b2 | ||
|
|
84ffa4a5b7 | ||
|
|
326a43de11 | ||
|
|
07f193d8d6 | ||
|
|
f79a57c3e2 | ||
|
|
f8319fcd02 | ||
|
|
815ef4c9c9 | ||
|
|
d1800aa6d0 | ||
|
|
dda940344e | ||
|
|
1fffeb430c | ||
|
|
7d0bbd0a4c | ||
|
|
15fd22681d | ||
|
|
6a2826b91c | ||
|
|
112111c7f9 | ||
|
|
ed8498f43f | ||
|
|
77a5bb9069 | ||
|
|
37f86803f7 | ||
|
|
160858b051 | ||
|
|
68f44c01ea | ||
|
|
bef8d7426f | ||
|
|
c758f079cd | ||
|
|
7e404b7c19 | ||
|
|
4b7faea552 | ||
|
|
4ddd391033 | ||
|
|
e52416fd47 | ||
|
|
f67a2d2f46 | ||
|
|
fcdda8d7a7 | ||
|
|
1f0b936e82 | ||
|
|
b70793db5c | ||
|
|
0f044f6c21 | ||
|
|
4c205dfde9 | ||
|
|
d58d460119 | ||
|
|
24a6edef9e | ||
|
|
a5485096ac | ||
|
|
60a5ccf70b | ||
|
|
d93a7c2997 | ||
|
|
af5f8e8a4a | ||
|
|
1596c855ff | ||
|
|
f45dd7a748 | ||
|
|
a036363e85 | ||
|
|
4aceea41fd | ||
|
|
7bbfcbaefd | ||
|
|
18eaa9bb92 | ||
|
|
6826d5444b | ||
|
|
622ec69216 | ||
|
|
d38c109d49 | ||
|
|
a31b2d0259 | ||
|
|
b13c076881 | ||
|
|
c429a55382 | ||
|
|
20c4b21c39 | ||
|
|
d3289dc688 | ||
|
|
685c0b844e | ||
|
|
57c9b14198 | ||
|
|
d0a13cb12a | ||
|
|
71c72f74a1 | ||
|
|
ad24fe7017 | ||
|
|
e5578a8ef3 | ||
|
|
3a40d5e243 | ||
|
|
8e34898b4e | ||
|
|
0b0d049071 | ||
|
|
9e74ac24fa | ||
|
|
cbe612baa5 | ||
|
|
899d36b2c9 | ||
|
|
530977d6b3 | ||
|
|
aa682fa2c9 | ||
|
|
e3893b1887 |
@@ -1,2 +1,3 @@
|
||||
awx/ui/node_modules
|
||||
Dockerfile
|
||||
.git
|
||||
|
||||
52
.github/workflows/ci.yml
vendored
52
.github/workflows/ci.yml
vendored
@@ -4,8 +4,6 @@ env:
|
||||
BRANCH: ${{ github.base_ref || 'devel' }}
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [devel]
|
||||
jobs:
|
||||
api-test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -21,7 +19,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -45,7 +43,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -93,7 +91,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -117,7 +115,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -141,7 +139,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -165,7 +163,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -175,3 +173,41 @@ jobs:
|
||||
run: |
|
||||
docker run -u $(id -u) --rm -v ${{ github.workspace}}:/awx_devel/:Z \
|
||||
--workdir=/awx_devel ghcr.io/${{ github.repository_owner }}/awx_devel:${{ env.BRANCH }} make ui-test
|
||||
awx-operator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout awx
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: awx
|
||||
|
||||
- name: Checkout awx-operator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ansible/awx-operator
|
||||
path: awx-operator
|
||||
|
||||
- name: Install playbook dependencies
|
||||
run: |
|
||||
python3 -m pip install docker
|
||||
|
||||
- name: Build AWX image
|
||||
working-directory: awx
|
||||
run: |
|
||||
ansible-playbook -v tools/ansible/build.yml \
|
||||
-e headless=yes \
|
||||
-e awx_image=awx \
|
||||
-e awx_image_tag=ci \
|
||||
-e ansible_python_interpreter=$(which python3)
|
||||
|
||||
- name: Run test deployment with awx-operator
|
||||
working-directory: awx-operator
|
||||
run: |
|
||||
python3 -m pip install -r molecule/requirements.txt
|
||||
ansible-galaxy collection install -r molecule/requirements.yml
|
||||
sudo rm -f $(which kustomize)
|
||||
make kustomize
|
||||
KUSTOMIZE_PATH=$(readlink -f bin/kustomize) molecule test -s kind
|
||||
env:
|
||||
AWX_TEST_IMAGE: awx
|
||||
AWX_TEST_VERSION: ci
|
||||
|
||||
2
.github/workflows/e2e_test.yml
vendored
2
.github/workflows/e2e_test.yml
vendored
@@ -85,7 +85,7 @@ jobs:
|
||||
-e CYPRESS_baseUrl="https://$AWX_IP:8043" \
|
||||
-e CYPRESS_AWX_E2E_USERNAME=admin \
|
||||
-e CYPRESS_AWX_E2E_PASSWORD='password' \
|
||||
-e COMMAND="npm run cypress-gha" \
|
||||
-e COMMAND="npm run cypress-concurrently-gha" \
|
||||
-v /dev/shm:/dev/shm \
|
||||
-v $PWD:/e2e \
|
||||
-w /e2e \
|
||||
|
||||
26
.github/workflows/promote.yml
vendored
Normal file
26
.github/workflows/promote.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: Promote Release
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
promote:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Log in to Quay
|
||||
run: |
|
||||
echo ${{ secrets.QUAY_TOKEN }} | docker login quay.io -u ${{ secrets.QUAY_USER }} --password-stdin
|
||||
|
||||
- name: Re-tag and promote awx image
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker tag ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} quay.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker tag ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} quay.io/${{ github.repository }}:latest
|
||||
docker push quay.io/${{ github.repository }}:${{ github.event.release.tag_name }}
|
||||
docker push quay.io/${{ github.repository }}:latest
|
||||
|
||||
56
.github/workflows/release.yml
vendored
56
.github/workflows/release.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: Release AWX
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version'
|
||||
required: true
|
||||
default: ''
|
||||
confirm:
|
||||
description: 'Are you sure? Set this to yes.'
|
||||
required: true
|
||||
default: 'no'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: "Verify inputs"
|
||||
run: |
|
||||
set -e
|
||||
|
||||
if [[ ${{ github.event.inputs.confirm }} != "yes" ]]; then
|
||||
>&2 echo "Confirm must be 'yes'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${{ github.event.inputs.version }} == "" ]]; then
|
||||
>&2 echo "Set version to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
- name: Generate changelog
|
||||
uses: shanemcd/simple-changelog-generator@v1
|
||||
id: changelog
|
||||
with:
|
||||
repo: "${{ github.repository }}"
|
||||
|
||||
- name: Write changelog to file
|
||||
run: |
|
||||
cat << 'EOF' > /tmp/changelog
|
||||
${{ steps.changelog.outputs.changelog }}
|
||||
EOF
|
||||
|
||||
- name: Release AWX
|
||||
run: |
|
||||
ansible-playbook -v tools/ansible/release.yml \
|
||||
-e changelog_path=/tmp/changelog \
|
||||
-e version=${{ github.event.inputs.version }} \
|
||||
-e github_token=${{ secrets.GITHUB_TOKEN }} \
|
||||
-e repo=${{ github.repository }}
|
||||
|
||||
|
||||
123
.github/workflows/stage.yml
vendored
Normal file
123
.github/workflows/stage.yml
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
name: Stage Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'AWX version.'
|
||||
required: true
|
||||
default: ''
|
||||
operator_version:
|
||||
description: 'Operator version. Leave blank to skip staging awx-operator.'
|
||||
default: ''
|
||||
confirm:
|
||||
description: 'Are you sure? Set this to yes.'
|
||||
required: true
|
||||
default: 'no'
|
||||
|
||||
jobs:
|
||||
stage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: write
|
||||
steps:
|
||||
- name: Verify inputs
|
||||
run: |
|
||||
set -e
|
||||
|
||||
if [[ ${{ github.event.inputs.confirm }} != "yes" ]]; then
|
||||
>&2 echo "Confirm must be 'yes'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${{ github.event.inputs.version }} == "" ]]; then
|
||||
>&2 echo "Set version to continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
- name: Checkout awx
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: awx
|
||||
|
||||
- name: Checkout awx-logos
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ansible/awx-logos
|
||||
path: awx-logos
|
||||
|
||||
- name: Checkout awx-operator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/awx-operator
|
||||
path: awx-operator
|
||||
|
||||
- name: Install playbook dependencies
|
||||
run: |
|
||||
python3 -m pip install docker
|
||||
|
||||
- name: Build and stage AWX
|
||||
working-directory: awx
|
||||
run: |
|
||||
ansible-playbook -v tools/ansible/build.yml \
|
||||
-e registry=ghcr.io \
|
||||
-e registry_username=${{ github.actor }} \
|
||||
-e registry_password=${{ secrets.GITHUB_TOKEN }} \
|
||||
-e awx_image=${{ github.repository }} \
|
||||
-e awx_version=${{ github.event.inputs.version }} \
|
||||
-e ansible_python_interpreter=$(which python3) \
|
||||
-e push=yes \
|
||||
-e awx_official=yes
|
||||
|
||||
- name: Build and stage awx-operator
|
||||
working-directory: awx-operator
|
||||
run: |
|
||||
BUILD_ARGS="--build-arg DEFAULT_AWX_VERSION=${{ github.event.inputs.version }}" \
|
||||
IMAGE_TAG_BASE=ghcr.io/${{ github.repository_owner }}/awx-operator \
|
||||
VERSION=${{ github.event.inputs.operator_version }} make docker-build docker-push
|
||||
|
||||
- name: Run test deployment with awx-operator
|
||||
working-directory: awx-operator
|
||||
run: |
|
||||
python3 -m pip install -r molecule/requirements.txt
|
||||
ansible-galaxy collection install -r molecule/requirements.yml
|
||||
sudo rm -f $(which kustomize)
|
||||
make kustomize
|
||||
KUSTOMIZE_PATH=$(readlink -f bin/kustomize) molecule test -s kind
|
||||
env:
|
||||
AWX_TEST_IMAGE: ${{ github.repository }}
|
||||
AWX_TEST_VERSION: ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Generate changelog
|
||||
uses: shanemcd/simple-changelog-generator@v1
|
||||
id: changelog
|
||||
with:
|
||||
repo: "${{ github.repository }}"
|
||||
|
||||
- name: Write changelog to file
|
||||
run: |
|
||||
cat << 'EOF' > /tmp/awx-changelog
|
||||
${{ steps.changelog.outputs.changelog }}
|
||||
EOF
|
||||
|
||||
- name: Create draft release for AWX
|
||||
working-directory: awx
|
||||
run: |
|
||||
ansible-playbook -v tools/ansible/stage.yml \
|
||||
-e changelog_path=/tmp/awx-changelog \
|
||||
-e repo=${{ github.repository }} \
|
||||
-e awx_image=ghcr.io/${{ github.repository }} \
|
||||
-e version=${{ github.event.inputs.version }} \
|
||||
-e github_token=${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create draft release for awx-operator
|
||||
if: ${{ github.event.inputs.operator_version != '' }}
|
||||
working-directory: awx
|
||||
run: |
|
||||
ansible-playbook tools/ansible/stage.yml \
|
||||
-e version=${{ github.event.inputs.operator_version }} \
|
||||
-e repo=${{ github.repository_owner }}/awx-operator \
|
||||
-e github_token=${{ secrets.AWX_OPERATOR_RELEASE_TOKEN }}
|
||||
2
.github/workflows/upload_schema.yml
vendored
2
.github/workflows/upload_schema.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
- name: Pre-pull image to warm build cache
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${GITHUB_REF##*/}
|
||||
docker pull ghcr.io/${{ github.repository_owner }}/awx_devel:${GITHUB_REF##*/} || :
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -58,6 +58,7 @@ __pycache__
|
||||
/dist
|
||||
/*.egg-info
|
||||
*.py[c,o]
|
||||
/.eggs
|
||||
|
||||
# JavaScript
|
||||
/Gruntfile.js
|
||||
|
||||
@@ -6,8 +6,11 @@ ignore: |
|
||||
# vault files
|
||||
awx/main/tests/data/ansible_utils/playbooks/valid/vault.yml
|
||||
awx/ui/test/e2e/tests/smoke-vars.yml
|
||||
awx/ui/node_modules
|
||||
tools/docker-compose/_sources
|
||||
|
||||
extends: default
|
||||
|
||||
rules:
|
||||
line-length: disable
|
||||
truthy: disable
|
||||
|
||||
@@ -110,7 +110,7 @@ For feature work, take a look at the current [Enhancements](https://github.com/a
|
||||
|
||||
If it has someone assigned to it then that person is the person responsible for working the enhancement. If you feel like you could contribute then reach out to that person.
|
||||
|
||||
Fixing bugs, adding translations, and updating the documentation are always appreciated, so reviewing the backlog of issues is always a good place to start. For extra information on debugging tools, see [Debugging](https://github.com/ansible/awx/blob/devel/docs/debugging.md).
|
||||
Fixing bugs, adding translations, and updating the documentation are always appreciated, so reviewing the backlog of issues is always a good place to start. For extra information on debugging tools, see [Debugging](./docs/debugging/).
|
||||
|
||||
**NOTE**
|
||||
|
||||
|
||||
43
Makefile
43
Makefile
@@ -6,7 +6,8 @@ NPM_BIN ?= npm
|
||||
CHROMIUM_BIN=/tmp/chrome-linux/chrome
|
||||
GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
MANAGEMENT_COMMAND ?= awx-manage
|
||||
VERSION := $(shell cat VERSION)
|
||||
VERSION := $(shell $(PYTHON) setup.py --version)
|
||||
COLLECTION_VERSION := $(shell $(PYTHON) setup.py --version | cut -d . -f 1-3)
|
||||
|
||||
# NOTE: This defaults the container image version to the branch that's active
|
||||
COMPOSE_TAG ?= $(GIT_BRANCH)
|
||||
@@ -23,7 +24,7 @@ DEVEL_IMAGE_NAME ?= $(DEV_DOCKER_TAG_BASE)/awx_devel:$(COMPOSE_TAG)
|
||||
SRC_ONLY_PKGS ?= cffi,pycparser,psycopg2,twilio
|
||||
# These should be upgraded in the AWX and Ansible venv before attempting
|
||||
# to install the actual requirements
|
||||
VENV_BOOTSTRAP ?= pip==19.3.1 setuptools==41.6.0 wheel==0.36.2
|
||||
VENV_BOOTSTRAP ?= pip==21.2.4 setuptools==58.2.0 wheel==0.36.2
|
||||
|
||||
NAME ?= awx
|
||||
|
||||
@@ -290,7 +291,6 @@ test:
|
||||
. $(VENV_BASE)/awx/bin/activate; \
|
||||
fi; \
|
||||
PYTHONDONTWRITEBYTECODE=1 py.test -p no:cacheprovider -n auto $(TEST_DIRS)
|
||||
cmp VERSION awxkit/VERSION || "VERSION and awxkit/VERSION *must* match"
|
||||
cd awxkit && $(VENV_BASE)/awx/bin/tox -re py3
|
||||
awx-manage check_migrations --dry-run --check -n 'missing_migration_file'
|
||||
|
||||
@@ -322,12 +322,16 @@ symlink_collection:
|
||||
ln -s $(shell pwd)/awx_collection $(COLLECTION_INSTALL)
|
||||
|
||||
build_collection:
|
||||
ansible-playbook -i localhost, awx_collection/tools/template_galaxy.yml -e collection_package=$(COLLECTION_PACKAGE) -e collection_namespace=$(COLLECTION_NAMESPACE) -e collection_version=$(VERSION) -e '{"awx_template_version":false}'
|
||||
ansible-playbook -i localhost, awx_collection/tools/template_galaxy.yml \
|
||||
-e collection_package=$(COLLECTION_PACKAGE) \
|
||||
-e collection_namespace=$(COLLECTION_NAMESPACE) \
|
||||
-e collection_version=$(COLLECTION_VERSION) \
|
||||
-e '{"awx_template_version":false}'
|
||||
ansible-galaxy collection build awx_collection_build --force --output-path=awx_collection_build
|
||||
|
||||
install_collection: build_collection
|
||||
rm -rf $(COLLECTION_INSTALL)
|
||||
ansible-galaxy collection install awx_collection_build/$(COLLECTION_NAMESPACE)-$(COLLECTION_PACKAGE)-$(VERSION).tar.gz
|
||||
ansible-galaxy collection install awx_collection_build/$(COLLECTION_NAMESPACE)-$(COLLECTION_PACKAGE)-$(COLLECTION_VERSION).tar.gz
|
||||
|
||||
test_collection_sanity: install_collection
|
||||
cd $(COLLECTION_INSTALL) && ansible-test sanity
|
||||
@@ -380,7 +384,7 @@ clean-ui:
|
||||
awx/ui/node_modules:
|
||||
NODE_OPTIONS=--max-old-space-size=4096 $(NPM_BIN) --prefix awx/ui --loglevel warn ci
|
||||
|
||||
$(UI_BUILD_FLAG_FILE):
|
||||
$(UI_BUILD_FLAG_FILE): awx/ui/node_modules
|
||||
$(PYTHON) tools/scripts/compilemessages.py
|
||||
$(NPM_BIN) --prefix awx/ui --loglevel warn run compile-strings
|
||||
$(NPM_BIN) --prefix awx/ui --loglevel warn run build
|
||||
@@ -392,7 +396,9 @@ $(UI_BUILD_FLAG_FILE):
|
||||
cp -r awx/ui/build/static/media/* awx/public/static/media
|
||||
touch $@
|
||||
|
||||
ui-release: awx/ui/node_modules $(UI_BUILD_FLAG_FILE)
|
||||
|
||||
|
||||
ui-release: $(UI_BUILD_FLAG_FILE)
|
||||
|
||||
ui-devel: awx/ui/node_modules
|
||||
@$(MAKE) -B $(UI_BUILD_FLAG_FILE)
|
||||
@@ -421,10 +427,17 @@ dev_build:
|
||||
release_build:
|
||||
$(PYTHON) setup.py release_build
|
||||
|
||||
dist/$(SDIST_TAR_FILE): ui-release VERSION
|
||||
HEADLESS ?= no
|
||||
ifeq ($(HEADLESS), yes)
|
||||
dist/$(SDIST_TAR_FILE):
|
||||
else
|
||||
dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE)
|
||||
endif
|
||||
$(PYTHON) setup.py $(SDIST_COMMAND)
|
||||
ln -sf $(SDIST_TAR_FILE) dist/awx.tar.gz
|
||||
|
||||
sdist: dist/$(SDIST_TAR_FILE)
|
||||
echo $(HEADLESS)
|
||||
@echo "#############################################"
|
||||
@echo "Artifacts:"
|
||||
@echo dist/$(SDIST_TAR_FILE)
|
||||
@@ -455,14 +468,14 @@ docker-compose-sources: .git/hooks/pre-commit
|
||||
-e minikube_container_group=$(MINIKUBE_CONTAINER_GROUP)
|
||||
|
||||
|
||||
docker-compose: docker-auth awx/projects docker-compose-sources
|
||||
docker-compose: awx/projects docker-compose-sources
|
||||
docker-compose -f tools/docker-compose/_sources/docker-compose.yml $(COMPOSE_OPTS) up $(COMPOSE_UP_OPTS) --remove-orphans
|
||||
|
||||
docker-compose-credential-plugins: docker-auth awx/projects docker-compose-sources
|
||||
docker-compose-credential-plugins: awx/projects docker-compose-sources
|
||||
echo -e "\033[0;31mTo generate a CyberArk Conjur API key: docker exec -it tools_conjur_1 conjurctl account create quick-start\033[0m"
|
||||
docker-compose -f tools/docker-compose/_sources/docker-compose.yml -f tools/docker-credential-plugins-override.yml up --no-recreate awx_1 --remove-orphans
|
||||
|
||||
docker-compose-test: docker-auth awx/projects docker-compose-sources
|
||||
docker-compose-test: awx/projects docker-compose-sources
|
||||
docker-compose -f tools/docker-compose/_sources/docker-compose.yml run --rm --service-ports awx_1 /bin/bash
|
||||
|
||||
docker-compose-runtest: awx/projects docker-compose-sources
|
||||
@@ -494,8 +507,8 @@ docker-compose-build:
|
||||
|
||||
docker-clean:
|
||||
$(foreach container_id,$(shell docker ps -f name=tools_awx -aq && docker ps -f name=tools_receptor -aq),docker stop $(container_id); docker rm -f $(container_id);)
|
||||
if [ $(shell docker images | grep "awx_devel") ]; then \
|
||||
docker images | grep "awx_devel" | awk '{print $$3}' | xargs docker rmi --force; \
|
||||
if [ "$(shell docker images | grep awx_devel)" ]; then \
|
||||
docker images | grep awx_devel | awk '{print $$3}' | xargs docker rmi --force; \
|
||||
fi
|
||||
|
||||
docker-clean-volumes: docker-compose-clean docker-compose-container-group-clean
|
||||
@@ -504,10 +517,10 @@ docker-clean-volumes: docker-compose-clean docker-compose-container-group-clean
|
||||
docker-refresh: docker-clean docker-compose
|
||||
|
||||
# Docker Development Environment with Elastic Stack Connected
|
||||
docker-compose-elk: docker-auth awx/projects docker-compose-sources
|
||||
docker-compose-elk: awx/projects docker-compose-sources
|
||||
docker-compose -f tools/docker-compose/_sources/docker-compose.yml -f tools/elastic/docker-compose.logstash-link.yml -f tools/elastic/docker-compose.elastic-override.yml up --no-recreate
|
||||
|
||||
docker-compose-cluster-elk: docker-auth awx/projects docker-compose-sources
|
||||
docker-compose-cluster-elk: awx/projects docker-compose-sources
|
||||
docker-compose -f tools/docker-compose/_sources/docker-compose.yml -f tools/elastic/docker-compose.logstash-link-cluster.yml -f tools/elastic/docker-compose.elastic-override.yml up --no-recreate
|
||||
|
||||
prometheus:
|
||||
|
||||
@@ -151,7 +151,7 @@ def manage():
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
# enforce the postgres version is equal to 12. if not, then terminate program with exit code of 1
|
||||
if not MODE == 'development':
|
||||
if not os.getenv('SKIP_PG_VERSION_CHECK', False) and not MODE == 'development':
|
||||
if (connection.pg_version // 10000) < 12:
|
||||
sys.stderr.write("Postgres version 12 is required\n")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -5003,6 +5003,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
||||
('credential_type', ('id', 'name', 'description', 'kind', 'managed')),
|
||||
('ad_hoc_command', ('id', 'name', 'status', 'limit')),
|
||||
('workflow_approval', ('id', 'name', 'unified_job_id')),
|
||||
('instance', ('id', 'hostname')),
|
||||
]
|
||||
return field_list
|
||||
|
||||
|
||||
@@ -4856,7 +4856,7 @@ msgid "Exception connecting to PagerDuty: {}"
|
||||
msgstr ""
|
||||
|
||||
#: awx/main/notifications/pagerduty_backend.py:87
|
||||
#: awx/main/notifications/slack_backend.py:48
|
||||
#: awx/main/notifications/slack_backend.py:49
|
||||
#: awx/main/notifications/twilio_backend.py:47
|
||||
msgid "Exception sending messages: {}"
|
||||
msgstr ""
|
||||
|
||||
@@ -40,7 +40,7 @@ msgstr "secondes"
|
||||
|
||||
#: awx/api/conf.py:29
|
||||
msgid "Maximum number of simultaneous logged in sessions"
|
||||
msgstr "Le nombre maximum de sessions actives en simultané"
|
||||
msgstr "Nombre maximum de sessions actives en simultané"
|
||||
|
||||
#: awx/api/conf.py:30
|
||||
msgid ""
|
||||
|
||||
@@ -337,7 +337,11 @@ def _events_table(since, full_path, until, tbl, where_column, project_job_create
|
||||
{tbl}.parent_uuid,
|
||||
{tbl}.event,
|
||||
task_action,
|
||||
(CASE WHEN event = 'playbook_on_stats' THEN event_data END) as playbook_on_stats,
|
||||
-- '-' operator listed here:
|
||||
-- https://www.postgresql.org/docs/12/functions-json.html
|
||||
-- note that operator is only supported by jsonb objects
|
||||
-- https://www.postgresql.org/docs/current/datatype-json.html
|
||||
(CASE WHEN event = 'playbook_on_stats' THEN {event_data} - 'artifact_data' END) as playbook_on_stats,
|
||||
{tbl}.failed,
|
||||
{tbl}.changed,
|
||||
{tbl}.playbook,
|
||||
@@ -357,9 +361,9 @@ def _events_table(since, full_path, until, tbl, where_column, project_job_create
|
||||
return query
|
||||
|
||||
try:
|
||||
return _copy_table(table='events', query=query(f"{tbl}.event_data::json"), path=full_path)
|
||||
return _copy_table(table='events', query=query(f"{tbl}.event_data::jsonb"), path=full_path)
|
||||
except UntranslatableCharacter:
|
||||
return _copy_table(table='events', query=query(f"replace({tbl}.event_data::text, '\\u0000', '')::json"), path=full_path)
|
||||
return _copy_table(table='events', query=query(f"replace({tbl}.event_data::text, '\\u0000', '')::jsonb"), path=full_path)
|
||||
|
||||
|
||||
@register('events_table', '1.3', format='csv', description=_('Automation task records'), expensive=four_hour_slicing)
|
||||
|
||||
@@ -408,6 +408,21 @@ register(
|
||||
unit=_('seconds'),
|
||||
)
|
||||
|
||||
register(
|
||||
'DEFAULT_JOB_IDLE_TIMEOUT',
|
||||
field_class=fields.IntegerField,
|
||||
min_value=0,
|
||||
default=0,
|
||||
label=_('Default Job Idle Timeout'),
|
||||
help_text=_(
|
||||
'If no output is detected from ansible in this number of seconds the execution will be terminated. '
|
||||
'Use value of 0 to used default idle_timeout is 600s.'
|
||||
),
|
||||
category=_('Jobs'),
|
||||
category_slug='jobs',
|
||||
unit=_('seconds'),
|
||||
)
|
||||
|
||||
register(
|
||||
'DEFAULT_INVENTORY_UPDATE_TIMEOUT',
|
||||
field_class=fields.IntegerField,
|
||||
|
||||
@@ -81,3 +81,7 @@ LOGGER_BLOCKLIST = (
|
||||
# Reported version for node seen in receptor mesh but for which capacity check
|
||||
# failed or is in progress
|
||||
RECEPTOR_PENDING = 'ansible-runner-???'
|
||||
|
||||
# Naming pattern for AWX jobs in /tmp folder, like /tmp/awx_42_xiwm
|
||||
# also update awxkit.api.pages.unified_jobs if changed
|
||||
JOB_FOLDER_PREFIX = 'awx_%s_'
|
||||
|
||||
@@ -36,3 +36,7 @@ class PostRunError(Exception):
|
||||
self.status = status
|
||||
self.tb = tb
|
||||
super(PostRunError, self).__init__(msg)
|
||||
|
||||
|
||||
class ReceptorNodeNotFound(RuntimeError):
|
||||
pass
|
||||
|
||||
@@ -10,6 +10,6 @@ def is_ha_environment():
|
||||
otherwise.
|
||||
"""
|
||||
# If there are two or more instances, then we are in an HA environment.
|
||||
if Instance.objects.count() > 1:
|
||||
if Instance.objects.filter(node_type__in=('control', 'hybrid')).count() > 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -76,7 +76,10 @@ class AnsibleInventoryLoader(object):
|
||||
bargs.extend(['-v', '{0}:{0}:Z'.format(self.source)])
|
||||
for key, value in STANDARD_INVENTORY_UPDATE_ENV.items():
|
||||
bargs.extend(['-e', '{0}={1}'.format(key, value)])
|
||||
bargs.extend([get_default_execution_environment().image])
|
||||
ee = get_default_execution_environment()
|
||||
|
||||
bargs.extend([ee.image])
|
||||
|
||||
bargs.extend(['ansible-inventory', '-i', self.source])
|
||||
bargs.extend(['--playbook-dir', functioning_dir(self.source)])
|
||||
if self.verbosity:
|
||||
@@ -111,9 +114,7 @@ class AnsibleInventoryLoader(object):
|
||||
|
||||
def load(self):
|
||||
base_args = self.get_base_args()
|
||||
|
||||
logger.info('Reading Ansible inventory source: %s', self.source)
|
||||
|
||||
return self.command_to_json(base_args)
|
||||
|
||||
|
||||
@@ -138,7 +139,7 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
default=None,
|
||||
metavar='v',
|
||||
help='host variable used to ' 'set/clear enabled flag when host is online/offline, may ' 'be specified as "foo.bar" to traverse nested dicts.',
|
||||
help='host variable used to set/clear enabled flag when host is online/offline, may be specified as "foo.bar" to traverse nested dicts.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--enabled-value',
|
||||
@@ -146,7 +147,7 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
default=None,
|
||||
metavar='v',
|
||||
help='value of host variable ' 'specified by --enabled-var that indicates host is ' 'enabled/online.',
|
||||
help='value of host variable specified by --enabled-var that indicates host is enabled/online.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--group-filter',
|
||||
@@ -154,7 +155,7 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
default=None,
|
||||
metavar='regex',
|
||||
help='regular expression ' 'to filter group name(s); only matches are imported.',
|
||||
help='regular expression to filter group name(s); only matches are imported.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--host-filter',
|
||||
@@ -162,14 +163,14 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
default=None,
|
||||
metavar='regex',
|
||||
help='regular expression ' 'to filter host name(s); only matches are imported.',
|
||||
help='regular expression to filter host name(s); only matches are imported.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--exclude-empty-groups',
|
||||
dest='exclude_empty_groups',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='when set, ' 'exclude all groups that have no child groups, hosts, or ' 'variables.',
|
||||
help='when set, exclude all groups that have no child groups, hosts, or variables.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--instance-id-var',
|
||||
@@ -177,7 +178,7 @@ class Command(BaseCommand):
|
||||
type=str,
|
||||
default=None,
|
||||
metavar='v',
|
||||
help='host variable that ' 'specifies the unique, immutable instance ID, may be ' 'specified as "foo.bar" to traverse nested dicts.',
|
||||
help='host variable that specifies the unique, immutable instance ID, may be specified as "foo.bar" to traverse nested dicts.',
|
||||
)
|
||||
|
||||
def set_logging_level(self, verbosity):
|
||||
@@ -1017,4 +1018,4 @@ class Command(BaseCommand):
|
||||
if settings.SQL_DEBUG:
|
||||
queries_this_import = connection.queries[queries_before:]
|
||||
sqltime = sum(float(x['time']) for x in queries_this_import)
|
||||
logger.warning('Inventory import required %d queries ' 'taking %0.3fs', len(queries_this_import), sqltime)
|
||||
logger.warning('Inventory import required %d queries taking %0.3fs', len(queries_this_import), sqltime)
|
||||
|
||||
@@ -47,7 +47,7 @@ class Command(BaseCommand):
|
||||
color = '\033[90m[DISABLED] '
|
||||
if no_color:
|
||||
color = ''
|
||||
fmt = '\t' + color + '{0.hostname} capacity={0.capacity} version={1}'
|
||||
fmt = '\t' + color + '{0.hostname} capacity={0.capacity} node_type={0.node_type} version={1}'
|
||||
if x.capacity:
|
||||
fmt += ' heartbeat="{0.modified:%Y-%m-%d %H:%M:%S}"'
|
||||
print((fmt + '\033[0m').format(x, x.version or '?'))
|
||||
|
||||
@@ -36,7 +36,7 @@ class RegisterQueue:
|
||||
ig.policy_instance_minimum = self.instance_min
|
||||
changed = True
|
||||
|
||||
if self.is_container_group:
|
||||
if self.is_container_group and (ig.is_container_group != self.is_container_group):
|
||||
ig.is_container_group = self.is_container_group
|
||||
changed = True
|
||||
|
||||
|
||||
@@ -9,12 +9,6 @@ def remove_iso_instances(apps, schema_editor):
|
||||
Instance.objects.filter(rampart_groups__controller__isnull=False).delete()
|
||||
|
||||
|
||||
def remove_iso_groups(apps, schema_editor):
|
||||
InstanceGroup = apps.get_model('main', 'InstanceGroup')
|
||||
with transaction.atomic():
|
||||
InstanceGroup.objects.filter(controller__isnull=False).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
|
||||
@@ -24,7 +18,6 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(remove_iso_instances),
|
||||
migrations.RunPython(remove_iso_groups),
|
||||
migrations.RemoveField(
|
||||
model_name='instance',
|
||||
name='last_isolated_check',
|
||||
|
||||
@@ -201,6 +201,8 @@ activity_stream_registrar.connect(Organization)
|
||||
activity_stream_registrar.connect(Inventory)
|
||||
activity_stream_registrar.connect(Host)
|
||||
activity_stream_registrar.connect(Group)
|
||||
activity_stream_registrar.connect(Instance)
|
||||
activity_stream_registrar.connect(InstanceGroup)
|
||||
activity_stream_registrar.connect(InventorySource)
|
||||
# activity_stream_registrar.connect(InventoryUpdate)
|
||||
activity_stream_registrar.connect(Credential)
|
||||
|
||||
@@ -20,6 +20,7 @@ from awx import __version__ as awx_application_version
|
||||
from awx.api.versioning import reverse
|
||||
from awx.main.managers import InstanceManager, InstanceGroupManager, UUID_DEFAULT
|
||||
from awx.main.fields import JSONField
|
||||
from awx.main.constants import JOB_FOLDER_PREFIX
|
||||
from awx.main.models.base import BaseModel, HasEditsMixin, prevent_search
|
||||
from awx.main.models.unified_jobs import UnifiedJob
|
||||
from awx.main.utils.common import get_corrected_cpu, get_cpu_effective_capacity, get_corrected_memory, get_mem_effective_capacity
|
||||
@@ -155,6 +156,24 @@ class Instance(HasPolicyEditsMixin, BaseModel):
|
||||
Instance.objects.filter(enabled=True, capacity__gt=0).filter(node_type__in=['control', 'hybrid']).values_list('hostname', flat=True)
|
||||
)
|
||||
|
||||
def get_cleanup_task_kwargs(self, **kwargs):
|
||||
"""
|
||||
Produce options to use for the command: ansible-runner worker cleanup
|
||||
returns a dict that is passed to the python interface for the runner method corresponding to that command
|
||||
any kwargs will override that key=value combination in the returned dict
|
||||
"""
|
||||
vargs = dict()
|
||||
if settings.AWX_CLEANUP_PATHS:
|
||||
vargs['file_pattern'] = '/tmp/{}*'.format(JOB_FOLDER_PREFIX % '*')
|
||||
vargs.update(kwargs)
|
||||
if 'exclude_strings' not in vargs and vargs.get('file_pattern'):
|
||||
active_pks = list(UnifiedJob.objects.filter(execution_node=self.hostname, status__in=('running', 'waiting')).values_list('pk', flat=True))
|
||||
if active_pks:
|
||||
vargs['exclude_strings'] = [JOB_FOLDER_PREFIX % job_id for job_id in active_pks]
|
||||
if 'remove_images' in vargs or 'image_prune' in vargs:
|
||||
vargs.setdefault('process_isolation_executable', 'podman')
|
||||
return vargs
|
||||
|
||||
def is_lost(self, ref_time=None):
|
||||
if self.last_seen is None:
|
||||
return True
|
||||
|
||||
@@ -118,7 +118,7 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVi
|
||||
from awx.main.models import Credential
|
||||
|
||||
public_galaxy_credential = Credential.objects.filter(managed=True, name='Ansible Galaxy').first()
|
||||
if public_galaxy_credential not in self.galaxy_credentials.all():
|
||||
if public_galaxy_credential is not None and public_galaxy_credential not in self.galaxy_credentials.all():
|
||||
self.galaxy_credentials.add(public_galaxy_credential)
|
||||
|
||||
|
||||
|
||||
@@ -1497,7 +1497,12 @@ class UnifiedJob(
|
||||
return False
|
||||
|
||||
def log_lifecycle(self, state, blocked_by=None):
|
||||
extra = {'type': self._meta.model_name, 'task_id': self.id, 'state': state}
|
||||
extra = {
|
||||
'type': self._meta.model_name,
|
||||
'task_id': self.id,
|
||||
'state': state,
|
||||
'work_unit_id': self.work_unit_id,
|
||||
}
|
||||
if self.unified_job_template:
|
||||
extra["template_name"] = self.unified_job_template.name
|
||||
if state == "blocked" and blocked_by:
|
||||
@@ -1506,6 +1511,11 @@ class UnifiedJob(
|
||||
extra["blocked_by"] = blocked_by_msg
|
||||
else:
|
||||
msg = f"{self._meta.model_name}-{self.id} {state.replace('_', ' ')}"
|
||||
|
||||
if state == "controller_node_chosen":
|
||||
extra["controller_node"] = self.controller_node or "NOT_SET"
|
||||
elif state == "execution_node_chosen":
|
||||
extra["execution_node"] = self.execution_node or "NOT_SET"
|
||||
logger_job_lifecycle.debug(msg, extra=extra)
|
||||
|
||||
@property
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from awx.main.notifications.base import AWXBaseEmailBackend
|
||||
from awx.main.utils import get_awx_http_client_headers
|
||||
from awx.main.notifications.custom_notification_base import CustomNotificationBase
|
||||
|
||||
logger = logging.getLogger('awx.main.notifications.rocketchat_backend')
|
||||
@@ -38,7 +39,9 @@ class RocketChatBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
||||
if optvalue is not None:
|
||||
payload[optval] = optvalue.strip()
|
||||
|
||||
r = requests.post("{}".format(m.recipients()[0]), data=json.dumps(payload), verify=(not self.rocketchat_no_verify_ssl))
|
||||
r = requests.post(
|
||||
"{}".format(m.recipients()[0]), data=json.dumps(payload), headers=get_awx_http_client_headers(), verify=(not self.rocketchat_no_verify_ssl)
|
||||
)
|
||||
|
||||
if r.status_code >= 400:
|
||||
logger.error(smart_text(_("Error sending notification rocket.chat: {}").format(r.status_code)))
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# All Rights Reserved.
|
||||
|
||||
import logging
|
||||
from slackclient import SlackClient
|
||||
from slack_sdk import WebClient
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -28,23 +29,30 @@ class SlackBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
||||
self.color = hex_color
|
||||
|
||||
def send_messages(self, messages):
|
||||
connection = SlackClient(self.token)
|
||||
client = WebClient(self.token)
|
||||
sent_messages = 0
|
||||
for m in messages:
|
||||
try:
|
||||
for r in m.recipients():
|
||||
if r.startswith('#'):
|
||||
r = r[1:]
|
||||
thread = None
|
||||
channel = r
|
||||
thread = None
|
||||
if ',' in r:
|
||||
channel, thread = r.split(',')
|
||||
if self.color:
|
||||
ret = connection.api_call("chat.postMessage", channel=r, as_user=True, attachments=[{"color": self.color, "text": m.subject}])
|
||||
response = client.chat_postMessage(
|
||||
channel=channel, thread_ts=thread, as_user=True, attachments=[{"color": self.color, "text": m.subject}]
|
||||
)
|
||||
else:
|
||||
ret = connection.api_call("chat.postMessage", channel=r, as_user=True, text=m.subject)
|
||||
logger.debug(ret)
|
||||
if ret['ok']:
|
||||
response = client.chat_postMessage(channel=channel, thread_ts=thread, as_user=True, text=m.subject)
|
||||
logger.debug(response)
|
||||
if response['ok']:
|
||||
sent_messages += 1
|
||||
else:
|
||||
raise RuntimeError("Slack Notification unable to send {}: {} ({})".format(r, m.subject, ret['error']))
|
||||
except Exception as e:
|
||||
raise RuntimeError("Slack Notification unable to send {}: {} ({})".format(r, m.subject, response['error']))
|
||||
except SlackApiError as e:
|
||||
logger.error(smart_text(_("Exception sending messages: {}").format(e)))
|
||||
if not self.fail_silently:
|
||||
raise
|
||||
|
||||
@@ -291,6 +291,7 @@ class TaskManager:
|
||||
# act as the controller for k8s API interaction
|
||||
try:
|
||||
task.controller_node = Instance.choose_online_control_plane_node()
|
||||
task.log_lifecycle("controller_node_chosen")
|
||||
except IndexError:
|
||||
logger.warning("No control plane nodes available to run containerized job {}".format(task.log_format))
|
||||
return
|
||||
@@ -298,19 +299,23 @@ class TaskManager:
|
||||
# project updates and system jobs don't *actually* run in pods, so
|
||||
# just pick *any* non-containerized host and use it as the execution node
|
||||
task.execution_node = Instance.choose_online_control_plane_node()
|
||||
task.log_lifecycle("execution_node_chosen")
|
||||
logger.debug('Submitting containerized {} to queue {}.'.format(task.log_format, task.execution_node))
|
||||
else:
|
||||
task.instance_group = rampart_group
|
||||
task.execution_node = instance.hostname
|
||||
task.log_lifecycle("execution_node_chosen")
|
||||
if instance.node_type == 'execution':
|
||||
try:
|
||||
task.controller_node = Instance.choose_online_control_plane_node()
|
||||
task.log_lifecycle("controller_node_chosen")
|
||||
except IndexError:
|
||||
logger.warning("No control plane nodes available to manage {}".format(task.log_format))
|
||||
return
|
||||
else:
|
||||
# control plane nodes will manage jobs locally for performance and resilience
|
||||
task.controller_node = task.execution_node
|
||||
task.log_lifecycle("controller_node_chosen")
|
||||
logger.debug('Submitting job {} to queue {} controlled by {}.'.format(task.log_format, task.execution_node, task.controller_node))
|
||||
with disable_activity_stream():
|
||||
task.celery_task_id = str(uuid.uuid4())
|
||||
|
||||
@@ -34,7 +34,6 @@ from awx.main.models import (
|
||||
ExecutionEnvironment,
|
||||
Group,
|
||||
Host,
|
||||
InstanceGroup,
|
||||
Inventory,
|
||||
InventorySource,
|
||||
Job,
|
||||
@@ -58,7 +57,7 @@ from awx.main.models import (
|
||||
from awx.main.constants import CENSOR_VALUE
|
||||
from awx.main.utils import model_instance_diff, model_to_dict, camelcase_to_underscore, get_current_apps
|
||||
from awx.main.utils import ignore_inventory_computed_fields, ignore_inventory_group_removal, _inventory_updates
|
||||
from awx.main.tasks import update_inventory_computed_fields
|
||||
from awx.main.tasks import update_inventory_computed_fields, handle_removed_image
|
||||
from awx.main.fields import (
|
||||
is_implicit_parent,
|
||||
update_role_parentage_for_instance,
|
||||
@@ -377,6 +376,7 @@ def model_serializer_mapping():
|
||||
models.Inventory: serializers.InventorySerializer,
|
||||
models.Host: serializers.HostSerializer,
|
||||
models.Group: serializers.GroupSerializer,
|
||||
models.Instance: serializers.InstanceSerializer,
|
||||
models.InstanceGroup: serializers.InstanceGroupSerializer,
|
||||
models.InventorySource: serializers.InventorySourceSerializer,
|
||||
models.Credential: serializers.CredentialSerializer,
|
||||
@@ -624,10 +624,26 @@ def deny_orphaned_approvals(sender, instance, **kwargs):
|
||||
approval.deny()
|
||||
|
||||
|
||||
def _handle_image_cleanup(removed_image, pk):
|
||||
if (not removed_image) or ExecutionEnvironment.objects.filter(image=removed_image).exclude(pk=pk).exists():
|
||||
return # if other EE objects reference the tag, then do not purge it
|
||||
handle_removed_image.delay(remove_images=[removed_image])
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=ExecutionEnvironment)
|
||||
def remove_default_ee(sender, instance, **kwargs):
|
||||
if instance.id == getattr(settings.DEFAULT_EXECUTION_ENVIRONMENT, 'id', None):
|
||||
settings.DEFAULT_EXECUTION_ENVIRONMENT = None
|
||||
_handle_image_cleanup(instance.image, instance.pk)
|
||||
|
||||
|
||||
@receiver(post_save, sender=ExecutionEnvironment)
|
||||
def remove_stale_image(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
return
|
||||
removed_image = instance._prior_values_store.get('image')
|
||||
if removed_image and removed_image != instance.image:
|
||||
_handle_image_cleanup(removed_image, instance.pk)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Session)
|
||||
@@ -659,9 +675,3 @@ def create_access_token_user_if_missing(sender, **kwargs):
|
||||
post_save.disconnect(create_access_token_user_if_missing, sender=OAuth2AccessToken)
|
||||
obj.save()
|
||||
post_save.connect(create_access_token_user_if_missing, sender=OAuth2AccessToken)
|
||||
|
||||
|
||||
# Connect the Instance Group to Activity Stream receivers.
|
||||
post_save.connect(activity_stream_create, sender=InstanceGroup, dispatch_uid=str(InstanceGroup) + "_create")
|
||||
pre_save.connect(activity_stream_update, sender=InstanceGroup, dispatch_uid=str(InstanceGroup) + "_update")
|
||||
pre_delete.connect(activity_stream_delete, sender=InstanceGroup, dispatch_uid=str(InstanceGroup) + "_delete")
|
||||
|
||||
@@ -11,6 +11,8 @@ import importlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout
|
||||
import shutil
|
||||
import stat
|
||||
import tempfile
|
||||
@@ -27,7 +29,6 @@ import socket
|
||||
import threading
|
||||
import concurrent.futures
|
||||
from base64 import b64encode
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Django
|
||||
@@ -51,13 +52,14 @@ from gitdb.exc import BadName as BadGitName
|
||||
|
||||
# Runner
|
||||
import ansible_runner
|
||||
import ansible_runner.cleanup
|
||||
|
||||
# dateutil
|
||||
from dateutil.parser import parse as parse_date
|
||||
|
||||
# AWX
|
||||
from awx import __version__ as awx_application_version
|
||||
from awx.main.constants import PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV, MINIMAL_EVENTS
|
||||
from awx.main.constants import PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV, MINIMAL_EVENTS, JOB_FOLDER_PREFIX
|
||||
from awx.main.access import access_registry
|
||||
from awx.main.redact import UriCleaner
|
||||
from awx.main.models import (
|
||||
@@ -83,7 +85,7 @@ from awx.main.models import (
|
||||
build_safe_env,
|
||||
)
|
||||
from awx.main.constants import ACTIVE_STATES
|
||||
from awx.main.exceptions import AwxTaskError, PostRunError
|
||||
from awx.main.exceptions import AwxTaskError, PostRunError, ReceptorNodeNotFound
|
||||
from awx.main.queue import CallbackQueueDispatcher
|
||||
from awx.main.dispatch.publish import task
|
||||
from awx.main.dispatch import get_local_queuename, reaper
|
||||
@@ -106,7 +108,7 @@ from awx.main.utils.safe_yaml import safe_dump, sanitize_jinja
|
||||
from awx.main.utils.reload import stop_local_services
|
||||
from awx.main.utils.pglock import advisory_lock
|
||||
from awx.main.utils.handlers import SpecialInventoryHandler
|
||||
from awx.main.utils.receptor import get_receptor_ctl, worker_info, get_conn_type, get_tls_client
|
||||
from awx.main.utils.receptor import get_receptor_ctl, worker_info, get_conn_type, get_tls_client, worker_cleanup, administrative_workunit_reaper
|
||||
from awx.main.consumers import emit_channel_notification
|
||||
from awx.main import analytics
|
||||
from awx.conf import settings_registry
|
||||
@@ -189,6 +191,8 @@ def inform_cluster_of_shutdown():
|
||||
|
||||
@task(queue=get_local_queuename)
|
||||
def apply_cluster_membership_policies():
|
||||
from awx.main.signals import disable_activity_stream
|
||||
|
||||
started_waiting = time.time()
|
||||
with advisory_lock('cluster_policy_lock', wait=True):
|
||||
lock_time = time.time() - started_waiting
|
||||
@@ -280,18 +284,19 @@ def apply_cluster_membership_policies():
|
||||
|
||||
# On a differential basis, apply instances to groups
|
||||
with transaction.atomic():
|
||||
for g in actual_groups:
|
||||
if g.obj.is_container_group:
|
||||
logger.debug('Skipping containerized group {} for policy calculation'.format(g.obj.name))
|
||||
continue
|
||||
instances_to_add = set(g.instances) - set(g.prior_instances)
|
||||
instances_to_remove = set(g.prior_instances) - set(g.instances)
|
||||
if instances_to_add:
|
||||
logger.debug('Adding instances {} to group {}'.format(list(instances_to_add), g.obj.name))
|
||||
g.obj.instances.add(*instances_to_add)
|
||||
if instances_to_remove:
|
||||
logger.debug('Removing instances {} from group {}'.format(list(instances_to_remove), g.obj.name))
|
||||
g.obj.instances.remove(*instances_to_remove)
|
||||
with disable_activity_stream():
|
||||
for g in actual_groups:
|
||||
if g.obj.is_container_group:
|
||||
logger.debug('Skipping containerized group {} for policy calculation'.format(g.obj.name))
|
||||
continue
|
||||
instances_to_add = set(g.instances) - set(g.prior_instances)
|
||||
instances_to_remove = set(g.prior_instances) - set(g.instances)
|
||||
if instances_to_add:
|
||||
logger.debug('Adding instances {} to group {}'.format(list(instances_to_add), g.obj.name))
|
||||
g.obj.instances.add(*instances_to_add)
|
||||
if instances_to_remove:
|
||||
logger.debug('Removing instances {} from group {}'.format(list(instances_to_remove), g.obj.name))
|
||||
g.obj.instances.remove(*instances_to_remove)
|
||||
logger.debug('Cluster policy computation finished in {} seconds'.format(time.time() - started_compute))
|
||||
|
||||
|
||||
@@ -390,29 +395,51 @@ def purge_old_stdout_files():
|
||||
logger.debug("Removing {}".format(os.path.join(settings.JOBOUTPUT_ROOT, f)))
|
||||
|
||||
|
||||
@task(queue=get_local_queuename)
|
||||
def cleanup_execution_environment_images():
|
||||
def _cleanup_images_and_files(**kwargs):
|
||||
if settings.IS_K8S:
|
||||
return
|
||||
process = subprocess.run('podman images --filter="dangling=true" --format json'.split(" "), capture_output=True)
|
||||
if process.returncode != 0:
|
||||
logger.debug("Cleanup execution environment images: could not get list of images")
|
||||
return
|
||||
if len(process.stdout) > 0:
|
||||
images_system = json.loads(process.stdout)
|
||||
for e in images_system:
|
||||
image_name = e["Id"]
|
||||
logger.debug(f"Cleanup execution environment images: deleting {image_name}")
|
||||
process = subprocess.run(['podman', 'rmi', image_name, '-f'], stdout=subprocess.DEVNULL)
|
||||
if process.returncode != 0:
|
||||
logger.debug(f"Failed to delete image {image_name}")
|
||||
this_inst = Instance.objects.me()
|
||||
runner_cleanup_kwargs = this_inst.get_cleanup_task_kwargs(**kwargs)
|
||||
if runner_cleanup_kwargs:
|
||||
stdout = ''
|
||||
with StringIO() as buffer:
|
||||
with redirect_stdout(buffer):
|
||||
ansible_runner.cleanup.run_cleanup(runner_cleanup_kwargs)
|
||||
stdout = buffer.getvalue()
|
||||
if '(changed: True)' in stdout:
|
||||
logger.info(f'Performed local cleanup with kwargs {kwargs}, output:\n{stdout}')
|
||||
|
||||
# if we are the first instance alphabetically, then run cleanup on execution nodes
|
||||
checker_instance = Instance.objects.filter(node_type__in=['hybrid', 'control'], enabled=True, capacity__gt=0).order_by('-hostname').first()
|
||||
if checker_instance and this_inst.hostname == checker_instance.hostname:
|
||||
for inst in Instance.objects.filter(node_type='execution', enabled=True, capacity__gt=0):
|
||||
runner_cleanup_kwargs = inst.get_cleanup_task_kwargs(**kwargs)
|
||||
if not runner_cleanup_kwargs:
|
||||
continue
|
||||
try:
|
||||
stdout = worker_cleanup(inst.hostname, runner_cleanup_kwargs)
|
||||
if '(changed: True)' in stdout:
|
||||
logger.info(f'Performed cleanup on execution node {inst.hostname} with output:\n{stdout}')
|
||||
except RuntimeError:
|
||||
logger.exception(f'Error running cleanup on execution node {inst.hostname}')
|
||||
|
||||
|
||||
@task(queue='tower_broadcast_all')
|
||||
def handle_removed_image(remove_images=None):
|
||||
"""Special broadcast invocation of this method to handle case of deleted EE"""
|
||||
_cleanup_images_and_files(remove_images=remove_images, file_pattern='')
|
||||
|
||||
|
||||
@task(queue=get_local_queuename)
|
||||
def cleanup_images_and_files():
|
||||
_cleanup_images_and_files()
|
||||
|
||||
|
||||
@task(queue=get_local_queuename)
|
||||
def cluster_node_health_check(node):
|
||||
'''
|
||||
"""
|
||||
Used for the health check endpoint, refreshes the status of the instance, but must be ran on target node
|
||||
'''
|
||||
"""
|
||||
if node == '':
|
||||
logger.warn('Local health check incorrectly called with blank string')
|
||||
return
|
||||
@@ -441,7 +468,7 @@ def execution_node_health_check(node):
|
||||
if instance.node_type != 'execution':
|
||||
raise RuntimeError(f'Execution node health check ran against {instance.node_type} node {instance.hostname}')
|
||||
|
||||
data = worker_info(node, work_type='ansible-runner' if instance.node_type == 'execution' else 'local')
|
||||
data = worker_info(node)
|
||||
|
||||
prior_capacity = instance.capacity
|
||||
|
||||
@@ -478,7 +505,10 @@ def inspect_execution_nodes(instance_list):
|
||||
for ad in connections:
|
||||
hostname = ad['NodeID']
|
||||
commands = ad.get('WorkCommands') or []
|
||||
if 'ansible-runner' not in commands:
|
||||
worktypes = []
|
||||
for c in commands:
|
||||
worktypes.append(c["WorkType"])
|
||||
if 'ansible-runner' not in worktypes:
|
||||
continue
|
||||
changed = False
|
||||
if hostname in node_lookup:
|
||||
@@ -489,6 +519,7 @@ def inspect_execution_nodes(instance_list):
|
||||
logger.warn(f"Registered execution node '{hostname}' (marked disabled by default)")
|
||||
else:
|
||||
logger.warn(f"Unrecognized node on mesh advertising ansible-runner work type: {hostname}")
|
||||
continue
|
||||
|
||||
was_lost = instance.is_lost(ref_time=nowtime)
|
||||
last_seen = parse_date(ad['Time'])
|
||||
@@ -506,7 +537,7 @@ def inspect_execution_nodes(instance_list):
|
||||
# check
|
||||
logger.warn(f'Execution node attempting to rejoin as instance {hostname}.')
|
||||
execution_node_health_check.apply_async([hostname])
|
||||
elif instance.capacity == 0:
|
||||
elif instance.capacity == 0 and instance.enabled:
|
||||
# nodes with proven connection but need remediation run health checks are reduced frequency
|
||||
if not instance.last_health_check or (nowtime - instance.last_health_check).total_seconds() >= settings.EXECUTION_NODE_REMEDIATION_CHECKS:
|
||||
# Periodically re-run the health check of errored nodes, in case someone fixed it
|
||||
@@ -623,6 +654,8 @@ def awx_receptor_workunit_reaper():
|
||||
receptor_ctl.simple_command(f"work cancel {job.work_unit_id}")
|
||||
receptor_ctl.simple_command(f"work release {job.work_unit_id}")
|
||||
|
||||
administrative_workunit_reaper(receptor_work_list)
|
||||
|
||||
|
||||
@task(queue=get_local_queuename)
|
||||
def awx_k8s_reaper():
|
||||
@@ -977,7 +1010,7 @@ class BaseTask(object):
|
||||
"""
|
||||
Create a temporary directory for job-related files.
|
||||
"""
|
||||
path = tempfile.mkdtemp(prefix='awx_%s_' % instance.pk, dir=settings.AWX_ISOLATION_BASE_PATH)
|
||||
path = tempfile.mkdtemp(prefix=JOB_FOLDER_PREFIX % instance.pk, dir=settings.AWX_ISOLATION_BASE_PATH)
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||
if settings.AWX_CLEANUP_PATHS:
|
||||
self.cleanup_paths.append(path)
|
||||
@@ -1462,6 +1495,10 @@ class BaseTask(object):
|
||||
},
|
||||
}
|
||||
|
||||
idle_timeout = getattr(settings, 'DEFAULT_JOB_IDLE_TIMEOUT', 0)
|
||||
if idle_timeout > 0:
|
||||
params['settings']['idle_timeout'] = idle_timeout
|
||||
|
||||
if isinstance(self.instance, AdHocCommand):
|
||||
params['module'] = self.build_module_name(self.instance)
|
||||
params['module_args'] = self.build_module_args(self.instance)
|
||||
@@ -1512,6 +1549,8 @@ class BaseTask(object):
|
||||
# ensure failure notification sends even if playbook_on_stats event is not triggered
|
||||
handle_success_and_failure_notifications.apply_async([self.instance.job.id])
|
||||
|
||||
except ReceptorNodeNotFound as exc:
|
||||
extra_update_fields['job_explanation'] = str(exc)
|
||||
except Exception:
|
||||
# this could catch programming or file system errors
|
||||
extra_update_fields['result_traceback'] = traceback.format_exc()
|
||||
@@ -1875,6 +1914,7 @@ class RunJob(BaseTask):
|
||||
status='running',
|
||||
instance_group=pu_ig,
|
||||
execution_node=pu_en,
|
||||
controller_node=pu_en,
|
||||
celery_task_id=job.celery_task_id,
|
||||
)
|
||||
if branch_override:
|
||||
@@ -1883,6 +1923,8 @@ class RunJob(BaseTask):
|
||||
if 'update_' not in sync_metafields['job_tags']:
|
||||
sync_metafields['scm_revision'] = job_revision
|
||||
local_project_sync = job.project.create_project_update(_eager_fields=sync_metafields)
|
||||
local_project_sync.log_lifecycle("controller_node_chosen")
|
||||
local_project_sync.log_lifecycle("execution_node_chosen")
|
||||
create_partition(local_project_sync.event_class._meta.db_table, start=local_project_sync.created)
|
||||
# save the associated job before calling run() so that a
|
||||
# cancel() call on the job can cancel the project update
|
||||
@@ -2175,10 +2217,13 @@ class RunProjectUpdate(BaseTask):
|
||||
status='running',
|
||||
instance_group=instance_group,
|
||||
execution_node=project_update.execution_node,
|
||||
controller_node=project_update.execution_node,
|
||||
source_project_update=project_update,
|
||||
celery_task_id=project_update.celery_task_id,
|
||||
)
|
||||
)
|
||||
local_inv_update.log_lifecycle("controller_node_chosen")
|
||||
local_inv_update.log_lifecycle("execution_node_chosen")
|
||||
try:
|
||||
create_partition(local_inv_update.event_class._meta.db_table, start=local_inv_update.created)
|
||||
inv_update_class().run(local_inv_update.id)
|
||||
@@ -2625,11 +2670,15 @@ class RunInventoryUpdate(BaseTask):
|
||||
job_type='run',
|
||||
job_tags=','.join(sync_needs),
|
||||
status='running',
|
||||
execution_node=inventory_update.execution_node,
|
||||
execution_node=Instance.objects.me().hostname,
|
||||
controller_node=Instance.objects.me().hostname,
|
||||
instance_group=inventory_update.instance_group,
|
||||
celery_task_id=inventory_update.celery_task_id,
|
||||
)
|
||||
)
|
||||
local_project_sync.log_lifecycle("controller_node_chosen")
|
||||
local_project_sync.log_lifecycle("execution_node_chosen")
|
||||
create_partition(local_project_sync.event_class._meta.db_table, start=local_project_sync.created)
|
||||
# associate the inventory update before calling run() so that a
|
||||
# cancel() call on the inventory update can cancel the project update
|
||||
local_project_sync.scm_inventory_updates.add(inventory_update)
|
||||
@@ -3020,6 +3069,9 @@ class AWXReceptorJob:
|
||||
execution_environment_params = self.task.build_execution_environment_params(self.task.instance, runner_params['private_data_dir'])
|
||||
self.runner_params.update(execution_environment_params)
|
||||
|
||||
if not settings.IS_K8S and self.work_type == 'local' and 'only_transmit_kwargs' not in self.runner_params:
|
||||
self.runner_params['only_transmit_kwargs'] = True
|
||||
|
||||
def run(self):
|
||||
# We establish a connection to the Receptor socket
|
||||
receptor_ctl = get_receptor_ctl()
|
||||
@@ -3031,10 +3083,14 @@ class AWXReceptorJob:
|
||||
finally:
|
||||
# Make sure to always release the work unit if we established it
|
||||
if self.unit_id is not None and settings.RECEPTOR_RELEASE_WORK:
|
||||
receptor_ctl.simple_command(f"work release {self.unit_id}")
|
||||
# If an error occured without the job itself failing, it could be a broken instance
|
||||
if self.work_type == 'ansible-runner' and ((res is None) or (getattr(res, 'rc', None) is None)):
|
||||
execution_node_health_check(self.task.instance.execution_node)
|
||||
try:
|
||||
receptor_ctl.simple_command(f"work release {self.unit_id}")
|
||||
except Exception:
|
||||
logger.exception(f"Error releasing work unit {self.unit_id}.")
|
||||
|
||||
@property
|
||||
def sign_work(self):
|
||||
return False if settings.IS_K8S else True
|
||||
|
||||
def _run_internal(self, receptor_ctl):
|
||||
# Create a socketpair. Where the left side will be used for writing our payload
|
||||
@@ -3052,10 +3108,23 @@ class AWXReceptorJob:
|
||||
_kw['node'] = self.task.instance.execution_node
|
||||
use_stream_tls = get_conn_type(_kw['node'], receptor_ctl).name == "STREAMTLS"
|
||||
_kw['tlsclient'] = get_tls_client(use_stream_tls)
|
||||
|
||||
result = receptor_ctl.submit_work(worktype=self.work_type, payload=sockout.makefile('rb'), params=self.receptor_params, **_kw)
|
||||
result = receptor_ctl.submit_work(worktype=self.work_type, payload=sockout.makefile('rb'), params=self.receptor_params, signwork=self.sign_work, **_kw)
|
||||
self.unit_id = result['unitid']
|
||||
# Update the job with the work unit in-memory so that the log_lifecycle
|
||||
# will print out the work unit that is to be associated with the job in the database
|
||||
# via the update_model() call.
|
||||
# We want to log the work_unit_id as early as possible. A failure can happen in between
|
||||
# when we start the job in receptor and when we associate the job <-> work_unit_id.
|
||||
# In that case, there will be work running in receptor and Controller will not know
|
||||
# which Job it is associated with.
|
||||
# We do not programatically handle this case. Ideally, we would handle this with a reaper case.
|
||||
# The two distinct job lifecycle log events below allow for us to at least detect when this
|
||||
# edge case occurs. If the lifecycle event work_unit_id_received occurs without the
|
||||
# work_unit_id_assigned event then this case may have occured.
|
||||
self.task.instance.work_unit_id = result['unitid'] # Set work_unit_id in-memory only
|
||||
self.task.instance.log_lifecycle("work_unit_id_received")
|
||||
self.task.update_model(self.task.instance.pk, work_unit_id=result['unitid'])
|
||||
self.task.instance.log_lifecycle("work_unit_id_assigned")
|
||||
|
||||
sockin.close()
|
||||
sockout.close()
|
||||
@@ -3084,9 +3153,14 @@ class AWXReceptorJob:
|
||||
resultsock.shutdown(socket.SHUT_RDWR)
|
||||
resultfile.close()
|
||||
elif res.status == 'error':
|
||||
unit_status = receptor_ctl.simple_command(f'work status {self.unit_id}')
|
||||
detail = unit_status['Detail']
|
||||
state_name = unit_status['StateName']
|
||||
try:
|
||||
unit_status = receptor_ctl.simple_command(f'work status {self.unit_id}')
|
||||
detail = unit_status.get('Detail', None)
|
||||
state_name = unit_status.get('StateName', None)
|
||||
except Exception:
|
||||
detail = ''
|
||||
state_name = ''
|
||||
logger.exception(f'An error was encountered while getting status for work unit {self.unit_id}')
|
||||
|
||||
if 'exceeded quota' in detail:
|
||||
logger.warn(detail)
|
||||
@@ -3103,20 +3177,25 @@ class AWXReceptorJob:
|
||||
try:
|
||||
resultsock = receptor_ctl.get_work_results(self.unit_id, return_sockfile=True)
|
||||
lines = resultsock.readlines()
|
||||
self.task.instance.result_traceback = b"".join(lines).decode()
|
||||
self.task.instance.save(update_fields=['result_traceback'])
|
||||
receptor_output = b"".join(lines).decode()
|
||||
if receptor_output:
|
||||
self.task.instance.result_traceback = receptor_output
|
||||
self.task.instance.save(update_fields=['result_traceback'])
|
||||
elif detail:
|
||||
self.task.instance.result_traceback = detail
|
||||
self.task.instance.save(update_fields=['result_traceback'])
|
||||
else:
|
||||
logger.warn(f'No result details or output from {self.task.instance.log_format}, status:\n{unit_status}')
|
||||
except Exception:
|
||||
raise RuntimeError(detail)
|
||||
|
||||
time.sleep(3)
|
||||
return res
|
||||
|
||||
# Spawned in a thread so Receptor can start reading before we finish writing, we
|
||||
# write our payload to the left side of our socketpair.
|
||||
@cleanup_new_process
|
||||
def transmit(self, _socket):
|
||||
if not settings.IS_K8S and self.work_type == 'local' and 'only_transmit_kwargs' not in self.runner_params:
|
||||
self.runner_params['only_transmit_kwargs'] = True
|
||||
|
||||
try:
|
||||
ansible_runner.interface.run(streamer='transmit', _output=_socket.makefile('wb'), **self.runner_params)
|
||||
finally:
|
||||
@@ -3150,7 +3229,7 @@ class AWXReceptorJob:
|
||||
receptor_params["secret_kube_config"] = kubeconfig_yaml
|
||||
else:
|
||||
private_data_dir = self.runner_params['private_data_dir']
|
||||
if self.work_type == 'ansible-runner':
|
||||
if self.work_type == 'ansible-runner' and settings.AWX_CLEANUP_PATHS:
|
||||
# on execution nodes, we rely on the private data dir being deleted
|
||||
cli_params = f"--private-data-dir={private_data_dir} --delete"
|
||||
else:
|
||||
|
||||
@@ -3,6 +3,7 @@ import pytest
|
||||
from unittest import mock
|
||||
|
||||
from awx.api.versioning import reverse
|
||||
from awx.main.models.activity_stream import ActivityStream
|
||||
from awx.main.models.ha import Instance
|
||||
|
||||
import redis
|
||||
@@ -17,6 +18,7 @@ INSTANCE_KWARGS = dict(hostname='example-host', cpu=6, memory=36000000000, cpu_c
|
||||
@pytest.mark.django_db
|
||||
def test_disabled_zeros_capacity(patch, admin_user):
|
||||
instance = Instance.objects.create(**INSTANCE_KWARGS)
|
||||
assert ActivityStream.objects.filter(instance=instance).count() == 1
|
||||
|
||||
url = reverse('api:instance_detail', kwargs={'pk': instance.pk})
|
||||
|
||||
@@ -25,12 +27,14 @@ def test_disabled_zeros_capacity(patch, admin_user):
|
||||
|
||||
instance.refresh_from_db()
|
||||
assert instance.capacity == 0
|
||||
assert ActivityStream.objects.filter(instance=instance).count() == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_enabled_sets_capacity(patch, admin_user):
|
||||
instance = Instance.objects.create(enabled=False, capacity=0, **INSTANCE_KWARGS)
|
||||
assert instance.capacity == 0
|
||||
assert ActivityStream.objects.filter(instance=instance).count() == 1
|
||||
|
||||
url = reverse('api:instance_detail', kwargs={'pk': instance.pk})
|
||||
|
||||
@@ -39,6 +43,7 @@ def test_enabled_sets_capacity(patch, admin_user):
|
||||
|
||||
instance.refresh_from_db()
|
||||
assert instance.capacity > 0
|
||||
assert ActivityStream.objects.filter(instance=instance).count() == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -50,6 +55,20 @@ def test_auditor_user_health_check(get, post, system_auditor):
|
||||
post(url=url, user=system_auditor, expect=403)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_health_check_throws_error(post, admin_user):
|
||||
instance = Instance.objects.create(node_type='execution', **INSTANCE_KWARGS)
|
||||
url = reverse('api:instance_health_check', kwargs={'pk': instance.pk})
|
||||
# we will simulate a receptor error, similar to this one
|
||||
# https://github.com/ansible/receptor/blob/156e6e24a49fbf868734507f9943ac96208ed8f5/receptorctl/receptorctl/socket_interface.py#L204
|
||||
# related to issue https://github.com/ansible/tower/issues/5315
|
||||
with mock.patch('awx.main.utils.receptor.run_until_complete', side_effect=RuntimeError('Remote error: foobar')):
|
||||
post(url=url, user=admin_user, expect=200)
|
||||
instance.refresh_from_db()
|
||||
assert 'Remote error: foobar' in instance.errors
|
||||
assert instance.capacity == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch.object(redis.client.Redis, 'ping', lambda self: True)
|
||||
def test_health_check_usage(get, post, admin_user):
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
from awx.api.versioning import reverse
|
||||
from awx.main.models import (
|
||||
ActivityStream,
|
||||
Instance,
|
||||
InstanceGroup,
|
||||
ProjectUpdate,
|
||||
@@ -213,9 +214,23 @@ def test_containerized_group_default_fields(instance_group, kube_credential):
|
||||
def test_instance_attach_to_instance_group(post, instance_group, node_type_instance, admin, node_type):
|
||||
instance = node_type_instance(hostname=node_type, node_type=node_type)
|
||||
|
||||
count = ActivityStream.objects.count()
|
||||
|
||||
url = reverse(f'api:instance_group_instance_list', kwargs={'pk': instance_group.pk})
|
||||
post(url, {'associate': True, 'id': instance.id}, admin, expect=204 if node_type != 'control' else 400)
|
||||
|
||||
new_activity = ActivityStream.objects.all()[count:]
|
||||
if node_type != 'control':
|
||||
assert len(new_activity) == 2 # the second is an update of the instance group policy
|
||||
new_activity = new_activity[0]
|
||||
assert new_activity.operation == 'associate'
|
||||
assert new_activity.object1 == 'instance_group'
|
||||
assert new_activity.object2 == 'instance'
|
||||
assert new_activity.instance.first() == instance
|
||||
assert new_activity.instance_group.first() == instance_group
|
||||
else:
|
||||
assert not new_activity
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('node_type', ['control', 'hybrid', 'execution'])
|
||||
@@ -223,18 +238,46 @@ def test_instance_unattach_from_instance_group(post, instance_group, node_type_i
|
||||
instance = node_type_instance(hostname=node_type, node_type=node_type)
|
||||
instance_group.instances.add(instance)
|
||||
|
||||
count = ActivityStream.objects.count()
|
||||
|
||||
url = reverse(f'api:instance_group_instance_list', kwargs={'pk': instance_group.pk})
|
||||
post(url, {'disassociate': True, 'id': instance.id}, admin, expect=204 if node_type != 'control' else 400)
|
||||
|
||||
new_activity = ActivityStream.objects.all()[count:]
|
||||
if node_type != 'control':
|
||||
assert len(new_activity) == 1
|
||||
new_activity = new_activity[0]
|
||||
assert new_activity.operation == 'disassociate'
|
||||
assert new_activity.object1 == 'instance_group'
|
||||
assert new_activity.object2 == 'instance'
|
||||
assert new_activity.instance.first() == instance
|
||||
assert new_activity.instance_group.first() == instance_group
|
||||
else:
|
||||
assert not new_activity
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('node_type', ['control', 'hybrid', 'execution'])
|
||||
def test_instance_group_attach_to_instance(post, instance_group, node_type_instance, admin, node_type):
|
||||
instance = node_type_instance(hostname=node_type, node_type=node_type)
|
||||
|
||||
count = ActivityStream.objects.count()
|
||||
|
||||
url = reverse(f'api:instance_instance_groups_list', kwargs={'pk': instance.pk})
|
||||
post(url, {'associate': True, 'id': instance_group.id}, admin, expect=204 if node_type != 'control' else 400)
|
||||
|
||||
new_activity = ActivityStream.objects.all()[count:]
|
||||
if node_type != 'control':
|
||||
assert len(new_activity) == 2 # the second is an update of the instance group policy
|
||||
new_activity = new_activity[0]
|
||||
assert new_activity.operation == 'associate'
|
||||
assert new_activity.object1 == 'instance'
|
||||
assert new_activity.object2 == 'instance_group'
|
||||
assert new_activity.instance.first() == instance
|
||||
assert new_activity.instance_group.first() == instance_group
|
||||
else:
|
||||
assert not new_activity
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('node_type', ['control', 'hybrid', 'execution'])
|
||||
@@ -242,5 +285,19 @@ def test_instance_group_unattach_from_instance(post, instance_group, node_type_i
|
||||
instance = node_type_instance(hostname=node_type, node_type=node_type)
|
||||
instance_group.instances.add(instance)
|
||||
|
||||
count = ActivityStream.objects.count()
|
||||
|
||||
url = reverse(f'api:instance_instance_groups_list', kwargs={'pk': instance.pk})
|
||||
post(url, {'disassociate': True, 'id': instance_group.id}, admin, expect=204 if node_type != 'control' else 400)
|
||||
|
||||
new_activity = ActivityStream.objects.all()[count:]
|
||||
if node_type != 'control':
|
||||
assert len(new_activity) == 1
|
||||
new_activity = new_activity[0]
|
||||
assert new_activity.operation == 'disassociate'
|
||||
assert new_activity.object1 == 'instance'
|
||||
assert new_activity.object2 == 'instance_group'
|
||||
assert new_activity.instance.first() == instance
|
||||
assert new_activity.instance_group.first() == instance_group
|
||||
else:
|
||||
assert not new_activity
|
||||
|
||||
26
awx/main/tests/functional/commands/test_register_queue.py
Normal file
26
awx/main/tests/functional/commands/test_register_queue.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout
|
||||
|
||||
import pytest
|
||||
|
||||
from awx.main.management.commands.register_queue import RegisterQueue
|
||||
from awx.main.models.ha import InstanceGroup
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_openshift_idempotence():
|
||||
def perform_register():
|
||||
with StringIO() as buffer:
|
||||
with redirect_stdout(buffer):
|
||||
RegisterQueue('default', 100, 0, [], is_container_group=True).register()
|
||||
return buffer.getvalue()
|
||||
|
||||
assert '(changed: True)' in perform_register()
|
||||
assert '(changed: True)' not in perform_register()
|
||||
assert '(changed: True)' not in perform_register()
|
||||
|
||||
ig = InstanceGroup.objects.get(name='default')
|
||||
assert ig.policy_instance_percentage == 100
|
||||
assert ig.policy_instance_minimum == 0
|
||||
assert ig.policy_instance_list == []
|
||||
assert ig.is_container_group is True
|
||||
@@ -170,7 +170,7 @@ def test_activity_stream_actor(admin_user):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_annon_user_action():
|
||||
def test_anon_user_action():
|
||||
with mock.patch('awx.main.signals.get_current_user') as u_mock:
|
||||
u_mock.return_value = AnonymousUser()
|
||||
inv = Inventory.objects.create(name='ainventory')
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import pytest
|
||||
|
||||
from awx.main.models.execution_environments import ExecutionEnvironment
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cleanup_patch(mocker):
|
||||
return mocker.patch('awx.main.signals.handle_removed_image')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_image_unchanged_no_delete_task(cleanup_patch):
|
||||
"""When an irrelevant EE field is changed, we do not run the image cleanup task"""
|
||||
execution_environment = ExecutionEnvironment.objects.create(name='test-ee', image='quay.io/foo/bar')
|
||||
execution_environment.description = 'foobar'
|
||||
execution_environment.save()
|
||||
|
||||
cleanup_patch.delay.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_image_changed_creates_delete_task(cleanup_patch):
|
||||
execution_environment = ExecutionEnvironment.objects.create(name='test-ee', image='quay.io/foo/bar')
|
||||
execution_environment.image = 'quay.io/new/image'
|
||||
execution_environment.save()
|
||||
|
||||
cleanup_patch.delay.assert_called_once_with(remove_images=['quay.io/foo/bar'])
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_image_still_in_use(cleanup_patch):
|
||||
"""When an image is still in use by another EE, we do not clean it up"""
|
||||
ExecutionEnvironment.objects.create(name='unrelated-ee', image='quay.io/foo/bar')
|
||||
execution_environment = ExecutionEnvironment.objects.create(name='test-ee', image='quay.io/foo/bar')
|
||||
execution_environment.image = 'quay.io/new/image'
|
||||
execution_environment.save()
|
||||
|
||||
cleanup_patch.delay.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_image_deletion_creates_delete_task(cleanup_patch):
|
||||
execution_environment = ExecutionEnvironment.objects.create(name='test-ee', image='quay.io/foo/bar')
|
||||
execution_environment.delete()
|
||||
|
||||
cleanup_patch.delay.assert_called_once_with(remove_images=['quay.io/foo/bar'])
|
||||
19
awx/main/tests/functional/test_ha.py
Normal file
19
awx/main/tests/functional/test_ha.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import pytest
|
||||
|
||||
# AWX
|
||||
from awx.main.ha import is_ha_environment
|
||||
from awx.main.models.ha import Instance
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_multiple_instances():
|
||||
for i in range(2):
|
||||
Instance.objects.create(hostname=f'foo{i}', node_type='hybrid')
|
||||
assert is_ha_environment()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_db_localhost():
|
||||
Instance.objects.create(hostname='foo', node_type='hybrid')
|
||||
Instance.objects.create(hostname='bar', node_type='execution')
|
||||
assert is_ha_environment() is False
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
from unittest import mock
|
||||
|
||||
from awx.main.models import AdHocCommand, InventoryUpdate, JobTemplate, ProjectUpdate
|
||||
from awx.main.models.activity_stream import ActivityStream
|
||||
from awx.main.models.ha import Instance, InstanceGroup
|
||||
from awx.main.tasks import apply_cluster_membership_policies
|
||||
from awx.api.versioning import reverse
|
||||
@@ -72,6 +73,7 @@ def test_instance_dup(org_admin, organization, project, instance_factory, instan
|
||||
i1 = instance_factory("i1")
|
||||
i2 = instance_factory("i2")
|
||||
i3 = instance_factory("i3")
|
||||
|
||||
ig_all = instance_group_factory("all", instances=[i1, i2, i3])
|
||||
ig_dup = instance_group_factory("duplicates", instances=[i1])
|
||||
project.organization.instance_groups.add(ig_all, ig_dup)
|
||||
@@ -83,7 +85,7 @@ def test_instance_dup(org_admin, organization, project, instance_factory, instan
|
||||
api_num_instances_oa = list(list_response2.data.items())[0][1]
|
||||
|
||||
assert actual_num_instances == api_num_instances_auditor
|
||||
# Note: The org_admin will not see the default 'tower' node (instance fixture) because it is not in it's group, as expected
|
||||
# Note: The org_admin will not see the default 'tower' node (instance fixture) because it is not in its group, as expected
|
||||
assert api_num_instances_oa == (actual_num_instances - 1)
|
||||
|
||||
|
||||
@@ -94,7 +96,13 @@ def test_policy_instance_few_instances(instance_factory, instance_group_factory)
|
||||
ig_2 = instance_group_factory("ig2", percentage=25)
|
||||
ig_3 = instance_group_factory("ig3", percentage=25)
|
||||
ig_4 = instance_group_factory("ig4", percentage=25)
|
||||
|
||||
count = ActivityStream.objects.count()
|
||||
|
||||
apply_cluster_membership_policies()
|
||||
# running apply_cluster_membership_policies shouldn't spam the activity stream
|
||||
assert ActivityStream.objects.count() == count
|
||||
|
||||
assert len(ig_1.instances.all()) == 1
|
||||
assert i1 in ig_1.instances.all()
|
||||
assert len(ig_2.instances.all()) == 1
|
||||
@@ -103,8 +111,12 @@ def test_policy_instance_few_instances(instance_factory, instance_group_factory)
|
||||
assert i1 in ig_3.instances.all()
|
||||
assert len(ig_4.instances.all()) == 1
|
||||
assert i1 in ig_4.instances.all()
|
||||
|
||||
i2 = instance_factory("i2")
|
||||
count += 1
|
||||
apply_cluster_membership_policies()
|
||||
assert ActivityStream.objects.count() == count
|
||||
|
||||
assert len(ig_1.instances.all()) == 1
|
||||
assert i1 in ig_1.instances.all()
|
||||
assert len(ig_2.instances.all()) == 1
|
||||
|
||||
@@ -9,6 +9,8 @@ try:
|
||||
except ImportError:
|
||||
from pip.req import parse_requirements
|
||||
|
||||
from pip._internal.req.constructors import parse_req_from_line
|
||||
|
||||
|
||||
def test_python_and_js_licenses():
|
||||
def index_licenses(path):
|
||||
@@ -53,15 +55,16 @@ def test_python_and_js_licenses():
|
||||
fname = '%s/%s' % (path, req_file)
|
||||
|
||||
for reqt in parse_requirements(fname, session=''):
|
||||
name = reqt.name
|
||||
version = str(reqt.specifier)
|
||||
parsed_requirement = parse_req_from_line(reqt.requirement, None)
|
||||
name = parsed_requirement.requirement.name
|
||||
version = str(parsed_requirement.requirement.specifier)
|
||||
if version.startswith('=='):
|
||||
version = version[2:]
|
||||
if reqt.link:
|
||||
if str(reqt.link).startswith(('http://', 'https://')):
|
||||
(name, version) = str(reqt.req).split('==', 1)
|
||||
if parsed_requirement.link:
|
||||
if str(parsed_requirement.link).startswith(('http://', 'https://')):
|
||||
(name, version) = str(parsed_requirement.requirement).split('==', 1)
|
||||
else:
|
||||
(name, version) = reqt.link.filename.split('@', 1)
|
||||
(name, version) = parsed_requirement.link.filename.split('@', 1)
|
||||
if name.endswith('.git'):
|
||||
name = name[:-4]
|
||||
if name == 'receptor':
|
||||
|
||||
@@ -89,3 +89,19 @@ class TestInstanceGroup(object):
|
||||
assert ig.find_largest_idle_instance(instances_online_only) is None, reason
|
||||
else:
|
||||
assert ig.find_largest_idle_instance(instances_online_only) == instances[instance_fit_index], reason
|
||||
|
||||
|
||||
def test_cleanup_params_defaults():
|
||||
inst = Instance(hostname='foobar')
|
||||
assert inst.get_cleanup_task_kwargs(exclude_strings=['awx_423_']) == {'exclude_strings': ['awx_423_'], 'file_pattern': '/tmp/awx_*_*'}
|
||||
|
||||
|
||||
def test_cleanup_params_for_image_cleanup():
|
||||
inst = Instance(hostname='foobar')
|
||||
# see CLI conversion in awx.main.tests.unit.utils.test_receptor
|
||||
assert inst.get_cleanup_task_kwargs(file_pattern='', remove_images=['quay.invalid/foo/bar'], image_prune=True) == {
|
||||
'file_pattern': '',
|
||||
'process_isolation_executable': 'podman',
|
||||
'remove_images': ['quay.invalid/foo/bar'],
|
||||
'image_prune': True,
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@ import awx.main.notifications.rocketchat_backend as rocketchat_backend
|
||||
|
||||
|
||||
def test_send_messages():
|
||||
with mock.patch('awx.main.notifications.rocketchat_backend.requests') as requests_mock:
|
||||
with mock.patch('awx.main.notifications.rocketchat_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.rocketchat_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 201
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = rocketchat_backend.RocketChatBackend()
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
@@ -23,7 +26,12 @@ def test_send_messages():
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with('http://example.com', data='{"text": "test subject"}', verify=True)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
data='{"text": "test subject"}',
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
@@ -84,8 +92,11 @@ def test_send_messages_with_icon_url():
|
||||
|
||||
|
||||
def test_send_messages_with_no_verify_ssl():
|
||||
with mock.patch('awx.main.notifications.rocketchat_backend.requests') as requests_mock:
|
||||
with mock.patch('awx.main.notifications.rocketchat_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.rocketchat_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 201
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = rocketchat_backend.RocketChatBackend(rocketchat_no_verify_ssl=True)
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
@@ -100,5 +111,10 @@ def test_send_messages_with_no_verify_ssl():
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with('http://example.com', data='{"text": "test subject"}', verify=False)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
data='{"text": "test subject"}',
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=False,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
75
awx/main/tests/unit/notifications/test_slack.py
Normal file
75
awx/main/tests/unit/notifications/test_slack.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import pytest
|
||||
|
||||
from unittest import mock
|
||||
from django.core.mail.message import EmailMessage
|
||||
|
||||
import awx.main.notifications.slack_backend as slack_backend
|
||||
|
||||
|
||||
def test_send_messages():
|
||||
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock:
|
||||
WebClient_mock = slack_sdk_mock.return_value
|
||||
WebClient_mock.chat_postMessage.return_value = {'ok': True}
|
||||
backend = slack_backend.SlackBackend('slack_access_token')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
'test body',
|
||||
[],
|
||||
[
|
||||
'#random',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', thread_ts=None, as_user=True, text='test subject')
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_color():
|
||||
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock:
|
||||
WebClient_mock = slack_sdk_mock.return_value
|
||||
WebClient_mock.chat_postMessage.return_value = {'ok': True}
|
||||
backend = slack_backend.SlackBackend('slack_access_token', hex_color='#006699')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
'test body',
|
||||
[],
|
||||
[
|
||||
'#random',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(
|
||||
channel='random', as_user=True, thread_ts=None, attachments=[{'color': '#006699', 'text': 'test subject'}]
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_fail():
|
||||
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock, pytest.raises(RuntimeError, match=r'.*not_in_channel.*'):
|
||||
WebClient_mock = slack_sdk_mock.return_value
|
||||
WebClient_mock.chat_postMessage.return_value = {'ok': False, 'error': 'not_in_channel'}
|
||||
backend = slack_backend.SlackBackend('slack_access_token')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
'test body',
|
||||
[],
|
||||
[
|
||||
'#not_existing',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
WebClient_mock.chat_postMessage.assert_called_once_with(channel='not_existing', as_user=True, text='test subject')
|
||||
assert sent_messages == 0
|
||||
221
awx/main/tests/unit/notifications/test_webhook.py
Normal file
221
awx/main/tests/unit/notifications/test_webhook.py
Normal file
@@ -0,0 +1,221 @@
|
||||
import json
|
||||
|
||||
from unittest import mock
|
||||
from django.core.mail.message import EmailMessage
|
||||
|
||||
import awx.main.notifications.webhook_backend as webhook_backend
|
||||
|
||||
|
||||
def test_send_messages_as_POST():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', None)
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=None,
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_as_PUT():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.put.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('PUT', None)
|
||||
message = EmailMessage(
|
||||
'test subject 2',
|
||||
{'text': 'test body 2'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.put.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=None,
|
||||
data=json.dumps({'text': 'test body 2'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_username():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', None, username='userstring')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=('userstring', None),
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_password():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', None, password='passwordstring')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=(None, 'passwordstring'),
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_username_and_password():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', None, username='userstring', password='passwordstring')
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=('userstring', 'passwordstring'),
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_no_verify_ssl():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', None, disable_ssl_verification=True)
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=None,
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'},
|
||||
verify=False,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
|
||||
|
||||
def test_send_messages_with_additional_headers():
|
||||
with mock.patch('awx.main.notifications.webhook_backend.requests') as requests_mock, mock.patch(
|
||||
'awx.main.notifications.webhook_backend.get_awx_http_client_headers'
|
||||
) as version_mock:
|
||||
requests_mock.post.return_value.status_code = 200
|
||||
version_mock.return_value = {'Content-Type': 'application/json', 'User-Agent': 'AWX 0.0.1.dev (open)'}
|
||||
backend = webhook_backend.WebhookBackend('POST', {'X-Test-Header1': 'test-content-1', 'X-Test-Header2': 'test-content-2'})
|
||||
message = EmailMessage(
|
||||
'test subject',
|
||||
{'text': 'test body'},
|
||||
[],
|
||||
[
|
||||
'http://example.com',
|
||||
],
|
||||
)
|
||||
sent_messages = backend.send_messages(
|
||||
[
|
||||
message,
|
||||
]
|
||||
)
|
||||
requests_mock.post.assert_called_once_with(
|
||||
'http://example.com',
|
||||
auth=None,
|
||||
data=json.dumps({'text': 'test body'}, ensure_ascii=False).encode('utf-8'),
|
||||
headers={
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'AWX 0.0.1.dev (open)',
|
||||
'X-Test-Header1': 'test-content-1',
|
||||
'X-Test-Header2': 'test-content-2',
|
||||
},
|
||||
verify=True,
|
||||
)
|
||||
assert sent_messages == 1
|
||||
@@ -1,17 +0,0 @@
|
||||
# Copyright (c) 2016 Ansible, Inc.
|
||||
|
||||
# Python
|
||||
from unittest import mock
|
||||
|
||||
# AWX
|
||||
from awx.main.ha import is_ha_environment
|
||||
|
||||
|
||||
@mock.patch('awx.main.models.Instance.objects.count', lambda: 2)
|
||||
def test_multiple_instances():
|
||||
assert is_ha_environment()
|
||||
|
||||
|
||||
@mock.patch('awx.main.models.Instance.objects.count', lambda: 1)
|
||||
def test_db_localhost():
|
||||
assert is_ha_environment() is False
|
||||
21
awx/main/tests/unit/utils/test_receptor.py
Normal file
21
awx/main/tests/unit/utils/test_receptor.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from awx.main.utils.receptor import _convert_args_to_cli
|
||||
|
||||
|
||||
def test_file_cleanup_scenario():
|
||||
args = _convert_args_to_cli({'exclude_strings': ['awx_423_', 'awx_582_'], 'file_pattern': '/tmp/awx_*_*'})
|
||||
assert ' '.join(args) == 'cleanup --exclude-strings=awx_423_ awx_582_ --file-pattern=/tmp/awx_*_*'
|
||||
|
||||
|
||||
def test_image_cleanup_scenario():
|
||||
# See input dict in awx.main.tests.unit.models.test_ha
|
||||
args = _convert_args_to_cli(
|
||||
{
|
||||
'file_pattern': '',
|
||||
'process_isolation_executable': 'podman',
|
||||
'remove_images': ['quay.invalid/foo/bar:latest', 'quay.invalid/foo/bar:devel'],
|
||||
'image_prune': True,
|
||||
}
|
||||
)
|
||||
assert (
|
||||
' '.join(args) == 'cleanup --remove-images=quay.invalid/foo/bar:latest quay.invalid/foo/bar:devel --image-prune --process-isolation-executable=podman'
|
||||
)
|
||||
@@ -1,15 +1,21 @@
|
||||
import logging
|
||||
import yaml
|
||||
import time
|
||||
from enum import Enum, unique
|
||||
|
||||
from receptorctl.socket_interface import ReceptorControl
|
||||
|
||||
from enum import Enum, unique
|
||||
from awx.main.exceptions import ReceptorNodeNotFound
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
logger = logging.getLogger('awx.main.utils.receptor')
|
||||
|
||||
__RECEPTOR_CONF = '/etc/receptor/receptor.conf'
|
||||
|
||||
RECEPTOR_ACTIVE_STATES = ('Pending', 'Running')
|
||||
|
||||
|
||||
@unique
|
||||
class ReceptorConnectionType(Enum):
|
||||
@@ -59,62 +65,109 @@ def get_conn_type(node_name, receptor_ctl):
|
||||
for node in all_nodes:
|
||||
if node.get('NodeID') == node_name:
|
||||
return ReceptorConnectionType(node.get('ConnType'))
|
||||
raise ReceptorNodeNotFound(f'Instance {node_name} is not in the receptor mesh')
|
||||
|
||||
|
||||
def worker_info(node_name, work_type='ansible-runner'):
|
||||
def administrative_workunit_reaper(work_list=None):
|
||||
"""
|
||||
This releases completed work units that were spawned by actions inside of this module
|
||||
specifically, this should catch any completed work unit left by
|
||||
- worker_info
|
||||
- worker_cleanup
|
||||
These should ordinarily be released when the method finishes, but this is a
|
||||
cleanup of last-resort, in case something went awry
|
||||
"""
|
||||
receptor_ctl = get_receptor_ctl()
|
||||
use_stream_tls = getattr(get_conn_type(node_name, receptor_ctl), 'name', None) == "STREAMTLS"
|
||||
transmit_start = time.time()
|
||||
error_list = []
|
||||
data = {'errors': error_list, 'transmit_timing': 0.0}
|
||||
if work_list is None:
|
||||
work_list = receptor_ctl.simple_command("work list")
|
||||
|
||||
kwargs = {}
|
||||
kwargs['tlsclient'] = get_tls_client(use_stream_tls)
|
||||
if work_type != 'local':
|
||||
kwargs['ttl'] = '20s'
|
||||
result = receptor_ctl.submit_work(worktype=work_type, payload='', params={"params": f"--worker-info"}, node=node_name, **kwargs)
|
||||
for unit_id, work_data in work_list.items():
|
||||
extra_data = work_data.get('ExtraData')
|
||||
if (extra_data is None) or (extra_data.get('RemoteWorkType') != 'ansible-runner'):
|
||||
continue # if this is not ansible-runner work, we do not want to touch it
|
||||
params = extra_data.get('RemoteParams', {}).get('params')
|
||||
if not params:
|
||||
continue
|
||||
if not (params == '--worker-info' or params.startswith('cleanup')):
|
||||
continue # if this is not a cleanup or health check, we do not want to touch it
|
||||
if work_data.get('StateName') in RECEPTOR_ACTIVE_STATES:
|
||||
continue # do not want to touch active work units
|
||||
logger.info(f'Reaping orphaned work unit {unit_id} with params {params}')
|
||||
receptor_ctl.simple_command(f"work release {unit_id}")
|
||||
|
||||
|
||||
class RemoteJobError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def run_until_complete(node, timing_data=None, **kwargs):
|
||||
"""
|
||||
Runs an ansible-runner work_type on remote node, waits until it completes, then returns stdout.
|
||||
"""
|
||||
receptor_ctl = get_receptor_ctl()
|
||||
|
||||
use_stream_tls = getattr(get_conn_type(node, receptor_ctl), 'name', None) == "STREAMTLS"
|
||||
kwargs.setdefault('tlsclient', get_tls_client(use_stream_tls))
|
||||
kwargs.setdefault('ttl', '20s')
|
||||
kwargs.setdefault('payload', '')
|
||||
|
||||
transmit_start = time.time()
|
||||
sign_work = False if settings.IS_K8S else True
|
||||
result = receptor_ctl.submit_work(worktype='ansible-runner', node=node, signwork=sign_work, **kwargs)
|
||||
|
||||
unit_id = result['unitid']
|
||||
run_start = time.time()
|
||||
data['transmit_timing'] = run_start - transmit_start
|
||||
data['run_timing'] = 0.0
|
||||
if timing_data:
|
||||
timing_data['transmit_timing'] = run_start - transmit_start
|
||||
run_timing = 0.0
|
||||
stdout = ''
|
||||
|
||||
try:
|
||||
|
||||
resultfile = receptor_ctl.get_work_results(unit_id)
|
||||
|
||||
stdout = ''
|
||||
|
||||
while data['run_timing'] < 20.0:
|
||||
while run_timing < 20.0:
|
||||
status = receptor_ctl.simple_command(f'work status {unit_id}')
|
||||
state_name = status.get('StateName')
|
||||
if state_name not in ('Pending', 'Running'):
|
||||
if state_name not in RECEPTOR_ACTIVE_STATES:
|
||||
break
|
||||
data['run_timing'] = time.time() - run_start
|
||||
run_timing = time.time() - run_start
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
error_list.append(f'Timeout getting worker info on {node_name}, state remains in {state_name}')
|
||||
raise RemoteJobError(f'Receptor job timeout on {node} after {run_timing} seconds, state remains in {state_name}')
|
||||
|
||||
if timing_data:
|
||||
timing_data['run_timing'] = run_timing
|
||||
|
||||
stdout = resultfile.read()
|
||||
stdout = str(stdout, encoding='utf-8')
|
||||
|
||||
finally:
|
||||
|
||||
res = receptor_ctl.simple_command(f"work release {unit_id}")
|
||||
if res != {'released': unit_id}:
|
||||
logger.warn(f'Could not confirm release of receptor work unit id {unit_id} from {node_name}, data: {res}')
|
||||
if settings.RECEPTOR_RELEASE_WORK:
|
||||
res = receptor_ctl.simple_command(f"work release {unit_id}")
|
||||
if res != {'released': unit_id}:
|
||||
logger.warn(f'Could not confirm release of receptor work unit id {unit_id} from {node}, data: {res}')
|
||||
|
||||
receptor_ctl.close()
|
||||
|
||||
if state_name.lower() == 'failed':
|
||||
work_detail = status.get('Detail', '')
|
||||
if not work_detail.startswith('exit status'):
|
||||
error_list.append(f'Receptor error getting worker info from {node_name}, detail:\n{work_detail}')
|
||||
elif 'unrecognized arguments: --worker-info' in stdout:
|
||||
error_list.append(f'Old version (2.0.1 or earlier) of ansible-runner on node {node_name} without --worker-info')
|
||||
if work_detail:
|
||||
raise RemoteJobError(f'Receptor error from {node}, detail:\n{work_detail}')
|
||||
else:
|
||||
error_list.append(f'Unknown ansible-runner error on node {node_name}, stdout:\n{stdout}')
|
||||
else:
|
||||
raise RemoteJobError(f'Unknown ansible-runner error on node {node}, stdout:\n{stdout}')
|
||||
|
||||
return stdout
|
||||
|
||||
|
||||
def worker_info(node_name, work_type='ansible-runner'):
|
||||
error_list = []
|
||||
data = {'errors': error_list, 'transmit_timing': 0.0}
|
||||
|
||||
try:
|
||||
stdout = run_until_complete(node=node_name, timing_data=data, params={"params": "--worker-info"})
|
||||
|
||||
yaml_stdout = stdout.strip()
|
||||
remote_data = {}
|
||||
try:
|
||||
@@ -128,6 +181,16 @@ def worker_info(node_name, work_type='ansible-runner'):
|
||||
error_list.extend(remote_data.pop('errors', [])) # merge both error lists
|
||||
data.update(remote_data)
|
||||
|
||||
except RemoteJobError as exc:
|
||||
details = exc.args[0]
|
||||
if 'unrecognized arguments: --worker-info' in details:
|
||||
error_list.append(f'Old version (2.0.1 or earlier) of ansible-runner on node {node_name} without --worker-info')
|
||||
else:
|
||||
error_list.append(details)
|
||||
|
||||
except (ReceptorNodeNotFound, RuntimeError) as exc:
|
||||
error_list.append(str(exc))
|
||||
|
||||
# If we have a connection error, missing keys would be trivial consequence of that
|
||||
if not data['errors']:
|
||||
# see tasks.py usage of keys
|
||||
@@ -136,3 +199,32 @@ def worker_info(node_name, work_type='ansible-runner'):
|
||||
data['errors'].append('Worker failed to return keys {}'.format(' '.join(missing_keys)))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def _convert_args_to_cli(vargs):
|
||||
"""
|
||||
For the ansible-runner worker cleanup command
|
||||
converts the dictionary (parsed argparse variables) used for python interface
|
||||
into a string of CLI options, which has to be used on execution nodes.
|
||||
"""
|
||||
args = ['cleanup']
|
||||
for option in ('exclude_strings', 'remove_images'):
|
||||
if vargs.get(option):
|
||||
args.append('--{}={}'.format(option.replace('_', '-'), ' '.join(vargs.get(option))))
|
||||
for option in ('file_pattern', 'image_prune', 'process_isolation_executable', 'grace_period'):
|
||||
if vargs.get(option) is True:
|
||||
args.append('--{}'.format(option.replace('_', '-')))
|
||||
elif vargs.get(option) not in (None, ''):
|
||||
args.append('--{}={}'.format(option.replace('_', '-'), vargs.get(option)))
|
||||
return args
|
||||
|
||||
|
||||
def worker_cleanup(node_name, vargs, timeout=300.0):
|
||||
args = _convert_args_to_cli(vargs)
|
||||
|
||||
remote_command = ' '.join(args)
|
||||
logger.debug(f'Running command over receptor mesh on {node_name}: ansible-runner worker {remote_command}')
|
||||
|
||||
stdout = run_until_complete(node=node_name, params={"params": remote_command})
|
||||
|
||||
return stdout
|
||||
|
||||
@@ -68,7 +68,6 @@ DATABASES = {
|
||||
# the K8S cluster where awx itself is running)
|
||||
IS_K8S = False
|
||||
|
||||
RECEPTOR_RELEASE_WORK = True
|
||||
AWX_CONTAINER_GROUP_K8S_API_TIMEOUT = 10
|
||||
AWX_CONTAINER_GROUP_DEFAULT_NAMESPACE = os.getenv('MY_POD_NAMESPACE', 'default')
|
||||
# Timeout when waiting for pod to enter running state. If the pod is still in pending state , it will be terminated. Valid time units are "s", "m", "h". Example : "5m" , "10s".
|
||||
@@ -243,6 +242,9 @@ SUBSYSTEM_METRICS_INTERVAL_SAVE_TO_REDIS = 2
|
||||
# The maximum allowed jobs to start on a given task manager cycle
|
||||
START_TASK_LIMIT = 100
|
||||
|
||||
# Name of our session cookie
|
||||
SESSION_COOKIE_NAME = 'awxsessionid'
|
||||
|
||||
# Disallow sending session cookies over insecure connections
|
||||
SESSION_COOKIE_SECURE = True
|
||||
|
||||
@@ -426,7 +428,7 @@ os.environ.setdefault('DJANGO_LIVE_TEST_SERVER_ADDRESS', 'localhost:9013-9199')
|
||||
# heartbeat period can factor into some forms of logic, so it is maintained as a setting here
|
||||
CLUSTER_NODE_HEARTBEAT_PERIOD = 60
|
||||
RECEPTOR_SERVICE_ADVERTISEMENT_PERIOD = 60 # https://github.com/ansible/receptor/blob/aa1d589e154d8a0cb99a220aff8f98faf2273be6/pkg/netceptor/netceptor.go#L34
|
||||
EXECUTION_NODE_REMEDIATION_CHECKS = 60 * 10 # once every 10 minutes check if an execution node errors have been resolved
|
||||
EXECUTION_NODE_REMEDIATION_CHECKS = 60 * 30 # once every 30 minutes check if an execution node errors have been resolved
|
||||
|
||||
BROKER_URL = 'unix:///var/run/redis/redis.sock'
|
||||
CELERYBEAT_SCHEDULE = {
|
||||
@@ -441,7 +443,7 @@ CELERYBEAT_SCHEDULE = {
|
||||
'k8s_reaper': {'task': 'awx.main.tasks.awx_k8s_reaper', 'schedule': timedelta(seconds=60), 'options': {'expires': 50}},
|
||||
'receptor_reaper': {'task': 'awx.main.tasks.awx_receptor_workunit_reaper', 'schedule': timedelta(seconds=60)},
|
||||
'send_subsystem_metrics': {'task': 'awx.main.analytics.analytics_tasks.send_subsystem_metrics', 'schedule': timedelta(seconds=20)},
|
||||
'cleanup_images': {'task': 'awx.main.tasks.cleanup_execution_environment_images', 'schedule': timedelta(hours=3)},
|
||||
'cleanup_images': {'task': 'awx.main.tasks.cleanup_images_and_files', 'schedule': timedelta(hours=3)},
|
||||
}
|
||||
|
||||
# Django Caching Configuration
|
||||
@@ -931,6 +933,9 @@ AWX_CALLBACK_PROFILE = False
|
||||
# Delete temporary directories created to store playbook run-time
|
||||
AWX_CLEANUP_PATHS = True
|
||||
|
||||
# Delete completed work units in receptor
|
||||
RECEPTOR_RELEASE_WORK = True
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django_guid.middleware.GuidMiddleware',
|
||||
'awx.main.middleware.TimingMiddleware',
|
||||
|
||||
@@ -9,6 +9,7 @@ import copy
|
||||
import errno
|
||||
import sys
|
||||
import traceback
|
||||
import socket
|
||||
|
||||
# Django Split Settings
|
||||
from split_settings.tools import optional, include
|
||||
@@ -88,4 +89,8 @@ except IOError:
|
||||
|
||||
# The below runs AFTER all of the custom settings are imported.
|
||||
|
||||
DATABASES['default'].setdefault('OPTIONS', dict()).setdefault('application_name', f'{CLUSTER_HOST_ID}-{os.getpid()}-{" ".join(sys.argv)}'[:63]) # noqa
|
||||
CLUSTER_HOST_ID = socket.gethostname()
|
||||
|
||||
DATABASES.setdefault('default', dict()).setdefault('OPTIONS', dict()).setdefault(
|
||||
'application_name', f'{CLUSTER_HOST_ID}-{os.getpid()}-{" ".join(sys.argv)}'[:63]
|
||||
) # noqa
|
||||
|
||||
@@ -5,10 +5,13 @@ ARG TARGET='https://awx:8043'
|
||||
ENV TARGET=${TARGET}
|
||||
ENV CI=true
|
||||
WORKDIR /ui
|
||||
ADD .eslintignore .eslintignore
|
||||
ADD .eslintrc .eslintrc
|
||||
ADD .linguirc .linguirc
|
||||
ADD jsconfig.json jsconfig.json
|
||||
ADD public public
|
||||
ADD package.json package.json
|
||||
ADD package-lock.json package-lock.json
|
||||
ADD .linguirc .linguirc
|
||||
COPY ${NPMRC_FILE} .npmrc
|
||||
RUN npm install
|
||||
ADD src src
|
||||
|
||||
1096
awx/ui/package-lock.json
generated
1096
awx/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,19 +6,19 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@lingui/react": "3.9.0",
|
||||
"@patternfly/patternfly": "^4.102.1",
|
||||
"@patternfly/patternfly": "4.102.1",
|
||||
"@patternfly/react-core": "4.121.1",
|
||||
"@patternfly/react-icons": "4.7.22",
|
||||
"@patternfly/react-table": "^4.19.15",
|
||||
"@patternfly/react-table": "4.26.7",
|
||||
"ace-builds": "^1.4.12",
|
||||
"ansi-to-html": "0.7.0",
|
||||
"axios": "^0.21.1",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"axios": "0.22.0",
|
||||
"babel-plugin-macros": "^3.0.1",
|
||||
"codemirror": "^5.47.0",
|
||||
"d3": "6.7.0",
|
||||
"d3": "7.1.1",
|
||||
"dagre": "^0.8.4",
|
||||
"formik": "2.2.9",
|
||||
"has-ansi": "4.0.0",
|
||||
"has-ansi": "5.0.1",
|
||||
"html-entities": "2.3.2",
|
||||
"js-yaml": "^3.13.1",
|
||||
"luxon": "^2.0.1",
|
||||
@@ -101,6 +101,10 @@
|
||||
"coveragePathIgnorePatterns": [
|
||||
"<rootDir>/src/locales",
|
||||
"index.js"
|
||||
],
|
||||
"transformIgnorePatterns": [
|
||||
"<rootDir>/node_modules/(?!d3)/",
|
||||
"<rootDir>/node_modules/(?!has-ansi)/"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +98,21 @@ const AuthorizedRoutes = ({ routeConfig }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ProtectedRoute = ({ children, ...rest }) => {
|
||||
const { authRedirectTo, setAuthRedirectTo } = useSession();
|
||||
const { pathname } = useLocation();
|
||||
export function ProtectedRoute({ children, ...rest }) {
|
||||
const {
|
||||
authRedirectTo,
|
||||
setAuthRedirectTo,
|
||||
loginRedirectOverride,
|
||||
isUserBeingLoggedOut,
|
||||
} = useSession();
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
setAuthRedirectTo(authRedirectTo === '/logout' ? '/' : pathname);
|
||||
setAuthRedirectTo(
|
||||
authRedirectTo === '/logout'
|
||||
? '/'
|
||||
: `${location.pathname}${location.search}`
|
||||
);
|
||||
});
|
||||
|
||||
if (isAuthenticated(document.cookie)) {
|
||||
@@ -116,8 +125,16 @@ const ProtectedRoute = ({ children, ...rest }) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
loginRedirectOverride &&
|
||||
!window.location.href.includes('/login') &&
|
||||
!isUserBeingLoggedOut
|
||||
) {
|
||||
window.location.replace(loginRedirectOverride);
|
||||
return null;
|
||||
}
|
||||
return <Redirect to="/login" />;
|
||||
};
|
||||
}
|
||||
|
||||
function App() {
|
||||
const history = useHistory();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { act } from 'react-dom/test-utils';
|
||||
import { RootAPI } from 'api';
|
||||
import * as SessionContext from 'contexts/Session';
|
||||
import { mountWithContexts } from '../testUtils/enzymeHelpers';
|
||||
import App from './App';
|
||||
import App, { ProtectedRoute } from './App';
|
||||
|
||||
jest.mock('./api');
|
||||
|
||||
@@ -20,6 +20,8 @@ describe('<App />', () => {
|
||||
const contextValues = {
|
||||
setAuthRedirectTo: jest.fn(),
|
||||
isSessionExpired: false,
|
||||
isUserBeingLoggedOut: false,
|
||||
loginRedirectOverride: null,
|
||||
};
|
||||
jest
|
||||
.spyOn(SessionContext, 'useSession')
|
||||
@@ -32,4 +34,36 @@ describe('<App />', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('redirect to login override', async () => {
|
||||
const { location } = window;
|
||||
delete window.location;
|
||||
window.location = {
|
||||
replace: jest.fn(),
|
||||
href: '/',
|
||||
};
|
||||
|
||||
expect(window.location.replace).not.toHaveBeenCalled();
|
||||
|
||||
const contextValues = {
|
||||
setAuthRedirectTo: jest.fn(),
|
||||
isSessionExpired: false,
|
||||
isUserBeingLoggedOut: false,
|
||||
loginRedirectOverride: '/sso/test',
|
||||
};
|
||||
jest
|
||||
.spyOn(SessionContext, 'useSession')
|
||||
.mockImplementation(() => contextValues);
|
||||
|
||||
await act(async () => {
|
||||
mountWithContexts(
|
||||
<ProtectedRoute>
|
||||
<div>foo</div>
|
||||
</ProtectedRoute>
|
||||
);
|
||||
});
|
||||
|
||||
expect(window.location.replace).toHaveBeenCalled();
|
||||
window.location = location;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,10 +18,7 @@ const QS_CONFIG = (order_by = 'name') =>
|
||||
|
||||
function AssociateModal({
|
||||
header = t`Items`,
|
||||
columns = [
|
||||
{ key: 'hostname', name: t`Name` },
|
||||
{ key: 'node_type', name: t`Node Type` },
|
||||
],
|
||||
columns = [],
|
||||
title = t`Select Items`,
|
||||
onClose,
|
||||
onAssociate,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { t } from '@lingui/macro';
|
||||
import {
|
||||
Button,
|
||||
@@ -56,6 +56,7 @@ function DataListToolbar({
|
||||
enableNegativeFiltering,
|
||||
enableRelatedFuzzyFiltering,
|
||||
}) {
|
||||
const { search } = useLocation();
|
||||
const showExpandCollapse = onCompact && onExpand;
|
||||
const [isKebabOpen, setIsKebabOpen] = useState(false);
|
||||
const [isKebabModalOpen, setIsKebabModalOpen] = useState(false);
|
||||
@@ -81,7 +82,7 @@ function DataListToolbar({
|
||||
id={`${qsConfig.namespace}-list-toolbar`}
|
||||
clearAllFilters={clearAllFilters}
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
clearFiltersButtonText={t`Clear all filters`}
|
||||
clearFiltersButtonText={Boolean(search) && t`Clear all filters`}
|
||||
>
|
||||
<ToolbarContent>
|
||||
{onExpandAll && (
|
||||
|
||||
@@ -5,6 +5,14 @@ import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
import DataListToolbar from './DataListToolbar';
|
||||
import AddDropDownButton from '../AddDropDownButton/AddDropDownButton';
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: () => ({
|
||||
pathname: '/organizations',
|
||||
search: 'template.name__icontains=name',
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('<DataListToolbar />', () => {
|
||||
let toolbar;
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ function InstanceToggle({ className, fetchInstances, instance, onToggle }) {
|
||||
className={className}
|
||||
css="display: inline-flex;"
|
||||
id={`host-${instance.id}-toggle`}
|
||||
label={t`On`}
|
||||
labelOff={t`Off`}
|
||||
label={t`Enabled`}
|
||||
labelOff={t`Disabled`}
|
||||
isChecked={isEnabled}
|
||||
isDisabled={isLoading || !me?.is_superuser}
|
||||
onChange={toggleInstance}
|
||||
|
||||
@@ -98,15 +98,14 @@ function JobList({ defaultParams, showTypeColumn = false }) {
|
||||
fetchJobs();
|
||||
}, [fetchJobs]);
|
||||
|
||||
// TODO: update QS_CONFIG to be safe for deps array
|
||||
const fetchJobsById = useCallback(
|
||||
async (ids) => {
|
||||
const params = parseQueryString(qsConfig, location.search);
|
||||
async (ids, qs = {}) => {
|
||||
const params = parseQueryString(qs, location.search);
|
||||
params.id__in = ids.join(',');
|
||||
const { data } = await UnifiedJobsAPI.read(params);
|
||||
return data.results;
|
||||
},
|
||||
[location.search] // eslint-disable-line react-hooks/exhaustive-deps
|
||||
[location.search]
|
||||
);
|
||||
|
||||
const jobs = useWsJobs(results, fetchJobsById, qsConfig);
|
||||
|
||||
@@ -265,6 +265,61 @@ describe('<JobList />', () => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('should query jobs list after delete API requests', async () => {
|
||||
UnifiedJobsAPI.read.mockResolvedValue({
|
||||
data: {
|
||||
count: 1,
|
||||
results: [
|
||||
{
|
||||
id: 1,
|
||||
url: '/api/v2/project_updates/1',
|
||||
name: 'job 1',
|
||||
type: 'project_update',
|
||||
status: 'running',
|
||||
related: {
|
||||
cancel: '/api/v2/project_updates/1/cancel',
|
||||
},
|
||||
summary_fields: {
|
||||
user_capabilities: {
|
||||
delete: true,
|
||||
start: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const jobListParams = {
|
||||
order_by: '-finished',
|
||||
not__launch_type: 'sync',
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
};
|
||||
let wrapper;
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<JobList />);
|
||||
});
|
||||
await waitForLoaded(wrapper);
|
||||
|
||||
act(() => {
|
||||
expect(UnifiedJobsAPI.read).toHaveBeenCalledTimes(1);
|
||||
wrapper.find('DataListToolbar').invoke('onSelectAll')(true);
|
||||
});
|
||||
wrapper.update();
|
||||
wrapper.find('JobListItem');
|
||||
expect(
|
||||
wrapper.find('ToolbarDeleteButton').prop('itemsToDelete')
|
||||
).toHaveLength(1);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('ToolbarDeleteButton').invoke('onDelete')();
|
||||
expect(UnifiedJobsAPI.read).toHaveBeenCalledTimes(1);
|
||||
expect(UnifiedJobsAPI.read).toHaveBeenCalledWith(jobListParams);
|
||||
});
|
||||
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('should display message about job running status', async () => {
|
||||
UnifiedJobsAPI.read.mockResolvedValue({
|
||||
data: {
|
||||
|
||||
@@ -128,9 +128,9 @@ function checkForError(launchConfig, surveyConfig, values) {
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
if (isNumeric && (value || value === 0)) {
|
||||
if (isNumeric) {
|
||||
if (
|
||||
(value < question.min || value > question.max) &&
|
||||
(value < question.min || value > question.max || value === '') &&
|
||||
question.required
|
||||
) {
|
||||
hasError = true;
|
||||
|
||||
@@ -7,13 +7,14 @@ const ActionsGrid = styled.div`
|
||||
display: grid;
|
||||
grid-gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
${(props) => {
|
||||
const columns = props.gridColumns || '40px '.repeat(props.numActions || 1);
|
||||
return css`
|
||||
grid-template-columns: ${columns};
|
||||
`;
|
||||
}}
|
||||
padding-right: 20px
|
||||
${(props) => {
|
||||
const columns =
|
||||
props.gridColumns || '40px '.repeat(props.numActions || 1);
|
||||
return css`
|
||||
grid-template-columns: ${columns};
|
||||
`;
|
||||
}};
|
||||
`;
|
||||
ActionsGrid.displayName = 'ActionsGrid';
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import { t } from '@lingui/macro';
|
||||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
Divider,
|
||||
InputGroup,
|
||||
Select,
|
||||
SelectGroup,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
TextInput,
|
||||
@@ -41,15 +43,9 @@ function AdvancedSearch({
|
||||
enableNegativeFiltering,
|
||||
enableRelatedFuzzyFiltering,
|
||||
}) {
|
||||
// TODO: blocked by pf bug, eventually separate these into two groups in the select
|
||||
// for now, I'm spreading set to get rid of duplicate keys...when they are grouped
|
||||
// we might want to revisit that.
|
||||
const allKeys = [
|
||||
...new Set([
|
||||
...(searchableKeys.map((k) => k.key) || []),
|
||||
...(relatedSearchableKeys || []),
|
||||
]),
|
||||
];
|
||||
const relatedKeys = relatedSearchableKeys.filter(
|
||||
(sKey) => !searchableKeys.map(({ key }) => key).includes(sKey)
|
||||
);
|
||||
|
||||
const [isPrefixDropdownOpen, setIsPrefixDropdownOpen] = useState(false);
|
||||
const [isKeyDropdownOpen, setIsKeyDropdownOpen] = useState(false);
|
||||
@@ -165,19 +161,44 @@ function AdvancedSearch({
|
||||
isOpen={isKeyDropdownOpen}
|
||||
placeholderText={t`Key`}
|
||||
isCreatable
|
||||
isGrouped
|
||||
onCreateOption={setKeySelection}
|
||||
maxHeight={maxSelectHeight}
|
||||
noResultsFoundText={t`No results found`}
|
||||
>
|
||||
{allKeys.map((optionKey) => (
|
||||
<SelectOption
|
||||
key={optionKey}
|
||||
value={optionKey}
|
||||
id={`select-option-${optionKey}`}
|
||||
>
|
||||
{optionKey}
|
||||
</SelectOption>
|
||||
))}
|
||||
{[
|
||||
...(searchableKeys.length
|
||||
? [
|
||||
<SelectGroup key="direct keys" label={t`Direct Keys`}>
|
||||
{searchableKeys.map((k) => (
|
||||
<SelectOption
|
||||
value={k.key}
|
||||
key={k.key}
|
||||
id={`select-option-${k.key}`}
|
||||
>
|
||||
{k.key}
|
||||
</SelectOption>
|
||||
))}
|
||||
</SelectGroup>,
|
||||
<Divider key="divider" />,
|
||||
]
|
||||
: []),
|
||||
...(relatedKeys.length
|
||||
? [
|
||||
<SelectGroup key="related keys" label={t`Related Keys`}>
|
||||
{relatedKeys.map((rKey) => (
|
||||
<SelectOption
|
||||
value={rKey}
|
||||
key={rKey}
|
||||
id={`select-option-${rKey}`}
|
||||
>
|
||||
{rKey}
|
||||
</SelectOption>
|
||||
))}
|
||||
</SelectGroup>,
|
||||
]
|
||||
: []),
|
||||
]}
|
||||
</Select>
|
||||
{relatedSearchKeySelected ? (
|
||||
<RelatedLookupTypeInput
|
||||
|
||||
@@ -215,6 +215,10 @@ function TemplateList({ defaultParams }) {
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Label`,
|
||||
key: 'labels__name__icontains',
|
||||
},
|
||||
]}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
|
||||
@@ -5,10 +5,11 @@ import React, {
|
||||
useRef,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useHistory, Redirect } from 'react-router-dom';
|
||||
import { DateTime } from 'luxon';
|
||||
import { RootAPI, MeAPI } from 'api';
|
||||
import { isAuthenticated } from 'util/auth';
|
||||
import useRequest from 'hooks/useRequest';
|
||||
import { SESSION_TIMEOUT_KEY } from '../constants';
|
||||
|
||||
// The maximum supported timeout for setTimeout(), in milliseconds,
|
||||
@@ -72,8 +73,31 @@ function SessionProvider({ children }) {
|
||||
const [sessionTimeout, setSessionTimeout] = useStorage(SESSION_TIMEOUT_KEY);
|
||||
const [sessionCountdown, setSessionCountdown] = useState(0);
|
||||
const [authRedirectTo, setAuthRedirectTo] = useState('/');
|
||||
const [isUserBeingLoggedOut, setIsUserBeingLoggedOut] = useState(false);
|
||||
|
||||
const {
|
||||
request: fetchLoginRedirectOverride,
|
||||
result: { loginRedirectOverride },
|
||||
isLoading,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const { data } = await RootAPI.read();
|
||||
return {
|
||||
loginRedirectOverride: data?.login_redirect_override,
|
||||
};
|
||||
}, []),
|
||||
{
|
||||
loginRedirectOverride: null,
|
||||
isLoading: true,
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLoginRedirectOverride();
|
||||
}, [fetchLoginRedirectOverride]);
|
||||
|
||||
const logout = useCallback(async () => {
|
||||
setIsUserBeingLoggedOut(true);
|
||||
if (!isSessionExpired.current) {
|
||||
setAuthRedirectTo('/logout');
|
||||
}
|
||||
@@ -82,14 +106,13 @@ function SessionProvider({ children }) {
|
||||
setSessionCountdown(0);
|
||||
clearTimeout(sessionTimeoutId.current);
|
||||
clearInterval(sessionIntervalId.current);
|
||||
return <Redirect to="/login" />;
|
||||
}, [setSessionTimeout, setSessionCountdown]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated(document.cookie)) {
|
||||
history.replace('/login');
|
||||
return () => {};
|
||||
}
|
||||
|
||||
const calcRemaining = () => {
|
||||
if (sessionTimeout) {
|
||||
return Math.max(
|
||||
@@ -140,9 +163,15 @@ function SessionProvider({ children }) {
|
||||
clearInterval(sessionIntervalId.current);
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SessionContext.Provider
|
||||
value={{
|
||||
isUserBeingLoggedOut,
|
||||
loginRedirectOverride,
|
||||
authRedirectTo,
|
||||
handleSessionContinue,
|
||||
isSessionExpired,
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(Limited to first 10)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(Prompt on launch)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
|
||||
@@ -450,8 +450,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "An inventory must be selected"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -515,8 +515,8 @@ msgstr "Applications & Tokens"
|
||||
msgid "Approval"
|
||||
msgstr "Approval"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -593,7 +593,7 @@ msgstr "Are you sure you want to submit the request to cancel this job?"
|
||||
msgid "Arguments"
|
||||
msgstr "Arguments"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "Artifacts"
|
||||
|
||||
@@ -943,7 +943,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "Cancel subscription edit"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "Cancel {0}"
|
||||
@@ -951,7 +951,7 @@ msgstr "Cancel {0}"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "Canceled"
|
||||
@@ -1465,11 +1465,11 @@ msgstr "Create user token"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1478,7 +1478,7 @@ msgstr "Create user token"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1551,13 +1551,13 @@ msgstr "Created by (username)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1758,9 +1758,9 @@ msgstr "Define system-level features and functions"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1772,7 +1772,7 @@ msgstr "Define system-level features and functions"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1783,8 +1783,8 @@ msgstr "Define system-level features and functions"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
@@ -1792,15 +1792,15 @@ msgstr ""
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "Delete All Groups and Hosts"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "Delete Credential"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "Delete Execution Environment"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "Delete Host"
|
||||
@@ -1809,7 +1809,7 @@ msgstr "Delete Host"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "Delete Inventory"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1851,11 +1851,11 @@ msgstr "Delete Team"
|
||||
msgid "Delete User"
|
||||
msgstr "Delete User"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "Delete User Token"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "Delete Workflow Approval"
|
||||
|
||||
@@ -1957,8 +1957,8 @@ msgstr "Denied - {0}. See the Activity Stream for more information."
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "Denied by {0} - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2298,10 +2298,10 @@ msgstr ""
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2547,7 +2547,7 @@ msgstr "Edit workflow"
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "Elapsed"
|
||||
|
||||
@@ -2627,7 +2627,7 @@ msgstr "Enabled"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2806,7 +2806,7 @@ msgstr ""
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
|
||||
@@ -2847,7 +2847,7 @@ msgstr "Enter variables using either JSON or YAML syntax. Use the radio button t
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2897,10 +2897,10 @@ msgstr "Error saving the workflow!"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2951,11 +2951,11 @@ msgstr "Error saving the workflow!"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3193,7 +3193,7 @@ msgstr "Failed jobs"
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "Failed to approve one or more workflow approval."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "Failed to approve workflow approval."
|
||||
|
||||
@@ -3230,7 +3230,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "Failed to cancel one or more jobs."
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "Failed to cancel {0}"
|
||||
@@ -3260,7 +3260,7 @@ msgstr "Failed to copy template."
|
||||
msgid "Failed to delete application."
|
||||
msgstr "Failed to delete application."
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "Failed to delete credential."
|
||||
|
||||
@@ -3268,7 +3268,7 @@ msgstr "Failed to delete credential."
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "Failed to delete group {0}."
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "Failed to delete host."
|
||||
@@ -3407,7 +3407,7 @@ msgstr "Failed to delete team."
|
||||
msgid "Failed to delete user."
|
||||
msgstr "Failed to delete user."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "Failed to delete workflow approval."
|
||||
|
||||
@@ -3424,7 +3424,7 @@ msgstr "Failed to delete {name}."
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "Failed to deny one or more workflow approval."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "Failed to deny workflow approval."
|
||||
|
||||
@@ -3518,7 +3518,7 @@ msgstr "Failed to update capacity adjustment."
|
||||
msgid "Failed to update survey."
|
||||
msgstr "Failed to update survey."
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "Failed to user token."
|
||||
|
||||
@@ -3588,7 +3588,7 @@ msgid "Finish Time"
|
||||
msgstr "Finish Time"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "Finished"
|
||||
|
||||
@@ -4537,14 +4537,14 @@ msgid "Job"
|
||||
msgstr "Job"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "Job Cancel Error"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4794,24 +4794,24 @@ msgstr "Last Login"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr ""
|
||||
|
||||
@@ -6095,7 +6095,7 @@ msgstr "Pending delete"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "Perform a search to define a host filter"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr "Personal Access Token"
|
||||
@@ -6518,6 +6518,10 @@ msgstr "Recipient List"
|
||||
msgid "Recipient list"
|
||||
msgstr "Recipient list"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr "Red Hat Ansible Automation Platform"
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6615,8 +6619,8 @@ msgstr "Related search type typeahead"
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "Relaunch"
|
||||
@@ -7227,13 +7231,13 @@ msgstr "Select a subscription"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8573,7 +8577,7 @@ msgstr "This action will disassociate the following:"
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
|
||||
@@ -8601,7 +8605,7 @@ msgstr ""
|
||||
"future releases of the Tower Software and help\n"
|
||||
"streamline customer experience and success."
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
|
||||
@@ -9274,7 +9278,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -9283,7 +9287,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9973,8 +9977,8 @@ msgid "documentation"
|
||||
msgstr "documentation"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -10179,8 +10183,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?} other {Deleting these inventory sources could impact other resources that rely on them. Are you sure you want to delete anyway}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(Limitado a los primeros 10)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(Preguntar al ejecutar)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "* Este campo se recuperará de un sistema de gestión de claves secretas externo con la credencial especificada."
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "Debe seleccionar un inventario"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr "Aplicaciones y tokens"
|
||||
msgid "Approval"
|
||||
msgstr "Aprobación"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr "¿Está seguro de que desea enviar la solicitud para cancelar este traba
|
||||
msgid "Arguments"
|
||||
msgstr "Argumentos"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "Artefactos"
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "Cancelar modificación de la suscripción"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "Cancelar {0}"
|
||||
@@ -934,7 +934,7 @@ msgstr "Cancelar {0}"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "Cancelado"
|
||||
@@ -1437,11 +1437,11 @@ msgstr "Crear token de usuario"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1450,7 +1450,7 @@ msgstr "Crear token de usuario"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1523,13 +1523,13 @@ msgstr "Creado por (nombre de usuario)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1730,9 +1730,9 @@ msgstr "Defina características y funciones a nivel del sistema"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1744,7 +1744,7 @@ msgstr "Defina características y funciones a nivel del sistema"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1755,8 +1755,8 @@ msgstr "Defina características y funciones a nivel del sistema"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr "ELIMINAR"
|
||||
|
||||
@@ -1764,15 +1764,15 @@ msgstr "ELIMINAR"
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "Eliminar todos los grupos y hosts"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "Eliminar credencial"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "Eliminar entorno de ejecución"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "Borrar un host"
|
||||
@@ -1781,7 +1781,7 @@ msgstr "Borrar un host"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "Eliminar inventario"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1823,11 +1823,11 @@ msgstr "Eliminar el equipo"
|
||||
msgid "Delete User"
|
||||
msgstr "Eliminar usuario"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "Eliminar token de usuario"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "Eliminar la aprobación del flujo de trabajo"
|
||||
|
||||
@@ -1925,8 +1925,8 @@ msgstr "Denegado: {0}. Consulte el flujo de actividad para obtener más informa
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "Denegado por {0} - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2258,10 +2258,10 @@ msgstr "Cada vez que una tarea se ejecute con este proyecto, actualice la revisi
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2507,7 +2507,7 @@ msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "Tiempo transcurrido"
|
||||
|
||||
@@ -2587,7 +2587,7 @@ msgstr "Habilitado"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2736,7 +2736,7 @@ msgstr "Ingrese el número asociado con el \"Servicio de mensajería\" en Twilio
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "Introduzca las variables para configurar la fuente de inventario. Consulte <0>Complementos de inventario</0> en la documentación y la guía de configuración del complemento <1>Tower</1> para obtener una descripción detallada de cómo configurar este complemento."
|
||||
|
||||
@@ -2777,7 +2777,7 @@ msgstr "Ingrese variables con sintaxis JSON o YAML. Use el botón de selección
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2827,10 +2827,10 @@ msgstr "Error al guardar el flujo de trabajo"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2881,11 +2881,11 @@ msgstr "Error al guardar el flujo de trabajo"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3123,7 +3123,7 @@ msgstr "Tareas fallidas"
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "No se pudo aprobar uno o más flujos de trabajo."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "No se pudo aprobar el flujo de trabajo."
|
||||
|
||||
@@ -3160,7 +3160,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "No se pudo cancelar una o varias tareas."
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "No se pudo cancelar {0}"
|
||||
@@ -3190,7 +3190,7 @@ msgstr "No se pudo copiar la plantilla."
|
||||
msgid "Failed to delete application."
|
||||
msgstr "No se pudo eliminar la aplicación."
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "No se pudo eliminar la credencial."
|
||||
|
||||
@@ -3198,7 +3198,7 @@ msgstr "No se pudo eliminar la credencial."
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "No se pudo eliminar el grupo {0}."
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "No se pudo eliminar el host."
|
||||
@@ -3337,7 +3337,7 @@ msgstr "No se pudo eliminar el equipo."
|
||||
msgid "Failed to delete user."
|
||||
msgstr "No se pudo eliminar el usuario."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "No se pudo eliminar la aprobación del flujo de trabajo."
|
||||
|
||||
@@ -3354,7 +3354,7 @@ msgstr "No se pudo eliminar {nombre}."
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "No se pudo denegar una o más aprobaciones del flujo de trabajo."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "No se pudo denegar la aprobación del flujo de trabajo."
|
||||
|
||||
@@ -3448,7 +3448,7 @@ msgstr "No se pudo actualizar el ajuste de capacidad."
|
||||
msgid "Failed to update survey."
|
||||
msgstr "No se pudo actualizar la encuesta."
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "Error en el token de usuario."
|
||||
|
||||
@@ -3518,7 +3518,7 @@ msgid "Finish Time"
|
||||
msgstr "Hora de finalización"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "Finalizado"
|
||||
|
||||
@@ -4437,14 +4437,14 @@ msgid "Job"
|
||||
msgstr "Tarea"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "Error en la cancelación de tarea"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4694,24 +4694,24 @@ msgstr "Último inicio de sesión"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr "Último modificado"
|
||||
|
||||
@@ -5973,7 +5973,7 @@ msgstr "Eliminación pendiente"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "Realice una búsqueda para definir un filtro de host"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr ""
|
||||
@@ -6378,6 +6378,10 @@ msgstr "Lista de destinatarios"
|
||||
msgid "Recipient list"
|
||||
msgstr "Lista de destinatarios"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6473,8 +6477,8 @@ msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "Relanzar"
|
||||
@@ -7081,13 +7085,13 @@ msgstr "Seleccionar una suscripción"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8352,7 +8356,7 @@ msgstr "Esta acción disociará lo siguiente:"
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Este grupo de contenedores está siendo utilizado por otros recursos. ¿Está seguro de que desea eliminarlo?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Esta credencial está siendo utilizada por otros recursos. ¿Está seguro de que desea eliminarla?"
|
||||
|
||||
@@ -8377,7 +8381,7 @@ msgid ""
|
||||
"streamline customer experience and success."
|
||||
msgstr "Estos datos se utilizan para mejorar futuras versiones del software Tower y para ayudar a optimizar el éxito y la experiencia del cliente."
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Este entorno de ejecución está siendo utilizado por otros recursos. ¿Está seguro de que desea eliminarlo?"
|
||||
|
||||
@@ -9034,7 +9038,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -9043,7 +9047,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9725,8 +9729,8 @@ msgid "documentation"
|
||||
msgstr "documentación"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9931,8 +9935,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {Esta fuente de inventario está siendo utilizada por otros recursos que dependen de ella. ¿Estás seguro de que desea eliminarla?} other {Eliminar estas fuentes de inventario podría afectar a otros recursos que dependen de ellas. ¿Está seguro de que desea eliminarlas de todos modos?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {Esta organización está siendo utilizada por otros recursos. ¿Está seguro de que desea eliminarla?} other {Eliminar estas organizaciones podría afectar a otros recursos que dependen de ellas. ¿Está seguro de que desea eliminarlas de todos modos?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {Esta organización está siendo utilizada por otros recursos. ¿Está seguro de que desea eliminarla?} other {Eliminar estas organizaciones podría afectar a otros recursos que dependen de ellas. ¿Está seguro de que desea eliminarlas de todos modos?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(10 premiers seulement)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(Me le demander au lancement)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "* Ce champ sera récupéré dans un système externe de gestion des secrets en utilisant le justificatif d'identité spécifié."
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "Un inventaire doit être sélectionné"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr "Applications & Jetons"
|
||||
msgid "Approval"
|
||||
msgstr "Approbation"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr "Voulez-vous vraiment demander l'annulation de ce job ?"
|
||||
msgid "Arguments"
|
||||
msgstr "Arguments"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "Artefacts"
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "Annuler l'édition de l'abonnement"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "Annuler {0}"
|
||||
@@ -934,7 +934,7 @@ msgstr "Annuler {0}"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "Annulé"
|
||||
@@ -1437,11 +1437,11 @@ msgstr "Créer un jeton d'utilisateur"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1450,7 +1450,7 @@ msgstr "Créer un jeton d'utilisateur"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1523,13 +1523,13 @@ msgstr "Créé par (username)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1730,9 +1730,9 @@ msgstr "Définir les fonctions et fonctionnalités niveau système"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1744,7 +1744,7 @@ msgstr "Définir les fonctions et fonctionnalités niveau système"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1755,8 +1755,8 @@ msgstr "Définir les fonctions et fonctionnalités niveau système"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
@@ -1764,15 +1764,15 @@ msgstr "Supprimer"
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "Supprimer les groupes et les hôtes"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "Supprimer les informations d’identification"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "Supprimer l'environnement d'exécution"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "Supprimer l'hôte"
|
||||
@@ -1781,7 +1781,7 @@ msgstr "Supprimer l'hôte"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "Supprimer l’inventaire"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1823,11 +1823,11 @@ msgstr "Supprimer l’équipe"
|
||||
msgid "Delete User"
|
||||
msgstr "Supprimer l’utilisateur"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "Supprimer un jeton d'utilisateur"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "Supprimer l'approbation du flux de travail"
|
||||
|
||||
@@ -1925,8 +1925,8 @@ msgstr "Refusé - {0}. Voir le flux d'activité pour plus d'informations."
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "Refusé par {0} - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2258,10 +2258,10 @@ msgstr "Chaque fois qu’un job s’exécute avec ce projet, réalisez une mise
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2507,7 +2507,7 @@ msgstr "Modifier le flux de travail"
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "Écoulé"
|
||||
|
||||
@@ -2583,7 +2583,7 @@ msgstr "Activé"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2628,7 +2628,7 @@ msgstr ""
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:148
|
||||
#: screens/Setting/shared/SettingDetail.js:87
|
||||
msgid "Encrypted"
|
||||
msgstr "Crypté"
|
||||
msgstr "Chiffré"
|
||||
|
||||
#: components/Schedule/shared/FrequencyDetailSubform.js:490
|
||||
msgid "End"
|
||||
@@ -2726,7 +2726,7 @@ msgstr "Numéro associé au \"Service de messagerie\" de Twilio sous le format +
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr "Saisissez les variables pour configurer la source d'inventaire. Pour une description détaillée de la configuration de ce plugin, voir <0>Les plugins d'inventaire</0> dans la documentation et le guide de configuration du plugin <1>insights</1>."
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "Saisissez les variables pour configurer la source d'inventaire. Pour une description détaillée de la configuration de ce plugin, voir <0>Plugins d'inventaire</0> dans la documentation et le guide de configuration du plugin <1>Tower</1>."
|
||||
|
||||
@@ -2767,7 +2767,7 @@ msgstr "Entrez les variables avec la syntaxe JSON ou YAML. Utilisez le bouton ra
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2817,10 +2817,10 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2871,11 +2871,11 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3113,7 +3113,7 @@ msgstr "Jobs ayant échoué"
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "N'a pas approuvé un ou plusieurs flux de travail."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "N'a pas approuvé le flux de travail."
|
||||
|
||||
@@ -3150,7 +3150,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "N'a pas réussi à supprimer un ou plusieurs Jobs"
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "Échec de l'annulation {0}"
|
||||
@@ -3180,7 +3180,7 @@ msgstr "Impossible de copier le modèle."
|
||||
msgid "Failed to delete application."
|
||||
msgstr "N'a pas réussi à supprimer l’application"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "N'a pas réussi à supprimer l’identifiant."
|
||||
|
||||
@@ -3188,7 +3188,7 @@ msgstr "N'a pas réussi à supprimer l’identifiant."
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "Échec de la suppression du groupe {0}."
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "N'a pas réussi à supprimer l'hôte."
|
||||
@@ -3327,7 +3327,7 @@ msgstr "N'a pas réussi à supprimer l'équipe."
|
||||
msgid "Failed to delete user."
|
||||
msgstr "Impossible de supprimer l'utilisateur."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "N'a pas réussi à supprimer l'approbation du flux de travail."
|
||||
|
||||
@@ -3344,7 +3344,7 @@ msgstr "Échec de la suppression de {nom}."
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "N'a pas refusé d'approuver un ou plusieurs flux de travail."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "N'a pas refusé l'approbation du flux de travail."
|
||||
|
||||
@@ -3438,7 +3438,7 @@ msgstr "Échec de la mise à jour de l'ajustement des capacités."
|
||||
msgid "Failed to update survey."
|
||||
msgstr "N'a pas réussi à mettre à jour l'enquête."
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "Échec du jeton d'utilisateur."
|
||||
|
||||
@@ -3508,7 +3508,7 @@ msgid "Finish Time"
|
||||
msgstr "Heure de Fin"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "Terminé"
|
||||
|
||||
@@ -4416,14 +4416,14 @@ msgid "Job"
|
||||
msgstr "Job"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "Erreur d'annulation d'un Job"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4673,24 +4673,24 @@ msgstr "Dernière connexion"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr "Dernière modification"
|
||||
|
||||
@@ -5685,7 +5685,7 @@ msgstr "Désactivé"
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:233
|
||||
#: screens/Template/shared/JobTemplateForm.js:504
|
||||
msgid "On"
|
||||
msgstr "Le"
|
||||
msgstr "Activé"
|
||||
|
||||
#: components/Workflow/WorkflowLegend.js:126
|
||||
#: components/Workflow/WorkflowLinkHelp.js:30
|
||||
@@ -5950,7 +5950,7 @@ msgstr "En attente de suppression"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "Effectuez une recherche ci-dessus pour définir un filtre d'hôte"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr "Jeton d'accès personnel"
|
||||
@@ -6352,6 +6352,10 @@ msgstr "Liste de destinataires"
|
||||
msgid "Recipient list"
|
||||
msgstr "Liste de destinataires"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6447,8 +6451,8 @@ msgstr "Recherche connexe : type typeahead"
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "Relancer"
|
||||
@@ -7055,13 +7059,13 @@ msgstr "Sélectionnez un abonnement"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8286,7 +8290,7 @@ msgstr "Cette action dissociera les éléments suivants :"
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Ce groupe de conteneurs est actuellement utilisé par d'autres ressources. Êtes-vous sûr de vouloir le supprimer ?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Cette accréditation est actuellement utilisée par d'autres ressources. Êtes-vous sûr de vouloir la supprimer ?"
|
||||
|
||||
@@ -8314,7 +8318,7 @@ msgstr ""
|
||||
"les futures versions du logiciel Tower et contribuer à\n"
|
||||
"à rationaliser l'expérience des clients."
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Cet environnement d'exécution est actuellement utilisé par d'autres ressources. Êtes-vous sûr de vouloir le supprimer ?"
|
||||
|
||||
@@ -8967,7 +8971,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -8976,7 +8980,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9652,8 +9656,8 @@ msgid "documentation"
|
||||
msgstr "documentation"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9667,7 +9671,7 @@ msgstr "Modifier"
|
||||
|
||||
#: screens/Template/Survey/SurveyListItem.js:65
|
||||
msgid "encrypted"
|
||||
msgstr "crypté"
|
||||
msgstr "chiffré"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:232
|
||||
msgid "for more info."
|
||||
@@ -9846,8 +9850,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {Cette source d'inventaire est actuellement utilisée par d'autres ressources qui en dépendent. Êtes-vous sûr de vouloir la supprimer ? } other {La suppression de ces sources d'inventaire pourrait avoir un impact sur d'autres ressources qui en dépendent. Êtes-vous sûr de vouloir les supprimer quand même}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {Cette organisation est actuellement utilisée par d'autres ressources. Êtes-vous sûr de vouloir la supprimer ? } other {La suppression de ces organisations pourrait avoir un impact sur les autres ressources qui en dépendent. Êtes-vous sûr de vouloir les supprimer quand même ? }}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {Cette organisation est actuellement utilisée par d'autres ressources. Êtes-vous sûr de vouloir la supprimer ? } other {La suppression de ces organisations pourrait avoir un impact sur les autres ressources qui en dépendent. Êtes-vous sûr de vouloir les supprimer quand même ? }}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(最初の 10 件に制限)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(起動プロンプト)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "*このフィールドは、指定された認証情報を使用して外部のシークレット管理システムから取得されます。"
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "インベントリーを選択する必要があります"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr "アプリケーションおよびトークン"
|
||||
msgid "Approval"
|
||||
msgstr "承認"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr "このジョブを取り消す要求を送信してよろしいですか
|
||||
msgid "Arguments"
|
||||
msgstr "引数"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "アーティファクト"
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "サブスクリプションの編集の取り消し"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "{0} の取り消し"
|
||||
@@ -934,7 +934,7 @@ msgstr "{0} の取り消し"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "取り消し済み"
|
||||
@@ -1435,11 +1435,11 @@ msgstr "ユーザートークンの作成"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1448,7 +1448,7 @@ msgstr "ユーザートークンの作成"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1521,13 +1521,13 @@ msgstr "作成者 (ユーザー名)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1728,9 +1728,9 @@ msgstr "システムレベルの機能および関数の定義"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1742,7 +1742,7 @@ msgstr "システムレベルの機能および関数の定義"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1753,8 +1753,8 @@ msgstr "システムレベルの機能および関数の定義"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
@@ -1762,15 +1762,15 @@ msgstr "削除"
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "すべてのグループおよびホストの削除"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "認証情報の削除"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "実行環境の削除"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "ホストの削除"
|
||||
@@ -1779,7 +1779,7 @@ msgstr "ホストの削除"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "インベントリーの削除"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1821,11 +1821,11 @@ msgstr "チームの削除"
|
||||
msgid "Delete User"
|
||||
msgstr "ユーザーの削除"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "ユーザートークンの削除"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "ワークフロー承認の削除"
|
||||
|
||||
@@ -1923,8 +1923,8 @@ msgstr "拒否されました - {0}。詳細については、アクティビテ
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "{0} に拒否されました - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2256,10 +2256,10 @@ msgstr "このプロジェクトでジョブを実行する際は常に、ジョ
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2505,7 +2505,7 @@ msgstr "ワークフローの編集"
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "経過時間"
|
||||
|
||||
@@ -2581,7 +2581,7 @@ msgstr "有効化"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2716,7 +2716,7 @@ msgstr "Twilio の \"メッセージングサービス\" に関連付けられ
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr "変数を入力して、インベントリーソースを設定します。このプラグインの設定方法の詳細については、ドキュメントの <0>インベントリープラグイン</0> および <1>Insights</1> プラグイン設定ガイドを参照してください。"
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "変数を入力して、インベントリーソースを設定します。このプラグインの設定方法の詳細については、ドキュメントの <0>インベントリープラグイン</0> および <1>Tower</1> プラグイン設定ガイドを参照してください。"
|
||||
|
||||
@@ -2757,7 +2757,7 @@ msgstr "JSON または YAML 構文のいずれかを使用して変数を入力
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2807,10 +2807,10 @@ msgstr "ワークフローの保存中にエラー!"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2861,11 +2861,11 @@ msgstr "ワークフローの保存中にエラー!"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3103,7 +3103,7 @@ msgstr "失敗したジョブ"
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "1 つ以上のワークフロー承認を承認できませんでした。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "ワークフローの承認を承認できませんでした。"
|
||||
|
||||
@@ -3140,7 +3140,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "1 つ以上のジョブを取り消すことができませんでした。"
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "{0} を取り消すことができませんでした。"
|
||||
@@ -3170,7 +3170,7 @@ msgstr "テンプレートをコピーできませんでした。"
|
||||
msgid "Failed to delete application."
|
||||
msgstr "アプリケーションを削除できませんでした。"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "認証情報を削除できませんでした。"
|
||||
|
||||
@@ -3178,7 +3178,7 @@ msgstr "認証情報を削除できませんでした。"
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "グループ {0} を削除できませんでした。"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "ホストを削除できませんでした。"
|
||||
@@ -3317,7 +3317,7 @@ msgstr "チームを削除できませんでした。"
|
||||
msgid "Failed to delete user."
|
||||
msgstr "ユーザーを削除できませんでした。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "ワークフロー承認を削除できませんでした。"
|
||||
|
||||
@@ -3334,7 +3334,7 @@ msgstr "{name} を削除できませんでした。"
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "1 つ以上のワークフロー承認を拒否できませんでした。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "ワークフローの承認を拒否できませんでした。"
|
||||
|
||||
@@ -3428,7 +3428,7 @@ msgstr "容量調整の更新に失敗しました。"
|
||||
msgid "Failed to update survey."
|
||||
msgstr "調査の更新に失敗しました。"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "ユーザートークンに失敗しました。"
|
||||
|
||||
@@ -3498,7 +3498,7 @@ msgid "Finish Time"
|
||||
msgstr "終了時間"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "終了日時"
|
||||
|
||||
@@ -4406,14 +4406,14 @@ msgid "Job"
|
||||
msgstr "Job"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "ジョブキャンセルエラー"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4663,24 +4663,24 @@ msgstr "前回のログイン"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr "最終更新日"
|
||||
|
||||
@@ -5940,7 +5940,7 @@ msgstr "保留中の削除"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "検索を実行して、ホストフィルターを定義します。"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr "パーソナルアクセストークン"
|
||||
@@ -6338,6 +6338,10 @@ msgstr "受信者リスト"
|
||||
msgid "Recipient list"
|
||||
msgstr "受信者リスト"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6433,8 +6437,8 @@ msgstr "関連する検索タイプの先行入力"
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "再起動"
|
||||
@@ -7041,13 +7045,13 @@ msgstr "サブスクリプションの選択"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8267,7 +8271,7 @@ msgstr "このアクションにより、以下の関連付けが解除されま
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "このコンテナーグループは、現在他のリソースで使用されています。削除してもよろしいですか?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "この認証情報は、現在他のリソースで使用されています。削除してもよろしいですか?"
|
||||
|
||||
@@ -8289,7 +8293,7 @@ msgid ""
|
||||
"streamline customer experience and success."
|
||||
msgstr "このデータは、Tower ソフトウェアの今後のリリースを強化し、顧客へのサービスを効率化し、成功に導くサポートをします。"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "この実行環境は、現在他のリソースで使用されています。削除してもよろしいですか?"
|
||||
|
||||
@@ -8940,7 +8944,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -8949,7 +8953,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9625,8 +9629,8 @@ msgid "documentation"
|
||||
msgstr "ドキュメント"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9819,8 +9823,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {このインベントリーソースは、現在、そのインベントリーソースに依存している他のリソースで使用されています。削除してもよろしいですか?} other {これらのインベントリーソースを削除すると、そのインベントリーソースに依存している他のリソースに影響を与える可能性があります。削除してもよろしいですか}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {この組織は、現在他のリソースで使用されています。削除してもよろしいですか?} other {これらの組織を削除すると、その組織に依存している他のリソースに影響を与える可能性があります。削除してもよろしいですか?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {この組織は、現在他のリソースで使用されています。削除してもよろしいですか?} other {これらの組織を削除すると、その組織に依存している他のリソースに影響を与える可能性があります。削除してもよろしいですか?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(Beperkt tot de eerste 10)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(Melding bij opstarten)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "* Dit veld wordt met behulp van de opgegeven referentie opgehaald uit een extern geheimbeheersysteem."
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "Er moet een inventaris worden gekozen"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr "Toepassingen en tokens"
|
||||
msgid "Approval"
|
||||
msgstr "Goedkeuring"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr "Weet u zeker dat u het verzoek om deze taak te annuleren in wilt dienen?
|
||||
msgid "Arguments"
|
||||
msgstr "Argumenten"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "Artefacten"
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "Abonnement bewerken annuleren"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "{0} annuleren"
|
||||
@@ -934,7 +934,7 @@ msgstr "{0} annuleren"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "Geannuleerd"
|
||||
@@ -1435,11 +1435,11 @@ msgstr "Gebruikerstoken maken"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1448,7 +1448,7 @@ msgstr "Gebruikerstoken maken"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1521,13 +1521,13 @@ msgstr "Gemaakt door (gebruikersnaam)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1728,9 +1728,9 @@ msgstr "Kenmerken en functies op systeemniveau definiëren"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1742,7 +1742,7 @@ msgstr "Kenmerken en functies op systeemniveau definiëren"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1753,8 +1753,8 @@ msgstr "Kenmerken en functies op systeemniveau definiëren"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
@@ -1762,15 +1762,15 @@ msgstr "Verwijderen"
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "Alle groepen en hosts verwijderen"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "Toegangsgegevens verwijderen"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "Uitvoeringsomgeving verwijderen"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "Host verwijderen"
|
||||
@@ -1779,7 +1779,7 @@ msgstr "Host verwijderen"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "Inventaris verwijderen"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1821,11 +1821,11 @@ msgstr "Team verwijderen"
|
||||
msgid "Delete User"
|
||||
msgstr "Gebruiker verwijderen"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "Gebruikerstoken verwijderen"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "Workflowgoedkeuring verwijderen"
|
||||
|
||||
@@ -1923,8 +1923,8 @@ msgstr "Geweigerd - {0}. Zie het activiteitenlogboek voor meer informatie."
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "Geweigerd door {0} - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2256,10 +2256,10 @@ msgstr "Voer iedere keer dat een taak uitgevoerd wordt met dit project een updat
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2505,7 +2505,7 @@ msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "Verlopen"
|
||||
|
||||
@@ -2585,7 +2585,7 @@ msgstr "Ingeschakeld"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2734,7 +2734,7 @@ msgstr "Voer het telefoonnummer in dat hoort bij de 'Berichtenservice' in Twilio
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "Voer variabelen in om de inventarisbron te configureren. Voor een gedetailleerde beschrijving om deze plug-in te configureren, zie <0>Inventarisplug-ins</0> in de documentatie en de plug-inconfiguratiegids voor <1>Tower</1>."
|
||||
|
||||
@@ -2775,7 +2775,7 @@ msgstr "Voer variabelen in met JSON- of YAML-syntaxis. Gebruik de radioknop om t
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2825,10 +2825,10 @@ msgstr "Fout bij het opslaan van de workflow!"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2879,11 +2879,11 @@ msgstr "Fout bij het opslaan van de workflow!"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3121,7 +3121,7 @@ msgstr "Mislukte taken."
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "Eén of meer workflowgoedkeuringen goed te zijn niet goedgekeurd."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "Workflowgoedkeuring is mislukt."
|
||||
|
||||
@@ -3158,7 +3158,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "Kan een of meer taken niet annuleren."
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "Kan {0} niet annuleren"
|
||||
@@ -3188,7 +3188,7 @@ msgstr "Kan sjabloon niet kopiëren."
|
||||
msgid "Failed to delete application."
|
||||
msgstr "Kan toepassing niet verwijderen."
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "Kan toegangsgegevens niet verwijderen"
|
||||
|
||||
@@ -3196,7 +3196,7 @@ msgstr "Kan toegangsgegevens niet verwijderen"
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "Kan groep {0} niet verwijderen."
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "Kan host niet verwijderen."
|
||||
@@ -3335,7 +3335,7 @@ msgstr "Kan team niet verwijderen."
|
||||
msgid "Failed to delete user."
|
||||
msgstr "Kan gebruiker niet verwijderen."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "Kan workflowgoedkeuring niet verwijderen."
|
||||
|
||||
@@ -3352,7 +3352,7 @@ msgstr "Kan {naam} niet verwijderen."
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "Een of meer workflowgoedkeuringen kunnen niet worden geweigerd."
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "Kan workflowgoedkeuring niet weigeren."
|
||||
|
||||
@@ -3446,7 +3446,7 @@ msgstr "Kan de capaciteitsaanpassing niet bijwerken."
|
||||
msgid "Failed to update survey."
|
||||
msgstr "Kan de vragenlijst niet bijwerken."
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "Kan gebruikerstoken niet bijwerken."
|
||||
|
||||
@@ -3516,7 +3516,7 @@ msgid "Finish Time"
|
||||
msgstr "Voltooiingstijd"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "Voltooid"
|
||||
|
||||
@@ -4434,14 +4434,14 @@ msgid "Job"
|
||||
msgstr "Taak"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "Fout bij annuleren taak"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4691,24 +4691,24 @@ msgstr "Laatste login"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr "Laatst aangepast"
|
||||
|
||||
@@ -5968,7 +5968,7 @@ msgstr "In afwachting om verwijderd te worden"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "Voer een zoekopdracht uit om een hostfilter te definiëren"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr ""
|
||||
@@ -6370,6 +6370,10 @@ msgstr "Lijst met ontvangers"
|
||||
msgid "Recipient list"
|
||||
msgstr "Lijst met ontvangers"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6465,8 +6469,8 @@ msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "Opnieuw starten"
|
||||
@@ -7073,13 +7077,13 @@ msgstr "Abonnement selecteren"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8340,7 +8344,7 @@ msgstr "Deze actie ontkoppelt het volgende:"
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Deze containergroep wordt momenteel door andere bronnen gebruikt. Weet u zeker dat u hem wilt verwijderen?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Deze toegangsgegevens worden momenteel door andere bronnen gebruikt. Weet u zeker dat u ze wilt verwijderen?"
|
||||
|
||||
@@ -8365,7 +8369,7 @@ msgid ""
|
||||
"streamline customer experience and success."
|
||||
msgstr "Deze gegevens worden gebruikt om toekomstige versies van de Tower-software en de ervaring en uitkomst voor klanten te verbeteren."
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "Deze uitvoeringsomgeving wordt momenteel gebruikt door andere bronnen. Weet u zeker dat u deze wilt verwijderen?"
|
||||
|
||||
@@ -9020,7 +9024,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -9029,7 +9033,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9713,8 +9717,8 @@ msgid "documentation"
|
||||
msgstr "documentatie"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9919,8 +9923,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {Deze inventarisbron wordt momenteel gebruikt door andere bronnen die erop vertrouwen. Weet u zeker dat u deze wilt verwijderen?} other {Het verwijderen van deze inventarisbronnen kan impact hebben op andere bronnen die er op vertrouwen. Weet u zeker dat u ze toch wilt verwijderen?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {Deze organisatie wordt momenteel door andere bronnen gebruikt. Weet je zeker dat u deze wilt verwijderen?} other {Het verwijderen van deze organisaties kan gevolgen hebben voor andere bronnen die ervan afhankelijk zijn. Weet u zeker dat u ze toch wilt verwijderen?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {Deze organisatie wordt momenteel door andere bronnen gebruikt. Weet je zeker dat u deze wilt verwijderen?} other {Het verwijderen van deze organisaties kan gevolgen hebben voor andere bronnen die ervan afhankelijk zijn. Weet u zeker dat u ze toch wilt verwijderen?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr "(限制为前 10)"
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr "(启动时提示)"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr "* 此字段将使用指定的凭证从外部 secret 管理系统检索。"
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr "必须选择一个清单"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr "Ansible Tower"
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr "Ansible Tower"
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr "应用程序和令牌"
|
||||
msgid "Approval"
|
||||
msgstr "批准"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr "您确定要提交取消此作业的请求吗?"
|
||||
msgid "Arguments"
|
||||
msgstr "参数"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr "工件"
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr "取消订阅编辑"
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr "取消 {0}"
|
||||
@@ -934,7 +934,7 @@ msgstr "取消 {0}"
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr "已取消"
|
||||
@@ -1435,11 +1435,11 @@ msgstr "创建用户令牌"
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1448,7 +1448,7 @@ msgstr "创建用户令牌"
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1521,13 +1521,13 @@ msgstr "创建者(用户名)"
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1728,9 +1728,9 @@ msgstr "定义系统级的特性和功能"
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1742,7 +1742,7 @@ msgstr "定义系统级的特性和功能"
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1753,8 +1753,8 @@ msgstr "定义系统级的特性和功能"
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
||||
@@ -1762,15 +1762,15 @@ msgstr "删除"
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr "删除所有组和主机"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr "删除凭证"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr "删除执行环境"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr "删除主机"
|
||||
@@ -1779,7 +1779,7 @@ msgstr "删除主机"
|
||||
msgid "Delete Inventory"
|
||||
msgstr "删除清单"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1821,11 +1821,11 @@ msgstr "删除团队"
|
||||
msgid "Delete User"
|
||||
msgstr "删除用户"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr "删除用户令牌"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr "删除工作流批准"
|
||||
|
||||
@@ -1923,8 +1923,8 @@ msgstr "拒绝 - {0}。详情请查看活动流。"
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr "拒绝于 {0} - {1}"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2256,10 +2256,10 @@ msgstr "每次使用此项目运行作业时,请在启动该作业前更新项
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2505,7 +2505,7 @@ msgstr "编辑工作流"
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr "已经过"
|
||||
|
||||
@@ -2581,7 +2581,7 @@ msgstr "启用"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2716,7 +2716,7 @@ msgstr "在 Twilio 中输入与“信息服务”关联的号码,格式为 +18
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr "输入变量来配置清单源。有关如何配置此插件的详细描述,请参阅文档中的<0>清单插件</0>部分,以及 <1>Insights</1> 插件配置指南 。"
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr "输入变量来配置清单源。有关如何配置此插件的详细描述,请参阅文档中的<0>清单插件</0>部分,以及 <1>Tower</1> 插件配置指南 。"
|
||||
|
||||
@@ -2757,7 +2757,7 @@ msgstr "使用 JSON 或 YAML 语法输入变量。使用单选按钮在两者之
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2807,10 +2807,10 @@ msgstr "保存工作流时出错!"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2861,11 +2861,11 @@ msgstr "保存工作流时出错!"
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3103,7 +3103,7 @@ msgstr "失败的作业"
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr "批准一个或多个工作流批准失败。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr "批准工作流批准失败。"
|
||||
|
||||
@@ -3140,7 +3140,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr "取消一个或多个作业失败。"
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr "取消 {0} 失败"
|
||||
@@ -3170,7 +3170,7 @@ msgstr "复制模板失败。"
|
||||
msgid "Failed to delete application."
|
||||
msgstr "删除应用程序失败。"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr "删除凭证失败。"
|
||||
|
||||
@@ -3178,7 +3178,7 @@ msgstr "删除凭证失败。"
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr "删除组 {0} 失败。"
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr "删除主机失败。"
|
||||
@@ -3317,7 +3317,7 @@ msgstr "删除团队失败。"
|
||||
msgid "Failed to delete user."
|
||||
msgstr "删除用户失败。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr "删除工作流批准失败。"
|
||||
|
||||
@@ -3334,7 +3334,7 @@ msgstr "删除 {name} 失败。"
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr "拒绝一个或多个工作流批准失败。"
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr "拒绝工作流批准失败。"
|
||||
|
||||
@@ -3428,7 +3428,7 @@ msgstr "更新容量调整失败。"
|
||||
msgid "Failed to update survey."
|
||||
msgstr "更新问卷调查失败。"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr "用户令牌失败。"
|
||||
|
||||
@@ -3498,7 +3498,7 @@ msgid "Finish Time"
|
||||
msgstr "完成时间"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr "完成"
|
||||
|
||||
@@ -4406,14 +4406,14 @@ msgid "Job"
|
||||
msgstr "作业"
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr "作业取消错误"
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4663,24 +4663,24 @@ msgstr "最近登陆"
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr "最后修改"
|
||||
|
||||
@@ -5942,7 +5942,7 @@ msgstr "等待删除"
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr "执行搜索以定义主机过滤器"
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr "个人访问令牌"
|
||||
@@ -6342,6 +6342,10 @@ msgstr "接收者列表"
|
||||
msgid "Recipient list"
|
||||
msgstr "接收者列表"
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6437,8 +6441,8 @@ msgstr "相关的搜索类型 typeahead"
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr "重新启动"
|
||||
@@ -7045,13 +7049,13 @@ msgstr "导入一个订阅"
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8267,7 +8271,7 @@ msgstr "此操作将解除以下关联:"
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr "其他资源目前正在此容器组中。确定要删除它吗?"
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "其他资源目前正在使用此凭证。确定要删除它吗?"
|
||||
|
||||
@@ -8289,7 +8293,7 @@ msgid ""
|
||||
"streamline customer experience and success."
|
||||
msgstr "这些数据用于增强未来的 Tower 软件发行版本,并帮助简化客户体验和成功。"
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr "其他资源目前正在使用此执行环境。确定要删除它吗?"
|
||||
|
||||
@@ -8940,7 +8944,7 @@ msgstr "VMware vCenter"
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -8949,7 +8953,7 @@ msgstr "VMware vCenter"
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9625,8 +9629,8 @@ msgid "documentation"
|
||||
msgstr "文档"
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9819,8 +9823,12 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr "{0, plural, one {这个清单源正被依赖它的其他资源使用。您确定要删除它吗?} other {删除这些清单源可能会影响到其他依赖它的资源。您确定要删除吗?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr "{0, plural, one {这个机构正被其他资源使用。您确定要删除它吗?} other {删除这些机构可能会影响到其他依赖它的资源。您确定要删除吗?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr "{0, plural, one {这个机构正被其他资源使用。您确定要删除它吗?} other {删除这些机构可能会影响到其他依赖它的资源。您确定要删除吗?}}"
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
msgid "{0, plural, one {This project is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these projects could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
|
||||
@@ -23,7 +23,7 @@ msgstr ""
|
||||
msgid "(Prompt on launch)"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:271
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:269
|
||||
msgid "* This field will be retrieved from an external secret management system using the specified credential."
|
||||
msgstr ""
|
||||
|
||||
@@ -441,8 +441,8 @@ msgid "An inventory must be selected"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Ansible Tower"
|
||||
msgstr ""
|
||||
#~ msgid "Ansible Tower"
|
||||
#~ msgstr ""
|
||||
|
||||
#: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:96
|
||||
msgid "Ansible Tower Documentation."
|
||||
@@ -506,8 +506,8 @@ msgstr ""
|
||||
msgid "Approval"
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:176
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:53
|
||||
@@ -584,7 +584,7 @@ msgstr ""
|
||||
msgid "Arguments"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:435
|
||||
#: screens/Job/JobDetail/JobDetail.js:430
|
||||
msgid "Artifacts"
|
||||
msgstr ""
|
||||
|
||||
@@ -926,7 +926,7 @@ msgid "Cancel subscription edit"
|
||||
msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:106
|
||||
#: screens/Job/JobDetail/JobDetail.js:475
|
||||
#: screens/Job/JobDetail/JobDetail.js:470
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:135
|
||||
msgid "Cancel {0}"
|
||||
msgstr ""
|
||||
@@ -934,7 +934,7 @@ msgstr ""
|
||||
#: components/JobList/JobList.js:227
|
||||
#: components/StatusLabel/StatusLabel.js:65
|
||||
#: components/Workflow/WorkflowNodeHelp.js:111
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:166
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:163
|
||||
#: screens/WorkflowApproval/shared/WorkflowApprovalStatus.js:20
|
||||
msgid "Canceled"
|
||||
msgstr ""
|
||||
@@ -1435,11 +1435,11 @@ msgstr ""
|
||||
#: components/PromptDetail/PromptDetail.js:138
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:277
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:100
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:243
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:242
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:86
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:99
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:137
|
||||
#: screens/Host/HostDetail/HostDetail.js:85
|
||||
#: screens/Host/HostDetail/HostDetail.js:83
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:66
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:103
|
||||
@@ -1448,7 +1448,7 @@ msgstr ""
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:260
|
||||
#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:140
|
||||
#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47
|
||||
#: screens/Job/JobDetail/JobDetail.js:408
|
||||
#: screens/Job/JobDetail/JobDetail.js:407
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:339
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:231
|
||||
@@ -1521,13 +1521,13 @@ msgstr ""
|
||||
#: screens/InstanceGroup/shared/ContainerGroupForm.js:53
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:79
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:42
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:41
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:41
|
||||
#: util/getRelatedResourceDeleteDetails.js:166
|
||||
@@ -1728,9 +1728,9 @@ msgstr ""
|
||||
#: components/ResourceAccessList/DeleteRoleConfirmationModal.js:28
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:123
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:294
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:120
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:131
|
||||
@@ -1742,7 +1742,7 @@ msgstr ""
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:72
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:76
|
||||
#: screens/Inventory/shared/InventoryGroupsDeleteModal.js:99
|
||||
#: screens/Job/JobDetail/JobDetail.js:487
|
||||
#: screens/Job/JobDetail/JobDetail.js:482
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:376
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:279
|
||||
@@ -1753,8 +1753,8 @@ msgstr ""
|
||||
#: screens/Template/Survey/SurveyToolbar.js:92
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247
|
||||
#: screens/User/UserDetail/UserDetail.js:107
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:76
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:74
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
@@ -1762,15 +1762,15 @@ msgstr ""
|
||||
msgid "Delete All Groups and Hosts"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:288
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:286
|
||||
msgid "Delete Credential"
|
||||
msgstr ""
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:125
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:123
|
||||
msgid "Delete Execution Environment"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:116
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109
|
||||
msgid "Delete Host"
|
||||
msgstr ""
|
||||
@@ -1779,7 +1779,7 @@ msgstr ""
|
||||
msgid "Delete Inventory"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:483
|
||||
#: screens/Job/JobDetail/JobDetail.js:478
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:193
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:197
|
||||
msgid "Delete Job"
|
||||
@@ -1821,11 +1821,11 @@ msgstr ""
|
||||
msgid "Delete User"
|
||||
msgstr ""
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:72
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:70
|
||||
msgid "Delete User Token"
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199
|
||||
msgid "Delete Workflow Approval"
|
||||
msgstr ""
|
||||
|
||||
@@ -1923,8 +1923,8 @@ msgstr ""
|
||||
msgid "Denied by {0} - {1}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:185
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:190
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:195
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:45
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:53
|
||||
@@ -2256,10 +2256,10 @@ msgstr ""
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:396
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:110
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:112
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:281
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:279
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:119
|
||||
#: screens/Host/HostDetail/HostDetail.js:110
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117
|
||||
#: screens/Host/HostDetail/HostDetail.js:104
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:98
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:110
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:120
|
||||
@@ -2505,7 +2505,7 @@ msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.js:170
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:123
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:171
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:167
|
||||
msgid "Elapsed"
|
||||
msgstr ""
|
||||
|
||||
@@ -2585,7 +2585,7 @@ msgstr ""
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:189
|
||||
#: components/PromptDetail/PromptProjectDetail.js:112
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:97
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:256
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:254
|
||||
#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:250
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:241
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280
|
||||
@@ -2734,7 +2734,7 @@ msgstr ""
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Insights</1> plugin configuration guide."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:60
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:60
|
||||
msgid "Enter variables to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins</0> in the documentation and the <1>Tower</1> plugin configuration guide."
|
||||
msgstr ""
|
||||
|
||||
@@ -2775,7 +2775,7 @@ msgstr ""
|
||||
#: components/Workflow/WorkflowNodeHelp.js:108
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:129
|
||||
#: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:141
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:139
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:215
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:121
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:133
|
||||
@@ -2825,10 +2825,10 @@ msgstr ""
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:131
|
||||
#: screens/Application/ApplicationTokens/ApplicationTokenList.js:155
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:185
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:302
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:300
|
||||
#: screens/Credential/CredentialList/CredentialList.js:194
|
||||
#: screens/Host/HostDetail/HostDetail.js:56
|
||||
#: screens/Host/HostDetail/HostDetail.js:125
|
||||
#: screens/Host/HostDetail/HostDetail.js:119
|
||||
#: screens/Host/HostGroups/HostGroupsList.js:244
|
||||
#: screens/Host/HostList/HostList.js:222
|
||||
#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:294
|
||||
@@ -2879,11 +2879,11 @@ msgstr ""
|
||||
#: screens/User/UserRoles/UserRolesList.js:243
|
||||
#: screens/User/UserRoles/UserRolesList.js:254
|
||||
#: screens/User/UserTeams/UserTeamList.js:259
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:83
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:81
|
||||
#: screens/User/UserTokenList/UserTokenList.js:209
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:211
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:233
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:246
|
||||
#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:257
|
||||
msgid "Error!"
|
||||
@@ -3121,7 +3121,7 @@ msgstr ""
|
||||
msgid "Failed to approve one or more workflow approval."
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:230
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:225
|
||||
msgid "Failed to approve workflow approval."
|
||||
msgstr ""
|
||||
|
||||
@@ -3158,7 +3158,7 @@ msgid "Failed to cancel one or more jobs."
|
||||
msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:107
|
||||
#: screens/Job/JobDetail/JobDetail.js:476
|
||||
#: screens/Job/JobDetail/JobDetail.js:471
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:136
|
||||
msgid "Failed to cancel {0}"
|
||||
msgstr ""
|
||||
@@ -3188,7 +3188,7 @@ msgstr ""
|
||||
msgid "Failed to delete application."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:305
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:303
|
||||
msgid "Failed to delete credential."
|
||||
msgstr ""
|
||||
|
||||
@@ -3196,7 +3196,7 @@ msgstr ""
|
||||
msgid "Failed to delete group {0}."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Host/HostDetail/HostDetail.js:128
|
||||
#: screens/Host/HostDetail/HostDetail.js:122
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121
|
||||
msgid "Failed to delete host."
|
||||
msgstr ""
|
||||
@@ -3335,7 +3335,7 @@ msgstr ""
|
||||
msgid "Failed to delete user."
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:219
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:214
|
||||
msgid "Failed to delete workflow approval."
|
||||
msgstr ""
|
||||
|
||||
@@ -3352,7 +3352,7 @@ msgstr ""
|
||||
msgid "Failed to deny one or more workflow approval."
|
||||
msgstr ""
|
||||
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:241
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:236
|
||||
msgid "Failed to deny workflow approval."
|
||||
msgstr ""
|
||||
|
||||
@@ -3446,7 +3446,7 @@ msgstr ""
|
||||
msgid "Failed to update survey."
|
||||
msgstr ""
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:86
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:84
|
||||
msgid "Failed to user token."
|
||||
msgstr ""
|
||||
|
||||
@@ -3516,7 +3516,7 @@ msgid "Finish Time"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:139
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:161
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:159
|
||||
msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
@@ -4428,14 +4428,14 @@ msgid "Job"
|
||||
msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:105
|
||||
#: screens/Job/JobDetail/JobDetail.js:474
|
||||
#: screens/Job/JobDetail/JobDetail.js:469
|
||||
#: screens/Job/JobOutput/JobOutput.js:557
|
||||
#: screens/Job/JobOutput/JobOutput.js:558
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:134
|
||||
msgid "Job Cancel Error"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Job/JobDetail/JobDetail.js:496
|
||||
#: screens/Job/JobDetail/JobDetail.js:491
|
||||
#: screens/Job/JobOutput/JobOutput.js:546
|
||||
#: screens/Job/JobOutput/JobOutput.js:547
|
||||
msgid "Job Delete Error"
|
||||
@@ -4685,24 +4685,24 @@ msgstr ""
|
||||
#: screens/Application/ApplicationDetails/ApplicationDetails.js:101
|
||||
#: screens/Application/ApplicationsList/ApplicationListItem.js:42
|
||||
#: screens/Application/ApplicationsList/ApplicationsList.js:159
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:250
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:248
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:105
|
||||
#: screens/Host/HostDetail/HostDetail.js:91
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:104
|
||||
#: screens/Host/HostDetail/HostDetail.js:86
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:95
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:108
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:44
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85
|
||||
#: screens/Job/JobDetail/JobDetail.js:414
|
||||
#: screens/Job/JobDetail/JobDetail.js:411
|
||||
#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:344
|
||||
#: screens/Organization/OrganizationDetail/OrganizationDetail.js:110
|
||||
#: screens/Project/ProjectDetail/ProjectDetail.js:236
|
||||
#: screens/Team/TeamDetail/TeamDetail.js:48
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:275
|
||||
#: screens/User/UserDetail/UserDetail.js:84
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:63
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:156
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:62
|
||||
#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:155
|
||||
msgid "Last Modified"
|
||||
msgstr ""
|
||||
|
||||
@@ -5962,7 +5962,7 @@ msgstr ""
|
||||
msgid "Perform a search to define a host filter"
|
||||
msgstr ""
|
||||
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:71
|
||||
#: screens/User/UserTokenDetail/UserTokenDetail.js:69
|
||||
#: screens/User/UserTokenList/UserTokenList.js:105
|
||||
msgid "Personal Access Token"
|
||||
msgstr ""
|
||||
@@ -6360,6 +6360,10 @@ msgstr ""
|
||||
msgid "Recipient list"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:105
|
||||
msgid "Red Hat Ansible Automation Platform"
|
||||
msgstr ""
|
||||
|
||||
#: components/Lookup/ProjectLookup.js:138
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92
|
||||
#: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161
|
||||
@@ -6455,8 +6459,8 @@ msgstr ""
|
||||
|
||||
#: components/JobList/JobListItem.js:139
|
||||
#: components/LaunchButton/ReLaunchDropDown.js:81
|
||||
#: screens/Job/JobDetail/JobDetail.js:455
|
||||
#: screens/Job/JobDetail/JobDetail.js:463
|
||||
#: screens/Job/JobDetail/JobDetail.js:450
|
||||
#: screens/Job/JobDetail/JobDetail.js:458
|
||||
#: screens/Job/JobOutput/shared/OutputToolbar.js:165
|
||||
msgid "Relaunch"
|
||||
msgstr ""
|
||||
@@ -7063,13 +7067,13 @@ msgstr ""
|
||||
#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:77
|
||||
#: screens/Inventory/shared/InventoryForm.js:54
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:34
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:92
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/TowerSubForm.js:50
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:49
|
||||
#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:49
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:67
|
||||
@@ -8326,7 +8330,7 @@ msgstr ""
|
||||
msgid "This container group is currently being by other resources. Are you sure you want to delete it?"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:292
|
||||
#: screens/Credential/CredentialDetail/CredentialDetail.js:290
|
||||
msgid "This credential is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr ""
|
||||
|
||||
@@ -8348,7 +8352,7 @@ msgid ""
|
||||
"streamline customer experience and success."
|
||||
msgstr ""
|
||||
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:130
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:128
|
||||
msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?"
|
||||
msgstr ""
|
||||
|
||||
@@ -9003,7 +9007,7 @@ msgstr ""
|
||||
#: components/PromptDetail/PromptJobTemplateDetail.js:271
|
||||
#: components/PromptDetail/PromptWFJobTemplateDetail.js:131
|
||||
#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381
|
||||
#: screens/Host/HostDetail/HostDetail.js:96
|
||||
#: screens/Host/HostDetail/HostDetail.js:90
|
||||
#: screens/Inventory/InventoryDetail/InventoryDetail.js:97
|
||||
#: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89
|
||||
@@ -9012,7 +9016,7 @@ msgstr ""
|
||||
#: screens/Inventory/shared/InventoryForm.js:68
|
||||
#: screens/Inventory/shared/InventoryGroupForm.js:46
|
||||
#: screens/Inventory/shared/SmartInventoryForm.js:93
|
||||
#: screens/Job/JobDetail/JobDetail.js:424
|
||||
#: screens/Job/JobDetail/JobDetail.js:419
|
||||
#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:366
|
||||
#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:204
|
||||
#: screens/Template/shared/JobTemplateForm.js:411
|
||||
@@ -9692,8 +9696,8 @@ msgid "documentation"
|
||||
msgstr ""
|
||||
|
||||
#: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:101
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:115
|
||||
#: screens/Host/HostDetail/HostDetail.js:106
|
||||
#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:113
|
||||
#: screens/Host/HostDetail/HostDetail.js:100
|
||||
#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:94
|
||||
#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:106
|
||||
#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99
|
||||
@@ -9898,7 +9902,11 @@ msgid "{0, plural, one {This inventory source is currently being used by other r
|
||||
msgstr ""
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgid "{0, plural, one {This organization is currently being by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
#~ msgstr ""
|
||||
|
||||
#: screens/Organization/OrganizationList/OrganizationList.js:166
|
||||
msgid "{0, plural, one {This organization is currently being used by other resources. Are you sure you want to delete it?} other {Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?}}"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Project/ProjectList/ProjectList.js:238
|
||||
|
||||
@@ -188,6 +188,10 @@ function ActivityStream() {
|
||||
>
|
||||
{t`Notification Templates`}
|
||||
</SelectOption>
|
||||
<SelectOption
|
||||
key="instance"
|
||||
value="instance"
|
||||
>{t`Instances`}</SelectOption>
|
||||
<SelectOption key="instance_groups" value="instance_group">
|
||||
{t`Instance Groups`}
|
||||
</SelectOption>
|
||||
|
||||
@@ -27,6 +27,24 @@ function ExecutionEnvironmentAdd() {
|
||||
const handleCancel = () => {
|
||||
history.push(`/execution_environments`);
|
||||
};
|
||||
|
||||
const hubParams = {
|
||||
description: '',
|
||||
image: '',
|
||||
name: '',
|
||||
};
|
||||
|
||||
history.location.search
|
||||
.replace(/^\?/, '')
|
||||
.split('&')
|
||||
.map((s) => s.split('='))
|
||||
.forEach(([key, val]) => {
|
||||
if (!(key in hubParams)) {
|
||||
return;
|
||||
}
|
||||
hubParams[key] = decodeURIComponent(val);
|
||||
});
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
@@ -38,6 +56,7 @@ function ExecutionEnvironmentAdd() {
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
me={me || {}}
|
||||
executionEnvironment={hubParams}
|
||||
/>
|
||||
)}
|
||||
</Config>
|
||||
|
||||
@@ -86,6 +86,8 @@ describe('<ExecutionEnvironmentAdd/>', () => {
|
||||
context: { router: { history } },
|
||||
});
|
||||
});
|
||||
|
||||
await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -108,8 +110,6 @@ describe('<ExecutionEnvironmentAdd/>', () => {
|
||||
});
|
||||
|
||||
test('handleCancel should return the user back to the execution environments list', async () => {
|
||||
await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
|
||||
|
||||
wrapper.find('Button[aria-label="Cancel"]').simulate('click');
|
||||
expect(history.location.pathname).toEqual('/execution_environments');
|
||||
});
|
||||
@@ -131,4 +131,23 @@ describe('<ExecutionEnvironmentAdd/>', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
||||
});
|
||||
|
||||
test('should parse and prefill select form fields from query params', async () => {
|
||||
history = createMemoryHistory({
|
||||
initialEntries: [
|
||||
'/execution_environments/add?image=https://myhub.io/repo:2.0',
|
||||
],
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ExecutionEnvironmentAdd me={mockMe} />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
});
|
||||
|
||||
await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
|
||||
|
||||
expect(
|
||||
wrapper.find('input#execution-environment-image').prop('value')
|
||||
).toEqual('https://myhub.io/repo:2.0');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -212,6 +212,7 @@ function ExecutionEnvironmentForm({
|
||||
};
|
||||
return (
|
||||
<Formik
|
||||
enableReinitialize
|
||||
initialValues={initialValues}
|
||||
onSubmit={(values) => onSubmit(values)}
|
||||
>
|
||||
|
||||
@@ -31,24 +31,29 @@ function InstanceGroup({ setBreadcrumb }) {
|
||||
isLoading,
|
||||
error: contentError,
|
||||
request: fetchInstanceGroups,
|
||||
result: { instanceGroup, defaultControlPlane },
|
||||
result: { instanceGroup, defaultControlPlane, defaultExecution },
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const [
|
||||
{ data },
|
||||
{
|
||||
data: { DEFAULT_CONTROL_PLANE_QUEUE_NAME },
|
||||
data: {
|
||||
DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
},
|
||||
},
|
||||
] = await Promise.all([
|
||||
InstanceGroupsAPI.readDetail(id),
|
||||
SettingsAPI.readAll(),
|
||||
]);
|
||||
|
||||
return {
|
||||
instanceGroup: data,
|
||||
defaultControlPlane: DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
defaultExecution: DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
};
|
||||
}, [id]),
|
||||
{ instanceGroup: null, defaultControlPlane: '' }
|
||||
{ instanceGroup: null, defaultControlPlane: '', defaultExecution: '' }
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -130,11 +135,13 @@ function InstanceGroup({ setBreadcrumb }) {
|
||||
<Route path="/instance_groups/:id/edit">
|
||||
<InstanceGroupEdit
|
||||
instanceGroup={instanceGroup}
|
||||
defaultExecution={defaultExecution}
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/instance_groups/:id/details">
|
||||
<InstanceGroupDetails
|
||||
defaultExecution={defaultExecution}
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
instanceGroup={instanceGroup}
|
||||
/>
|
||||
|
||||
@@ -23,7 +23,11 @@ const Unavailable = styled.span`
|
||||
color: var(--pf-global--danger-color--200);
|
||||
`;
|
||||
|
||||
function InstanceGroupDetails({ instanceGroup, defaultControlPlane }) {
|
||||
function InstanceGroupDetails({
|
||||
instanceGroup,
|
||||
defaultControlPlane,
|
||||
defaultExecution,
|
||||
}) {
|
||||
const { id, name } = instanceGroup;
|
||||
|
||||
const history = useHistory();
|
||||
@@ -42,7 +46,8 @@ function InstanceGroupDetails({ instanceGroup, defaultControlPlane }) {
|
||||
const { error, dismissError } = useDismissableError(deleteError);
|
||||
const deleteDetailsRequests =
|
||||
relatedResourceDeleteRequests.instanceGroup(instanceGroup);
|
||||
|
||||
const isDefaultInstanceGroup =
|
||||
name === defaultControlPlane || name === defaultExecution;
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList>
|
||||
@@ -110,7 +115,7 @@ function InstanceGroupDetails({ instanceGroup, defaultControlPlane }) {
|
||||
{t`Edit`}
|
||||
</Button>
|
||||
)}
|
||||
{name !== defaultControlPlane &&
|
||||
{!isDefaultInstanceGroup &&
|
||||
instanceGroup.summary_fields.user_capabilities &&
|
||||
instanceGroup.summary_fields.user_capabilities.delete && (
|
||||
<DeleteButton
|
||||
|
||||
@@ -5,7 +5,11 @@ import { CardBody } from 'components/Card';
|
||||
import { InstanceGroupsAPI } from 'api';
|
||||
import InstanceGroupForm from '../shared/InstanceGroupForm';
|
||||
|
||||
function InstanceGroupEdit({ instanceGroup, defaultControlPlane }) {
|
||||
function InstanceGroupEdit({
|
||||
instanceGroup,
|
||||
defaultControlPlane,
|
||||
defaultExecution,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
const detailsUrl = `/instance_groups/${instanceGroup.id}/details`;
|
||||
@@ -28,6 +32,7 @@ function InstanceGroupEdit({ instanceGroup, defaultControlPlane }) {
|
||||
<InstanceGroupForm
|
||||
instanceGroup={instanceGroup}
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
onSubmit={handleSubmit}
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
|
||||
@@ -58,7 +58,7 @@ function InstanceGroupList({
|
||||
const match = useRouteMatch();
|
||||
const {
|
||||
error: protectedItemsError,
|
||||
isloading: isLoadingProtectedItems,
|
||||
isLoading: isLoadingProtectedItems,
|
||||
request: fetchProtectedItems,
|
||||
result: { defaultControlPlane, defaultExecution },
|
||||
} = useRequest(
|
||||
@@ -248,6 +248,13 @@ function InstanceGroupList({
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DatalistToolbar
|
||||
{...props}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { Route, Switch, useLocation } from 'react-router-dom';
|
||||
|
||||
import useRequest from 'hooks/useRequest';
|
||||
import { SettingsAPI } from 'api';
|
||||
@@ -14,6 +14,7 @@ import ContainerGroupAdd from './ContainerGroupAdd';
|
||||
import ContainerGroup from './ContainerGroup';
|
||||
|
||||
function InstanceGroups() {
|
||||
const { pathname } = useLocation();
|
||||
const {
|
||||
request: settingsRequest,
|
||||
isLoading: isSettingsRequestLoading,
|
||||
@@ -62,10 +63,14 @@ function InstanceGroups() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const streamType = pathname.includes('instances')
|
||||
? 'instance'
|
||||
: 'instance_group';
|
||||
|
||||
return (
|
||||
<>
|
||||
<ScreenHeader
|
||||
streamType="instance_group"
|
||||
streamType={streamType}
|
||||
breadcrumbConfig={breadcrumbConfig}
|
||||
/>
|
||||
<Switch>
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { InstanceGroupsAPI } from 'api';
|
||||
import InstanceGroups from './InstanceGroups';
|
||||
|
||||
const mockUseLocationValue = {
|
||||
pathname: '',
|
||||
};
|
||||
jest.mock('api');
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: () => mockUseLocationValue,
|
||||
}));
|
||||
describe('<InstanceGroups/>', () => {
|
||||
test('should set breadcrumbs', () => {
|
||||
mockUseLocationValue.pathname = '/instance_groups';
|
||||
|
||||
const wrapper = shallow(<InstanceGroups />);
|
||||
|
||||
const header = wrapper.find('ScreenHeader');
|
||||
@@ -15,4 +25,17 @@ describe('<InstanceGroups/>', () => {
|
||||
'/instance_groups/container_group/add': 'Create new container group',
|
||||
});
|
||||
});
|
||||
test('should set breadcrumbs', async () => {
|
||||
mockUseLocationValue.pathname = '/instance_groups/1/instances';
|
||||
InstanceGroupsAPI.readInstances.mockResolvedValue({
|
||||
data: { results: [{ hostname: 'EC2', id: 1 }] },
|
||||
});
|
||||
InstanceGroupsAPI.readInstanceOptions.mockResolvedValue({
|
||||
data: { actions: {} },
|
||||
});
|
||||
|
||||
const wrapper = shallow(<InstanceGroups />);
|
||||
|
||||
expect(wrapper.find('ScreenHeader').prop('streamType')).toEqual('instance');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -147,7 +147,10 @@ function InstanceList() {
|
||||
const fetchInstancesToAssociate = useCallback(
|
||||
(params) =>
|
||||
InstancesAPI.read(
|
||||
mergeParams(params, { not__rampart_groups__id: instanceGroupId })
|
||||
mergeParams(params, {
|
||||
...{ not__rampart_groups__id: instanceGroupId },
|
||||
...{ not__node_type: 'control' },
|
||||
})
|
||||
),
|
||||
[instanceGroupId]
|
||||
);
|
||||
@@ -175,7 +178,7 @@ function InstanceList() {
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'hostname',
|
||||
key: 'hostname__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
]}
|
||||
@@ -280,6 +283,10 @@ function InstanceList() {
|
||||
title={t`Select Instances`}
|
||||
optionsRequest={readInstancesOptions}
|
||||
displayKey="hostname"
|
||||
columns={[
|
||||
{ key: 'hostname', name: t`Name` },
|
||||
{ key: 'node_type', name: t`Node Type` },
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
{error && (
|
||||
|
||||
@@ -3,27 +3,42 @@ import { func, shape } from 'prop-types';
|
||||
import { Formik, useField } from 'formik';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import { Form } from '@patternfly/react-core';
|
||||
import { Form, Tooltip } from '@patternfly/react-core';
|
||||
|
||||
import FormField, { FormSubmitError } from 'components/FormField';
|
||||
import FormActionGroup from 'components/FormActionGroup';
|
||||
import { required, minMaxValue } from 'util/validators';
|
||||
import { FormColumnLayout } from 'components/FormLayout';
|
||||
|
||||
function InstanceGroupFormFields({ defaultControlPlane }) {
|
||||
const [instanceGroupNameField, ,] = useField('name');
|
||||
function InstanceGroupFormFields({ defaultControlPlane, defaultExecution }) {
|
||||
const [{ value }, ,] = useField('name');
|
||||
const isDisabled =
|
||||
value === defaultExecution || value === defaultControlPlane;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
name="name"
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
isDisabled={instanceGroupNameField.value === defaultControlPlane}
|
||||
/>
|
||||
{isDisabled ? (
|
||||
<Tooltip content={t`Name cannot be changed on this Instance Group`}>
|
||||
<FormField
|
||||
name="name"
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<FormField
|
||||
name="name"
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
/>
|
||||
)}
|
||||
<FormField
|
||||
id="instance-group-policy-instance-minimum"
|
||||
label={t`Policy instance minimum`}
|
||||
|
||||
@@ -116,4 +116,44 @@ describe('<InstanceGroupForm/>', () => {
|
||||
wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();
|
||||
expect(onCancel).toBeCalled();
|
||||
});
|
||||
|
||||
test('Name field should be disabled, default', async () => {
|
||||
let defaultInstanceGroupWrapper;
|
||||
await act(async () => {
|
||||
defaultInstanceGroupWrapper = mountWithContexts(
|
||||
<InstanceGroupForm
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
defaultControlPlane="controlplane"
|
||||
defaultExecution="default"
|
||||
instanceGroup={{ ...instanceGroup, name: 'default' }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
expect(
|
||||
defaultInstanceGroupWrapper
|
||||
.find('TextInput[name="name"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('Name field should be disabled, controlplane', async () => {
|
||||
let defaultInstanceGroupWrapper;
|
||||
await act(async () => {
|
||||
defaultInstanceGroupWrapper = mountWithContexts(
|
||||
<InstanceGroupForm
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
defaultControlPlane="controlplane"
|
||||
defaultExecution="default"
|
||||
instanceGroup={{ ...instanceGroup, name: 'controlplane' }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
expect(
|
||||
defaultInstanceGroupWrapper
|
||||
.find('TextInput[name="name"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ function SmartInventoryHostList({ inventory }) {
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name',
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -62,10 +62,10 @@ async function checkOutput(wrapper, expectedLines) {
|
||||
jobEventLines.forEach((line) => {
|
||||
actualLines.push(line.text());
|
||||
});
|
||||
expect(actualLines.length).toEqual(expectedLines.length);
|
||||
expectedLines.forEach((line, index) => {
|
||||
expect(actualLines[index]).toEqual(line);
|
||||
});
|
||||
|
||||
expect(
|
||||
wrapper.find('JobEvent[event="playbook_on_stats"]').prop('end_line')
|
||||
).toEqual(expectedLines.length);
|
||||
}
|
||||
|
||||
async function findScrollButtons(wrapper) {
|
||||
@@ -112,7 +112,6 @@ describe('<JobOutput />', () => {
|
||||
wrapper = mountWithContexts(<JobOutput job={mockJob} />);
|
||||
});
|
||||
await waitForElement(wrapper, 'JobEvent', (el) => el.length > 0);
|
||||
|
||||
await checkOutput(wrapper, generateChattyRows());
|
||||
|
||||
expect(wrapper.find('JobOutput').length).toBe(1);
|
||||
|
||||
@@ -47,18 +47,12 @@ function AWXLogin({ alt, isAuthenticated }) {
|
||||
isLoading: isCustomLoginInfoLoading,
|
||||
error: customLoginInfoError,
|
||||
request: fetchCustomLoginInfo,
|
||||
result: {
|
||||
brandName,
|
||||
logo,
|
||||
loginInfo,
|
||||
socialAuthOptions,
|
||||
loginRedirectOverride,
|
||||
},
|
||||
result: { brandName, logo, loginInfo, socialAuthOptions },
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const [
|
||||
{
|
||||
data: { custom_logo, custom_login_info, login_redirect_override },
|
||||
data: { custom_logo, custom_login_info },
|
||||
},
|
||||
{
|
||||
data: { BRAND_NAME },
|
||||
@@ -78,7 +72,6 @@ function AWXLogin({ alt, isAuthenticated }) {
|
||||
logo: logoSrc,
|
||||
loginInfo: custom_login_info,
|
||||
socialAuthOptions: authData,
|
||||
loginRedirectOverride: login_redirect_override,
|
||||
};
|
||||
}, []),
|
||||
{
|
||||
@@ -118,10 +111,6 @@ function AWXLogin({ alt, isAuthenticated }) {
|
||||
if (isCustomLoginInfoLoading) {
|
||||
return null;
|
||||
}
|
||||
if (!isAuthenticated(document.cookie) && loginRedirectOverride) {
|
||||
window.location.replace(loginRedirectOverride);
|
||||
return null;
|
||||
}
|
||||
if (isAuthenticated(document.cookie)) {
|
||||
return <Redirect to={authRedirectTo || '/'} />;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
@@ -20,13 +20,20 @@ import {
|
||||
import CodeDetail from 'components/DetailList/CodeDetail';
|
||||
import DeleteButton from 'components/DeleteButton';
|
||||
import ErrorDetail from 'components/ErrorDetail';
|
||||
import { NotificationTemplatesAPI } from 'api';
|
||||
import { NotificationTemplatesAPI, NotificationsAPI } from 'api';
|
||||
import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||
import StatusLabel from 'components/StatusLabel';
|
||||
import hasCustomMessages from '../shared/hasCustomMessages';
|
||||
import { NOTIFICATION_TYPES } from '../constants';
|
||||
|
||||
const NUM_RETRIES = 25;
|
||||
const RETRY_TIMEOUT = 5000;
|
||||
|
||||
function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
const history = useHistory();
|
||||
const [testStatus, setTestStatus] = useState(
|
||||
template.summary_fields?.recent_notifications[0]?.status ?? undefined
|
||||
);
|
||||
|
||||
const {
|
||||
created,
|
||||
@@ -64,9 +71,35 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
}, [template.id, history])
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(deleteError);
|
||||
const typeMessageDefaults = defaultMessages[template.notification_type];
|
||||
const { request: sendTestNotification, error: testError } = useRequest(
|
||||
useCallback(async () => {
|
||||
setTestStatus('running');
|
||||
|
||||
let retries = NUM_RETRIES;
|
||||
const {
|
||||
data: { notification: notificationId },
|
||||
} = await NotificationTemplatesAPI.test(template.id);
|
||||
|
||||
async function pollForStatusChange() {
|
||||
const { data: notification } = await NotificationsAPI.readDetail(
|
||||
notificationId
|
||||
);
|
||||
if (notification.status !== 'pending') {
|
||||
setTestStatus(notification.status);
|
||||
return;
|
||||
}
|
||||
retries--;
|
||||
if (retries > 0) {
|
||||
setTimeout(pollForStatusChange, RETRY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(pollForStatusChange, RETRY_TIMEOUT);
|
||||
}, [template.id])
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(deleteError || testError);
|
||||
const typeMessageDefaults = defaultMessages[template.notification_type];
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
@@ -76,6 +109,12 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
value={template.description}
|
||||
dataCy="nt-detail-description"
|
||||
/>
|
||||
{summary_fields.recent_notifications.length && (
|
||||
<Detail
|
||||
label={t`Status`}
|
||||
value={<StatusLabel status={testStatus} />}
|
||||
/>
|
||||
)}
|
||||
{summary_fields.organization ? (
|
||||
<Detail
|
||||
label={t`Organization`}
|
||||
@@ -354,8 +393,8 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
)}
|
||||
</DetailList>
|
||||
<CardActionsRow>
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.edit && (
|
||||
{summary_fields.user_capabilities?.edit && (
|
||||
<>
|
||||
<Button
|
||||
ouiaId="notification-template-detail-edit-button"
|
||||
component={Link}
|
||||
@@ -364,18 +403,23 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
>
|
||||
{t`Edit`}
|
||||
</Button>
|
||||
)}
|
||||
{summary_fields.user_capabilities &&
|
||||
summary_fields.user_capabilities.delete && (
|
||||
<DeleteButton
|
||||
name={template.name}
|
||||
modalTitle={t`Delete Notification`}
|
||||
onConfirm={deleteTemplate}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{t`Delete`}
|
||||
</DeleteButton>
|
||||
)}
|
||||
<Button
|
||||
onClick={sendTestNotification}
|
||||
variant="secondary"
|
||||
isDisabled={testStatus === ('running' || 'pending')}
|
||||
>{t`Test`}</Button>
|
||||
</>
|
||||
)}
|
||||
{summary_fields.user_capabilities?.delete && (
|
||||
<DeleteButton
|
||||
name={template.name}
|
||||
modalTitle={t`Delete Notification`}
|
||||
onConfirm={deleteTemplate}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{t`Delete`}
|
||||
</DeleteButton>
|
||||
)}
|
||||
</CardActionsRow>
|
||||
{error && (
|
||||
<AlertModal
|
||||
@@ -384,7 +428,9 @@ function NotificationTemplateDetail({ template, defaultMessages }) {
|
||||
title={t`Error!`}
|
||||
onClose={dismissError}
|
||||
>
|
||||
{t`Failed to delete notification.`}
|
||||
{deleteError
|
||||
? t`Failed to delete notification.`
|
||||
: t`Notification test failed.`}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
|
||||
@@ -45,7 +45,7 @@ const mockTemplate = {
|
||||
delete: true,
|
||||
copy: true,
|
||||
},
|
||||
recent_notifications: [],
|
||||
recent_notifications: [{ status: 'success' }],
|
||||
},
|
||||
created: '2021-06-16T18:52:23.811374Z',
|
||||
modified: '2021-06-16T18:53:37.631371Z',
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('<NotificationTemplateListItem />', () => {
|
||||
});
|
||||
|
||||
test('should call api to copy inventory', async () => {
|
||||
NotificationTemplatesAPI.copy.mockResolvedValue();
|
||||
NotificationTemplatesAPI.copy.mockResolvedValue({ name: 'Foo' });
|
||||
|
||||
const wrapper = mountWithContexts(
|
||||
<table>
|
||||
@@ -91,7 +91,18 @@ describe('<NotificationTemplateListItem />', () => {
|
||||
});
|
||||
|
||||
test('should render proper alert modal on copy error', async () => {
|
||||
NotificationTemplatesAPI.copy.mockRejectedValue(new Error());
|
||||
NotificationTemplatesAPI.copy.mockRejectedValue(
|
||||
new Error({
|
||||
response: {
|
||||
config: {
|
||||
method: 'post',
|
||||
url: '/api/v2/notification_templates/3/copy',
|
||||
},
|
||||
data: 'An error ocurred',
|
||||
status: 403,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const wrapper = mountWithContexts(
|
||||
<table>
|
||||
@@ -104,10 +115,12 @@ describe('<NotificationTemplateListItem />', () => {
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
expect(wrapper.find('Modal').length).toBe(0);
|
||||
await act(async () =>
|
||||
wrapper.find('Button[aria-label="Copy"]').prop('onClick')()
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('Modal').length).toBe(1);
|
||||
expect(wrapper.find('Modal').prop('isOpen')).toBe(true);
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -362,8 +362,14 @@ function SlackFields() {
|
||||
type="textarea"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
tooltip={t`Enter one Slack channel per line. The pound symbol (#)
|
||||
is required for channels.`}
|
||||
tooltip={
|
||||
<>
|
||||
{t`Enter one Slack channel per line. The pound symbol (#)
|
||||
is required for channels. To respond to or start a thread to a specific message add the parent message Id to the channel where the parent message Id is 16 digits. A dot (.) must be manually inserted after the 10th digit. ie:#destination-channel, 1231257890.006423. See Slack`}{' '}
|
||||
<a href="https://api.slack.com/messaging/retrieving#individual_messages">{t`documentation`}</a>{' '}
|
||||
<span>{t`for more information.`}</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<PasswordField
|
||||
id="slack-token"
|
||||
|
||||
@@ -165,7 +165,7 @@ function OrganizationsList() {
|
||||
deleteMessage={
|
||||
<Plural
|
||||
value={selected.length}
|
||||
one="This organization is currently being by other resources. Are you sure you want to delete it?"
|
||||
one="This organization is currently being used by other resources. Are you sure you want to delete it?"
|
||||
other="Deleting these organizations could impact other resources that rely on them. Are you sure you want to delete anyway?"
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -94,10 +94,9 @@ function AzureADEdit() {
|
||||
const initialValues = (fields) =>
|
||||
Object.keys(fields).reduce((acc, key) => {
|
||||
if (fields[key].type === 'list' || fields[key].type === 'nested object') {
|
||||
const emptyDefault = fields[key].type === 'list' ? '[]' : '{}';
|
||||
acc[key] = fields[key].value
|
||||
? JSON.stringify(fields[key].value, null, 2)
|
||||
: emptyDefault;
|
||||
: null;
|
||||
} else {
|
||||
acc[key] = fields[key].value ?? '';
|
||||
}
|
||||
|
||||
@@ -147,8 +147,8 @@ describe('<GitHubDetail />', () => {
|
||||
);
|
||||
assertDetail(wrapper, 'GitHub OAuth2 Key', 'mock github key');
|
||||
assertDetail(wrapper, 'GitHub OAuth2 Secret', 'Encrypted');
|
||||
assertVariableDetail(wrapper, 'GitHub OAuth2 Organization Map', '{}');
|
||||
assertVariableDetail(wrapper, 'GitHub OAuth2 Team Map', '{}');
|
||||
assertVariableDetail(wrapper, 'GitHub OAuth2 Organization Map', 'null');
|
||||
assertVariableDetail(wrapper, 'GitHub OAuth2 Team Map', 'null');
|
||||
});
|
||||
|
||||
test('should hide edit button from non-superusers', async () => {
|
||||
@@ -226,12 +226,12 @@ describe('<GitHubDetail />', () => {
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Organization OAuth2 Organization Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Organization OAuth2 Team Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -333,9 +333,13 @@ describe('<GitHubDetail />', () => {
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise OAuth2 Organization Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise OAuth2 Team Map',
|
||||
'null'
|
||||
);
|
||||
assertVariableDetail(wrapper, 'GitHub Enterprise OAuth2 Team Map', '{}');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -398,12 +402,12 @@ describe('<GitHubDetail />', () => {
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise Organization OAuth2 Organization Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise Organization OAuth2 Team Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -463,12 +467,12 @@ describe('<GitHubDetail />', () => {
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise Team OAuth2 Organization Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
assertVariableDetail(
|
||||
wrapper,
|
||||
'GitHub Enterprise Team OAuth2 Team Map',
|
||||
'{}'
|
||||
'null'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -92,10 +92,9 @@ function GitHubEdit() {
|
||||
const initialValues = (fields) =>
|
||||
Object.keys(fields).reduce((acc, key) => {
|
||||
if (fields[key].type === 'list' || fields[key].type === 'nested object') {
|
||||
const emptyDefault = fields[key].type === 'list' ? '[]' : '{}';
|
||||
acc[key] = fields[key].value
|
||||
? JSON.stringify(fields[key].value, null, 2)
|
||||
: emptyDefault;
|
||||
: null;
|
||||
} else {
|
||||
acc[key] = fields[key].value ?? '';
|
||||
}
|
||||
|
||||
@@ -94,10 +94,9 @@ function GitHubEnterpriseEdit() {
|
||||
const initialValues = (fields) =>
|
||||
Object.keys(fields).reduce((acc, key) => {
|
||||
if (fields[key].type === 'list' || fields[key].type === 'nested object') {
|
||||
const emptyDefault = fields[key].type === 'list' ? '[]' : '{}';
|
||||
acc[key] = fields[key].value
|
||||
? JSON.stringify(fields[key].value, null, 2)
|
||||
: emptyDefault;
|
||||
: null;
|
||||
} else {
|
||||
acc[key] = fields[key].value ?? '';
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ describe('<GitHubEnterpriseEdit />', () => {
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL: '',
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_KEY: '',
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_SECRET: '',
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_TEAM_MAP: {},
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_TEAM_MAP: null,
|
||||
SOCIAL_AUTH_GITHUB_ENTERPRISE_ORGANIZATION_MAP: {
|
||||
Default: {
|
||||
users: false,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user