From af6549ffcdc964316b40ab9637a259c66a231dae Mon Sep 17 00:00:00 2001 From: Jesse Wattenbarger Date: Mon, 13 Feb 2023 08:54:37 -0500 Subject: [PATCH 001/167] Fix a bug in clean languages The `$` was not escaped for make or shell. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 896dcf2c6c..33958ed4c6 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,7 @@ clean-schema: clean-languages: rm -f $(I18N_FLAG_FILE) - find ./awx/locale/ -type f -regex ".*\.mo$" -delete + find ./awx/locale/ -type f -regex '.*\.mo$$' -delete ## Remove temporary build files, compiled Python files. clean: clean-ui clean-api clean-awxkit clean-dist From 64b0e09e87dca32adedba8ee6ba812c1d2b6653d Mon Sep 17 00:00:00 2001 From: jainnikhil30 Date: Thu, 16 Mar 2023 18:04:20 +0530 Subject: [PATCH 002/167] dont user githubusercontent for containers.conf and podman-containers.conf --- .../ansible/roles/dockerfile/templates/Dockerfile.j2 | 4 ++-- tools/docker-compose/containers.conf | 12 ++++++++++++ tools/docker-compose/podman-containers.conf | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tools/docker-compose/containers.conf create mode 100644 tools/docker-compose/podman-containers.conf diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index e35234f622..2477153678 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -208,8 +208,8 @@ ADD tools/docker-compose/start_tests.sh /start_tests.sh ADD tools/docker-compose/bootstrap_development.sh /usr/bin/bootstrap_development.sh ADD tools/docker-compose/entrypoint.sh /entrypoint.sh ADD tools/scripts/config-watcher /usr/bin/config-watcher -ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf -ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /var/lib/awx/.config/containers/containers.conf +ADD tools/docker-compose/containers.conf /etc/containers/containers.conf +ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/containers.conf {% else %} ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh diff --git a/tools/docker-compose/containers.conf b/tools/docker-compose/containers.conf new file mode 100644 index 0000000000..220c1f850c --- /dev/null +++ b/tools/docker-compose/containers.conf @@ -0,0 +1,12 @@ +[containers] +netns="host" +userns="host" +ipcns="host" +utsns="host" +cgroupns="host" +cgroups="disabled" +log_driver = "k8s-file" +[engine] +cgroup_manager = "cgroupfs" +events_logger="file" +runtime="crun" diff --git a/tools/docker-compose/podman-containers.conf b/tools/docker-compose/podman-containers.conf new file mode 100644 index 0000000000..2bdd95a3b5 --- /dev/null +++ b/tools/docker-compose/podman-containers.conf @@ -0,0 +1,5 @@ +[containers] +volumes = [ + "/proc:/proc", +] +default_sysctls = [] From 42c848b57bec0f0ed76d345fdcd5cf5773603d9b Mon Sep 17 00:00:00 2001 From: Kia Lam Date: Tue, 21 Feb 2023 17:39:55 -0800 Subject: [PATCH 003/167] Add banner to dashboard page. Co-Authored-By: kialam <2293210+kialam@users.noreply.github.com> --- awx/ui/src/screens/Dashboard/Dashboard.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/awx/ui/src/screens/Dashboard/Dashboard.js b/awx/ui/src/screens/Dashboard/Dashboard.js index 1481b9ac5f..9ec35d7ba0 100644 --- a/awx/ui/src/screens/Dashboard/Dashboard.js +++ b/awx/ui/src/screens/Dashboard/Dashboard.js @@ -1,14 +1,16 @@ import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; -import { t } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; import { + Banner, Card, PageSection, Tabs, Tab, TabTitleText, } from '@patternfly/react-core'; +import { InfoCircleIcon } from '@patternfly/react-icons'; import useRequest from 'hooks/useRequest'; import { DashboardAPI } from 'api'; @@ -69,6 +71,15 @@ function Dashboard() { } return ( <> + + +

+ A tech preview of the new Ansible Automation + Platform user interface can be found{' '} + here. +

+
+
Date: Tue, 21 Feb 2023 16:40:47 -0500 Subject: [PATCH 004/167] Build and serve UI_NEXT - Add new makefile for building ui_next - Add setting to toggle ui_next - Add URL path for displaying ui_next - Update collectstatic and template dir config to serve ui_next --- .gitignore | 4 ++ MANIFEST.in | 1 + Makefile | 16 +++-- awx/main/conf.py | 10 +++ awx/settings/defaults.py | 15 ++++- awx/ui_next/Makefile | 142 +++++++++++++++++++++++++++++++++++++++ awx/ui_next/README.md | 33 +++++++++ awx/ui_next/urls.py | 11 +++ awx/urls.py | 1 + 9 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 awx/ui_next/Makefile create mode 100644 awx/ui_next/README.md create mode 100644 awx/ui_next/urls.py diff --git a/.gitignore b/.gitignore index 6231ea4071..0ecdb823a2 100644 --- a/.gitignore +++ b/.gitignore @@ -157,7 +157,11 @@ use_dev_supervisor.txt *.unison.tmp *.# /awx/ui/.ui-built +/awx/ui_next/.ui-built /Dockerfile /_build/ /_build_kube_dev/ /Dockerfile.kube-dev + +awx/ui_next/src +awx/ui_next/build diff --git a/MANIFEST.in b/MANIFEST.in index 04cde5e9f6..09a5392c50 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,6 +6,7 @@ recursive-include awx/templates *.html recursive-include awx/api/templates *.md *.html *.yml recursive-include awx/ui/build *.html recursive-include awx/ui/build * +recursive-include awx/ui_next/build * recursive-include awx/playbooks *.yml recursive-include awx/lib/site-packages * recursive-include awx/plugins *.ps1 diff --git a/Makefile b/Makefile index 88b2047f8a..f4404e8809 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +-include awx/ui_next/Makefile + PYTHON ?= python3.9 DOCKER_COMPOSE ?= docker-compose OFFICIAL ?= no @@ -449,7 +451,7 @@ HEADLESS ?= no ifeq ($(HEADLESS), yes) dist/$(SDIST_TAR_FILE): else -dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE) +dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE) awx/ui_next/build endif $(PYTHON) -m build -s ln -sf $(SDIST_TAR_FILE) dist/awx.tar.gz @@ -497,8 +499,6 @@ docker-compose-sources: .git/hooks/pre-commit -e enable_prometheus=$(PROMETHEUS) \ -e enable_grafana=$(GRAFANA) $(EXTRA_SOURCES_ANSIBLE_OPTS) - - 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 @@ -592,7 +592,7 @@ awx-kube-dev-build: Dockerfile.kube-dev -t $(DEV_DOCKER_TAG_BASE)/awx_kube_devel:$(COMPOSE_TAG) . ## Build awx image for deployment on Kubernetes environment. -awx-kube-build: Dockerfile +awx-kube-build: Dockerfile awx/ui_next/src DOCKER_BUILDKIT=1 docker build -f Dockerfile \ --build-arg VERSION=$(VERSION) \ --build-arg SETUPTOOLS_SCM_PRETEND_VERSION=$(VERSION) \ @@ -654,3 +654,11 @@ help/generate: } \ { lastLine = $$0 }' $(MAKEFILE_LIST) | sort -u @printf "\n" + +## Display help for a specific target folder +help/%: + @make -s help MAKEFILE_LIST="$*/Makefile" + +## Display help for a specific target folder +help/%/aliases: + @make -s help/all MAKEFILE_LIST="$*/Makefile.aliases" diff --git a/awx/main/conf.py b/awx/main/conf.py index f72e12fd0d..6634271b93 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -795,6 +795,16 @@ register( category_slug='bulk', ) +register( + 'UI_NEXT', + field_class=fields.BooleanField, + default=False, + label=_('Enable Preview of New User Interface'), + help_text=_('Enable preview of new user interface.'), + category=_('System'), + category_slug='system', +) + def logging_validate(serializer, attrs): if not serializer.instance or not hasattr(serializer.instance, 'LOG_AGGREGATOR_HOST') or not hasattr(serializer.instance, 'LOG_AGGREGATOR_TYPE'): diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index c0a5318638..b36dcc15ec 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -85,7 +85,11 @@ USE_L10N = True USE_TZ = True -STATICFILES_DIRS = [os.path.join(BASE_DIR, 'ui', 'build', 'static'), os.path.join(BASE_DIR, 'static')] +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'ui', 'build', 'static'), + os.path.join(BASE_DIR, 'ui_next', 'build'), + os.path.join(BASE_DIR, 'static'), +] # Absolute filesystem path to the directory where static file are collected via # the collectstatic command. @@ -299,7 +303,12 @@ TEMPLATES = [ ], 'builtins': ['awx.main.templatetags.swagger'], }, - 'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'ui', 'build'), os.path.join(BASE_DIR, 'ui', 'public')], + 'DIRS': [ + os.path.join(BASE_DIR, 'templates'), + os.path.join(BASE_DIR, 'ui', 'build'), + os.path.join(BASE_DIR, 'ui', 'public'), + os.path.join(BASE_DIR, 'ui_next', 'build', 'awx'), + ], }, ] @@ -1017,3 +1026,5 @@ AWX_MOUNT_ISOLATED_PATHS_ON_K8S = False # This is overridden downstream via /etc/tower/conf.d/cluster_host_id.py CLUSTER_HOST_ID = socket.gethostname() + +UI_NEXT = True diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile new file mode 100644 index 0000000000..6fed498d5f --- /dev/null +++ b/awx/ui_next/Makefile @@ -0,0 +1,142 @@ +## UI_NEXT_MKFILE_PATH: Path to this Makefile +UI_NEXT_MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) + +## UI_NEXT_DIR_ABS: Absolute path to the directory containing this Makefile +UI_NEXT_DIR_ABS := $(dir $(UI_NEXT_MKFILE_PATH)) + +## UI_NEXT_REL_DIR: Relative path to the directory containing this Makefile +# NOTE: UI_NEXT_REL_DIR swallowed the / because we want to be able to run `make src` from the ui_next dir +UI_NEXT_REL_DIR := $(subst $(CURDIR)/,, $(UI_NEXT_DIR_ABS)) + +## UI_NEXT_SRC_DIR: Path to the ui_next src directory +UI_NEXT_SRC_DIR := $(UI_NEXT_REL_DIR)src + +## UI_NEXT_BUILD_DIR: Path to the ui_next build directory +UI_NEXT_BUILD_DIR := $(UI_NEXT_REL_DIR)build + +## Path to your local clone of the UI_NEXT repo +# NOTE: This does not work with docker-compose development environment +UI_NEXT_LOCAL ?= + +# Git repo and branch to the UI_NEXT repo +UI_NEXT_GIT_REPO_SSH ?= git@github.com:ansible/ansible-ui.git +UI_NEXT_GIT_REPO_HTTPS ?= https://github.com/ansible/ansible-ui.git +UI_NEXT_GIT_BRANCH ?= main + +# awx-manage collect static require the awx/ui_next/build to exist +# therefore we have to commit the build directory to source control +# so that make docker-compose will be able to start up uwsgi +# UI_NEXT_BUILT_FILE is here so that we can use it as the non-phony build target +UI_NEXT_BUILT_FILE = $(UI_NEXT_REL_DIR).ui-built + +## Default target of this Makefile build the ui_next/build from source +ui-next: ui_next/build + +.PHONY: ui_next/clone-https +## Shallow clone the ui_next repo via https skip if UI_NEXT_GIT_REPO_HTTPS is undefined +ui_next/clone-https: + @if [ -z "$(UI_NEXT_GIT_REPO_HTTPS)" ]; then \ + echo "SKIP: ui_next/clone-https. UI_NEXT_GIT_REPO_HTTPS is not set."; \ + elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ + echo "SKIP: ui_next/clone-https. $(UI_NEXT_SRC_DIR) already exists."; \ + else \ + git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO_HTTPS) $(UI_NEXT_SRC_DIR) || true; \ + fi + +.PHONY: ui_next/clone-ssh +## Shallow clone the ui_next repo via ssh. +ui_next/clone-ssh: + @if [ -z "$(UI_NEXT_GIT_REPO_SSH)" ]; then \ + echo "SKIP: ui_next/clone-ssh. UI_NEXT_GIT_REPO_SSH is not set."; \ + elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ + echo "SKIP: ui_next/clone-ssh. $(UI_NEXT_SRC_DIR) already exists."; \ + else \ + git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO_SSH) $(UI_NEXT_SRC_DIR) || true; \ + fi + +.PHONY: ui_next/link-local +## Link to a existing local clone of ui_next repo. If method will not be able to build inside docker-compose environment +ui_next/link-local: + @if [ -z "$(UI_NEXT_LOCAL)" ]; then \ + echo "SKIP: ui_next/link-local. UI_NEXT_LOCAL is not set."; \ + elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ + echo "SKIP: ui_next/link-local. $(UI_NEXT_SRC_DIR) already exists."; \ + else \ + ln -s $(UI_NEXT_LOCAL) $(UI_NEXT_SRC_DIR); \ + fi + +.PHONY: ui_next/src +## Try to link to a local clone of ui_next repo if it exist otherwise clone via ssh than https. +ui_next/src: + @if [ -d $(UI_NEXT_SRC_DIR) ]; then \ + echo "SKIP: ui_next. $(UI_NEXT_SRC_DIR) already exists."; \ + else \ + $(MAKE) ui_next/link-local ui_next/clone-ssh ui_next/clone-https; \ + fi + +## Alias for ui_next, will not run if ui_next/src already exist +$(UI_NEXT_SRC_DIR): + $(MAKE) ui_next/src + +## Alias for ui_next/build, will not run if ui_next/src/build already exist +$(UI_NEXT_SRC_DIR)/build: + $(MAKE) ui_next/src/build + +.PHONY: ui_next/build +## Build ui_next from source +ui_next/src/build: $(UI_NEXT_SRC_DIR) $(UI_NEXT_SRC_DIR)/node_modules/webpack + @cd $(UI_NEXT_SRC_DIR) && npm run build:awx + + +## Install webpack if does not exist. +ui_next/src/node_modules/webpack: $(UI_NEXT_SRC_DIR) + @if [ -d $(UI_NEXT_SRC_DIR)/node_modules/webpack ]; then \ + echo "SKIP: ui_next/src/node_modules/webpack. $(UI_NEXT_SRC_DIR)/node_modules/webpack already exists."; \ + else \ + cd $(UI_NEXT_SRC_DIR) && npm install webpack; \ + fi + +## Alias for ui_next/src/node_modules/webpack. will not run if webpack already exist +$(UI_NEXT_SRC_DIR)/node_modules/webpack: + $(MAKE) ui_next/src/node_modules/webpack + +## Copy ui_next/src/build to ui_next/build +ui_next/build: ui_next/clean/build + $(MAKE) $(UI_NEXT_SRC_DIR)/build + @mkdir $(UI_NEXT_DIR_ABS)build && \ + cp -r $(UI_NEXT_SRC_DIR)/build/awx $(UI_NEXT_DIR_ABS)build/awx &&\ + touch $(UI_NEXT_BUILT_FILE) + +## Alias for ui_next/build. Will not run if .ui-built file already exist +$(UI_NEXT_BUILT_FILE): + $(MAKE) ui_next/build + +## Alias for ui_next/build. +.PHONY: $(UI_NEXT_BUILD_DIR) +$(UI_NEXT_BUILD_DIR): + $(MAKE) ui_next/build + +.PHONY: $(UI_NEXT_REL_DIR)clean +## Alias for ui_next/clean. +$(UI_NEXT_REL_DIR)clean: + rm -rf $(UI_NEXT_SRC_DIR) + rm -rf $(UI_NEXT_BUILD_DIR) + +.PHONY: ui_next/clean +## Clean ui_next +ui_next/clean: ui_next/clean/build + rm -rf $(UI_NEXT_SRC_DIR) + +.PHONY: ui_next/clean/src +## Clean ui_next src +ui_next/clean/src: + rm -rf $(UI_NEXT_SRC_DIR) + +.PHONY: ui_next/clean/build +## Clean ui_next build +ui_next/clean/build: + rm -rf $(UI_NEXT_BUILD_DIR) + rm -rf $(UI_NEXT_BUILT_FILE) + +print-%: + @echo $($*) \ No newline at end of file diff --git a/awx/ui_next/README.md b/awx/ui_next/README.md new file mode 100644 index 0000000000..35c5beb7c2 --- /dev/null +++ b/awx/ui_next/README.md @@ -0,0 +1,33 @@ +# Instruction to build ui_next directly from this directory + +## Set src of the ui_next repo + +### via GIT + +```bash +export UI_NEXT_GIT_BRANCH_REPO_HTTPS=https:// +``` + +or + +```bash +export UI_NEXT_GIT_BRANCH_REPO_SSH=git@ +``` + +optionally set branch (default is main) + +```bash +export UI_NEXT_GIT_BRANCH_BRANCH=main +``` + +### via symlink to existing clone + +```bash +export UI_NEXT_LOCAL = /path/to/your/ui_next +``` + +## Build + +```bash +make ui_next/build +``` diff --git a/awx/ui_next/urls.py b/awx/ui_next/urls.py new file mode 100644 index 0000000000..e2aa74e420 --- /dev/null +++ b/awx/ui_next/urls.py @@ -0,0 +1,11 @@ +from django.urls import re_path +from django.views.generic.base import TemplateView + + +class IndexView(TemplateView): + template_name = 'index_awx.html' + + +app_name = 'ui_next' + +urlpatterns = [re_path(r'^$', IndexView.as_view(), name='index')] diff --git a/awx/urls.py b/awx/urls.py index c99eda011c..605f549d23 100644 --- a/awx/urls.py +++ b/awx/urls.py @@ -9,6 +9,7 @@ from awx.main.views import handle_400, handle_403, handle_404, handle_500, handl urlpatterns = [ re_path(r'', include('awx.ui.urls', namespace='ui')), + re_path(r'^ui_next/.*', include('awx.ui_next.urls', namespace='ui_next')), re_path(r'^api/', include('awx.api.urls', namespace='api')), re_path(r'^sso/', include('awx.sso.urls', namespace='sso')), re_path(r'^sso/', include('social_django.urls', namespace='social')), From d1370868700e07096660f17b6a4466b1139fd590 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Thu, 9 Mar 2023 10:41:00 -0500 Subject: [PATCH 005/167] Adds UI bits for new UI_NEXT system setting --- .../MiscSystemDetail/MiscSystemDetail.js | 3 ++- .../MiscSystemDetail/MiscSystemDetail.test.js | 2 ++ .../MiscSystem/MiscSystemEdit/MiscSystemEdit.js | 4 +++- .../MiscSystemEdit/MiscSystemEdit.test.js | 1 + .../Setting/shared/data.allSettingOptions.json | 17 +++++++++++++++++ .../Setting/shared/data.allSettings.json | 3 ++- 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js index c3e1d04971..b7ed41969a 100644 --- a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js +++ b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js @@ -60,7 +60,8 @@ function MiscSystemDetail() { 'DEFAULT_EXECUTION_ENVIRONMENT', 'PROXY_IP_ALLOWED_LIST', 'AUTOMATION_ANALYTICS_LAST_GATHER', - 'AUTOMATION_ANALYTICS_LAST_ENTRIES' + 'AUTOMATION_ANALYTICS_LAST_ENTRIES', + 'UI_NEXT' ); const mergedData = {}; diff --git a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js index 0a15b3bdad..909fb6ad6d 100644 --- a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js +++ b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js @@ -43,6 +43,7 @@ describe('', () => { AUTOMATION_ANALYTICS_LAST_ENTRIES: '{"foo": "2021-11-24R06:35:15.179Z"}', AUTOMATION_ANALYTICS_GATHER_INTERVAL: 14400, + UI_NEXT: true, }, }); ExecutionEnvironmentsAPI.readDetail = jest.fn(); @@ -113,6 +114,7 @@ describe('', () => { assertVariableDetail(wrapper, 'Remote Host Headers', '[]'); assertVariableDetail(wrapper, 'Proxy IP Allowed List', '[]'); assertDetail(wrapper, 'Global default execution environment', 'Foo'); + assertDetail(wrapper, 'Enable Next Generation User Interface', 'On'); }); test('should render execution environment as not configured', async () => { diff --git a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemEdit/MiscSystemEdit.js b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemEdit/MiscSystemEdit.js index 4cb9604cb4..9f2bf48d09 100644 --- a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemEdit/MiscSystemEdit.js +++ b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemEdit/MiscSystemEdit.js @@ -52,7 +52,8 @@ function MiscSystemEdit() { 'REMOTE_HOST_HEADERS', 'TOWER_URL_BASE', 'DEFAULT_EXECUTION_ENVIRONMENT', - 'PROXY_IP_ALLOWED_LIST' + 'PROXY_IP_ALLOWED_LIST', + 'UI_NEXT' ); const mergedData = {}; @@ -222,6 +223,7 @@ function MiscSystemEdit() { type="number" isRequired /> + ', () => { diff --git a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json index 3eaf93eff0..029140287c 100644 --- a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json +++ b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json @@ -639,6 +639,15 @@ "unit": "seconds", "default": 14400 }, + "UI_NEXT": { + "type": "boolean", + "required": false, + "label": "Enable Next Generation User Interface", + "help_text": "Enable the next generation user interface.", + "category": "System", + "category_slug": "system", + "default": true + }, "SESSION_COOKIE_AGE": { "type": "integer", "required": true, @@ -4372,6 +4381,14 @@ "defined_in_file": false, "unit": "seconds" }, + "UI_NEXT": { + "type": "boolean", + "label": "Enable Next Generation User Interface", + "help_text": "Enable the next generation user interface.", + "category": "System", + "category_slug": "system", + "defined_in_file": false + }, "SESSION_COOKIE_AGE": { "type": "integer", "label": "Idle Time Force Log Out", diff --git a/awx/ui/src/screens/Setting/shared/data.allSettings.json b/awx/ui/src/screens/Setting/shared/data.allSettings.json index b2eaea2a12..171b2423e3 100644 --- a/awx/ui/src/screens/Setting/shared/data.allSettings.json +++ b/awx/ui/src/screens/Setting/shared/data.allSettings.json @@ -307,5 +307,6 @@ "instances":{"fields":["hostname"],"adj_list":[]} }, "DEFAULT_EXECUTION_ENVIRONMENT": 1, - "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": false + "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": false, + "UI_NEXT": false } From 229dbe0905f0c236655ac42001fafea9d8e72abd Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Tue, 14 Mar 2023 15:43:56 -0400 Subject: [PATCH 006/167] Add ui_next to /api/v2/config - Add ui_next to /api/v2/config - enable banner to show up for normal user since /api/v2/settings is only available to admin users --- awx/api/views/root.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 7211600a37..7b4eb8191e 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -272,6 +272,9 @@ class ApiV2ConfigView(APIView): pendo_state = settings.PENDO_TRACKING_STATE if settings.PENDO_TRACKING_STATE in ('off', 'anonymous', 'detailed') else 'off' + # Guarding against settings.UI_NEXT being set to a non-boolean value + ui_next_state = settings.UI_NEXT if settings.UI_NEXT in (True, False) else False + data = dict( time_zone=settings.TIME_ZONE, license_info=license_data, @@ -280,6 +283,7 @@ class ApiV2ConfigView(APIView): analytics_status=pendo_state, analytics_collectors=all_collectors(), become_methods=PRIVILEGE_ESCALATION_METHODS, + ui_next=ui_next_state, ) # If LDAP is enabled, user_ldap_fields will return a list of field From 41a4551c9157257dbbf89d13b7666597efee8a61 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Tue, 14 Mar 2023 17:18:18 -0400 Subject: [PATCH 007/167] Only show tech preview banner when config.ui_next is true. Use brandName variable in tech preview banner. --- awx/ui/src/screens/Dashboard/Dashboard.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/awx/ui/src/screens/Dashboard/Dashboard.js b/awx/ui/src/screens/Dashboard/Dashboard.js index 9ec35d7ba0..716aa322f4 100644 --- a/awx/ui/src/screens/Dashboard/Dashboard.js +++ b/awx/ui/src/screens/Dashboard/Dashboard.js @@ -12,6 +12,8 @@ import { } from '@patternfly/react-core'; import { InfoCircleIcon } from '@patternfly/react-icons'; +import { useConfig } from 'contexts/Config'; +import useBrandName from 'hooks/useBrandName'; import useRequest from 'hooks/useRequest'; import { DashboardAPI } from 'api'; import ScreenHeader from 'components/ScreenHeader'; @@ -42,6 +44,8 @@ const MainPageSection = styled(PageSection)` `; function Dashboard() { + const config = useConfig(); + const brandName = useBrandName(); const [activeTabId, setActiveTabId] = useState(0); const { @@ -71,15 +75,16 @@ function Dashboard() { } return ( <> - - -

- A tech preview of the new Ansible Automation - Platform user interface can be found{' '} - here. -

-
-
+ {config?.ui_next && ( + + +

+ A tech preview of the new {brandName} user + interface can be found here. +

+
+
+ )} Date: Tue, 14 Mar 2023 17:20:02 -0400 Subject: [PATCH 008/167] Fix use of brandName --- awx/ui/src/screens/Dashboard/Dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/src/screens/Dashboard/Dashboard.js b/awx/ui/src/screens/Dashboard/Dashboard.js index 716aa322f4..06c47ada10 100644 --- a/awx/ui/src/screens/Dashboard/Dashboard.js +++ b/awx/ui/src/screens/Dashboard/Dashboard.js @@ -79,7 +79,7 @@ function Dashboard() {

- A tech preview of the new {brandName} user + A tech preview of the new ${brandName} user interface can be found here.

From b75b098ee9cf1bc4c11629e3e5ec3d231d75e258 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Tue, 14 Mar 2023 22:42:43 -0400 Subject: [PATCH 009/167] throw 404 when UI_NEXT false --- awx/ui_next/urls.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/awx/ui_next/urls.py b/awx/ui_next/urls.py index e2aa74e420..5bf6d481da 100644 --- a/awx/ui_next/urls.py +++ b/awx/ui_next/urls.py @@ -1,3 +1,5 @@ +from django.conf import settings +from django.http import Http404 from django.urls import re_path from django.views.generic.base import TemplateView @@ -5,6 +7,12 @@ from django.views.generic.base import TemplateView class IndexView(TemplateView): template_name = 'index_awx.html' + def get_context_data(self, **kwargs): + if settings.UI_NEXT is False: + raise Http404() + + return super().get_context_data(**kwargs) + app_name = 'ui_next' From edbed92c95aa3dee00d9ff49d52068e46a643e13 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 15 Mar 2023 16:14:10 -0400 Subject: [PATCH 010/167] Refine UI_NEXT Makefile and update README --- Makefile | 7 +- awx/ui_next/Makefile | 203 ++++++++++++++++-------------------------- awx/ui_next/README.md | 12 ++- 3 files changed, 93 insertions(+), 129 deletions(-) diff --git a/Makefile b/Makefile index f4404e8809..9f428ce6d0 100644 --- a/Makefile +++ b/Makefile @@ -451,7 +451,7 @@ HEADLESS ?= no ifeq ($(HEADLESS), yes) dist/$(SDIST_TAR_FILE): else -dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE) awx/ui_next/build +dist/$(SDIST_TAR_FILE): $(UI_BUILD_FLAG_FILE) ui-next endif $(PYTHON) -m build -s ln -sf $(SDIST_TAR_FILE) dist/awx.tar.gz @@ -592,7 +592,7 @@ awx-kube-dev-build: Dockerfile.kube-dev -t $(DEV_DOCKER_TAG_BASE)/awx_kube_devel:$(COMPOSE_TAG) . ## Build awx image for deployment on Kubernetes environment. -awx-kube-build: Dockerfile awx/ui_next/src +awx-kube-build: Dockerfile DOCKER_BUILDKIT=1 docker build -f Dockerfile \ --build-arg VERSION=$(VERSION) \ --build-arg SETUPTOOLS_SCM_PRETEND_VERSION=$(VERSION) \ @@ -659,6 +659,9 @@ help/generate: help/%: @make -s help MAKEFILE_LIST="$*/Makefile" +help/ui-next: + @make -s help MAKEFILE_LIST="awx/ui_next/Makefile" + ## Display help for a specific target folder help/%/aliases: @make -s help/all MAKEFILE_LIST="$*/Makefile.aliases" diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index 6fed498d5f..bcbaf0f623 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -1,142 +1,97 @@ -## UI_NEXT_MKFILE_PATH: Path to this Makefile -UI_NEXT_MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +## UI_NEXT_DIR: Relative path to the directory containing this Makefile +UI_NEXT_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) -## UI_NEXT_DIR_ABS: Absolute path to the directory containing this Makefile -UI_NEXT_DIR_ABS := $(dir $(UI_NEXT_MKFILE_PATH)) - -## UI_NEXT_REL_DIR: Relative path to the directory containing this Makefile -# NOTE: UI_NEXT_REL_DIR swallowed the / because we want to be able to run `make src` from the ui_next dir -UI_NEXT_REL_DIR := $(subst $(CURDIR)/,, $(UI_NEXT_DIR_ABS)) - -## UI_NEXT_SRC_DIR: Path to the ui_next src directory -UI_NEXT_SRC_DIR := $(UI_NEXT_REL_DIR)src - -## UI_NEXT_BUILD_DIR: Path to the ui_next build directory -UI_NEXT_BUILD_DIR := $(UI_NEXT_REL_DIR)build - -## Path to your local clone of the UI_NEXT repo -# NOTE: This does not work with docker-compose development environment +# ## Path to your local clone of the UI_NEXT repo +# # NOTE: you will not be able to build within the docker-compose development environment if you use this option UI_NEXT_LOCAL ?= # Git repo and branch to the UI_NEXT repo -UI_NEXT_GIT_REPO_SSH ?= git@github.com:ansible/ansible-ui.git -UI_NEXT_GIT_REPO_HTTPS ?= https://github.com/ansible/ansible-ui.git +UI_NEXT_GIT_REPO ?= https://github.com/ansible/ansible-ui.git UI_NEXT_GIT_BRANCH ?= main -# awx-manage collect static require the awx/ui_next/build to exist -# therefore we have to commit the build directory to source control -# so that make docker-compose will be able to start up uwsgi -# UI_NEXT_BUILT_FILE is here so that we can use it as the non-phony build target -UI_NEXT_BUILT_FILE = $(UI_NEXT_REL_DIR).ui-built +.PHONY: ui-next +## Default build target of ui-next Makefile, builds ui-next/build +ui-next: ui-next/build -## Default target of this Makefile build the ui_next/build from source -ui-next: ui_next/build +.PHONY: ui-next/build +## Build ui-next/build +ui-next/build: $(UI_NEXT_DIR)/build -.PHONY: ui_next/clone-https -## Shallow clone the ui_next repo via https skip if UI_NEXT_GIT_REPO_HTTPS is undefined -ui_next/clone-https: - @if [ -z "$(UI_NEXT_GIT_REPO_HTTPS)" ]; then \ - echo "SKIP: ui_next/clone-https. UI_NEXT_GIT_REPO_HTTPS is not set."; \ - elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ - echo "SKIP: ui_next/clone-https. $(UI_NEXT_SRC_DIR) already exists."; \ +## Real target for ui-next. +$(UI_NEXT_DIR)/build: ui-next/src/build + @echo "=== Copying $(UI_NEXT_DIR)/src/build to $(UI_NEXT_DIR)/build ===" + @rm -rf $(UI_NEXT_DIR)/build + @cp -r $(UI_NEXT_DIR)/src/build $(UI_NEXT_DIR) + @echo "=== Done building $(UI_NEXT_DIR)/build ===" + +.PHONY: ui-next/src/build +## Build ui-next/src/build +ui-next/src/build: $(UI_NEXT_DIR)/src/build + +## Real target for ui-next/src/build. +$(UI_NEXT_DIR)/src/build: ui-next/src ui-next/src/webpack + @echo "=== Building ui_next ===" + @cd $(UI_NEXT_DIR)/src && npm run build:awx + +.PHONY: ui-next/src +ui-next/src: $(UI_NEXT_DIR)/src + +.PHONY: $(UI_NEXT_DIR)/src +## Real target for ui-next/src. +$(UI_NEXT_DIR)/src: + @echo "=== Setting up $(UI_NEXT_DIR)/src ===" + @if [ ! -z "$(UI_NEXT_LOCAL)" ]; then \ + if [ -d $(UI_NEXT_DIR)/src ]; then \ + if [ "$$(readlink $(UI_NEXT_DIR)/src)" = "$(UI_NEXT_LOCAL)" ]; then \ + echo "SKIP: ui-next/src. $(UI_NEXT_DIR)/src already linked to $(UI_NEXT_LOCAL)."; \ + else \ + echo "=== Linking $(UI_NEXT_DIR)/src to $(UI_NEXT_LOCAL) ==="; \ + rm -rf $(UI_NEXT_DIR)/src; \ + ln -s $(UI_NEXT_LOCAL) $(UI_NEXT_DIR)/src; \ + fi; \ + else \ + echo "=== Linking $(UI_NEXT_DIR)/src to $(UI_NEXT_LOCAL) ==="; \ + ln -s $(UI_NEXT_LOCAL) $(UI_NEXT_DIR)/src; \ + fi; \ + elif [ ! -z "$(UI_NEXT_GIT_REPO)" ]; then \ + if [ -d $(UI_NEXT_DIR)/src ]; then \ + GIT_REMOTE_ORIGIN=$$(cd $(UI_NEXT_DIR)/src && git remote get-url origin); \ + GIT_REMOTE_BRANCH=$$(cd $(UI_NEXT_DIR)/src && git rev-parse --abbrev-ref HEAD); \ + if [ "$$GIT_REMOTE_ORIGIN" = "$(UI_NEXT_GIT_REPO)" ] && [ "$$GIT_REMOTE_BRANCH" = "$(UI_NEXT_GIT_BRANCH)" ]; then \ + echo "=== Updating $(UI_NEXT_DIR)/src from $(UI_NEXT_GIT_BRANCH) of $(UI_NEXT_GIT_REPO) ==="; \ + git fetch && git pull; \ + else \ + echo "=== Cloning $(UI_NEXT_DIR)/src from $(UI_NEXT_GIT_BRANCH) of $(UI_NEXT_GIT_REPO) ==="; \ + rm -rf $(UI_NEXT_DIR)/src; \ + git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO) $(UI_NEXT_DIR)/src || true; \ + fi; \ + else \ + echo "=== Cloning $(UI_NEXT_DIR)/src from $(UI_NEXT_GIT_BRANCH) of $(UI_NEXT_GIT_REPO) ==="; \ + git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO) $(UI_NEXT_DIR)/src || true; \ + fi; \ else \ - git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO_HTTPS) $(UI_NEXT_SRC_DIR) || true; \ + echo "SKIP: ui-next/src. UI_NEXT_LOCAL and UI_NEXT_GIT_REPO are not set."; \ fi -.PHONY: ui_next/clone-ssh -## Shallow clone the ui_next repo via ssh. -ui_next/clone-ssh: - @if [ -z "$(UI_NEXT_GIT_REPO_SSH)" ]; then \ - echo "SKIP: ui_next/clone-ssh. UI_NEXT_GIT_REPO_SSH is not set."; \ - elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ - echo "SKIP: ui_next/clone-ssh. $(UI_NEXT_SRC_DIR) already exists."; \ - else \ - git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO_SSH) $(UI_NEXT_SRC_DIR) || true; \ - fi +.PHONY: ui-next/src/webpack +## Install webpack. +ui-next/src/webpack: $(UI_NEXT_DIR)/src/node_modules/webpack -.PHONY: ui_next/link-local -## Link to a existing local clone of ui_next repo. If method will not be able to build inside docker-compose environment -ui_next/link-local: - @if [ -z "$(UI_NEXT_LOCAL)" ]; then \ - echo "SKIP: ui_next/link-local. UI_NEXT_LOCAL is not set."; \ - elif [ -d $(UI_NEXT_SRC_DIR) ]; then \ - echo "SKIP: ui_next/link-local. $(UI_NEXT_SRC_DIR) already exists."; \ - else \ - ln -s $(UI_NEXT_LOCAL) $(UI_NEXT_SRC_DIR); \ - fi +## Real target for ui-next/src/webpack. +$(UI_NEXT_DIR)/src/node_modules/webpack: + @echo "=== Installing webpack ===" + @cd $(UI_NEXT_DIR)/src && npm install webpack -.PHONY: ui_next/src -## Try to link to a local clone of ui_next repo if it exist otherwise clone via ssh than https. -ui_next/src: - @if [ -d $(UI_NEXT_SRC_DIR) ]; then \ - echo "SKIP: ui_next. $(UI_NEXT_SRC_DIR) already exists."; \ - else \ - $(MAKE) ui_next/link-local ui_next/clone-ssh ui_next/clone-https; \ - fi - -## Alias for ui_next, will not run if ui_next/src already exist -$(UI_NEXT_SRC_DIR): - $(MAKE) ui_next/src - -## Alias for ui_next/build, will not run if ui_next/src/build already exist -$(UI_NEXT_SRC_DIR)/build: - $(MAKE) ui_next/src/build - -.PHONY: ui_next/build -## Build ui_next from source -ui_next/src/build: $(UI_NEXT_SRC_DIR) $(UI_NEXT_SRC_DIR)/node_modules/webpack - @cd $(UI_NEXT_SRC_DIR) && npm run build:awx - - -## Install webpack if does not exist. -ui_next/src/node_modules/webpack: $(UI_NEXT_SRC_DIR) - @if [ -d $(UI_NEXT_SRC_DIR)/node_modules/webpack ]; then \ - echo "SKIP: ui_next/src/node_modules/webpack. $(UI_NEXT_SRC_DIR)/node_modules/webpack already exists."; \ - else \ - cd $(UI_NEXT_SRC_DIR) && npm install webpack; \ - fi - -## Alias for ui_next/src/node_modules/webpack. will not run if webpack already exist -$(UI_NEXT_SRC_DIR)/node_modules/webpack: - $(MAKE) ui_next/src/node_modules/webpack - -## Copy ui_next/src/build to ui_next/build -ui_next/build: ui_next/clean/build - $(MAKE) $(UI_NEXT_SRC_DIR)/build - @mkdir $(UI_NEXT_DIR_ABS)build && \ - cp -r $(UI_NEXT_SRC_DIR)/build/awx $(UI_NEXT_DIR_ABS)build/awx &&\ - touch $(UI_NEXT_BUILT_FILE) - -## Alias for ui_next/build. Will not run if .ui-built file already exist -$(UI_NEXT_BUILT_FILE): - $(MAKE) ui_next/build - -## Alias for ui_next/build. -.PHONY: $(UI_NEXT_BUILD_DIR) -$(UI_NEXT_BUILD_DIR): - $(MAKE) ui_next/build - -.PHONY: $(UI_NEXT_REL_DIR)clean -## Alias for ui_next/clean. -$(UI_NEXT_REL_DIR)clean: - rm -rf $(UI_NEXT_SRC_DIR) - rm -rf $(UI_NEXT_BUILD_DIR) - -.PHONY: ui_next/clean +.PHONY: clean/ui-next ## Clean ui_next -ui_next/clean: ui_next/clean/build - rm -rf $(UI_NEXT_SRC_DIR) +clean/ui-next: clean/ui-next/build clean/ui-next/src -.PHONY: ui_next/clean/src +.PHONY: clean/ui-next/src ## Clean ui_next src -ui_next/clean/src: - rm -rf $(UI_NEXT_SRC_DIR) +clean/ui-next/src: + rm -rf $(UI_NEXT_DIR)/src -.PHONY: ui_next/clean/build +.PHONY: clean/ui-next/build ## Clean ui_next build -ui_next/clean/build: - rm -rf $(UI_NEXT_BUILD_DIR) - rm -rf $(UI_NEXT_BUILT_FILE) - -print-%: - @echo $($*) \ No newline at end of file +clean/ui-next/build: + rm -rf $(UI_NEXT_DIR)/build diff --git a/awx/ui_next/README.md b/awx/ui_next/README.md index 35c5beb7c2..77d719e050 100644 --- a/awx/ui_next/README.md +++ b/awx/ui_next/README.md @@ -5,13 +5,13 @@ ### via GIT ```bash -export UI_NEXT_GIT_BRANCH_REPO_HTTPS=https:// +export UI_NEXT_GIT_BRANCH_REPO=https:// ``` or ```bash -export UI_NEXT_GIT_BRANCH_REPO_SSH=git@ +export UI_NEXT_GIT_BRANCH_REPO=git@ ``` optionally set branch (default is main) @@ -29,5 +29,11 @@ export UI_NEXT_LOCAL = /path/to/your/ui_next ## Build ```bash -make ui_next/build +make ui-next +``` + +## Clean + +```bash +make clean/ui-next ``` From ae0d86868136ad82811352d6b2bc6ab55222b44f Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Thu, 16 Mar 2023 14:06:10 -0400 Subject: [PATCH 011/167] make dev-env test pass --- Makefile | 10 ++-------- tools/docker-compose/bootstrap_development.sh | 1 + 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 9f428ce6d0..e3d4d5c1f1 100644 --- a/Makefile +++ b/Makefile @@ -420,7 +420,7 @@ ui-devel: awx/ui/node_modules cp -r awx/ui/build/static/css/* /var/lib/awx/public/static/css; \ cp -r awx/ui/build/static/js/* /var/lib/awx/public/static/js; \ cp -r awx/ui/build/static/media/* /var/lib/awx/public/static/media; \ - fi + fi ui-devel-instrumented: awx/ui/node_modules $(NPM_BIN) --prefix awx/ui --loglevel warn run start-instrumented @@ -655,13 +655,7 @@ help/generate: { lastLine = $$0 }' $(MAKEFILE_LIST) | sort -u @printf "\n" -## Display help for a specific target folder -help/%: - @make -s help MAKEFILE_LIST="$*/Makefile" - +## Display help for ui-next targets help/ui-next: @make -s help MAKEFILE_LIST="awx/ui_next/Makefile" -## Display help for a specific target folder -help/%/aliases: - @make -s help/all MAKEFILE_LIST="$*/Makefile.aliases" diff --git a/tools/docker-compose/bootstrap_development.sh b/tools/docker-compose/bootstrap_development.sh index 1e5736f7b7..c049beeb23 100755 --- a/tools/docker-compose/bootstrap_development.sh +++ b/tools/docker-compose/bootstrap_development.sh @@ -25,6 +25,7 @@ fi # Make sure that the UI static file directory exists, Django complains otherwise. mkdir -p /awx_devel/awx/ui/build/static +mkdir -p /awx_devel/awx/ui_next/build/awx if output=$(awx-manage createsuperuser --noinput --username=admin --email=admin@localhost 2> /dev/null); then echo $output From 3636c5e95e64eee6dc6f31c6946c899e0f9f6ac3 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Thu, 16 Mar 2023 14:57:42 -0400 Subject: [PATCH 012/167] Adds missing mock for fetching the brand name --- awx/ui/src/screens/Dashboard/Dashboard.test.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/awx/ui/src/screens/Dashboard/Dashboard.test.js b/awx/ui/src/screens/Dashboard/Dashboard.test.js index 24fd37f744..dfc06ff604 100644 --- a/awx/ui/src/screens/Dashboard/Dashboard.test.js +++ b/awx/ui/src/screens/Dashboard/Dashboard.test.js @@ -1,9 +1,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; - -import { DashboardAPI } from 'api'; +import { DashboardAPI, RootAPI } from 'api'; import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; - import Dashboard from './Dashboard'; jest.mock('../../api'); @@ -15,6 +13,11 @@ describe('', () => { beforeEach(async () => { await act(async () => { DashboardAPI.read.mockResolvedValue({}); + RootAPI.readAssetVariables.mockResolvedValue({ + data: { + BRAND_NAME: 'AWX', + }, + }); graphRequest = DashboardAPI.readJobGraph; graphRequest.mockResolvedValue({}); pageWrapper = mountWithContexts(); From c30760aaa94114240559db1615bbb2b5dd985678 Mon Sep 17 00:00:00 2001 From: Kia Lam Date: Thu, 16 Mar 2023 14:13:37 -0700 Subject: [PATCH 013/167] Fix brandname in banner. --- awx/ui/src/screens/Dashboard/Dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/src/screens/Dashboard/Dashboard.js b/awx/ui/src/screens/Dashboard/Dashboard.js index 06c47ada10..716aa322f4 100644 --- a/awx/ui/src/screens/Dashboard/Dashboard.js +++ b/awx/ui/src/screens/Dashboard/Dashboard.js @@ -79,7 +79,7 @@ function Dashboard() {

- A tech preview of the new ${brandName} user + A tech preview of the new {brandName} user interface can be found here.

From 48a04bff5a9c0849eefbd5f359d49e36a8157729 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Thu, 16 Mar 2023 20:41:09 -0400 Subject: [PATCH 014/167] add new UI icons --- awx/ui/public/static/media/192.png | Bin 0 -> 19103 bytes awx/ui/public/static/media/256.png | Bin 0 -> 30521 bytes awx/ui/public/static/media/384.png | Bin 0 -> 57721 bytes awx/ui/public/static/media/512.png | Bin 0 -> 88884 bytes awx/ui/public/static/media/brand-logo.png | Bin 0 -> 7491 bytes awx/ui/public/static/media/brand-logo.svg | 232 +++++++++++++++++++ awx/ui/public/static/media/brand-logo192.png | Bin 0 -> 7854 bytes awx/ui/public/static/media/favicon.png | Bin 0 -> 3724 bytes awx/ui/public/static/media/favicon.svg | 232 +++++++++++++++++++ 9 files changed, 464 insertions(+) create mode 100644 awx/ui/public/static/media/192.png create mode 100644 awx/ui/public/static/media/256.png create mode 100644 awx/ui/public/static/media/384.png create mode 100644 awx/ui/public/static/media/512.png create mode 100644 awx/ui/public/static/media/brand-logo.png create mode 100644 awx/ui/public/static/media/brand-logo.svg create mode 100644 awx/ui/public/static/media/brand-logo192.png create mode 100644 awx/ui/public/static/media/favicon.png create mode 100644 awx/ui/public/static/media/favicon.svg diff --git a/awx/ui/public/static/media/192.png b/awx/ui/public/static/media/192.png new file mode 100644 index 0000000000000000000000000000000000000000..dd37dd9c035f3b737e1cae467de98ec3be678562 GIT binary patch literal 19103 zcmcGVbyFPQ)3+CQcUhd^^2Oa$`u z!2dUXbOcv^IuYFDm8B7mVbBT4z64B%)PB0)zbVQ}ecI3CNwO;d0Fc*{mlD_bv36ky zr?Ytc`0*`qL`kDlJ+V7*s63w*ns~5V`jCLg-;(zW&V;n>^#`WF0MfbYmR9quN0!!bB;g6s!NJl zcr*?HJGaJwKx`PON_656_yuTv5+a&k!sa@ald9<;?H)u@d_p`eKC#27#fH z)*7q1dZ2%hyWA=Pv+K3UPU=NL)t}^d_;Y|O|LFhZVr#(Et zcJGyAKdqvxmE*p7Hn@ffd-t{kC4q|@zcamM%yU_dICy$_Ur_7;2QY~ zAH(DY(;X`_$$|mM@MyC^5oawmf4#rMdCkrdvU1)P6sv&?Wb|)%>%L#`*uC(6og1=B ze-OS;PaHQ^9654WSBt#kz~i}Z#n~H>lJHG0!X#kC#t-AGe<^m$BQu-cwOz5j5xzId z04r34GMuHA#}|9!xVNSCW`007@hIP}6Z6QJIZ`ejl`DfZ8@W*bO5nikN|V6s5(QJD zJ>>m-FQ2(wAaqRY{tdBki(ClN(0+hrd`7XUGf-sxaG?p&NNu_2v5^y<$FGSHKzcw? zfexyT8rXQ}aT)xgj3^7F9a-cRkHqk-{KYraAwt|eK49X*?c0mRusJ%afisXpJYx&H zGQJfe+O(ZWct#JhBmIcuJ&V>*q}57Znn0t4=*pz$GYH$%BafLytzXgIZ7`Xau!hzc!Prq0-2NKm!rVHQ zRYuQZ^ME;SG$?IPF-Dq>6e|X33gAN_afu?bb%_2V z*^YXIPyTu}eYpofzIhn0@b-!Nc34r6#*w2M)4~oW4q=vl?&_lB6Yl%9>9U7VG@MSr zTke5e+N*RyoF_sQ*U!haZiS!)lX|0Hd2H4;j(l|`Z~KqEB4Mj2`;?xlR6^vuNR2P( zp{VO|38nVTPy-X2l;jV~Wts5Ki16#xJn-(0Bt$5}IDR(x0Pp6^Dx3X>wa854pc_#s z!>~2+jn>>?glWLC#N{-7LSwLwVntk6Ya_8hA8UEm^Lh(EUqJpQ5!drQLr;xKdOX8< z_G}i>{SB?;&cQ7`#9xyu+enynDnHkd6MCv9#oCTPMd)i?!E)}`*q|#dRI|Qg&<2H$ z;1&kFpsix|Fb907OiHXExOjDKl35Zp>x#c!sGyu(7)_zcHUIvUlfJ{9B&t^w#*2Z8 zl8zphV{Nr5Cm$8lMRmFez0=BZmYsD#ekJBBgf$>56ACaV#cQYqZ5k?o6Y!4GqJexc zU;ftfu&~gxsH>yBlbEN6eR{KyDA2?FTsT68(rir&2(0JZXc#0Ey{kirackCx=X3)Gx&y=lOF*K13G;i{``K|(Rv}B^3^qs3)APnW?h5r z`i!s-^%~7&*wSaWp^hTj`)^7T>+M1@>@wE$du`IR3%RicBn<*EyV#1PHCK_eVo#yp z@h33>jJGRZq7z!zCGo-=R@>+fZB5~Bp_bpDWZBzUwwaRWi@41nXUJ2)E#uCI<~BGu(1xvet_ zNy=&~fV7DcF8)?j2s#fk9ecT;5fhW;>)JNiK%0Wb#rqFa%!my4d=(?3cFV#uSUtW4 z&0ZXYbrj=N!OvJ+Wy7rOCePVhnNwaIqHn;0v%;xLzd<+w5fQM0RwCD7quj9mb6}*^ zVOsl~Ag~mFb6X_8d(B;Yz;XO3^;KefI{^Pu@ z&V9>2`NRKDsA@F=Xc193@eHDC8>sKz8UecHz zVyR6<^4s0-i4AoaQ4XDkUqSjwNwplxKDw; z(;p1w2nT?=AiTt-?$Q}MjYp_`rxrLHbnFH0Iw~r*o0*`hu-H=!E@jMSoCo?}e;YA4 zc%sXIQR?o4JWeFw2;$GVDX%i-;fSCrIBdXXfQC+kb-^OwD0rx(MJAKnV(BJkU1Ma|}AV{WXiL_hGlkTvV=7}*1Z1=f&1YH5EcfiFB z34P3XF8la{cdGl86Kntufk=wMS)h?p1`_RZt)d4E7bLr2Fe9jpL|4M-mVcsuCU!7|cceQ9H_|+Z-f!-`OaAKzzkn`jQ?eAo}+^WEk<; zu;_%-Rk%4lYsu6ANBZ~uMqdJYF9>2|NQB%g+!|6d>aV<(McY>;^^YC}THpIcSZx-3 zHFQbkUq@^n9y~S+#ZbI$dM7ab@|0dyvK;TJheY`YyVAGC+rbc~%u`virACIHcx015Vm<<|QK z4!%e)HYb-4+IBZ57vYlYhf{!@m(`Bowb#v!5^9_dPY^ettR4t93tiy#z}APBZt&W- zJ$DFWzl;{)BvN9HiJ=rE@&-xJwv`o;f=OF+)$DHA*=DQ?5f#SAO}^Wp*2bZmSev59 zlJLT_u&|`_nL=-Ldxh|W`6a`}OMeOC<_NH?!p*3b=FRKbfbV8;^6ytUf8&D;P~m*g z>tCTJXsrle{U>I|@L?Ap*PzUWajhWE<!>9WUg9EL=vcNjpBbYKGGB+fSEK3BgjWqX5v2f6&;htPzdY}6K?wp>=FQU$L zd%5cL2;fCsZdtgC4ZTHwJfkRZau9J-iBimi@uK|O=>r08ru!sHedx5L6;g`I{TkPZ z7nB`e9OBrc0rFq^iS{o3V*un9K6{^)FYVgLx5$|r>Xs`zKd5}URMFMX5U(Yk#}ml% zrHUV(XK__>wz#z2B>r-L4*2`U%}l=Tu?8jyYR5@}9`%9i+r6cWqiyRmh6gYFu(x|g zqG!DghOL@57>(-{yO{my>51KDfxcY54Bcm|FN+*TTHF`gT!&wb@)Ev;%}8u3>G03& zq?IFvG+nO`QXta_$n%nwp=gPHtbmGt!TV}WnrCfL%*ke6?0Qb!-K0PT2~bWk#n@WH z(W2xsScN7*ng(ERNh8|ykivXzFqP2Onw1ZiyLq0LFa)D$zeVXiBO)f}pjmBWk9ahN za_@J6mldguT%J5(`!Bu3F|F3&y;~ijNJK8st45zfRR4bY(=PvasRreYMPKZP72>PQ zDP6nUjZoy~rkJ>Rkg%hUK~hws>A$g8F;MGmQH6FTU}fvuNXHDt{l zUnT{bB5Ry#jvMu?&(<)Ztyz^EEoWSTOtEfNmE4aT&F7(0B41O{!M8=+!=nvruiWpy zKdN|8?808^H`_ur0#p448u-(p(tRd)gip|Z+g z>u)HFUYT_d=oThWlm9NKz=)M9C@AchI3g?otHtD1Ro~lX)_I&xcA)5mUB4y~r1wQW zL16<3#lyo`aLGPeQ33Ca7=dG`Xd&=d(19Fgs^#TQnF~Yf^ z43sGx^lsJAjEzOYbS)A3gpAw3Vjmte$tlWTx_BiB1GgY?f@qaNrmTi(WVC-9{oC^HqEO(X|?TF*)%b%j9T1M-U~ zz*Lp;fGT$U{!$MgaCHD9m-$lzj!jZim$Q!<#usjJbrXWK^{SR-?ou6{fJ;U7+(Z)= zCK5u+^blp$&XbQK#M2atK&21yQVZbA#fEx0f(IX!e@(z%z$$&jp_H~pC}8!TLCD#y zJyH((ZanS_(@{vhzS@q2ibc}M_x>IhLex^|5^*a=@hquYV*N%+!8!-iN`dFXZgn%V z*hfXn$mKf1HP+*akt;hS)+%dB-|b6;Tu$>%46&GdInc+*$jN&2JLG7Gb)~}t={$>2 z{YP02TCw6S-~blEqPfB!H&TYmTj2CcWb?ix zP^FG+v*P~Xw!q2bO|G5GoSeKm&C4tNZ8D(h=gx@6rwYkxMrI%IJKcAJ_b>r?p* zl(LIL<_B;&uy7wyV@!Y50htlq!yX!Pb|Yq{oXX-cvY(nUNEHxG-7J^S{p%gRdFqfJ z{vOYa@Z<;!qEfzYvO@Pinxrf)Vpa6G$i}0u;Y|YUVqQvAm~{>;o%(@So9$C#di^&A zX7Y`IRt0+GzBy~+bM;WyB*Y?bc~zYrfvc34^{it=4xUyR7??9YK&9Han}ujB+vRz+ zTDJ1n%7U7pY*CTek#Z|Snr&{bCD?+BdXbr4;*n_ua;q@MxbR#?`yd*CFYN`Ai5XeP z0yfc_YJ^0dJBa!hm7qx3++mZPqJK6Cbb#Or6>uiPG86u~uRqu6?*`HjArEFD>mrm> z@9zm@g2Z3#jbPS~RD#XW@vr-5P~TmeBT9tNO*!V$RztEWoy#px*N`?%5r`qZPcSAQ zmN2G|8}IejE`VaxN7Gr_aZ07LMJTi-6m(|NA&BS$G3dZ@O^m>5wLWNJ7B3%Npws;? zy_jUl^Gv5I47*(cbZcg8|AYbX*?oZx7#=RdJ%*HY4;xuZEJpeprL-)kKxNulL=*?CA8?gp|L1sf#9+K&iGtYVv z%4h9fO{4hkGO*bk=n)(eOtUN9DY_)f?jUEX!n0umOZ>uFaU&`tfGd8NLIc>jFIyV> zp(1JO;aCNKQ&2cmqUr#r(IQ`UeYgvC4Xgde1=~+;hSJ_*!;fq94A)qZ*;s;a{(uy` zH*sQebRZ^UKqVx8nJwsmZJsTN(q{}IYpqp+^^8C_Sy97d=FSSNl4m+O%tw>#Q8xX? z_IGZ2V8is#N_6R}%hrQp{({q+n(z6)ca<(osM2^jgyu~8U}q+7CoU`WP5Ty#jd|EF z{~98s6LafrV#s^zFi3US5#wmXCdyQ^b%8LJ+Gr8cKe3$rPiK~+AYWO?!%av5wj*wZ zvrHXU3(KH3R%FkZbb?*_XS+zVbvT#{Vm4F{5O@?%l_Y<5S+*ux&>}~g5*>LWylX;n z^cbxfCwq+t^SRkkbz4!pq>XDAZtnV63pO+yA?wL(BDR)CejMOK>6I@z2*I4K#Tyik z>Jz7Xe7&`5$J&8Aos+kX_Z1ZXXB;2_?hUC<&8=i`{iT-A#Y+(N(T%JtvPog-)Lu-2 zau^U`7&b<^J5#Po&Azk@^HG~4Zmf-PDsKqVtVTF%FZ`vN)#88{=dE0jrD=dj8^iC2XbayCDmEeHq7?AzMv{XOQ$UZ9u7rp-`|Bj9lNVA z-+5Zl1!d+!c}-|>h?(oGNr1tF)$36TQ5AvAA9p!_AmqZnfWbm4aZOD)W)_y+nKWaG zktVwO?~BMFZS4SV4>rxcOU9^&U7SPj{ACTSPTkhPlK+hUjAb-v&DR_MRgk31LVfGP zQ+1>tC7XK1u=%$tOqYOmugBS`emahoOFQvxL$REh#;e?xQf){GR_^;AW*Guv64Q^( zsTo|M1^IIS5K``4|}-Htn(z-3?Vs%u9;|tFnu+_l|#Aij`(z*vhamum*EisTWvOX)!Z! z`@jAeoBriy2o!dKb#rrLbpQ63a+Ft7JB&!2YGm2AusjYm*9thvwkBLgu6W&JkFUB4 zHh_(iJP`#M-)(ul?L@Eotu%K{{^|s;{nsm2Q>a*IfP#e^U-o#BfU{eRA-vW?12Ax3 z)*?HvEvg>Ue%E8HezC0=hU&+DP^tWQBI~%T!+8PYsH4CF1iCcXJ)W79MFPMa70Ke0 zZn#aO<<%5)9N{S#{hK~cA6GszqV;v%U+MVyiI7oHhyWe|4R^NrzpLPP!vWQ+I_D=8@*hHoNQ zfWG;X8g%}EI{K3VGnvUmslDV%Sa1!E{j@3tJl8D`63eWa{a?&8|`T}06 z5H=Zv71fEDy6$u~G`;u{pd&biu|zScD_n__A20;}u9h46opkoa3V|Nu%PJ;2FOc=wFPM_SP9)$hb@D$gFYS z8UE9e)S2mpvI_g1k(!Wb)F-79nzwmnxiVE zdnwtDVwW=qqZR*UP^Kss3l<@Xu0JDZV)uBzYiD{sVt4Jy%;{o774p^vbG@&GzI@Dvh3(*oo-KG(^hft*W1pVXb*V=$Ic@RByzj%auB~1 zb@5U>dg0^Z9ZAZoQrgxsuq4uNvW<+Mbi5MqCp9UQG(Id5s;D znk0dJu{;xqX}nIqBk!$R^>7yXvN8XhC_Fs%nKSQCW%R7*!Yt%n4;K=)|FGf|>U|@? zJv!bUWeht*?uiIYiZy}QPkXPdcTrcLJ5C4I!&TrC^;F+yy<14#>12P=55L2~I1QsG zt0Wbf>S^ZCNj*XDJtyxJj-gsaKhnkqZL0u7tLYvKii>r=|Gw^(fN3N1ynyO!<_+2G z1yWe#BWlIn2m9s0^)!-TA}+=Mg+|(qi=Vxg-FeWuC|OT`gneCaY;g54)eJ-f>b02- zBgXITPf(ToWVb{D%*^D)=g<&wjy->`Yq$xiCLLJLL(3_IQr9)~=3wb?!m2gufc|fG zP%P&b>M+K*#2}uSibUR$9(vnh)x?fQfHIfdD>naKxv^b&2x2o|ykx zNp#+r7B+nL3SEENWE&Eo^u?XR#4Ak_0p^se^G!xswVwM6#nb$Qs%wR5bxjEz zyTZ&eJcQc2Qtzx`Y)hDKMQ8qZn|%y&yP@L|X%Mpi#*)f;+)xPSC{rK!P*O6n)P@yr z=X}|=DA|HlBgW|aOnWe(>TzTHIOmeNvA92{_Nk(h1^tnQjIW7E zNe(a=z?bJz8RG*v$-0~W?YkpO#jA$+N&Du-1klaJTFjEwvpJIrz5dn4@2U7N)AbJj zV8`+g($CNVws`hF*;c~jy_PZk-pX@1>E8gOZq~LK8VVik*+l95G05o$t)A4d=LyEf zFfd;cBnDo_EFbRcHw7YL@FK*jC1d))-?U+7XxVSSjNjmB3(V9(xvE3pl}qJx3;=_9{!%wu|cBz2bK}Pp@?fLq>Jh zE|eKR;%dd|o`27p*!wC(U&7y_>H3=lmkXM|Fktv^?UA!JlzM9+M)ptrB>P<|kNFlf zAWEZ=gw(RjQa*)PTkSJHyrNl{d6| zzSu;S6BhiQ(qKeuM+Ms=HART}XkT+^Z0E5c>0ld7>=FRoXn@pNkp9VXj1vRNBq{=M8ywwV1o`sUZF3CnGORZzkduAg+C z4bgxK&r!X=4B3+M2_wew9F^n(qGwRqkIf=2G^g?`Qs%v`{yvEynqj>tw{I^=^vmBk zM6@tlIpAxM-XrxQNYRhSd&^#H5L;V0p?!&?@m+`x@=fTvxSJi!}1S+ z+Y>x9zbJQS3}oQl_q!70r-a{WI1 zlOxSw`NYpxK=)++xQs5?QG|5-p4z!+6@1|mX?3V4eJDk)b{guzrqvMMjb z`v3P|xEbe*UjjA)GJ~3n?fwGAXE=OZEEBd`Vf#L5Nhd$2zEsFPFeUN66ug++e9YRqiC9!k}7d@48zF|*0_@5B(waSDg%tfd> zj$gURFrv6q+}XxN?$gUeF~tuP7Qo!0$;;b7!m~#@6yI*d%WZNIM zU0s8tqp58-AV1M(3xLTx&u{C(AOjtcpM!BEAYCNFuhdNv<*2T{H^S1o4jSNzAfOMi zmwD&$E4Bt~d)Q$xP=2lV^bf$lp^AW*lu;d^IHk%p52Be{ngomhv`oK^8PAf{ZBtZf<|v zfTCyiR@p}U=g}IDchWYq8_>w3a@+BVhLl9kNZi8_&t)&wKy`b)lRv@~SCSK)ImN`p zoM|7t=ETaAB5O-_4p4JOr^ytVp{{QEJDDjlGoM{Se-`Co^HpXdh*xEcd3<*Y#Uk2M zWECs*4DZGUYCXXGZdaxvX&A}G54uL1Wkx75_(BCEpK&50;i1OaCH!POep#QMeou4*J7ygqG zei(Hf4e{DsnW|f87^CAVMvqWbhwrbMa=0E^iLt-Z5bztFC-RqjW(QD|B@(Y|$J~Zh z9mi=Ij3^n}`e3jlOX5|!iLiGwP#fIi1Cn7RG_~Hd$9AjDLthckiV~!!4oqxp0Rcor z;x_rf`Yjae7Wxb51J~Jmr0z=;eAGs5BP^yP_$L(;DjMaR?)Y~(cyL(Mvov4m@dnXKrc)MnQaq0eTuc9tM)W2^xrM}f2v zk;$LB?=h{ko9|cCQH6Ev3L*pIxfc&z8cwab#+GaD-Pc;;O*n@)-{(o9?M6TXNhz7@ z!f8TxcQPI}4DGWNAYHXd5Ws}j;e6MUgo1<_H+Z+=e7yq3>OJ`mQzi4GS145Kng8eB zthoTJ7$zS5ZRkoLjRpyq=)g}>GZI)Zk&6(+ou1cUQ=0P}f}vh18>0efp3Kp^UWx?L zG-9;BqweAMO@oyCH`|ULc1+M>L~&m&0hSo(mLqauc5J27wfumY)4NUY-w22r2l+U{ z#HYd*B7@>2CA(*!gyrnGkv4u z;*jQ1D=sYLs+{oZ3GX9_cJ5PA7bF_Fp~b2`-#y9XPxuh(dIr#=z%rUQd0O1l`CKPd zLW$wu`c0sVS>P=&sb(B}F9!F*QAb`i74|je{rd8aEgp+tcc97IA%Nu2T6o?0Gv0^I z-9jwNi)xkQ+!*o;RJcrcA5Lv&?ON)}e?^mtzLBk(aG=`6$PNbHy(~+pT3BE>!UP&T z=puP$20dlj`i?X5FE)1OjRSV}Xn#{_Q)OUW^)Kmy`{6N@Pn}EUNSzC#=qwZK%_^ z_W;pYg8Qf@sYOgA?~?A%$!x8IZ~0hW>8PsuW8zQ(vJIq2hk9Zv!!Lc#Z#Dbl(LMOl zZ;3oL!abDpU;DQ%FUiYSKKl1JjNipko^WECiiB3Uz6RK?xeUdbob;%3vFnQHb4)0( zQGB{9V!H)(jBx$N##do@|83c6C`xO%%$IE<0(e#J`2jXTe>`UJzK07S{svQ7Y`_)b z3;?g{fa~%C1(g3<@M1^>=PKjaE21tlmN8Pp1O_o$kFI0BmWe+nEplSs^4f(bAz+Bo z1IA>3{AX56Qy`OZM8ZoMFbO|)DGZoHV=)dETN3PXeIyyJ!6m>Ss6e|(z& z+*%=AE`Q|6<*$MsxRyjpV#P)i)>sbu^~nVeec~mfw$4?xXX#0g@ckQNa+H9TjHdle zohLXV(%N=@tp7ki&fAMC4kZDBQ?i6F3|XNpX|KK>rR)#V=1-5|Tz;JLg%kbIx4aHs zewIndlQe5BCWO@qGJ%ZH0O^@>!o=`17r+8`VqPp>F!9+6^yv(#LCM@$VpX|nPpNI7 zRsSMKu^7QQGYx=#Jti1l;TL^*M+xLMuiCLg21?8|vGCg}&G|A78%9)}fdv}3hJRwX zpu|?ACSpPq@PS0s520$5>Lc%D6x$dND)7YYQ$(b*dW9kdwEUrr!|*h}`1PZY_Dtx^ zG9{4W90po!50>qxOPHg<8W@LV5E-Z^&>X*ay;_jSR>Z?y%nu`3z$N@Pc`@AK1-ieh zV{S<8a~Bj8IBOY?9)N~8ykP4HD4`-0r{t#qc8H9&{XZXr11_OD9niko1FZ}uu zdeDNZ1~k?a4`2p;2FFt$Jl%{WsIjgt`+!%1V=45YQBpQ{H*fjQLg5=MfFyox@?b^2 zwDm{{=tmyDessKRvrwkx?&!4CSrhMc7WC5Akp|@BIE^nsG_<1<84XvO;MKkft*$~l zM#ac0hF4y2<`wThZz>_;P{0+pkQD7 zLo{1V<$=;Epk`*Y5l$azXbywrd)1JrC*^pM3AA*?QcQ&xX7;ZyYxF|tYtv-485s+9 zp~v&qF>UiJo{T9!YU1+ZLT^8j>G!VjkZrbsC3*1#fw`(V&T$&m{9H@|DsQ0;O;4`c z^Ua$VR2gdW(~2@4yidJ*YGm~L-t_*pKWy)penr_~Eb{r0t8S>5%aRD^4?55ADVf-? zf0MA3E3Nj1ul4quEh(EDEy>UM{~l(v{taU|#>H28{grE#n+pKID$mN3J=#Rx!$<`W z{=Rd2f#wE2ke$_) zM}P=+JXJ=UTOVd>nBaoX0tT;luh7o%MM1!B_V1CGzeU1h;))usgcAb;&$Qa&rpJ$dV_wO z#QEa5GThCf!9e3~yUgFymiwx=sbw5%l5yNHfrhdk0$(30R9Iho18|t*Z@#0kCo@-9 zYbN8p#a=;kLJJ1wdATO!avA_>6E{Ub?sOmor zUP2czORZ%KWF`!LpVv6x#hcdT*?dxFq7iPhXcR3*#Rg9UnRj%R0sVi7kxPz&X?bu` znmJz4X^k8<#4zfR2j0c3^2q$o#|hmP9v(m{20@c|X{FLoky+Z8$1^}qY*sf4z+5l* z8DMYm-`uwzrvMyqgR-A^Q}6W+biZUDWz9R)Leo8zGeIE3ZVv_L+v-Ggobkb6SDT5} zy_i^>9Kjxx4Qj9PjpS#K4D<98TF+!D4x?C6+BD~Ct$!r~IOhJt1n<4MfsCa46M2WF zI>28y;NEM`Sg%Vn$@NxGn49Id&hMWOF6IVmL^`+owK0@*mqrgbZ zX>SL;-T#T8J>UgCD?~*-v8_%CKt4D!7oG1y>ZoktdoB3{m-N{sqWn*3O&0U$2efuC zHpg09-XRlFq#`;+3TWPsBmDLdR|?C#tN)Q|Li^V@yhHeey<+_}`OLKm!8We7obpNi zO5Q_GDU?bP-)QuGi1!n!4))=c0trpg?Dp5Yav>^)IXJ3e_?@Ts5w>~K1qLgG@k>2M za&Ex=^*^0ejN_6z__rKXiiJ`9FJW-~Z3v!VjBQ|uie%@62VkzO+|_xsesKNBP-zkO zQ}AS4{4xSRXh^jX!4yOPZ)B7 zL0PHTJ9jhM<^XZl@9odLj6P7O(B|@N5{zdi8oyYdV~Lv`SrLs+C^XZ^ekZXpGla-o zl~&NdiE5G*-r2`=&zD(t9jT8(GPdPWJ-;{IFzx@tLG-+be_X@^Aj$#|FmWke;b`(8+w zjOsnogZ{!t!S`ohp)U?P(ZoL@sCt?| zME~5A0`n#4mdCJfc^!RD53tMnywU!L!SYjLRgaV%EL}YE_!7_F9$cdFHGW5Dj;`pv znRlloj|@*#KA$D?jU`?#z6s$nCw`uV?pHL{bXxvSx}|#rt9=ntl|acVyUE1;y61w9 zEgXP}=FL&bR!M2Y$>n|6d!f(x&wg2AR@PXV$atQR+%Zg{H&ca7)t!&SX= z95?0d1u<$5#QQeznLd9bhNUHMfs99y!9?sK^f@EsOVTo~2}f$#=WYO#2D7(Np#^@s zTtd@NPI=kWDE!{^ITyotO8)CPd5eEASd%y1e+ijAzqTW0@M_GI?Nm6+fd`4QOJRO2 ztJjzU%FXxe>*DbNNtqa>51^is-u^pYK!FA^#ygT{FnhOscxBKU92zfC>_3c(o3vCf zVF3lkfO#KKpOj(rNEa@*v_h80-pkj$3${5v*G@N02G++mB*5z2GAX!Ew64!@o$`c~ z-1xtNki~nAW)zUG@6{^>56i`3Tw}k2wwiaGSUs%uQtKtpwXER0cJyHayl^}*R7pJ9 z^6O~=V&Q$njkt zGlaQnb&gEHvCB1_s5-+s{y{bd8QDh$gZFpEl@5x`8^66v4d`3eO-GJrNjm+nC#Je< zi_P*aXxox1Xc9uqrjmQ4E1g1Q5`K2q&K6IeKU?d2qgD4u$o+WI0TiX6($>mgH(sls zHnEH{`=vQxvQH^V<*pRX7nPWCVes+ZVfpnCJ$PeNQBfL797Gdn3`M8!E)8ckSYq6DBjFSC*K_*AI@hSu}{8~S&{`1W4q2hsom zI@odtOKI;u0sI0xx{k23{hI9rM#Og#3oP>)qh}jtZ0aSiMe&kyrAR}4Qya@Bg)OFa zWsMVmVP8i@4U%p#VH!BCN;6fu0{`*G-<^!R5MR;%f|O)SgjE?|1#J?i^xW6Df4zRi z$6`z~Gm)(i7eJ1d1X>dicJU274d?O)anI4cmO3%2{Y-{YXNp_qOBJno~l!1CFNXyCh9@rTxHM`E8xMxQ*|v z+fsR3c~x72xVhdIMZy(qx@ou*?apuw0Soi%Ty6KjF^OhD3)?rJw&1cD zL{#pZE$E10UKf3mk~5hLzoiIGidf_Cnsh{M$|d!8)yaQ(b_On}XHzhw+6HS_St~UA z{MJSSlXu6b2Z{+oAEH{76V$9#$+*izw6NJ_kRbW|8lj~B4!)VZaq?9xl)8D})#Nns z9H3wMkBzid=_2~-0=?_I!Y!6X#Ojh%6(%OoQu*BYr6MbvudwtvXCuT|nLVCUD59 zEJBK$k+}YW(gQXlUM%it7Xq&LG@>|9-@<8CKAnpDQaEqds&vWlTV(nKt!oBqo41d= z_7BW1AGDl@0_|IErpSFrw!h5-sV?|T$)IUmly5rS|Oy2GVmT^~B=Qi80Sj zk#OK&1~aASch7GIuOVB&v1z}IrZJyHm_8#28NPC4FhCy&t@Pg+i^lEdng^HK(TH)@ z3Eo57ml>TD&}^y2f0rd1+aD@W`A4TI=CTEm_!jLyN7dtsDw`4znKj6gu=k<=bAi!=7pt;|O~!C2kv zTAeIl&bLH6o8ch`jCn_V0(iPa=4_Gp-g8zdH_;J%mKOno=Amn~8i@)EVcwn$b>fUn zThtU97U+!1OGQUyF12|Z9aE^;1JxQ+Mj~p`GI=>EP;GU_LBAq;18F%&6wvw_s^{)V zCy-9dt-KUCd$#7DSy@};#)wj<2yTlcDa<3B1MC14qnR;%zN_$y9I8jp_WL^wKFUQ~ zr!o5zWf=d#l-;49wAR;Sx->TJuFlgrJsuffPduqRnJ<5l%Md1$xxWnzM7P(OrM~qY zAIg)+IjSi7c34oOHZ8e^GlkZNAKmQphxCC8EvV-A&Cicy?86E~KyeD~u=z15Xd1@f zKOK0EPO?`9o>~}I`uT2WAViWnMT*uW8xBs-XJsEN5_W6SKu|HPglPWpT-NG6DyX{U zC-%p!ea1ILCE>2O`GRN|OYA!ML1;b0aX082w%wG#mC6>QVI-4-Wq{q1oc_Co|rRNY*Jo?qSwcZOJ+2LRLO*>bx*o1 zYdyon`U%p~_1rHEwU4*mELi1>@e_Tb-cSnYH<0&HD%qYISgZVsK&GAYPX%4q9Mf`Z z{^X|%XfHa`^4}!JHwA-NDQ+f?s=o*cFiIUkY&VXx+jVx>Ji=cuav5eXOVnR<@E)v| zsnW1DzX1<@i#gexET%`+Wxv^{FhL-m?V0K+7j6swx!#rkKI4P^Y=LI8y=EFMjhEXo zHJ(6#-6;jaCshCnFcj{@;mr2@SvMc0z{H9-J&SD68%>f?E`lytV%{B1z(NvkE!f|KSf zfJA*@p#Wbv%ksDv;U@q4 zjeQptQOJ_)+aQi3LSrW#42HRLp7T8SxzD|y@2B_6`+NT1|L^<%*C8isXQ^ff{$TD0 z?wSJzPaeo}OfjZSbY8=A32$Emq_|&o`6JYGJULDNo$-`lW2f}s zL+pCEA`;|Of;OiZ!iSx9u9qubM%CV{1Qk-2hW29Ed3LvQF0hqLAIWK2eC zbesxv;t-cRT_+GD9K1d~s@U*tV~pdA(b+VeSDkP6`#0R?Z45``;>SZ%e$72&5TG4g zPvBlNchyIsETMb`eNB;ePuv}13uJak2Qx@Dl=7daugMy0!n&L?CmSMUPSz6+F%FSG zf5P11uUx}g zPx|GjZ1xJ$`W^#SF5j7K5OfK=*S`lAii%(D-^BUqyenCXTM4PMI#*VNHwK#}V7p2> z&z^UmihWXunG_h1&GaS40b7$so9e^8{Hg)k z8}kk!`G)~G@*%YM)?!)7-d#hk-BBz~HgjZBgtuC@QuL3ks`pd}i)h!kjupkzf^H{j zr%SO4`5r>BYV`y(k_Hkvnk-!aM`=6TEc-ZI^1_<8Oy4g%56IJ^@TYci>uuy}55lBCM} zmu38VCRkFrDbcJI1k+Zdj`(@=_cd7{0=BOW&%23d?Ek7&kD%NU+1|CpsVG~w?=@ig zBE;TEed-pL=W_nYFygChdfKSX_LvwPG_X3r0QRywmZs9-0XR^|p%Cj`uP9fEW|$fc zFv0Xwb8GQ;u4~c_LAC$P-9tSoZc&xU(yz ztq7Rtc3nU7I%^4U$`OV!%sYC0k)VkKhQIZdnz_Y)NB2d0>a4gW?TlZTsk96te);qB zfeh0G7ut9{D92~J@+t^Y)EDz8H7_5$uojPx8Zx(G3i68bx)KD)BNRnALkPnm?W5ft@unJJPNU|qHock^P#g+W&CdqERXS#1u`muK71rl7&LY-5`(95=`%|>qjuYu# zsKs9Tn3$Sm>Pf5|P3*2^cVp|MqTg@qw~=n@jRCv-J#ng8E46;8!ooO|c@*&Y-p5I3 z$+<5Jy%#DJgWq+1y&?R)ypK1h&wv}C*Awjc%A;}1Z41Ldkcm?(?epTIQ<0oc9o;q} z@{;81ym|rnCYVE^q;%?- z8rfO3neCOX!LEE6H#h;}X+nsoiPo)Erk7t(qf(JR=jY>~DhnVpaCH$pd;p}`>uNVF za1=DMf&p8;Dho_`?l9cfZhFk2PDgS{YZ_mMa(F^XOSp9Q#t1!a8J29{v5kZJjeVoW zSgAhodlEf2+@zn4oU$j54(Og|O5t_2@mPLQyp8|XcQ*)(QnMah$-Z*XJD|5qeNZ8t zF)iy#EPq@N>|-1LD7IgLVW@!f&T!1A%xza&r{rezB^n&BxI4q|svL4yd&Je(3@;B{ zCZsNb6x2}O{7hU$>70^Iv-Ssgg}#!w0BJEnHANx&`PD)7F6JZW9{%SA?zzF2Ukl20 zx2-DwOc*TMK(D-?UM2z^9RdYbxv(d1wO$6VjT|@E z66Xb%F%?~bTq|DbP__4QKAU`CwKw;Prn|gO?K<4b<1_ET_0xX$KR^K5kX%N!tuigPFG>4Ng4f1mpMj@bRMvGUtP36a z(_|XL_LXF0`6qI2pZOBk18jvNMV3)kve9F)c+wR|Vx{ujQS>labsFO4lwI!Zx~P&`t>08A@EoT>pe)$YDTJ#AHeTmxztX<9meTpyw2|Jvh z*y(F8VSM{2z5mP9U|20E?B;1I}MSTk$?KLB5xhnMHW{{=L){sHn2 siK8q)@!tvrFJH`k0@~N_zZgvjTvPiW=7kmY#@{LyrZy(k#Tp|8Kix93_^1H;K{I>_bx;WMLFsB`n^0zwFkeCcKx5UgqF|p zsWF1l+&+o8Q{P#h=0H(=eBpq!gj$gV*5}`6?21-|DO2Hrr^Ey zFF5DUJE|1U!Zmo~eE(m-nLs@JSD&@AI;mf{ULCw(NnH0#DC`w?l zq`>ogO`c~!BC6Y*l=KY~c2E{;HB8Ma9oZInN)cTx@0nvvhkm(t;zz zgT&BQQV07fIes}c!3DX`Y2C_Em;D{Efd3A9|5i;1olWdYt4yF)P_uzgL3^Q-@WafN4b4Y`0@%YOv_P zkTBT^_4^K+?*IX2F=s2^otf`k?e_;d8EZifntJS3qe3jNUtJln$NTBMPat2c;d4L9rYGP@>*2CiHZ0M(2MRDXcoy&EC#6UQROD$5 z#wi|}DgctMV_v>`unfPE0e>D%+vZioG?39Xvch3i0j-hGolp!@*`RT@LE+hz zgp$#Y4CR$3*&@&DY4_htR^c|w(1CL@gAKBmy=Wz11vbL3e#Pns!9bu^e|MqSYqr5X zKXGHXx}pqxaZX`s15Rb=tmaequ>Y7!Fg_mU(xIt_7_bbQB_Vpz$Om=v=00$=M6P-C zJbW0r&w2R!q?u(1AWflyMlyEcIM07&7jnqD*#7Xv^tjETO#3C7mQoW@2<)joRB$4_ zl+b{=%aW`|$cFDK_tjvccUjw`J0+g6ImIO63eQ?j*jQaTxH{OnmGxDe7MwU2x&4-= zk#ogj0945g6_}|`RlpW|<&JG`l$~Jy-`q<9M$4X^)e-YtTZuSwYSl~fnmnh~tZCI! zg(0Xrmh&2T=L@n;gJVi~gscREkp>@QP_X0nkPNvJ#p&NNyBLDM1Vsj=nuM7ssx#q- znyWA}n6%x;spo8O1TD{&oh|Cqvkm&PU4Ky@IaOb^-VWK0wg|CEUr?yM&XV zwReiDHKg|7zQ_rNa{>R8*pM+)=IJUOL5m%u9Z*QdvuDZVZ;UG|DpyGfhm1MYn=kPG z?W;<;Z1q%MB1zi(O!95Gd+2=r*M8a7XUC~YtAh_Z8T{>WcIHK7uNWUbZl0#8_)&|@ zGqP_bxVMg*rPmOn^VtQw7>ZUqe>i$%QJcOiB$a!Rphr^gZ7F1x{gAb)z<*KSmebEo z9iHlU(=hind6-LnVUE!G(4JWV9Vbrby7}HJH<6WS1;-lr8ocCM_U!Ta7Moit92@)m zZ+Fw@Op^wfSD@LW`hf#xfa9D}LEu>_&Jd=rZ?&XwcomB)-{G?R3h~0e_x*ZWq9?peDN8C*=D|u&~5V7^A>!h{UV!!A$ zmEfMZdOs?f*Q(Y~SZuDMjjYSG2}9XiJ*#7Y zB&(dpfgmHMdd*+^U}D$1LRP5{Q8WB}(oTt3j4pyTQUBo*lJSm4i2Dw{&1;1~PTT5C z3-LwlBS3j&Cv2W$)BqeNh5uqBB`!5RU!LRvau@q0V)IkpZL8})9|Fk&cTI(V)KJ4= zz0mTRe+pB@PL@F#nmkme!#8EF#Mg^S{f?o~>O%6%7F{1wD}tJl})X{04n)LQV4;eN%0BRzoPW_>7^I< zI7koFeljkX+l`p*Cs|9;(Xn*9eXDt$k!rKCvOQc@&rv!M6aC>3-tO_hnTF%X{;G7@ z#~20Y2M*{Y^;=6{ZPmE}nwn`U`)qB)vtL|`{j9~yh4qtdY#bgsZ6ea0zpZG@!2#uRf zK8LYp=Hm$cWfJwY^8Ob0Qq9vqL+aTuO*^R+>ppBMG|&pdCt652L^Wja?frciXf}D$ zRp*@}PWlBL?n)Tm;~isu5vUKXgZGgsn8Q)LJjUgm3l&IJKIb)jDtFYW?O-AwbTdAwy>+VN@j%9o) zI&*hsVM#+IZt)C{cB((o+?x1!zuQO$<(Q>BoVV=_Kg*ZogZ|Cm&StYe&y=Py2SA*I zbk<^B0ysfNd{`>%6rfTa^w3!rq}~i|DHB*@WmExr;>eV4m#VmwxWBtE&vPAZY+`@@ zPqTX)74b!`a>8-6&j4DeyRxaA^Sp4$aN*Ua5Gn^p+=IRWfs_u-)dsgN}INofvzCho_%XzhY-{>Ss!WV_c z!qWz(Xw&g$B@{V;oKkU;e3k_y*FSkiX$TKHy3Orhsui`qg?j0P1 z!T-@RihenYYs=)v|9Wg+KD8RQ22k-*qxgE_=rn(SJ#$ zq@K%iQ+d_kuB$WZm;G*k|FjIe*)$gB!CJk&J-EXH`^&q3P6C{^5&p5~Aqi?pQF(Jd zn&7K#I7`3z^V|w+x8=Yie*(q^J%AO?*5HRH@P%w(cnU6Sk$p6BR2=pwR$wCZL$4ZG zg(a&Vhy$nB)DFn%Q)X!^!49ifd)(FQ)$~B(Tbt*vd(fGY_;AtrHS_3MU0gh-L_ztv z`xhe~qV<+PXF>ylG|qkP#Rn+qt_egtJG_Zpdsf}7oL6jN)VN#abP*7zQ%_|PyZ2U4 z*(WR1nJWldcIa)`GTsDb-X0J6_AahxQ@TL8zngsgsS!Ii?rSrH$=pn|o(hOBROBq| zCTb)86PyT8GfD)=9`J=K3bnyXYB0-->fG&1n9^^QdBP2!#WJ2UI-e!YDal z$sZPydq|s1ud=$jUj_w~>6cKM&<6QTvnHiXy7c_oYdu=H%~>t&|MJkg?HH5j#d`n4 zMoX9Izy=iKb3`un7Bo@j!pSgz!KZv3nalj?aW+P|w^Qn}*Nu}MIeznnB2A{77bPH# z2*c9P6XwNN^@Ixan65>;)RDc2vS#opa|I^s50o~r{h%fb)9Yn-?(PW z<0VUiBI6i#et!*n2T6oR@a4%dJmM6_k)~9(C$#d7b+|$C$WRwvbS{ng8yvMuUM5cY z2q}tXe9GY?I6K5miwGhJ^C+c0XPW5=>F#5qLW9T~`W4mT9Ar0_eOi6(3+O`eXPC?A z_$$F6$uG|^8kGFHz%~wach|3=%^~DXqQ}h*c4X_`)=@_BR&X-@BHt3p50xXZaLG*w z{6~ose^-yk#+6=q>Rzlvi}0?X(-|Vb+V%$K3+uf3zjSgpzi^HKx{ncIFCAN3qbX`W zn^<^f!aZC7Uz9jX+k3m=gXJu2$;0v*b3pkJ8C7F2GTzw|5-d?)NGnVq{%zG-JnL*T zvglGWb&~)G66}F;w97aBzzCvzB4u)JSEoXhya56kJq3Vn$tbG*eoAdb3zeq@g^_#R zu{q9_naY7eeA8qn6%^#V1-Yxgs_2vsEHO+cZ*A2dr7o#pJd0#rzb`Bm6ce)b1%GPT zh-W_+JsUFIgtFo0q9yj2HzBLkl0M7siHp7+FTGIq$j04tjiEqUfepw*w@0+1Nq88B zzx?|JI9L`_IY}CFL^pc>}>8g$bTrwtL>PrXatg(ixS8fsI+R)?gu$JA)UynjLz45Z+ajzw#q*+ z!k5)gGdh<8chV8<08;!=IB7&r=>qacPZ|28y@Gl39|oWDb>eIuvurWlX2N>UhU#3L zRPXI4)b6oUUXe4`@GfW&tUzig5p>+a8y&B#3AJU zhOTd^B7ic~Kq20!l*Aghpe72^tNJMCTe8jlVYgxZW&+e7r_jFs4TfjsQ3m4>yhal5wd}_H zysMv~?pqkrh7~)svWiiD9dr}bNRSkossOenf7oY4^Ds|B|2&7U&s$9&3$DYWLx?^8 zg%l^12yo$u_hOAlYl-@3LT0u^m~&FZFi1n~^UY2?5i}16OZwKp!u+;}(n-XGCD?%i zoZ7g6Pnt?HC!bm?nvQ!p_j$x@nGMVBAl<6TCUW`V0&cm!-m3pkPQIln%0rlN_+S;c z0WJ}%WIX)&v_0>BR2x=c-4jj83r0;KkE%K_hbi=S(G#<>!-UO38p3?c735kIW$7>C*^ z#X_?B#6oi5i798Tr?cV!X07m22Fii)8LTrL9G!K%4)zVDAv`UByH%KUWKE!e%?JRBd6Ty{e-CC z;@A8j^IN?OMNnLim7;Ge#64LfNULAf=IM!bl?o@X3Wz=S`T%6Dy!g=_rV;;S8ERHm zT0f_)iwu}KJfH9SXn=rmzr0oFp+`uxIEdP{)(IvT|B1;onbX_2!vM?4L|w|rP>Ytt z4@NL-k+M+(1L08dv*y*dN=K>RSP`Pb>*i+jT%?Reo{^RvF5|Kb z1K{L|%oIz5Ewx_lKbh-HmQ6=$_)`@4CCEdoQ1dx9*Q#QT8y_Xo3tj9Hp;md7R8HBe zNVgMc;k`MhJ!{jb1=KX=2UF%)I5?;w5)v1K(b#ns5AOH7&-%kEs4n1=i z7Vpp^q(j?LA~T5@?fPXT*`#C+#(sz%!Jq<%Cz9Ku`YG&r{y4)h9}E5Y<9j-SUjZoy z3(m*nmqd9NLc^+foo}!Kb7LatNWg(HE>igLDlYr4c6e5^m83p2-Hdp~{2@>yS(JOS zTtW3?Gy~&Vo_Eb*uqj>7^_^4B4mfb!Ao=l?To!C5o5vPFLIJ1PeE_#-aFZXjwyf4I z0dF@`M#bZzhS^;Me{=i?2@D3;wKPWPH`?^3umnTYgUIpTJ|VadDa)F6iCWzrPHKeh zAj&s>rhNCiJerRAYQuG+J8Xt@R#-bASk~Aof(?^MF0b27d1O%2c|e-OnEFFnumGGL zog?CCB6bfvZGYn2u*~EZT@R_XB1@q5+tBEb5j_ zsHbNbIbGP2St)}P!_U`O;;-!2JinWxFUW|pGQAm%ws`{lNU;}IlLyOaGs_uL>#_4{ zSJxR>C*uAXTz+?K&LHZzy!*!q!UmvB8oN}a+}(^oPos|CNCNM*jVgtOu489HYxK@b z8=yGCNS3kP`cT~LTVj(I-1mqWm1oI)M)8ZN*xK;z$kMk@A}__J%7-tKLN38doZ~3< zQ2&O?yb8 zx@DPmp%9Pj0=mWCWEe}ZQRJNM$i>dI)cxfE3XzZ%7LW886uAI9sdp-0YIAg+1>jS$ z|2uP1h$oyiyZ}wSTaU=&n9u4FA(an}3TP#w^T+t!{}316XIiCFy=eQTip+>~{li9Ixq@OMaD94I+O{~!6m;bCtm0vaX9 z?gzY}gp!W0+(m|hlD)rc^^;8>?@@N>*xA8X>PK}K?S+#l&_@uth*fnz9%B)d3I}rg z?tLmX4Ud{7)g^svFG=3>8Q4MO+TWYB{qtwus5M`4^hKde3Z5p2z!ceECqS=>0IP5$b%7mj}d1^|y zMSk&j2*fwoEm!tLF<;o3>_D*a`tJvIt$`PG+i+i;QI>0hWGKYaB@TDHS*v&PHyQ`k|JbF!iew;^$ zs~poB^U0Ghe>Z(10NZ_4F@U4IfSA&^z^j*XHMyD&ybHsK(Yaqu4=iDPc$H`JtKcI^ z(>NW@8gIG7w&^u}#1Pg{@2^+7J8){|GnD*N<)Al=Sa?>FJs{HMImIyxVzw-^Qu%+; zAfYBlv}yRl&EvK9&C5b0Cpi<;oa=A&%FJ{C94RR&y*8&0cqJtgzpH$!-EQGJp??ioV^@NWP^vC*s;n<1>nW@s}CgSzu*(ok= zScdXwk_=yip#|LH^~t7NuVMG;5Wt*ZdiQSSzGnCii1Q2|ZZTt7VG{KIyM80VhD-Pr z!%w>m@evDN!*r&L-Z_zl%!TS|#(@U9?oGj*F!yP$f4M5b!O8wwH*$%eA7Ye2ZWf1- z=omMf(n^cmKp9#}t?lyqp6|8#iuVPMhO*Qfsj>W!*Huy72GiCSACFy}iF-pC z2^R=NmVd!{WR-R1J;xRpRT88(*~6QNwuPk>)6LZwlO!i6D|Bz2WzAKB$bAwp{&kFEe>b>iCo%H-yoMI~b*BUwBmu(WSKg`}3?yN%yRU8%~b^{3#Jf zt1i;4)}+yhKaVxh5M3ISTuKoy4Y6$ZdXG*%!coI1P<45ty4mB=qI-nAlNeNsCP-et zi?;ICr}`z)j^@fV*nz{waQOJvHuxRSow8qv`!;*SC`s1fsi8cM45^PS&zH%Ya3_xj z=^$yk-c+w~I>v0GYdE0CeI5vcreaM79c6q)rR$-UqcdRs@y^g_uTDMh^8!dYD8=+x z70?O(M1!#vVE}eInI*yz!%rW8u-145FZU6M-p2|S(4rj|g()(qA~Y-#26pr5vTKl} z#tMz_?3pBG3w1fA5>tR%DShg#mq{Ea_L((+qXrz2rGK!47hUFyw13rc^O0a|cb;v) z&?<*Km@;VLa(-T5WgH%cK7$P}l3PN@^V}HQ?kllCM(q-dR1gUWk}jjj)eG8g4=fc! z(2~9ZuOJkyF3by~%N4H9agZLKU-Cb-ba?p)h~v_4@q96;=>;iA=G&*xhYirn+txeM z`Ox$|4AGMlfo9hf2i!f59H}Vf-+PysZEhZHn7(N_q;d)T{kZ8`3|!C7+&WyTOD4kO zhIiLcqeb-1$KXAhx?VRoRwBZ7$~r>Zpp!{v_OgzKa8Mj~AKBf=Zw28V7}oF@F1j;)-}ObMF^4}V1Ew22!tA07r9a!B@UfcXTc>N^je zzCMN*>23dOCj2E4&(GU#bT#6)tf#)2$|t_u?^yD~p?NFsOKp*{b`hDOq-TSJ^g_f; z5BTn?10sTdrLUJT+Emrs1^vX$dG*ZCoLONBo;aG%&#lE=?eI#Of3+<*%w3m2_Z`!f zRQD6YGkHRDm;J)d2J%~7K{|WSss)>Nf(TW~!YrS>d#3R}Mew(Id=s0uXR9Tmg(725jFxCr8k|rk*$?pkcRDqkNb7*By@diE~g&^Vz5m z@RQ&GrQBzwt@P{FV$3koMg*l2Z_alydGNX*lOw`0sdeRC-NuGPWMsB}BRaMI^3pmfd|qp%F>s*@0!X zd!37J`eL`^ZCc3METTuf!lC1z$DCU8LeqGAhZ0eja>FEg zR`Lls{X1#RZu^FkE*vmQAj57Nn{D%Kjm&BHDQ#cutw_WN09tlL;MZr1eII{|+H?u8k1c{EhMN$RZ;5JVBoH zFzko_r{YG{KuDTJfhtER$HlTOJp;J^q=WT6eG{p@^g4vs(yu2pq-I>4V!FASXTSuh zLph6EF=QL=>f4x%E?DI2kyKtbyV6ZdNcFcsy>eIIweU(=uau$iB}MQ2T^Q#g{Fkgh zkw@C=CJ)+LT6qZxm?vv5_^XSJ2uc1=k`1X;Cr4(W#>b!iWt+e2=K4uph(0t6&Xa{wHCqlihD%d)XIVn} z>I~GQ@)pU6-7ss~g>j0R3~9ouxC#s=-NgYYj6G0omtSu2`8vw^7Hp%ozU3xSZ=DB` zE46AGqK*dZ8WUoGJi@+m7n-};Vcz!_@fL0UEtkh?K?j>RXQO$ZuvZ zcO*=7Zi!kc=ZPRFF>;K{DEc2Sz%kLND~Ak_UvpaQnY{6QU8`Ts{H=|*5-Op|d*EUT zhudjfZ0f(*4`2AhZKVfm!Rs9KPm+u(s809Ht91whTm{#@K@$NX;uXaTXmL9?1vWw|i(t5pG0;cgT&zEbvel6^U~MEOVk-Ap^2g!Fg|aHk~PH!sG1vBo1VfJK46K^>C) z1uaa`^0ANNfST;;6O0|BK_w0af41#k#3%EG^_VR_gGr(0N?i_G$*;8I3dTDXBl3CKPOrfwq35cl-5jwE5Wu?>zz1b(fw%y_ zKRXdrMJo^5U?)E4iS%d~>GJ7&#a=@r_c}r@pNL4&Rh`1Q7Z!q>aeW3OwBJeU?B~E{ z^um<8C(zMtPwNjyR5#BuG%vj806!~Tku!LlK0jOCJ8uOn67zpZqL-CwYC-$yJrnu+ z)Bu`R%$Kw1Y-Z*9IXxmaJ9?n*YK*Qf*T&9IDaZ0Q(C0#9K$FF662tiwu-CXX%_c1({h*l&aTJEI5 z!D03*6J_oDW5iz~948pST`EpPxGeu{xed7Yl|_F3*u?)V!T|bRjc0*zrM0V1Y#2GY zBwi_AMX`oYAR`Q54i@UlwY3Z#RNM|5gx`-aTu~);D4ln$&~(O@W^um4jY~~{G2WUE zw{x2Md^uCSIiox(H0|c`R&AMWZ^3_Pa%C-$T2nTZ!9{`6zpbhhy(vp$(M;>if8*S( z9pvze*ZtUD8DnQ(mBz@YcS1r!{px&ZX3H}c7Vfn!qwZGNf+jN0ozz@^RFL2b^yYJg zK1X3vx$YUsJFg`w|0@1)|3K1G*GI%B@cGzl*!_64V$U6yP~vi}9ro=TcqDbT5HC@Y{m$`%98}@zhblLT+Rgc;)~?y7&kM>V`I6>H+fUW z4Nu(4Vz`a0ExE5#k)aOJWGR?-H~?eg(6~9wlCBCnhP2dp4^_2wKDFc7;kJ=n>z0&OY>}-XuaC3g-r%=37*b*%hLj z*yti#LkOskb$FNd_e*r!1)1-WwQk2y8N`d2zr z#UyZPhxEbg`^mvpA8Duh-*9ldldKK!Ip7SPrP6u517S`_6G5?21q%lcfN^^}1%13o zNzOx!b@*B_m8XMmS7wAicf0_2ksX~Xk6;$~z!RQhbA+{HMM)Ofbw3caa6m248~I7p zELe$>1nGyJye)043oD!aS0$~$ftO(w};2SE%*v2Ez?_ z=`7N5?bJIncYI#jRF?kA%<)dmkcxtMggWmol4JSzc@_n7mlq z3Uv7ZzRSSfI~Rzr5@w<7iG#bG91#T@_ZnqBGzkg!w}^{4GN->Sg++!Xm+VZ5Jiq7L zBNYkdz0VO5{O`tMEn+uo#cLsI!NGQF-Q;m~-p31I3<@FS$sCc$+{qk^=6kIuj=TAk zoq}s4Mo6hnrO=#q4F=m(Fuy|q98Raug-jaX0kuzegZHNA4ZJINJ1jK=*5P9DQ8dj9 z55^*4Rc9aIt@jYo?lD4Xd-$#!NE!fo(P@2_z@c!_gr1B4hmk04ls+#-8%yHz#Jx^F zIB5qziq~<@&#^co(kD^*HOhPq1&6HJ5mllaN93@!urEQ@ey2cDJNRANVUi293k7ka zar9k#7K$#(D1zMRs)R-O?2+szB6id5?S2!Uyhb|rG70$-bNO9|*nXW`>QStK!4t=P zjaB)4X(wT`0F|iniG(=+_{N|bnaXCEy7$K(U~4V`l%KX99{fYf??T#SH@)4Q=qLC= ztF~Yu)F;S7S?^;XZu}S*A%(*_fcx^&sx)yI&mY#p-<`^{IEi7CfvRAcl;vg?1PBnV zAN~wLX33G|$aHg>(Oc9qa$*FtPQ+*odo*9Ii3i-x8(B5Q$mn|?o$)Ye zhccC?_=9+?3_dH8MOhI(Z9KD-eoG~WM*OVT|WbQmTVioodyHwM^I%0#?iMQ~Z~Kv`cGQ>)Zri=ZL_ zQ;M*nv%lT46cvkv345RQ)S34$UT0sSKv0Owwcu_0WjU*J(~B>}_7*>BcnC#|yln`s zrQx$D!sTjHQnuErqCTF&acw;{;`;w;TCWRK;8=`BZTFQ_E%}+n;1M<9ljJHfvnEu| z;FPQIgcb4UC3T)sn$!ElT0;%p2`3*5TkY9Qy$N@o!ipM&G!{&7CuiY`FW&Pb)@cT} z`#^Bi4H(LLustQCudM)J*#Vi+&;XRpZ}71p4w-d$e@8TJj!GTSc;T9i8t)S-St0Tn zp>wwcFkTN(kGS{N!s*K9{-3*ukA}3#sI-m2Yopej&ZAbGTwE4X0%I7@OcJM=^F0cs zK&2DQ-!uNX7I)B9d`i=7JmW5+UC_JQkuIETckSau6w|}w$F)W2?e`3-*{J}9o_INj z)Atz)K4mmn6!W`3%GY7@mYwER#fAN-57E@LeK+P$}!vlhn&z z7hZw)%eVjc1N_!-MaIRyt{bN8SzS@g-w~qw@`l4WJ4> z_LBF$f+k0@=~Hs@vtt*1_@H)wdM8N+2&%QaDZ=rJ|NW?Z zhjDz&oMk8$^(y~o8J2>T$~z~F zY+T_t<}gvmGZioo%XsT@isoicXJe&U|KK&0XWC`UtNEB5tR`B29(^GV>LmGCWhvxE-e*9W z{ojo|lq-HWlcK4|wtws9ZkD`^h*Q{Cxg{549Vo}jHrJz+2RXa#-{_3RPJ)0wI*M$2Tx(MvB7b$_QTz{Y% z`8%m1!NG{!ci~334QgtKt_9-*lkL7n>CH(U)6svqe`y3O{!cPDzi9T61%dusDtHZ| zd6gi~;WJkgXwSr{+|Rbyj8vp`A;riDedZ;hoLD8$VANh5!n-11N3b^#qJhiIR>k#j zFP(_&`=z>hrw|C_+yjTe!?borhGn@C9f3XN~&Bp$}D29f%@9)PF{=YuZz5$-oyeufzq*@V@x5^e%w(Zxrp;7``-kF|sW z!0yeM+<+(I#}nU+diA<FIS;Y5`qz4t)8ixV4$&jyy4rt4Op<Tc0Za6dl|Ho zcbtuBg^P$vfb!5Guou#CIxeufeewcGktzR(XmMFiQLFC+UYhAHiiqO3 z|6$4Q5~fkfk5A%;s#x1#x2;ctJQgb)N}J1k;wwfRWA?m4S{0VQQ;q6WWu0e@8KqZZ13 z1qHtanX&x<;7$xp%{I}25fU}9YPSOd@G5_mj&{T%Z$gx&SV9_N-JgX^??Q^h=;R^U z<{R56ZhyB?hR1$e(2Y@?`EcM_u;7C*;@FL>=F=Odw~LdiYLL=|nnG&ZGI~SJK7Q8r zn!MJe1X9II9FEe3(P=m^Ck?`TSV)HJ0lX0efO<0{kicWDVd^_N4$SLNBr@S-6_5h& z+381qC=4$HAHq`SzCX~=3TUFKJs9|J7!~iwQHlPt)NPt&zS$cUO5TUBis{Wb^6R8dqeZt+!(}p_+I}lW`;uCTe}HW0C=I5mqKoWHHWRI#L}C7sEiv@ zidYxhGe_X3)S8idK8qO})Or2f#LQ?$=vv|}zQ7~Rpw*U*wo_{~#*C!@bkUltKSa5< z9HWe_(Bd6YbrAyN=fH5+tqMKXl!FB5I_eRfjo&_K*NA#^q5+a}P04{+f@-?Pz8L^t zr>&K6wMEVn7S=BwP%!Ree{EEY#PZ*EHEKoQAWm3;t&QZ_$-~J@Az0E%y*}wUtq~|+ zCOB)ewzn9Urv$D6N3pOZM(>!B4||ap+&d`yN|43Rv+aP3F5eHB zQ0-QdS^D;~QJWkf#f3a$@sT=pN`M?vEv#$ZJO)}4A~Xg}6DuAfTGu6od}cNCH{;jH z37CzI;Ss8p$1(UJ>j$c`7mQ8K$(~k<%9|?x<>2T!xf9<69=*q+WXNOWX_!bwN zinqbdOkJRd8FYrZj}*u78_eTMN@3Q^C!OdPU<2t^Z=!`5vGGZtgb@yUX6k(=;vi1d zm1WtSu@nDkYfbeN=uuyO+*m-#b-F7f;X&1ii>m6Y@KRp|{eevr(t+=ox3kB#Mg4m; zv|uABs^GMp(sxczz}6ap!LxbmM={eg*&;$vJlJ+Ndc#T{$#_$e6>_;NDd8Qi@4luI!LN` zUJL+4#I+I`hgJ2O)@1^Gn=)0NzS}qEA4E~)hbzROp;8I+BB;0+WB%*>Zsx1XA|O6W z7?eYZXqzV6eQAby_4&UFfR!>EEsPzeGi3|nPwtW#70JZ&#I zIY3fRJ50qFRgU`8tbed-nUSM2EVP@D}tjCXmLcXyg?voK0*W#m$__$~hXhRPPD z73Kw7noUDMin}8VuQcSB*sg;R9nJ%PsGg&h+L`TV=AX|MGi+c|QsA0=s^CEF%A6rl z4f5CHZXo==(TwA+k<*dIk(=F*Sd8};^nTnxl1?F{n8)~V_zo6%PN(^phTk4hg^adV zQw3EUj*YgdUckqO8ojzWqp!4kgbr{z>Luu4VCPt5!@s=YT@Ow^^WcQ+7eGGoVk==g zUwqtGxXeI=Bl$bX$-_P_l*SC#t(x?;U2;$)mk1?T)+4I)aflV8hh2#ncVP?@^_JW$ zq=%3-#5BnA3?N+1$SF_A`tqgbqm@TPLnhxf z?3XF!3SagX|957GmBO1YA=xyY1eIS{xJT2u17L_s3yUSB)qcY#6INfQQ9D|B{hWq? zIFeR89PGgIG86Z}#71=LglU^ZEpFh*@j|Wv?Z51;b1Fk)B|SivTNt;X>pZ8)R0YBC z`C#}m#fHmLzoS2@dF(KfBx&UEQcnDi>?opx(I;eSN!D*j*Ble~@c%xgVj4hP_;O|S z8EKamQa(+l*~vrz0ZZ-gBN;AFU^Z0s9>a-ADczmYKH4jSnqxC5fhSV@l(|PhMzaCD zU6wMU?*!g1$T$L0`Fwj9A7?f8N0X<|JD94))m`j}3UIS`Xo_t*zH|sCtVk zM=4>&8!9f>L9 zz@ayv(hWWwO6p0ebU{{^Z&mH2~$u@=R7C=V;;l-(x{rQaqVmZt(e#>9k zZZ2u7{!?GE1}_))`>_@_8>w9ah|(pNun&(1je8;f8V}KBRK<=s(9`7;j}iF{8hN@` zz**twe*m_S(Aqmx%`iOpH9N!&ken;0& zhMRNLtVg>@?bB&(aRHmQdxs*(`)M5vl!%S38^19BH+k>33rspxu~;5BKVa04e(IcU?)e;NAJ7U{NHL&l1N)nCD}8a|;~8JSFg zghJQ%d*&VY8b6p$Pp`GSs7V<=#F>V*bOzv_;gW@9{_SR-E_sF6m zVtBx`--9$VE`@%nG6HJ$ab^0=+h&Bk#MtSnJnK8PwieTSiICZ2`n zT{=8WX7&;I5FwWx_UKI2p2h!6zD%)w*%yb>lsGf;+3TkC!(SOfQSi7C?*d89cafeU zx0Kv04xHy3{)_`D&_xp*oEk0Ma>Lw6thV%?N(PEOS#^%w6mANDN}joYa^`@3c3J^dv^u3z$I$ua_tg@V67#Wgs^CAb84Nzp=aN^y57PO+lJb@I-vHM7>tKQQ@{PbW7wH}~9g zo@ejhPX9#9IBrr9!dcqg7`Ip~wTaX;rJhMHD-)f$_tI@}&{8s)_P}hP%HJLsp$KR^ zZ(NMS-T|I3hg9`=EcnDsJyl1NhTwj{>gI{@3O9T605O5dGD%5`R}mIi(N~dK_k-AZ zq--j0tnPe2u$jDl_?8A8$?DFYiM<{=Gkc4oeYR0$m{r-B{N(YOexaE;!&CNS zOhZM!0oKz1Y{#KIz?_DwMNhW(?htOvVYd?oA`C52t*zTs%yW<|?nF*Y$iVXeETE#q zqc|lOFvMIinQ0tx@nwUWkW1K%zfX?HrnWb2`wOC6P{y4}3<*kfTKZM1ZXz~GeGG2n zgsE7=o9bF#gJtUl1U;-5;bGdk2#*jGGpa3lT)Vr#@2#3Uujm26qRaZhhd7+_H{dV+ zi!w?MZqU_*n{b_$E)*%{U42&D<9-WuNRb+&X@+ANHbwrG=74(^!Px}7S z<;nyf5lnB66^##6Br@T{qR1G zSk(08uvh-@>`)Q~v7U4zq$R6_5!FA*gy0T(1)4c)_K7>Dg$~&_I3qQ{Cqp3kB{=`n zx(s{L+K@K;QX{GRFLjyN0#3M>1dT-cjq}~=P_zvqiNZVB=k1t7GfS}j+f@lFQro;3 zAfDQxlmyS;H$UP2L)9UIXw2prc@esh8o&q|+DBofhn(0c5TM3M*cAwFcSJ)WeGr==@Cy-5>x!TXU3!28CK$^rNB&n>SSGKa9DmZ+O_ICdJ!q}<-( zCh(j*Y$g1J)RzGLDh?YTsvgsjF@yDxQ9jXCcM(aH9~zBng=EA`gMCi-CADfwJ-FvP zK(2i;;1EG2s=Z%hqb9O1_irmJU_g*2d-iaG=F=lTGM3T4xz@!XBOnH$KrTgrFgq2h zPnJ;-S<;thUX1yVdF|j2PR>(}(c`}lzCT(K5j4x}eoRpU;Cc@e&3iQmTRL1|(60+H zSs{-Ul1BKjJ%xms=ubK2KRctO8osQ2>=Nwn<4=lGbnd5c9yscP$+dX91RI9)=%~W>Ztt>w{ERUATI4L)CJ;~uNG6#_ z1scUTL{g2Xm`Ii#V>*;vUY>a%&W3MY{_>nwbZr1igmcn$XAVDYP>WHWns?s86=hmY zaZ9I2#<|MeJ##eU3>UQ7fOGF8-$_Sej@g=Mrt{6jSeR#rBv*o0C=x${P1l(qx?>g} zPh1P;?eDj}I)Z(2P|kikGfKSi?C_(3$e72ihzmRIl0bfBAn~ATnjRB~Nt&~oGkZy8 z)_>jFHh6E*7u$BHGj%HW+2uJvG4O6OiXPB_GIyONB*i%E@PXlYF*x-qzayilK~fe7 z{waIBV)RAJh9!}hq~~Nqy+513bDBA&XY2c>0Gb7i3vY-8S-gNe`3n-am?d^4RAlVg3EvP@tBEM9w1qh zgG+wv8cc?$IW#^xT+l?(AW&opaA2{O5#xKNlKX3}00aS=YJ_~iu$pFpSABI7Q}H(1 zbeu2cijrRvN8)qh{;DENL(mH*+v(wdl0QkjDY>N9M%279I6lFg50P0-4)QL_>2ip> z8>yigdx%NM(i_EqttdAHwxUi4Q*T2e7t9TX$G+5vubKfbMM)yT8^Cj!Pn+1q_x2-p z$l;C8Uz;=|;vb97^guw6up$-t`g6gZ<6dOeZrS??^V^z;5;izs1Xq5-CeRjAnQVi2 zd9iB_h6ZB7OW#<#xDyAn-)v2z(@;}-(2ZHUTs%ni6+XNyouUZ`#XbdMAkI{3WP!sz zOE-)Q(XtRLHXhE++8aA0tejBV^3Kb!#_fISCy8-8Uf7{kKTNFJX-XbabSp zpPPCWPb+X2K_(}x#DI0WYn`OX<|Tc^M+-!c{*=N8Ci&{&FClqOOhESYm!{SpIr84Y z9BJ8g(9(!h8~YD5bgEp6EZ&~-7C_FB5f7U9UBkXZ^w6-g-!ib^k)D& z-@R+y1NLZT6O)N8$v4p{)`X8}bZs3h;a%t*k*x`KiHV(zjvmiO$dzLb50W7&m&h{r zlmZKCC(*!JzuTRc4zqq(6!P_oh&{Fu1b#xC60jl+VT-?$QLwty5q=xa@nG1P7_>?% z%DtQ~FGk8H`uS+UD9#2Mki7dM`USXrmm zDi^N?kF>D^?gF(3Kx(sL4i+3izfjNLwCuxw8jR%^0LwT01?6w_`hJRl)N_V51tzI< zfSJXmYEL->e0EL3gc&9SMvkgvX>)}hv1ocp($kq(F@fOnQw93}I@|;`cbBw#`{!TW z4VOP}b%k-=YGCRg?rX1_$n=UlMtJREobUc2ehagI&jea32;M06V6pH8!u)N`7sSa4 zt$fiW4N(7U>e!-WhBx9{MG7hs?YUS%@*q3{N91=9CMg7Y4nt+E#t=rFldZb^tyq#C zl|!+rw8?`%*l-Prv`Zg@S9{Qu6-|WED_5rXg@Le6L7x?khn~GGAF_bMqjtL!=>h@Q z_)tXwo+gHY2DSBkk}lDJez(D9==AN<1TX~9H8?q!MhH+CV8U~hW3m7XP}hb~DkXa{ zgAgxG|CQ4rI0_d%dkdo9QZC}S&Gw+p7$2n9N4qz+hmp;gynj>tg-3WXw|csaUPs;r;pA(>BLi{CZOL!fMv0uiYIYP_yyO!VFOhS9OlqzgTC)EykPVQ$`qV&YjX zYws3Sv$!v4<101kn&aPm7hYfNeO%#CeJi1%0>)5aVMI4AC88%z3&0>qs_!kcA*1xm z>UX79`{0QnkpvUkKyjv*n=RNb%xf4NF6VtZwavPt~*V3EgGGn5s=O7t;m$s84(mG!K>DB;bN+OmQ2H2tz#YQqT~#0 z6}ebys(Rt{k%;;!i1Yn3B|XC2uVWqL?z)gg=9I_=xA>Xss@gH`a1kZ|vmc?>MfJ9` z-hC}*=eLzAz4NY_?r6X+(-ejc)5tui1K_Y}?K>bt%R`8V?4;n|*N5kHw@@kmev1F@ z9DZX3osPA^iva>}j=wm7NXJP_$Psu=5HH)qz5XO=>~wOV{pn10($vN}gtuE6V_AE* zLkO;(e=i-HXBozI;6=BfX#BOj{6f1EiJ8}=mvSz;3T{B%%LFN$#DPps>^fenO-()K zg8Ej^w7TStB7l6@^^+DIXW+$BQDtuUsqZw8p%++9p>GVp>MC&7&lU@f;0l*?xN8Cj zhobpGtYVQWRA5f4SU(e_Q;OPENPRx;yjf6L!$eOorSmapsT&O39hWs9Qj+?>b#<`~ z2+P{Y2`^tZFca;A{;D-sMGlHC$oFy@QZqzj)<`i@L!cbGpvFGQ|g}7j^ z%C4_q)2S)>@&Yv>SqR;Moh15+2fZXAQ?SVq{SVr4;OvSDBA<#VOZAKe?0iv2j`B^< z^pKSJlqhYmcC8OU^ zM36T;1fjZPT9L&L&0Q+Teyq& zE6IvF;ic@Ayfpwj#`YW9@LY5q!-oVTpr8k2NU9Zkm)p$f!UL*Y^p=k!?7Bj(rs6`lJsz{;it58;^S(TC4JLbLf=Y&1YYJseuW_78?^K_)&PX zsQLzL`5NnGj0mD$M^QB|>1kR30Tz9#G*lE5Hhj;_0t!ehn@CAy7cA~r?MocNA}b9o zfQ!YXtty26-W;I49*_r~Tjt$6Eo3-P6w7G_Jfn>M-jAc;jiXr^ukg%0x6 zULiTbec$e;4{pVJ+?ga6T+Gy$&#M1)p9f9TM3V({GvrqS?G0W*PoU< zIH;=C{;gA=U=Ish*cbDQL%y2&bo<7M-hHut7H=b05%Q+uNzQ&kwxAfDN)m?I@MZ?8 z;Pb_O^Nh2*{~_E6?_dtc^!f--N3suU5^l9sQ)zm=K|mUf*;+|J=vW#BgaNrjc5P(M zlu<)Eu+fvUlz}p*K;owkp6_?pT#|-@KgsnUGW*}f;*w#N*cRiYCw1R*f^*j}3=-2! zyN6lOY;Y+i{$TzYVAl6**YF+ky97*}86#8|G1VMIMYni#`r8PwvNf@~&6A$;iA`bj z{q;O>^W6Z_WklIm@(do&_Q`gukKbTR?&v_-tMHg>LtNuX*(E!bto_;!79tVMe$F^` zziR)H&#_CS?b$voF0dQa2cH5uzYVit<~FlYR6o?C;mm-te5Fa|&s!K%0798CBSb-* zziO)?O3MzB0BpuW%v@2d%7678pZ6|@LC4b=iWn`S)cJW!*)?`YerLhBwD{mGY_YAw zrr^%T4?lnT?7Ob@t%aqqYOJrHX=sEwZ3JUG4c^PhgmY^~{mE%J1_7e%<(BZ!Rj=Qq zq8L_&{ri#iTAzy5@yp=*K}GZNa(j>v?(+(iE9m+V9nA1x%u&*0VvRs54`Av_7lnE6 z2>eH;Q&bDW%Bq|!(DVw~+yB$!eL!;6Dw0kJh#5idxR$T{^K&L#1{Sftrg4Enh|omz zO#*R6c#haLkr@ld9WWaUsX?y#SYBAtmxRwN{1L1OR!$tIV5^>r7}`2s4z#?mU^U#f z!;v&@j!-auaBYdw*Z`qzRvMTBK!M0j1;q_|fuHPIi2+*D8W*e1oIGQb5yz~!{Rx$p zf!c0#s0qGn)RO0=uJ z%G3SP<<)386F6K-WqKR%&0Y&!YWyjBz5rffw8@rG(RvWc!q!~K|-43n=2Pvd#Y zP?D0!j~hv4CxNxJzB6@RrAQItkVYJD&N70Mli?UyY9+Zi@Z$B3E`V$5!S1huPMhP@ zKJWs_^AtzN{Xblo(~E^-94su&zH1hirsJyhMcNbbN&tz}-#K2_AvQHi4yX0JfNNrQMXMw- zuR>0@(Vp{b;FNAE@zL%?HtK*uolI|67}tuCWN zushg2@x;0TRlmQCj7ve|2?-|G2TRe75l4Fgn?RfXQ8;c28?bExOI??2N-09W67sAX z-(zdUfif@|bF{S7bjaiI6UiwfCUivyry)IKPdE>lnM>Jkti{iX+!{=*IG&-IY&&$|M3QD>uJ)D>&`)o70Ob}iJhx-VGo zLB}MOx1&Li?F zqH$hjG3Uc8Pq260K{yRdHn9Iwcis&C=yj3|j2mG^Si!9Lh-E~dTvJg#r(0etmPjMJ zRrw~VJAn89=_(15OdS#-6c^xqK5Gtdf@JQ2Cu z8&Y3-&lm@{OA_QF&B0!fQD4v zui4zzF~0jYrM~fy0`21A`Ua#levs`cZ(1qQ*|4&p%7_~wO##&aR7r+B?zXaH38yqK z$Hf`RyL07%sjl78Ixn*zQ>CKI#E0fN|8vcal*%3@$0OvR;&-ZEkRH+1uzWT1vR?P; z37-G&V}AN=J0Jdxjyhp*mqO5cMZf@(y$v}r+OQIM4Iu^{LQYn4(A9~VGsIYH z|3rdKR(kl}b!p-80TD_tG&vEDx)>BfXhL8)Zcj^6QLH}t9|6z7_~JStRyUfc62K-r zhtWrM-SfL(-T&e>LN#6B?Uqy8nR>;hXN7={J=24#N|-rcIWj>em)O7;Yw1pcfxloG zic-ZJDu%eUI~K9FgNg+i?aG81GTKI&J*o)h9|jC_wxi}6Rp%7UeIGfp8dAnLqKVG$ ze`vLgT9Zn6MOS@4hrH^@b9glDk3iZ>;<~k7Zj)7H>z@@#cIZUx>N+FcH}FixUEp3y zI9;=0G5&Of1;xN4MGIj{Lf1|ED&rRWQ=V#husI25h3be3UC8MebwMTo8HHU;ioK8Y z2sqVRE@kmDB1DX{;j>ZTAR%|}oAhueVfqk6`ZrSq?Ku#gi~R4{OR!~m-=jlbS> z!e{;9FXxT+=!$Sz!s{)cBbwQ&Fp_sa3i#C4s8Xt(N5-sqPFKPP{jvKiph_7y+n$q3 za{RLhUgm4CudKnBjUc)w=U~i!C_U*1>$+Ln24{`saa~ zGTJfW&_NqlBkxoZagh|qgR2mcmV)_1KCu)jXEMMHMs!ggh*W~rWFP)yfnlxJa$?xk z3bsNdA}jd|C`GGO2ggJxbE2^0OtpvMp{c68vW=K)n_|JWr00um#jxOEkl}@mw{DPv zp~y*mfiI?GNUl1mi% zhNK@UBIZnC3?+GE>02XDMQEG?kgpWCh8>eKkTVSM@7mG(ba}?K!wVN+bCXnFMM6?G z{c~dHsx)X=@rZ|EQM6BUlj^}JB0=}~UFIUV3u*_Lu_$dlmzH&~k5wX0l|j(zxr4wm z1`dJOePm;)@2L{mubvx+SFDR60%-Vo+$F0SgZ=!JkI|7X;q^vo4>)SK5K z{90qOfagoGK)fY%rR-uZ(ef1~T9b$7YavA^Nmto7u4}TGk@wih#0GnS5%w%fDTI#W z23>}%)9%e%^`fMdvtO%eZ2!(**dTNeo}pdgyG;HrFHWW~(Ys*X^6p-x514ec^rf|- z!N=m$+r2nNaElj*BB0P7d95Tb%p;}y>%Fq_Yh5{gUMP_{yd##)09xo#rhT&@<+0EQ zbfIhwu@m3=&*Gyc>Or|aXfgM0TJ<+?ev z@($+f$Hql_iar`8+UOU=(El+O6>@4GU_SEd9U9XSbD;ao2XU!p4PfSGAGs&9R`xA}UjTkMGYjD(Om6Ur)6!N*KKX!*Pbu`vDkT_Yb znxd#oPmW=hWrTq=FY?Y%oW;dY4Yd2AVv*=8l@P?7nW2HtV}9v;h~Gs%&Gr&|-L{A@ z;RK}e%LG1 z6+_v-tqns`VeNbP8fdw!X<+znErNZw%lC!r`%cuKrf2mv`&h8qFjnm3eVjae6M) z_iMarU_Sul-yX*@)Cg7ZY(-#5vJ!beuM|mptrQg|w4a^y7dgxNJj7b{Es^mLKUs{@ zI?yqzeY+=`4L5fYD`RGbljNcZ=ac+0Ehq`w!)x>UFQ?}o|j_}qx z+^Ae$UkKN_F8_VG-$7jK@IkE0UBV>2aRtL4!<$kwWJ_V|Uiek?1b zqBXuaY-W#?iIw^&TWjfoOL(x}@|k(oPllet2BW>%38B!X3{T7pFIVj18M9oXO^97F zLE-i!Tdhl{Ah%?i$DcLQ6+ zk&uj5lGIfxU`pu-dAYjp6y|+mQI+6qJTuGrgM64vC~XaNx1R3V;$&$ZW@YVd_#$U# zDAX55ETMH1@*(kq0nPkt<}0t~%k(SXd_7_KlEa&bpp)Um$J^aox7ZmJuv*&X3m|SwU<9TG^9_9W- zaXYwmlXI=GkdkPpK=oJoH}}YfF;rp#ts__KTj8lNhhV~c!kiEpN)zz zzEYY}D*N+L?*a+^TTz2QtLWDb`l)CxnWF1HO+;SztePVAz2~xUFQKi8hvG=W$#pIt zo~dWfe@;&Ne?HPe2nxJz#e})^s*>&Q0pNUthC4utBF%_&fLbsUn52%vQTacMWVCqF z)Ea;ZAl_l7^ava}OMmQt)u&H2i=Hr0Ux!%0S-)(I=^-_jiAOXEJXGg6X2G(Cxgm(P zkcS+?EgZ&Yv3{6D-IxXx?-c1xRFq8LoE9u->;2oidE>X@RJtasR7 zXAlVj{?>2s_D#&kT3CT-&zpq-q`yT$OxoEFUzMSB)B2t=l^c~u|C$6*2QdxtxJa0h zO)7r^V+Vgl7)w@<@%(r-px6kOy_%@yyN5iciW@Zb2}g=}GI-< zZ2xc-p)S|SYaZ-KSN`Cmm}SjgAek{R*5Rm#{HMv!{>^Qb#j7*^kY@IxII$__J#6* zaUlW@7i-w2_U?bs{_ieU*GNNzu*wjU=g@D(T15jjGf<|y_$#VG(2pX;e(>(=I#qQb zH|SB+yXqUA;u`7K&6^Zyb?t1u;P#YN=XK^%g%PF<4RUX|E$_+S9q9uNSlL{s6JcIa zSMd7az65H&BtA2Nt#2TZazf~j3` zi)IG36Qg4jvLoP|!jb*OGG;;dFB^n`&raV$))x1D#Qq+yX$e|{7PCn#jS$p^JVS8S zLjLfX4bg@If($8;6$tt>WrmASm;`APX@c`o0*6e+OP}qldG8-|`M;CC@;r!rr83;J zU=9ruq_Y`tBh93=MmP81kA#D+Mq&cO*~R+`jBH|7NH-VB6S6sOwX*69G!+hTAa5aC zY!W=8Rr&~1pCzF?ot6sTI_WrZ*o}@~U3yBs^Bw2Tn|s;n zd7p{Rs0Z=0i^;7n_QQ)gF+x}_Z;l3t& zNVYzKttF9N^6=fdq*W5&4{EFvJ;L`w;&aM}I=PZK)^zLuUVQ*NYF^C`yBnL457S9n z3kCo3hxdQS#B(gRN*zjQzudVU|AiL_yM_Zr?@WYi9s43%N90VJ#g(0i%ve{rYAcO1 zN>2o<8$-A+)ingpHcC!%!*=rUX1=xA&np^C!|CejihzITi0U?!u2x~|%Od5_@>J;4 zK}^x#$v_v^mbl&Sl$eqj>HFct5oj2bAKpekjXm<*U-<4RP1vQ4kC|8RVZX2UVp^IN zEBgh4U-8u{p7i1n8P1%6{PIgRyWPus+1=o}A6@QjFRIO0K1 zt|tw;BN@Y3cOoaq?9yECtJeV=w~`$=KKD?8%Y(9-F}ktQhs?kt^Z;W8{VX#iT9f<3 z*YbBrPV!!naAts%te)2PcIZG^j(_%oN317)?WNHE$mGQa@EV2dq7^T2aT#J9Q9V1v z*OA!@m;98EDs8G&11o(awPVcHt}7vzI+0+}^A~Qjua{X7x|mY)fum7vn!dcqj}rxP zUoo2<17Xz;X=xRA8y<&0XR6={K1M_121f6}C{gX(&*RqUN!^dc51ldwYX!x3CoxR*YFB>;TAY~0h5;(=*w1U8d;HR|s+q$n<=P*{YkV zx4UmJ@=hCG9`#0=IsBldoTM0P8mTcu*~5Z}&0!X+j-*Y1vP43EAwKZ>D5iT;5N`2# zG%b+3D#n7+ASmHA7;)*Z4GUs&2wS1|pyL-LuIy1^3~Jd7x-VKyNI5Mkd!5#Q49dpR zA+h-yFM{|XrWLCRMXw%5K`{(;_Z#v+kWM%|a?I;To|k%3t+LJ6-}rLe?3$*?AR)Qf zM-zB@!`&+?a&wCb<<|wdchU0gl+$b%4{Qma>9?`@d$-F4_tFu=oAjcx?T75ju-o^> zcL~d$F#g>PF%*!P5X5j!O$Kr8Wn|osj6%MG6)%P-;S1S`f!7NI-6t|4QV7ePrzZnQ zIqmdtCi(G^3W{5yiDuDl?+8sOO6$*+L&|MBzG=1R7yqgL_@b%tF>_&2H(RiWL?7!* z$oP&wOom2aXD=wg$eM10Uy(&*I7;}Q7&U^!m_e{!gKX(git$II)-W%enivPA<+|y6 z6umQ4Gm_H%85oo>N%E62i+~W3Y|Ug<|I_p_C;q*>NDO@PTWJCJ@9+LR5VQ0TI#UGT>Bxu;tDcY zu8Q(-%YM*jT51$saiycxUQpCp@+!nXqAu77b;!zrzI!Vn_O@|Ch}hWs19n<>abwF- zE1U16$V$bC*J7m%=?==&q&7858+q?{I9j_M%07k;lN#+oA;EUH3KA9~PnIE|pVFQ= zBS6;n=~`mUZbP1AMJd#-hYZK;r-p~`(M{L5f+2b8J`@{jWzVPNU7v7i>F^d z@if(Xf&^D9b2C8_tUp z=q1rXR!QHtiU6ZW|N3gvzPnELUQi$wyz{WXp)7JglO3-6OXI)tS;2a$)D!9abdCz~ zQxl!G6@ally9Y$8bJ!F_qKH9)N6BD&fg~&^(nms|G!>y3*Yr_Mgs9|WtAJ8W6KCOt z4JN~<7$vxK67yoeaR{o=7T$o%46h|>txc_oWY2Eo3XpNI&1>GL(U2cu&L+VXQErgp zr`*UsyVX3PS|KIiy;UT?R+9* z$SsrPXg{_UdM1{(;O;BDF`S0fgtOn$qAdpghdyTse6{ty`l`|MxIR^9(ng6XiaTSP zC_hnR{h4myLPDSs#nu<&LMss|t$b2@BhPVr5qx80)n!tY7`fvBpL-ru1!gpID&a=Z!|7+E2#1-Vsr;a{ToAyu15*Z?Idg`H0n0$zq7A zzzBK0^3JdK=0^002R2m*=G?JibGw6m0%LuMcmEdu@y(eax}aPyDLM!6ob=|%I>GD- zak%?8F(!I1w$OWk#IEAX7mxZu>HK^ZxH`p;{pJ}#JmSw#abF;1>Yq@9sPs?!opC-m zTN~R)Kliu4xCJo1ZWNH;zn-#5VpdnJ7vI;H_T8*R`DUtU1h&$;+f;wUy!^M-H(ZQ& zvIpSt^W3`#4c3%bZqhxzFuSFqg14-~uguMKJ3<8hnLJ3OL4U5Q5(;zW4yp&dv;S<{ zSF*KfIj8yZB(p4o{e_iU51$o)laMF}Fy>gXNB>#SvA79^7a0y#TF8IK$43U&y`m4u z$*JBq3cRs+T@c!IwPTaK|LVb0c&Fr{tH;JX{9pVWQdp={12Tzi#goZ;>!m-1NF@4} zgxld7I~&)K-H5rVDVAMgFlKQWyeMe(^tdywCwe|x?7gZ7-*)J{cQ{&A!*RUH;biIOtD&4 z4A1ro+X*YqP?GhE#aPs^4eieGfL4DnBim*Skrfk>c2W1Lyp#;Q#9R2KfhtKU3p1!^ zzkOssUqX`8>r#(}htDxe$#k_OD0>Jt zWQqf?%xqR@>9{;>NG*n~Bpjoc4*k!sPhm|Cuu<+D766=q0H=}HmTsCYBN@DSF+n9B&KkV(PkZAp*W36+?0=t={m6tYCgnyMk%ISaJ2vo%yE)Y8w}Cyq z7wBkGMU}?5X`e4w@xTR7BV3b`!MaROL8naBCkDDNsR}p!q=DikAUr``5XsdehEmV8 zmQLHR=ml)w0b10-@-GOwx?1FeMcORgU$YOi(&q1;l-u`}~ZCe7(Jz%104w{IoT5ekO6r}ZmCFy0aEeJCw@qG+Cq zsz;WvGRvem!Hx3%6wZo!8p@C_5rl@?QWwel*#7N1nCrK~&HxU>q0c)fjzxUcp#0OF z%{vbsa6(l@y{Bw49}sk%IHLM;xL(MNb+`v`vMTS{!?gRL_>Y*Fr0;i5aQ}kM1>XEP z20Wp0Zv?8OCQ)%Eu6ghDB^4UBV=e>eb$}m`)?KH#8 z6cHexS?kg=p5;wbUVet`4!Uihi|`4Tka{?;=9b=T-d9$iBaDa=aYC{iHU>64a1w&! ziF>p|s+!H3=1~g1z82KDNTJ4OPmQX^UZ2`=65S@ zJi5a^fGRFl)p!Tynt>+7yvBn}m;tUPZT40Adn53N7%vOJh@(!J!`{_M1AMjD1O=4~ z`(!!x{X}zB%zR74f_okUKqYjWuV=MJY0_mI@W!`E2dNCK>#3CHn-JP8x6rSzkM>^F zM^xu$4}Hkf4y_v33~^u|dIy0kFW^BaBF`&RrD`ADW~=+#U(UY?8p%!yJlzKgn)K)w z>+7uu?ABEO5_^QNdaw1tpAZvc%Z!OToD*LBlWOE{v$e zg0^@!NRjdAony7GXON55xkx%ZFme|IjY%_SCUlN|35QsW!iImuiFLT%%a#e_uN;$}$@$xKGJV z%R3cX;_jeuz_pZB?;PfecqEtypgWtJcan4fgR2d6Gpr*Htsgub!FnvBRmx#hO>*<+ z{xo+~zNEDOO`@-iQyo3SW@@0k>*FE)sL`T(U5T}CmG&}rAG=^-{~x_}PR=Eh8h?nt zNolEs$G|ds$QgQATYA`tess5izX1gJ1m1A-z2W8;)D?ImD)3HJ=p82?pC}*SCiusH zxv~FefU~Q$gRSrXJK&A*{~A#E;5P#w!1lk7;NjqG^Tor`+3o)t^M+6K&D;MqCP!t? Q_`jnl$*F_tWGq7e2Q&_Y6aWAK literal 0 HcmV?d00001 diff --git a/awx/ui/public/static/media/384.png b/awx/ui/public/static/media/384.png new file mode 100644 index 0000000000000000000000000000000000000000..c5c9f66a8eafa55f86063287255821b6f04ea15b GIT binary patch literal 57721 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 literal 0 HcmV?d00001 diff --git a/awx/ui/public/static/media/512.png b/awx/ui/public/static/media/512.png new file mode 100644 index 0000000000000000000000000000000000000000..a53944ac70d51e01e03af3425a45d357ed3a6661 GIT binary patch literal 88884 zcmeEtg!V$3VJEx+U`}_8x z!?IVm$ho( zEk2VjMFcCW;TVkya0l4Dg^h zTT6X3{Fm1^qe{X1)+8X`o?f`O6=W^O<1xFR{=5+=-BCYE1gql-J20m7%>2n7(je6{ z=kviOVPRkg>JQ|c>V&GcY0}1T($2=k^K?=U;^)AFR#LXE=y{ksXaH8--)d?Va+n&; z=UezIMx>Lp0icET(FeRaa1!T{+oP(xay$F9`HDZOasubANr=dqx9l_E!fce(CK3sdu>N4qpLB}-l)qr+p;?Mo8J-Yt38FIz45c2}#zdKhG#Bk5!`aMRVe9St|(bStC zc96|qenID3YtLA2U^?{;{*MaF9Pr}Rl;+^e)^;aY$lk!wWz*Qc~ zd}fb0%_>H@k(imieE~jZX;k3M+$PW>f&jPryEux#)Z}+`M&`-8H<(F# z9TiepTLal1ytUoU{kyj^(7Iz1pQZ^do~?YUa>~1`w4^2La^%jdCqwoU|a_S}b>B zU#KX`KBTvl*@hYek4-RN`_Jm~`XS+3yxfd@>YjMv^vT~d**E@ooLpn>bsel4!pc~n z*D4+c9?Gw)gsc8H=gP)@ZT>_d{Os2bo1AagybBRZe?SIJI8Y5iHDZN4`R&!e3L~C3 z_b)heWyvhNq{$eGkOvE(bCd4{OzTpFIM>k`h=I*wK5hTKmmw6Yr4K~<)1KR zk`e4SW%=&Qgi>XB>r>DwbbDIReo>Qm!+#R_L0bRzr$=SYO3z95SB^W~;3!pqV#tKW zz8`2e#AARTVs9-Ha-1M-ju+}K`8g*Zzt{@)Gmei*PAkWUluQxN7yf7MkM#x0>;-(q z%Edknn#T@gr~WJUA3$_us)LICv|ldYb;~cKEwHD>?pePN7LtA%@%@REYHqndu3_IK zB`Z&RUh?y5P{urX!>GFRGH+<;dA+CizCKZlKki!TEL;tz4yrFxhJ8%6gN`XSp*0PSQfE-d>)Knjo8=sqfbjap;KGDEA6seq_cOmmhm|eyj!R#We(Y5GCyIPZz}JD( zU1$$&%2JQnI&*E{eVKUTvHcCOF}3)FAh zJr^X`;SARp<@Ah;z?4bobniFQ8wQ^ALX>hpO}Bqm6>7$!>qFuFynhslD2xwS8$O&m znA-iZIXi|WAxKGo{?p8v0_Fbt8bOFb^dl8p!UZgEU8Wy+AymKz=!$RFSHDy=bfN5GAXz4j+hDj9Q%=bw<>Z|?B}1V7NL7H=p{?O4B=)TH2!uy1yKMG+G; z&2pY~S)7k6F|COlTh`fP8ga4%lk;*D^+R_*yZ7ykL|0#2E)Me5Y(1V}2R!XDvi4hO zz4A|wI`(j&xeQtlhgP#!`S0zPBZsSPqSXbumukLT}WzrOBuH5Z5dk!`*`PY0?5@s^rcAb@&;U`gp>U-sa360R&3x)UHHtap|@QRb*Ozu5$i|PG3w)J?qU}&EL%0MCZx-z1ol-e&WXBNk!`* zB9tyU7}ye(+A_zH=adwDhy40%zpFFDMx9Pu5}vrTTI1y=;FX*k9sh9}mwNHeF6mUf zQS@qtW2iEL{}^Z!5u?w9PGC8=QLP@tO?~uH8N;&UOXbVOt{QkW0*!-z65vNQOA``+ zH+87#ECu*yQ|XM(uQ|vOlz-WL-VM@>BXm7?RkYJ7h;oL26vwxcp5xj!*iy zpZlFK@5@HZde{xHT#xD0H3?0)pcD{?+Np!MukE!N_{sp$Rm;|HI3ZeUkWEbln$m6DvUU0qF*cJ4SP=J! z(S!Nkyd9r_xFJ*QJZ>G0^f2_tDOZSZDpj0kbQvFMi9T4<*0r z?XP~>IWgJ+djwa%&uSYC9N-%u+?%mff4}N{T9skGKQunoVXr23sD9b}S2`_9dHe%mQSg3N z16f{Bgp7)h%Ab++Z;F4&?Phw*`yzX|hl7g>V#m_`;&Rr_>z^1)kR^Px*8}6*4uW4fU(&?bl>o>YdNuMg7N`e4%j0728Vldb+?~c-hM$Xkf7Ig zB4?l)Wh3M)c|KMzu&<(P0h3Eh0gI!;ui^J89@9HSa}k6eqf1F^o+iKxz65!{UiogG zOGa((H*P+`J62$^qKXsQQ_z#x)5Lr9P0UX};)pTSSknUnk-5$hM0k!$}X)8s{prDCijgiD@~@ASTieCiN&(q?3= zxfsZaA>m-RwjRW>b!Je{r?j1WVk7;aMbod>-28(po~V$I4&oJ;7F_o>T@2e=;Sx>YitSX$c~VylZ8rGJ zz0afo!#rx>dS`bSDfd?@Q3nNs++7e1U2oa**WEOlp+-o8QVVZRhHmy}$uhy(0NGbd z!1};AE9uNzFu2EXz;=1GryH}2c=^Y37>~^FFZja$AQERKSmm;IYJ&ay9Hglz!N9J? zojt#4)lK-wFgW=`b*$`JxclEje&__b(!RuZwx7`GJS}|)eB`2Y7ZJFYZ))u# za>C}R&^8csrV!w{R63995I75FqVgxmpWEjlPY8+%bC=9MDU^G{2K(y{$nmyvCdU5w zTmG{kK_Z)=a#r+kbe3=9Z14&f_nh;S5A(Hm2>$JUxx4KOwF=b!8W@Gt4C??ZCiO3# z&aVQa{V=1S_~jnVlT4}%lP&k-Gq@NbQX2N!97-v^MvLI3&Gjs+wNh}1FFO#8H&ziK zP`TX@`y-uu!$P_>qn|n5_dF0b#%;j8$Mq0PUGkrliJ2DUs}E{=l|;i*`H$W<6*lMg z)b|+b7GO6qM_JVD6-J(x04(-CW}}<|6GepxI?f$seH1t_S<{B-q5G< z$;t1F*u+Y~>P@E)+=Vj%hB~XKK{P|`0tRaC$6w3cKpulrmiF2{#kj(5_7D!jfD||Dl^33j)pk7(Ect z;P;IE(6}~M_=@}?vsd7=U}(_zAT!CV+b}3C;g7dTM$WVOBZh_ymz{mnSP5=JBo{62 zroG+E*{_Dc5N~@89pqF5fo3PK@T0^27&OXz6+s)Jks&Wi3}Q3nKfk1tk)?~Nt*DKt zHTqf|RsJUn?h^~4DK-y4{^ABB_d% z(l4{hS)lX{A$3WvV&+fXo2fAH;qq!dZ{l5mh9MR>!L5Jq;RLTze~Q|H^C4Of0?hS! z_U^NXa7~*7b`M_)7(Yv`j7Ly+7Ra_zsNK}D$``>qe)>@-(vifjm!w!m7XS6C);!VRxBlQ zs|K4vjY~*a@4Xv`k?~~WGGH_&gerr$!d(SZK~y!+FYlw*qU7;HC!t|ix}f)hy5Ud{&(@xOqC$cDOrG)FBOn;?cSU$C`Ky0DO9|XN~A1 zc^e#3Vin(_m2C75_5G^Ncw_cXwj*OmPV-HELjk&R?gHIh8JzwWqn0JS{1?6EweW++ zx;$w;QUYrbK7yXK}dP#& zDX^k&EE2_=)quM{pMob!fKh{xD^YqhX=0!=eGaL0;T5;~jELhy!($`S;#Hhf&^2>> zFT-T;o2Luj!P3G_3BAP$I94VJeq!L$(1w)umr(P;5!ad;&zKuEF@N*b{QGtW_1qICj_sb&B}!(Qpr;&6dGG1|9A4f8PhQ_ufs^R z-`Hs~BecFmI(yFF4!mHBQ!PGw)R-C2JHo7sdy{Oc=5axE7f?DU2q7BAW@N{Pe(Ac| zm9MAnZZ=Uk(^@wq0zIUSpLj2-Ix^g@p#)YPsibqpqwk7XCFnnvZUnW zjc2m7KSy2nU1MQc(Z^?M3Xfa=5`(QMX;J45F@->8h%k^wSt9Dt=G(lKE-(ECb#0If z+qb0q6Wq)V)Gvn`%r#0^_G!nOipYL$-TK&1YC-at&M+;f`2YNjki%+Oc$_3*_{-3?{kXB}x3E4zX*^+dFFO#-Jc=26p6zD-ogX>1G{_YQDDa_ONfgck9$%i=r8r^9HZMTK=%D*pdFrQO-!&$0BZaN; zd;s^YnlCF>Lg!6zls14k;{IeeYpZZ@!}+*QcgKL1%_=^I`7QK z_PTf|Hwu1hPH6g}Ub6ETq((FfQO4cb%$u$C-Qcm7- z8<~Pu$<2$sHUa~-aA)P0WOPDLX+Yn|vhz!g`kykB1LkAy?k#-ASHznH7w#%7T0tx( zA&oc8VdlNF2PeKOmR68|64%B88kgqq6nqBvj%`HS7WW&X4-3=f&@_-HVd&9Kr&Vi% zSRTLjsDE+Qp@LC_|LeJum#KDNju35SMzK)Af=}@;xwKSyU*>Sz`pwa!w=Ll)E!hzl z%>{jsg_ow4_bPE3MXveaOi4UJ6pRQmb>OiuYB=<0zm@#LVMkwO^pkA-U}C?Zeag-8Z9R{X^6d>~Zhw@q4MC{uAYsRa7gCW95!TdR_&TrLCh+ zY51-?R5wI~)43d3mR5WDT|cn9yxMacePnUlid}d+bZg{36#y9z=$6d+w6cQK5X$+a zvBJxq$Txa$)kdkJZH9XY=n@Sf<+=Op=x%vWB1ItU0OejU(d9Mt!i(WPAow|RT|;zkq1vs?z9;Kwigt(G)6wtlmLh}Ba8lR`PoB7TOK{jb zKm1m|I9G_wF2N%;2O~u@mJD)LvUQ0Mhrek)$GsPGwDfDvxgRU^4Mi5-4!{fruFBDW zEzqA&X@cSQvZV7X!iJF~%GirXwHT@;#!ViSFj5A!*`#Yh5VTEgN%tiPaix}adUGMu z^<5@__u`6(0x)PIX0v^xMI4aEtL|YLNZ*5NxBR;-^|p8`YcOauDfW$cRKRxOoP_>QSu&L|I{ZaxbiDK&w3|^BL#BRw-WtK+&rpocj@5%$2SCNB{cTH z^Cf6r?dKzwd>p}mar5FCUd`k@!jXH59Im0$IEm^v>evT7lPB2c+H`rx#2SNCo6Wj= zc(S1)F&pR-`8KAqd8Jz!+hFGAhG-Kb)wwq*jiSqk1Yk#ey2~x^P=tDhLcxZ=nXMnb z&n+da?}iq;#VyShsTxnP+#Urx9y|;+3Ra3gR&Qq>dzyzSMDuBtGkF$d-%exR@;zq- zvoB%x81q?=htRjiY0^^pu7qUDq_;H;)~KEaDm;bg`SHx)HIj2F^iSbvJd68f?BLtc zOy|e{MX1Bv^btnPTVx4&bo(Ce63lLje|y&RzZV5CYE|C{FSGjmBHjGNs>Gj zQhtkG<0G!Gg&5PFsUeD~o;`)O4N4UczpfMMm4dJWRv#y!LwWl!Bd?bX zLRKaFwN?c4GhS72d94&}IMjRljm5Q8^a;sI@N1y6Gy^;o`l>9RubVEXkRAd+G4Z2e zYIE5HWb&p}cv(9bm;Nmg61H~OKId4lW4ilneb-w`uou-Xj=G+F>Hx2zUe7eS|G7Bo zd%c^<`YlmTX7yx;C!Hkr#+>uQic-Z)mhJV=%=$-^CF=|-J%7us&P`CWbK8)+6dgD+ z1JVc@E4V7WV^sz&;`Pvs{{`@VF_ofjUw57R@d_}kL|@CKtOCdbdQn`b6e6*Mx9zvg z#;zIuMWBcAk_pU1(%-=Wp;;jYq{7Jz$&dGkV~#n;T{6P`7d3DkH?;`^o1wuZ!}{#* z(*bhBbp`|xXAM>mgUz5RR-hWTZaWLh z=p%`$E!>8aBK1_pOJMRhXU~5aN4&A<)i*-XqR&&xEAIWs$XppGENf?9VH)e4Q7n%4 z*96Dcr!6*LMFhHE`QAuwjIX>^6dxsVg;f$9vAG+wM!($uB-!B`U@YhDb9*l0#c)xo zs*?VXs+A?J$7J^JHkpv~?%3`<`;AKmAj@vrs&uOQ+HD2w@s$F~Z&?eoHaU0x4mRU> z=XB>??C6AUKVM$^ zjWKpvq*>shSYs$Cwm<#Yy#oP{24vBpnkd#3oK{OCMKq-GQLJn0GA7re-XtG#BB9ld zP=*}AqbQ!5r+_-nVhhSgfl;46=}H|sdhDA?`S>>6P&Gtah{#Xk-l17OL#+eWN3z~| z5Q0|+#>}{@__nn3`z$)5A@}UCdx_zBKr?T>hDj-LBRx)@s+W5mxdk)ibTo}Pz_QeAAByo2_@bt`x` z4mZ0Hxbz>t{|~bUn+s4tx2(~vf#WUNs2w#Ts7DX`PsUo2f=^cVE`dTC_Yv9!=CAZ2 z>>8=y0((zMY-BKr^6&+l#wKyPK?X}2YJ1L!p4~JO_^;vt!7Q%8+t1n4prdc ztspg(%qqrD$4?dcbtKD}u+Iu&cm3Rf7wrXe9k2Oi@4k^3rxpF7mY-TJm_;8c0WDu1 zBQ2KB?Hif@wHn|8JY8l!OsKZ$zpXUBApMyg4lKR?^$WJTC*bOtQ2THbN;?RcXt*l?9r(<@NT+a>Gti!#H zGn(`2er+jV z@insK_mgk^xZ6UXN?8)Z7Zh7(V&PGHz+X8oT1yVm30MC)gE3Mjl(k z>t}%l_IwR?u2K1@MgQw&UO-|ba`apQfdL!X}^`#1W_bI?(iT^TPsyW&#L*OnM_bTtpSxWXdfkeeB4lCMKhR2YXz|N z63rkkKPXNe5wf*nUOQR8MbhF&KM^E|Ymi=H3ER>H@Gp@Yd;YcEg(f`+1jCvwg8G;QJyf*_*bE#u)6B(8 z_9_2lb86&?w^ly6@S-^1aCliUEHCYtkwSy5lCsrV>Ihr`_nuEnv+>3e2Hkdk6gm6m z>{{m7$G2sc+$=*Dw2N#G^I>+pPl}Cm@H`5`ktr&3j76YUB+i_XYa18RZ7OH`%z*km z7~{54-*QnY;YASLFU0UIb}91lQrE6FFt_vLY$Mg>ndUaj9q*s>CtdsN9Z6&%5B3E5 zkr?!l8Z-9`Hr*5DnuP!L>N}Cz&zJf>GJ*73SWy|8Szz}qr-iRoe0j$a&d`S>^IOe!OTs_~MH+&JS+_X&UKZcp~rD9LHH*TwPPCVgZTDBlus* zDt-aL%kKFYAgfH(2X}4VAp1ApmEhg7g3y}X8@ZQ)pFTGP9FK&a_&47YV}l+T2B^~^ zG=?jL-n{<>uQp@8v`z7v-S_!fg;Wh_Uu_kwHg|kZ&d-N zyLWxZUyG^XA5$f66-xamyg9btW&tmsBpmMkZg{VqVK<}G>0t*dHJ<)W6mVyA6=jog z)Ef3)W$Z&fw&!dy7_pC4G94n!bq&f2^Rbo$x^8B_m$cYDU&-q&n zafw3S>BZKSLrF?0lNSB6h!!qZr=Gb}-^x(enYN|L%QESIcy!=QY_yVFrz@4{3>Wsj z!HIz@)~KbGhl?a=LC&k3F_sl1nacF#=XU+C0){O^h;anvdY%bvB!1h_&gV4k*7iWE z@@*|Gsz&u^aZHN1Sz9{wm!)y6DuA}e3siS^nO`}a$~Mt@6Z`B^j*RO+KXYy3(i4kv zd3E2OCoa8Tr7yF@BsSEIK5EZhLmaQpU3$Htu<-sj2_E{` z>0B(y%!HN-rnq&@4Bsxzmo|!CYQ}&|E2JZlWbFaiX&M@M7(C2-;U&Yvb^F+D9BJ0} zs|YEW5v~kv=iPg@zflQC{bb>Yk`-49`k!^>d`}Od+#(yNt+I+(zVPAcPr-V%2A;NT z;%y8zu^L3V?VL+WZ`8PABzJe1F9L~Ly))Z*H!Tabe+|p+->rGyrA0(6+;uO-(A}?c zgke-Kg{IprXV0|6(cl@@uuaIQUG&9?WY(1Ub6ELNH60;*`Ccd~ zX}DvoiTOt!eub4HhTI1Rg5)dNyOAijGFOtf89iS*rt2M7s=^W>yH1%y=>9*NaGz3i z&r%iiOSJUQJBTIPBKgZ(@}hqs-_!e}y_zAaA&Cx($eC0ppQcJt*RM3m`bfr@$t@q;sOXXKtX&WN9AE34-zr7BgxR$f%s56Zce zRiMHWcc-3T!N)yv{mw}>DMz8P`J`VLD%Ll4W$Nd*@;Edo+WZDfG{xWa9eR)4`@U+k zNQDz0Bo4Mf*{Ia?oYQowi<)6GoEjp>e$+B3a{>DMh?|8)A3HiD<5+9UVB!NrF+(Y) zr{wUmskDEmxOnBfQe8Z^)+T2UGRQ&m#xo#y_x3L@`|hsm*U>XHKmVY5zg}J(6K)bq zk}!6)Ok{UZRC$%9hcGwOpiJx^@#WB-=X%T(v+W7B%)!UYbBA(R58cKVYIzp%Mc`ok!%49RvNrEG`-iiRB}vP zs#FO}u_naiPx($|uh0`h``$KwtJBtxE()cY+wb#bBcz&eG&S|Ge3LHkTGAe5SE8Fm zgy)aK?i-yqPRh^v)!eAHRl^Z?G1Wg&*Ru9-GBboWoA%OeXzp}xq8KqhHI?jvf^xg*7cpkGEZ^eX6&}z6lXys)R79iM*+L%tF#WBsT170 zX_}-mlAWt)|F&;D`rYeLA5N9T3BtfPtm7;hzav7zxg-CKK8_!9$aQ3y7SYBuHSSw6 z?O*GPTUr<>l%ZHcR#(f{B-uJHzo5M=<;_Y*M39bRDMjOlcqJsN?w3!RwkMjHhMSWZ z84pYl5ql6ZzfDM`eI_16(B0+sHndhQQ2aS3+l#M~n0e$`=olKapVhA*n?IC#uX0y; z<_ld^-WmPS&N51E;SM*X0NmQA32?$vInO-pH6U;|ziBIdeB}zPYRkHdWPX{OYVsJ{x6g#VOJ34eAP{8`k zzp{bZk4gBFPN&3;nRp6m)gj|pk5c3Cvp1pG9epR)M1((v1$ zcxHUZ_cwKq!Zk}V#>aFF`iDf`XEAHHCly)%@Kdb7Y^K(X~k?eP&ZY#CVU-3#M!oF}(^A~VQU5LZ3xu$!8ho*c_tDa=N zn%an-B)-AVHQC>#ZflJJyQq=Xc7}nSDZneeD;-q*XG>Co`Gc{EjiBL+g+DHK5>2wc=|n zvF@KH9Fg7utHkZT%nSOu7se=;UU!iL`W^FrUEj+}pI~a|DRC+_k`A+MEKV2$bV7f| zh^&C2rEay@qk<2o)oU|h0x9(#hhoA<=^RhM-&o}d>bxJDy03W1BHFayZg0g7)5I19%l2eMjzXO zro(qrrXH;|Ay2$Kc5!8PckjeC{-mdNy7lFoE2eGdwYe5F>I9}f6m4~@^4Si?f278d zTAKxdhRWqi$*dsi3ridyoYiX3t4Q$^__$f$Aaz?eizf2jV34#z1s7`5Z+V1b`2OB% z0rl%~>J%+^8t;>VE{8HGe>(E$$O#pTK2-E|*PVElbxLNbgqxQg?E z;&=1H#haa_OC#9~p4lvy2Uh{V2?FeXbOOQNGF?)Z2frnz<5)N(f)WLrqu)s=U_vp( zj%pXiF)LKi?AY8G!st45-Q>E|Ae+(TVwyHw5hVXn~ ztPHul0rfI@e;7VtU`}#@GD3+GPQI=get;)oTq|`SaH2PlOg?#S8H~i30a(&8b@Agv zit%PXD>N6d9M_8MGq+xQe^B_BqSj1QJv!L_lfIDIt-b@x_d?Ee@7+m4+g=@ad1Khl zN@P|zDpsWFdlJi_eXMQa?G*UQVegdcpM@?s>pF z^7!R*}6SO+zAGCRvzrBQQobua!CIb^!#LqRW`$R?Kd6|{c8-GtreFz!~ z^eH9s!3whbDf|MPhK6UOqrWvZho{+v#8^!`RXvVgv^DFrc;_!ls8cNW1y(V?HIHOZ z0$~9CcPU}Z63c_slG)6OH_o`Y5lcRJ^DZS1ZZS>xJK0p}YO{1)N<<^o@-%rdFY_$d zlP0`3)Y#MtlKiY7_R5|K+beE`0x}25h~LvXE z45Tbmd^%j{D>~Trk!TVWch6jEs-^qKSspznEY>qJGW#jA4|HQ+mmnLD9qvG^{&?Qa zB&iaL7zubUvX+QP`jAKwr1wjQi2JIqUd$IO;46GNjD)@~gJN#5k#P-ZMEDha7hkjY zb4v`a>4_0!PWZF1U=`#vaP>RPsU;Bkf&%%($Xr*9$P1*Op>L4RslhABw2R}x$N#LZ zu4CZ)EL8>#O*YG~6oF^#NZFB}LesEbF{g?Cng`R{*~yanmsIg7Wn>mH-5i~Z$E(Ex zn>*sWU71(@#3)6)5Swz7ZkEh0Ld@eggNu)j_E&?eIMq`PMQ~#~G1^+vsciioUlF^) z1j$ZMrR^%m@#{i##X+IGfK?Yf_PudxW-cXO<1O^?iyo*XSr%4h{eY90<_Nh;-6~CO5CzWPDb`#qT6h?(xY0;Xy^% zu26+?p=ZH@~o3?42)QBn*xFOKs3x9LO;TRmJbLA(|E zKkLe>UW#A^rs`5M?e6Uv85wO1d3@?5HC{Oi=z$zZW@a&iCQ58M+YMu`+L|;gw_t4#ow`)pLiduwYTE%E1acv-_B&#lID}j>drSANv=EC`_qVC6#USa|5*UKVR;BO7PkV}&QN`{}3Bt{m{(nhYfy5`>_;mrzVGkxr>$F zS6$$G$TUZo4t1dEo0_8=2r>_Ea(3wbw|!4*93+33LME7JfPU0H-Az_gqTn;58DBO{ z#xEMP1x(0pKUMOlOJp~pU zIQgr<5whqN?!mp9H6Z^9DT$^3yT#Bg!$Vy=1AQ&FrmIki%L=|G2Ka=N zDt#`CFG&_p#P274Om)O`+vt(+k=XWv(oQ9Zx+*ok%@Ge%i--7NfGmI9-_tcaFYj)f z;(`TE2Vc7Y^uWrw!sEQdve7t&8{a7B{O8vi zcl3sm_ifPS-=oU9%NIR5#LqwLY+mit2KYwH$c9#1tWfA}Cqzb;&KX(`@!WF$JqfUv zk#PM!plv_Q>9=}?sH2_>Wx@1pH}_$k#Cz=4C)u{WAL6!td|; z#2a<_Ei=G8>$(a@$V>Ufk0I}#0y+|&0Tu>Hn4nxFj-f#R@m8687+QvH!0WNyu|3)< zw`Z*;c`vW@c_g1e_87%@1>yL({kDn<4*@N4+bh)|?lcUfdFJ)c+jX>DzZBJ+my*8N zL>A9CilPsOXz#%w?o#G_@jl77RYE@QUF(4vwNK)C69fqFI++o$m91Gr^NpQMW>>_x zvp2U*32RX`!|rH!#n4b7`mW|8AKo#zv7t{ritU(lz8V1k{+92)@!>D45}|VgBrKC~ zpA<2dBG}r6KYEnv>h!U<~5DcgI&(->n7<(ja(c(QL-tSOk>G_5o#mNj+jawcagV5p2?4{&vapWP#03y> z4?Q4!0s|0719&+=59oP=<@!HmqjBm)KV|YuFf?o@gfT}Sy^hr&-4}eMG*=J#R%nMZ z*>gC2keWpITUYlNTbCckZ#)%@-h>ywn>?yDw&OJFbyz4}gHN9fC^O7LX^gQ3};<-ZSE(4xRZON7@(0t%9WxC&mUBJD@|Xul+2BC`e2~rW^O63pg=E!%ii9e_NXvw zE@#A7nNe-I!y|LUGP=tTGXRlD^GH(W!dh{NXJJUE!*MdpT{W4?1L?RyR=G3)M*+&6=YPiyce4@|2cRb%v|XV$vn*_jGz zM|GZAnXMnD8-T|H^ukSJ|o2ZTBv1aoN)lAa5qtbq>x(GyGXgIJZdReZ>1U_7D5c zhYa_&VIx~AkPVqJ85SEdxX=mrZn-rmj$yur;s?{Vhw)u!a3Q!ti6@aaHWk6l;_e+B z+L%$o`*5dmafHk={sXo`#d5T+u1Na%L7R`}^GBG=9ig;IR+4|WLbfQ559q4i=u(sZ zV5KTqQb|+|9uvUhM_hlq$N^{o9d~62j1Bwj6$!eHD@EA}WFG52HfI$-U^&3^-09N> zIThVDC=ERvyNQ~hK-dxjaGnA1s=I6#zxJh}UoSojIl*uGALgOiCyk$cR&+Y4JOM0| zDIVjqDSZ=lJ4T?w{tr!W85LL4HjNIh!7V^=4ekuC!GZ>N_uy`WyK9064=}iU&;Y?< zaCe6gT;|MsKi~PY*Z#NH>fPN{U02oB65_PqcB|L_ymDA8C92rus_Iz!D$E&vpKD?C z`XaCgF(Z}M%VgDIKAa;Qkj%QS8}XUV}>Jy}!AX+8<=w2j-1Ct{G1R0jG+FwV5F%DUg?7iT2d zgCwbe?Ts-9;ia~xFL<=^G5UlUR||?c!jG3?WjuSd@bsV3h3@lTHBPy zL|$Tz+D8}8Gqd5@`xv6K$aumO>VzUxZ-PDFv5r{C$51IsU1#?)qG(ihK4EYi1G+>2 zOld;lvRK?#(D!V9dRl^q;1p5!U(P_&@FDkLXtNdwVjN)$7rf*I?`VMmXt_4KHhIet zzX?q;!ZgGW?VN01rNT~6eWjZAQ+~NwfHp?ea%C1($Tx)2jVjE=H&oX_0!G-D=2#fA@CL#Kzku zsxj`p|MTL~`nr_}=~Lbtr|qJEq@8l>q6IH07dci;(b4x!y)TP&qp^)QJQU(V{hgPh z)||_w?&m_=KJyn3NnHx6dRv(+&a}C7(W8jCa`}D4BgU8Fr~%JCA1Ki*T$OjzKo)(v zJ~NlqJ? zr<^VRgI(+-=oaV!Byb7+Yx2tTG66kqeK3FyPyM@c0Aa6S_31Jbg1o_?U&5jThbSU(kWs+_e>1aoX-N^3 zcR3u4F#$5;2&hdu7@8+2uN&fDJg>Ifz0Z{5vc0WczOptA-0B;Jv0qZcX~HIGs$#4c zV%AxxHDg@9_e2W9UmLqhPKYhT#4i2Q2vFX0=HGVc=jHy~^;mfS7WR8uktQ1i6 znsPwwV&WGG)yAC?tRR!t5`gi(%#0E}_E}zcyX-hRHj<RNpT)^opjZmgtQR(d=91yS1>&$0A#7LJ_R>U<{91 zOUunmZ2#yeJg$*v)>2k|Z>_^K=h`xg34Qb?ci(){k>84|;0wVJhA^|09(SG!P)N+0 zzu*fQg6o<03nRV^d_FhyEZi#}cB!~e15uB$0sMdnZmd^vT4ui`qdt&A6b8DJ+;QVURp z_RG_=vFKt#J?wyCK^j{`Fs>D(Ktz7OZaHrwLK?kYDA&9AV=g9Hikkn06N)L`P0|;Z z-(dfHTrs_Q@dO)TsBqIYO}${Ij!|fxWRBz@E| zI4L!3)XGmmMMZsVS^3Mokkd`N3t~ri!PQVe!Ha>(w*}dY_V@{_fr{#J-086=Voi=Rg04vCkIg z2|ZnZQlyv(5iAbZ;H1`4T)xNyrxoKkQBjMdsZf(Cw;m4ppvnf1{xoygUwp+)7Qo7G z@m!i2#3cIkz;Uf%?or(u7)SYKX~;?H7nZ9s;>>IdR+DN8ce@VzGR&C%lIKoxsvJBv z<_rf2x(`~i;=Y)>^qy8sp+hR4qaPtwDys@D;nh4CT4*?gPuH{>HLthya+S<3(@gkL zX^#l=?uBT7=3w_Z7v9{50qfq;5wk*rA2py3qOk{5XrNKz$?k}(%Xt3q57+f9#?Lcs z+}$wcc`WGFpRh}i*x8u%d|&Kei;*!UCIIpwcxo`Nm?&OLUr4R}5 z`4It|T;(kFixh^plSZXPN+KgE| zopu4AKyXRCrK#XY1;i+PUkIhM3iHqI;XhT|aMxHOnx!fQR&5JtVd4y+U@Ke$DT=orneKQ`TAakX~4`&I`Kc z_+*y7^x4hPu;{a5{rP^4<|DlLl!-fHiOg?tZk(+x9-Acmt?$q@B7lc)FNy>$6>j4D zWL=A#b;t9RqoOB7E3(W)-NofXQf%L_SjRtGPggqr4Wf^8UUaFH6(eQ8jd&;*Nu z%l82|lKvBCCShFC&&wFmtJCc7w9zt1u z$OYjQ$v9ip1H73XH9yB<%be6Srca0CBaM*5*wqP=%Yej<;c>qGG;E`lk;8AcESskp z(ggu$$ZCO0qKiUQu@<3BQb^Pq^3_~z9Y)*kSky>6mAXj-jL^!+%3;3SeIJSEN)X#k z-0XQ!@55Ec+W`JXc?ZH3nR9v0J#_imsOM2-Y-;m#xUa_j0v6^AC+6#Ty5W^LFpb1H z^Z}Tj@jp8Mhb-ze*n!;8jfupUQWNnRSt?{KZ@>y^+*=XC zc_Nfb(B{w}dAYtq9E6q1JGkaEE{$~^P!T3%I;X3k|$O*1TW^QVA0^sL-dFHrUF zukqJq(v*y_lZ()Yr&qXjW9$!zV)PmGmhD-8n<0$XkQN=L{a>={TVo9w&)sXc#MR!< z2vgL$m-oF7vNN-&Yf)UEKLn{bt+W=5{qt!?Fpb|O!}c4~Uqq-uqjuVo1L#ay&1pkf zOp*WO-otU~fcg$akXq{hJDyqbesyR`VG20{F1fZj2zpB^wilPgdK97+7p}jWRGk|s zN1r=x2-;$xqhx_<}&iQO*!{O!3-a$@DM zFR>D+T!T3->%;DF`QKl6m!UUAfIqJ6C}$A3|4B}iB+zw}xAKS9x2(;(s_XOb8?gyz zyMh2O*gjdBfd#LO)AR>)tn+i7aJaycwTQo>L6V5CrkX_iUB;L6Zg#h+R02XRB?yml zqgiLI4$}F`?PN#7^ZHHuo&DcHe%#)IFIPo`{T+4{WE@QCB}g#zHGf~PTSlj#l1fCz zvSVDuN`marU-(j=Uu6ua_)*#YElDHRn8TWzg7fG(?}?X1uz)_-u=*Rj``@tubH7^2 z!uLs^4273qj0cwq$u~A{syolw_~B#soFpbnbkL?SR1d`}X57tCy~!TLh9ZGJsP*0S zJSNCoqy4p|o;@lgKmEfcYd{Mqf579??t` zM~A6(=zkSau(Eucz~8JVxg&Y!x8ZF%ZRZP* z8v+UX^!n%iNgYFRs+bc}#i*U3Gak1Kqk$uq^X2$anpy*nDZa~_R=>Dwe~SMyb1vcQ z6owfG+9oG0KT{!uRCJ^a^2rNndrC^)w?Mg zRwW~Um>_u&&H0#H8fB0e>^2};mq#zas}uCZZGo-}MtcWXIA}vmZgaMj+iDQ}AKnF5 zi5tS@Zm+2;0Y2w2RfZMy!J60n2T1`XV~zV(3UbpFLIPLl!5^6ShovAq`$MH?&is*}5bCXr8PQUy->U@R7eN><#OfbHsmG6^P2E3u7&X@IoVbp+_a2lL{ z8eFHa^zeZ3sYHePNm3$f+eSL)u$uNphquuyb`)$A$I@4_zDaL9PMwn-<^{{MguNo# zi^3r)a+71V1)T>Q2sqdAkQbgJ3l~_Zs=5*rtLbdqdGm%}qauq|Yp7{0d41k$z|2OT zL5B)bb1Ir=6ms#&cJ#B+WOo#OL?5FmXW~Bj=*_R!wslS0L2N^#g8w6X_Md zN7!}o`Wzbg@&fgRH@(OehQkW^878Ggs67ULf&LHN{$e=&l(H)kB(pUZVxwjG_7Eob z8IeX)5ic^U16p)zMf}k1xvZ`jP=r-_ z2(S50%UHdfURljlQ|1FiQ&cI0mN;<@_;GGpGXdqD)_K)li}dt2i6VFKvtQ-Z2PZ9Io@4L!=dF-?-002< ztxzCvh@xQY03%$pVid8tH)`p``S>10Gd5p5ia~Lt6pA8?c{IDUP&V0 zm~m3&Z>GlhqTkGM@eP0Kmn%s>n7BNzrN~=5+%YKFbLB zEue2cfws1So`e20vIrpSqERR2x~pD^1Y7%8{=d^%k@}nC3nRAQOM;32N6?`p$EWDL zmUBToDJFVCNgSNWOX4@&Vd^;2Zl>rdd?7}qP^%E#T91tLdLsI0iEa3hbKB^ZOJ+Jz zgmf%=HjUspIR13adWKW`zw+vON^=a*u8P2{!a##edMmy5qDtnmPwD5jKWap)0(r!i zT+s8sF30g-i<}CW!eq~m8im>T$AF>7d7f*=U9rwII530wYyKgcW8X|tGGaBCrq%gp zi|Aqr4%>*-Gan}4$(Q$E26az{Y5?H*+Zqngn7H_19oA+U8j{y* zq>3mrHKup4{v7Ks@y(vMOI=g>$oxehT8Vh1`Adp>KZ}T1nh~3ta0PC`C%~4803SWq z2TTTgD6%-C2r9{S(0wnwI280T+$VMu(PfHi?Cbv|Ey?-~C{(GJkFa+A0vW4AP(U&| zka|!8^+&n}V#vzbZ|6ytD8^T?VyK=9=M~u}4R?59Y%f>YWkXtr)d@1ZssCWi@-ixL6OE^jR!q4pt;%DL zfJOes5g>!qb;4@7 z&<6NRHday5R^;d8=gv*Yae|Pb!H=Vv0Lx9N~d9J-kh(;-D)2fk;9GaRM%8o z(zx`X3ujm5?>ggJUveiK&yGZ}5^Xg8RNHZ{@g)W%6pH_SL$F&%|4VPD96e5|UuGwk{UT!Z#^A0Pa zP0CMEeYimwR5n$wt^ZM5xp%7+X`j%~b5Dgvrhx)PQkW4qANCPIzOy+6ufn#hAFI&H zf!n;&rG))8c0NVxI4<*2$tbB>g}RE8`g;E=OZ2td#(rdF+FC`=kyZ}ZdJmD>OPA8e zgf_%*ioUBSKAO?Mqd`qZWa2eW|8x{AkhgMjZ*}VXiq+Du)3t)tC=^mt%7C5ihiD!dOimqWb64Z8ceD)=hIz{cvLiu0t~5|boZ{>PGxdu#+*4y+^DY~2th zp445&+z*g>XYn8R!(=jYa=&TH2{OM|``T;gPJPhpF4Vx%u}SwGy_i)yNG#(*6wFO0 zVXi3QiJ+Rw`+gw%Xq>I%{O9XU6PH({C(GgQke$!GqskwaYGdEJSJ~%9EvY1gL7uC7 z;z$$-N!0|z=7#UD-lxpy*d2xQ&o zf9{FQ4!011Em7NK2A;BHHG= zGpySvmqGJarA|n;n|E|Kut@yk$8Ina%aUl1X`Akh9zWuDS#9L_A^ExtTGcO;lcZQx zgyR^p>*~=e5(IMpJhwin#Hzn@H9IDbtaC+$vtsN!^Jap%-pFZol(Zx)*vjgQ?6Nb@ z7MsGQ#DyvhLe2DAs$w!ON#?a0m!~*RBRg714g+)wxzc4v?Z3Nl8F7+$yl-X?FP2RD zRj5?EN*xQ|1j#ZYxOe<}A1NHlgc+Wm>eMPt5>av!-w4aLvg2_neViTBfPOpeQYzem zDfb>nl8eW#JzrK9OSjKiND=kBrVwA>oPIhl zTA}(_AR-XTQJF~)4I#qD;BdR^!GF+DhP=%Iq~w4AE4QD{H) z-bHZ-KH?mCzMcU$G;R#mhE?_iM}HbEoeU$Uvd|>-&j+*PX!36oW+S+z{Fb@c5Pu-I|++#Yz@D4bI>4kGKXkhw8DT!oDLPlb=^2T}aUwuu= zxohXwM4yXBsV*p&25M9KQRV;@jyzn5$Dsan62fqxvg#fIanic1TVxZKk^ZnwuaFr0 zP+H*cQ+kUDdbOc+0tDlH&MoFZRPTiL9s?Zz1msFLugFDx z&+nRY5Kf(fA+bRm!@6;rphSA24n=*6E+kltY;5dFDU;)Yp5UHO5g?i*7Hh3wKg zRvww?otH(nT5$@~`6bAaI-2xEMPVc9rsNEz+duU}33u5f zVLE=d`roQ79@4T%HVHZ=1szg$4Q%=y>o2vujYv%+{0Nkq{<``Udz5g~FaGhTnnFay z;zuXr5hFp4gB_`eynkw~SR~yq_=pA13R0)2aU;_rL+PeUalAw&{me+N@gjm$KDTkv zS(g^~-bY^2+GSjsiK9z5lWw8%kbeWgq4bn)+P}|AXpP)^`kE?6D=$54S|A>%L z*zN@A9oaS zIuY+AyX>ctk-#6K7+rd#b*)KTU2bx(_wOLugT|_qA_|VAWdNbWL9vgiKUby1)Oh4l*6J4y-j{IBOURr@L1=@N_b$?s%PvV!ljry|=Y`djl6!J?^3jl~ z?a{|Im@jK~xGmt!49>2IM)@C+GfG|k25!LLm+{?w(1ED-GN1k15MWr&OKVs%npZ8| z?MLlbEMnns(n87Xa$t_YNgzY1(E&=G9x2|&ysV23z}apoxfAY01oZ#{K0JtIHT3Ef zBdSEGzBnVOl3(;oHiMu4hm!KwaiF`4gI6lGm*#?Y+FV+KP~2#=wnQ9xW-AOp{_1Nh zkrqE<6?|TLbmjVE@2r*!yd$}pm-qIta)*G^+q3zr=AbBDmcJgdzCQBq9&pVJV;{mk&0tuBUSnOXh%J=JP3w3_jZCNS zX-OJqeXFEV=3&=n8KaRFq-`2JmWboTj4n=AA;24f%VVNKZ|;Scorb3>rC0Q$s<$4f zx~nh4pK-wS{K_v9Qdwib7MfkgFL*U-gr3_>b|`AWs`2#9Qc8!3w8G3}n!;fCIV)E+ z>yHi)=JTzlPd-Jwtn#HFI%qcvQo*y|$8Xh^(Z@r|D!^z4i9=EalLvn=#KQM8{kx1> zK?t3GraCG_QVn64AKSz(omRo&4{dW!{!w;;tf{YYe#@E0?ngi?{KE#v2{H8rWVmHZ zlW>m68C@|(@+CdGfuMuc!;rYcDZ7Tt+7V19d^p^f?|#wuYXUi+-Q4#tSonJAa^sS9 zOoG9V^+wO6T=l8Qw_EAvRYwYzR;yiwKHI>IqU&Nq&FocWKRzotIutyNgKnp~+Wcp0 ztb3xn+TZkz$cW~`8IvZDy=aBHj{>Qlvw|+Dp%c&>{)@#o>7d)oSAOVYZ2-OnE9hz8 zU}xsIdQP|Xbc-IvvY@kj5n{@9E&E%ur8#bE(GR481F794pHbN#T8GH~SlOdLn%uorXBK{vE zAw2;-AvEZOt|T~ek{C`>MQZrSD@j5tBatD_kItWH*|sp62oxXHV;mnT-9*KbvtE$4 zCGb|OVz06i&61|#9qWg=tSihrQ1%Sx!(#uk;ZDlN|| zPm%b~3AK6+KZg<;3jX?uvxDkG%6n(|t^Fp*>_DK*{4p)H$+vL~S`30t5k1;3ygWJw z{2FaI$P-BVd4s-sH6p|fUFf}EC7;k{#S2SK)=BU(-h|%t>EP~Eoj-Squsm6;o`BH1 zj<;3??@=YK4ZB6B|5wdCs$Wgu5J%a?3D9=pPsN8k3vhHHVz=F9FdhN*H-JDu*fFp0(@P7dj z5(@nicwl@`$#En_n}_te_Dx5iF|{iJ-jMN_?`u~-(KI4iLKOd~(lW#2?FtR0Y1u#W zJ@@m>$OI8wO+V(1iPPc0tLlC3)l|Eie;k?k~GeqP(?UU+L)YmY~g{GN6wJluUNs&;8*AlT5gIo1oVinq zy91+GZpL0&dLJ+@yx(R{tBKxwe#Plef`niB5$YLV>jXV9K$mL+(q!!)zKFXT5qTD? z>MRcmQ20KGx85>C)2@ zfqL>*;-6%A55iWJMsq&2bqv&Ct7fO1tX)xb>|AnKWR}anIr z`v`O_R0q$b4k+PbP{WMj0(YO{BSl$@&gFd=0tuM3Dq&gUfi9lo;+#3q9tiO zxkhU4a37mod$*;_25D0~R%Z1dEOsLY1~G&<&I$$j(=48ph=RrRJDaqjK1y8V1Gcs zJL;g7UsXO75)YxmO@lmdP{4!O)x3TuffTRKuVn!WkH-UH1F`?rWW}k9CauA`FDiR$ z;_GPXA$5eR$LNxE$N-HoWfTd)MfhOSj8+{xm%9_Q&CJ;WiWAeUtx2}f)5U4Y;2bts ze~^#A_9L93O2@0vJS=mY&@NYm`d$?EJvQ_4|1;U;il-lmN~gj&D zdKYZV<26kNZ;WGG@>h>HR@#dJAu^0zFdCjXkI)5KFGlq3;sm z5|z44|5Q;?VGgF_09N;U{}Y*_WJ)=(p}kk@rGh7weP}c&AK>b7q)b}EYA>J$;n$&} z4fZ(A#22_ZcfHPs<4)N1{=q_RDsA2poFqk+$f<~(`rCgob+k4*jhJO{sQirfY{S>S zQ$^9rkc4uz?c;g-MT!ay=jThR(|8T{d~tz_olJh+GsYkZ@6(e`W%WG;w>}IwgK{=s zyT!NsH$iy=<#Lw3D&?#D!_5wBo!(g}*c2|O5VjJ6+yaxUy{lw_O~1JN4gWvp?L{>X zoRO9FOw`k}&0%`bxiKO{TV}O>{44n5@3&@!B0t$NQJeA13JuBaaie}&YvM%3s!$!v zW=r-CxGY)l{@Z{zBdOz|XwnBffDyY@o=CxqolnNOcIzF);K`6BOTX(knF|rs-B<8S z(xvIcZftY--wq4cWj?g%-R#OrS);{y&*JQ|A9h_M1Er5?4%N*W?lt}Df^u**ed>Z0 zx$e!iS4K#hlQV`t-*Q@>ID%(^I;}|@AyTO7&6imkqpX_T24QH2zat7?b@#Az=jDI9d_j3v6vmUn9hxXV6(tu&C*7QT+(phl5D!rm|Cf4|s5 zw-E_t+L{K-nAsiDKyweEDnc4`+-`RBX*o>f>GNR7Tm22v-NWGXI7cQG(%&t>ZQl*z z;3U>y{{J<^mCbYu@EE*=Zd~5vK(8qO=3NFQF-EB>q#}a(P*6|;9;;0D%X{wlj00~8 zFE-kx3km;kon8-<{pH+LL&~-+3V$t`<;*+tLRMd+bElU*EUBQcR(uqPgmgnh+BB^=Lu+ zi=LC1r%bG7O*RCsQ{L7WMrwyD`Z@bnP~EKv8)2 zfIYD=CWQ`j@pB&Ep1|A7@1dlq^Ew+Xg&`WK>W0S@mVL88ff1#DDzE!x@CV&0Z4WHs zfsFxfBC8ovFNjxG)Pn`^J>dn9_Zyq3uJkT@vrpf95JIHUre|>#B?;u8ewfdy z%gm+?i2ymaDj#Pt(jGF<-|V?T>c$Ur8bkVC%guj>A;$1@kDpt2iq)?;VxoI6w(Rh+ zEHEW)(a0{hrx`%mWw^=~;R4>=V=V_N5WTgPTijMSrHe7YBKIt}j!EF5Bm#2owGsSc zBC1G|>6}?#=~iZ6KhV1G4{$Qif(Y6E?Ga^he7msIn@h=LH1=en!`_%{c&%kpwBY4k z8@%(s8^6^%sPq=sQUuqmyl=bPGpM_h{_X#*m!0-79cr0qcU&BF4lKr@vX%7dmJBYe z?+X=H+X*02|7BBS{JV6ifBrDs8MF+ImI6&f-f3#(ynuDym9S+E;B*)jyo3Q(2BWyz z=zdLFx6$3QM6a{Efv|n+F5w0;#=OM}Zn`gfCokXLE@3Z$1p@=Lu!Pd&FI$lV2pF2w zEfAN&Ha>aN(|!MaXOKJv7r6Petj397c8qA0pB1%EQvV9z(17$PN%btrfoIxB^$w%Z ziUbEU%<(;rXG7;6f$%qkA!G~JMsmv=&|(>mATACk$o`?~=##zd9ZGTg!TSJe002E`=UPdX%TvPv*J*DeURh)clflHXJdl_HK0V}-%IfIUHbJT z`v4gCo>FAz?B#{0dvZnpU+lhPOzE_mVwM(Z4-KZY-#XE1G0e>(9XWuNz*N0K+nL`d z9{L$NFiQYQ9adreS;CsTA^Gl zle{^ae*rk|M9jlW={X>rTu^SKQSW{HW60=hhRMyWHir)9W0+2gl!sP!IQ+M;DAn6=N zu{Sq6V$pZ~4Jn+MybC@*hbuNqQt3P|>B% zpl87Bs#r#ShTthNUx~_QW~HkTDC*=!6lY9Av4dMn39uv5hibcd4o!OZZ$RBy&MGy^ zj_AS4UCD{c+Lw(<29kf*;e!q10rtVOq;af@T}={%rD<_m zeS6N$%d6!o8Q`=OB;lk;vTI#+h(YZ;O0^U_{QEbz@#c$l<0uBBp2D_FfKZBgCz-3D zle-1z_iY##Y$i@vThKqQPVF{_b7gAeL{ypUWqy-|qtX^$XT*DmlW5U45oXQ`h+YUa zMSENw=>T<-z*U11v@}iG9#2WFraPVti<@!vPy0x~P5keQ6I%M0`qGSrv5NZA2Gu1p zv*_$Dob<$0)6Ue5)1BX21bsoh7AD%LUz%GS@Cqvbc2m0^&)j63hPS~96{u$h@LzwQ zRL(v5X2V8tMFOwJ17JZc3rJ)`7cfRekRbpOw54I@^z=V za}U&h7q(xd#iKXzmSQ$;o)%0S9-^N?orTRT~q z1gvlN)oPg?Gz{!Ms06ai;|-W&FcE=I12sT(SrA?32bjd@`A-0}vMR19Py*pIV-HhUN$@9Yz)C@jRDbYuV&bMa!XnC95hB(F3!V%H8Fs&_$ zPF*7ffI>)g9llQ-l7A?;x|+ddWGpu{GDRU(a76B_+TR47 zmIANo1^M7mEvJGxe_{yDgq%VLdUz`8rZgfP&6QCtO*FXFF`*FuF8HI!&vtC;D*OuP9?3xb#noKsXRmMS#n}pu1y^1S~*1csn zpH{^tNndV`?;I8z&n5Y_7u>lg6{A;qWNM|GW_YXJP{U%&RpIe6#)34(;Y?~I_=v+x zVs(tA0SotgR@qq^4*r*_JnCSi@ z*9AHmgIX*h0>P~HfOTNr>A|4Am~bcC~TTVS+7diQV-$InGh5M?(hAJ_f2KhJ*-MO1QH(}=H}&d7ff+} z+O@^LX!j3MCE&AdUG?ZNB25^!$yQzT1Eet8A*Gtl**Gul4LcQ_`b&F_1U|j;s}mHZ z2iVnc-M4gvDl%(P1FX+8^rSPzTy1()Vh!^SYo+e*zS~Fc{FEK9l-l`AP03+BxDqJx zPE_O=zsnE-ngR)* zEx$q2>er$vT>$K3wh^gjXN{{4E?+xGzyn$bF|Zh zO>}hA1j#)hze1hDP7{1njrU+CErLr2!0K2N@zhhwVe}?+*>N}^zi_;q=l<{pc>nR| zra`MyLu=>2Wa2Muc#)|Q-Em7Ht9&|3y-4Wp{XVhOi7rOAv5w^(jPetEsyr(@!oQdW8xsP*3APKRU)>y90K|45}qCV`Udvo+Zm+slRy@$Yj6}ArlgvX_wZOGP$4~?8#}HGwF&aU z;?J}cu`L1@1l{a9a4)6ai>BmvIL@amrKZ!YpgYFLBXL|AV#M(2>{s1zmtfQPU)T08ZcIYM7S}sC_NP zlTS5o{F49|ut|+92?zpcwCxofF42tGcauohDUSIKU*^)GVN;0F#nQC2L?TM|In;Lb z`*g|Tg#SrRzu)YgSat55IA3jrO*>CxK!FHSQTUgq(@zwu>(Qs32u>7^u63QVy^GXN zGEA!7>5JOkE3muY-71m%Pj1CaKZ=Kayk^6rW1;BuT3%RudP@}4WmoXB(z^zJjI%1v zy6m+oeZWcN2qhEv_3`@ZdPky~K7cuou;q|hWPgqHbmr67ABH&`q8OvP`vM}yj`Q*g zI1k}wy2Ws?N>R$8Y<2TSGvooXl37<2C5_aB)P<3&Sc+$K@{XV`Mj5Uy<}e9*QVXrs zwTPkFM5mT1MN&(HQk=>U?S7eC7&Fy_(}kcEneY3T7*@Q-d>Z(Q_K<&i2aYHT=JiCC zNHx7#13&qS(Zu7ZA5Dihco>H8x?6Yh07d|V%q zsg!8F;qa#{cTJk{>*ejO^;uexs8ze4dzFV(#*1ghLzbl!5ld;PR_aegbz%eLYGd^m z_X_RThud2N0~(I%w2c0nJ(}xI_~F{vZ(78|m=ezkKTG4{X6{uMw z`mp_L22HVU7m*Z5J@XQFQM-lGkYM1I$Yhx zaiwgl5#xf;$%V0wLJt#0`KihA^CCM40>)*<>ri9Y`zS8sD>jRfoFAn*=6Ru^%@d$U z4dCP5DhctV$98NUKEg91y3h`E8pA7As&=iA{^@QLWdxq`%P zInz1d)gf-tOB!?SKLYWkGbv+W1yI_oIeu6DJwbG|B#0c&M;~tMpmrXo8;3n4iV$`q zd3zEM<5d{{lE}!U^|v^TJ4nm7x0_EGw=4-+z$LpD@lLs9Ce=Po=k0DB-Pzkshf*SJE$oUk(9*k3Q zw^EI#J2i1hX@iU!M{CUH0bRrZ;6_GktWo4;3c7j9O zp58v4#U}9%7#f>#uv07Jp7X2I7R?<`+c)PYKLqOUj5frxj(<}rCr4onmOX6GVO~{* zWG&`_jucRyy```|Dc781E^WT&rT_*)_4hB+3egMh_j---A)!D&E#{;mm(*XruvTSQ z?_6$EqA+RT#RsuzLzx)j4K9e9QFr;(*M8u(qLC`UFnxmMlYj&gZ0Nxw1t=`25;4qt z9e-wIRn!ULWHZ}ns1$zBz4sNOS1Px>VbcZ=PkC5=kgz#8bTh@sO=K)Cv4%0nXBX6Gc%=F@q9ha1X9tnQdE7=;l*ArRYl-4 zHt4BPL{Lzdg`0n{@4s`UNU>fk3((Nkfth85r~XrQ8vAvQgjoRg>FB=kTR%&mU}TUU zA)w6sWHDNrfM$hFrZ&p9HA@U`*z^Wo_-8d}>i?tZEBxB*f3Dl>hx|IK!RdZo}P% z4jB%^-G<9>hvDw-Fnq(^-F-;k-oNMb{s+C%e3P8yI#7p~#EuFN3 z@@8pJiP1h>!SI4qktyfDW!De^g-$b!-QF8;BWK#+S!F<$MwBqeSwcS(71@3&P5o41 zO;=%+r8}hg<5K^OYnh{lqkLwSQ}mS6!?TJ$5YLW!^;V3%^Y2!-owOY@pl3$Ii5MG; zF+{OJ=wsBk-+H%}6nG9Ay%iUS@3F+ZtiS8mFkt=y_>cq7(IfC0GvS*#5ey(X2fizHB!^>e@uW{t*=4 zR|Yy;ck4#)!E=$xi}(i<#R}1q+2h?2(je(1ikK^3|Kb6Bl?LQjX3aYNPk)IFagL}8 zWwGa$ac{@?8!B85w5=vsRnoJ_IXZ+We;Osyej4Y>S43`{9EGwu<=@rzFya`Hwa?-; z=bzbTBc)7roe^zGfgP_hNQ0L7k1^cNQd>#@LrexYsQd(Fh^9OX6wyOND6w+y|G-C% zP)%UH{JVRTgqhTD!&(PL<7jxq@@p}cIgRA%Og3bDT`H~5TOr9Pg2v0|W(7{akgZwV zbD%mJ?4^h7xg8_++zA7e&<^?_$HObg$1l*!HH2SSf(GfF-NM5sGq_7wx{zh%oJTt? z%|ZCgXT}Zs#`8X=^ekEVFYOF(1f2TlpE*1pKkDVmZu)EbIy{qAp0zK6Kd5V&ao>cO zAbNgpK0gcKmP$w}c{bZiw5nEMRrmnjdB%)wRVrMkzCg2fZ?S%m9?TYr{gPI8ocGS| zupJs3b%mcN6#D(u!#|-W6az6|Rh?3poDK1M0A75J=H$*A-2?jSm+irv{2rmb%b41w zap|O@6#U+@sft;5jZJ%cN&8S?B`j&68UdD+S|}p346ce%1&9&4CoyBIh6{&GSu`Pu zci^@0XJG?Y-tH?bgWXrg;_pY55wn@QU;l?yrqA3$FoyLipiT7&Y^h$V>*)RPPim(eQ9 zf>m)vI)~3!M~H7nh;DvzLPYFjXiK6?RuGe1bkSFgLhhvFI}MK~^0Ze8l{sXb;3cb$ z%`K;nk^3%6pH<(mE*@tRUn>30`SrUMKX)7EU9DXVkfvLxTliDu+wJA4R3pZV^K^q& zn?fSah{bdkx6{3m>^^oFhqI3u)L9#vWIP&Wd|D+McuQt4Fr`0qQiy$YJjRRktc!g2 z+HeHy^C*7Cz!+qytTSoc{ZQnRI0mO}h0gEq6s|z{%}vBSL*-{m#@fMACrt`}Xw9g4 zE;BM?6jl|nq?%4X;SG}DZhN(}wYW~~hru0D^C}g!n3$%(CLUOI6S@#~a74I_jLe^H zr&j*`|4ULa13r;}&%70}b;Ej0hL5^m?~rQc&4kd;eF%!R++mosMXN|NdsdEH=BwXt zR%r?dshh(hs#qjDVk5vUNUE5xXZyv}pq&5YOn5&Y-N)}@e&g!T$u_6g;03k%pkHqR z{TjqOmd!jM0gJ}|!GDr8c%!qYJrkb&6JApk-UqZsH}b}sK0aSwq7vM#N+zsImtjAT z&`#5@?c=4kJ3Ou|D$K-p2mWOQNACH)KhT+@qPo@CA5FJlg<|9_*UYSr#zrSS;9Qm7h z+)UOzkO(=ysmAnAD%_DZaxij)MC#@YG5K6y`XW8E$ZPff&V#|q;t9pS5&_XEzcAF) zaK^2D*Y#LKG2o`A3zwFc8H6XG6lwS=0nbnpRkK|d$s<)U;Zd)38AsKX`ptWjo9!6Xu?Y<{U@ zurA(V`~t&S#uWNrB}-$M$fzIPIYvg7#$chL;r)tr=K;aA9z|$w3x98Q8P8*wb zYKl)-q=ccwE&n!1&_8b7Z{mJkg!iGDZ*ASIah}>C1a}p(OYY3=Mbv=P%&}5gyMGTp zEAb=CDb>2ze1o8u-_~e98;s<#XVMng=#4RUJZ_+XcOC*BoYF29$e>p?vbTAhJ)+Cj zsUtF;#3OEeLq5xHFRa(?gcl+{m8p^$;rzLSp%N`}qc}dTS7K5zWh@`n58^>*7)o0ghHKa*N+<^|Sf1C!*$}z%-o@@^A)O6I{J!P8 zLzPm~LR!xiQ_oMo-BaULnz#SiHlU|~jL5peMM@2klSwvkO|Ow-!I-@`jUHoIJAG#0 zAM}ufHg*sPR4}OFwF1eVC%C}ivZNow+fb4lKK`8Ni^#|n_G6b^R9EYu(Dx88*R%K_ zheb*NZ#89H9EZ%v5B8@m;KBMM$1aDhPznCXTDw=$vg`QuEcMj%bQ^R8mb4sG@M^Cb z002Qxn3D~pPP@1CL5qU>bxMQ|=!~CdlFyr&-`{ny2H()HE#TQs=_Ny~1*6Yd^k_64 zMI(E^N*dH{9O*xH#+DWGH8HV>(Iz9m362nhhq_-{aqVK3@M4aXd}e*6P;f1OnG~y8 z;K?+myhVJ0JcPd3+aD3dni3=DvK6GY)#P1P3st@>P{b&v6*ogv7@*Nmq>{su|7M(o z@VkGy3v!WB)&`7wp=sSwp$O^Gsi@@Q4H+7?RC6FMb@HSO;p@xyxqQ2se)}7#?)PjA znHL?}e?~3*AcM{puy1=s_g|FgrkGX6ck%MsrCDrg2|D9UjKre>N8s2W;{hl19wTwK zm=ur9%R#*h4*m-QU*GEorw)HqdbowMMBP&hmGJ<*4Z~sYe9#_p=}j8VpH=9NUeGZ- zE-BF;))smf@J>?nm;PwnWp^wcqq?}p_#GOKUnAD_$m}}h24|BtE*KaXaH?PxsjvA# zgjwktrtdQ3fOYi8BV>YI>2|C4?VIt}Wh$S3d~ALgDN#uiV#yi{MgJSH$vYHrE6UHtU^Y_FVAGJg=-i*8Po&7$|l(Y1}XUPZd1 z-@%2j%B3gVFC9ZJ$-w6HFr(t%J58BIC&p-jvGW47R&5BHNp)2pXv}Yoz)h?B77>7f zLnT8@ulPCHL8D+k%7%-GX)OTvG}ab&>qTU;#7EW~%6>H=_Hqa}*#IPLhv71^Gey~> z<*3Q))v0~h7`z1;WTtKHNB6ke5%;h^g6rHW~7b9PlYU**Ck6k6Z_Ca7RWi_%yU)c675HzBaAU?pL%LS*)2U1{l3 zw8Ggwt~;k2ESM6b`w}^{HIO8h6v&Qj_?TI=w2S@t31u??WA=QDJ5w?n&5uO;D5Td~ zDQBO+kkt(ZkMw|E_C0?@>yt^#=GKaP8nKTAnn$>O+fEe2}-P3_c@uhM`jU9Dg-H2Xe zdmxbORq`xHv;if1i~u&h32l?-8c0`<31km)qm>_;t1An~)1Z~SFeI;iatEkntIO|) zS6~V7MhASP?Ok4*yq=z}vpL}bY6%K6Vph?8bHw-Z4Dh_dAQSFicub*Ll8IyYxG*CV z>NOITwEqCD<4*o@PgK;Hu+_|5_QZ9yiuK&)tYTn*HXp5H!#cfBaleb^{jvFT`sj7q zvAO@YO77$e71!Y@^i-A-q0Qfx`}ZO4+$cEMdBkXwIBMXHV|RRQq{_KUZ%KsdS^E=Y z4i_rCz>Ed?wh7tIH1-fx;9u8ke)36Bv@6K1j!LDG`#F6`a~nb%dtQp2qXhVHXT{y z(CY90Kmx_R^jt>+&V0`u9nc2a zE}w@O;qGM9=o(o80AnJdg;St zxHRGcal_9pA(T?n8uKBQdZ!s%{t8>ht-pc~m21uqd$nrdPa2D%8Dmfgz5!>fv;12P zk3loCd^yOBsp;uk=wot~c^Nz>^DCZ(6gAx`;DMo@LBhL#gy{1vs;&Loc)C0#U{fb( z4huJ|tX399S}q2|+H`h7;4L7kfl51@mAv7&8Z$`Gtn~ncz&xdir(R*?7gnpPd^SV| zvMxGZ?Gxen)`#$V;n+D;1DPF|3~YsV7q6tE-qzs{E&IH5oqU(}A1}%3I_61{DIGvQ zpfL4ucZ{cxs1?GND)}K!>x!mVC4}!%K@;*Jx`e9o$5DW3nL8iPaD<3$0Or$Fic+Q6 z6{z&w-!(>{P+^n5@zrCVd>=Y$h|`|aHe3{e$JW;k-C)gkV(8OZ}DpBSc>FF$C>~X$h=2f zx3XzzzMn`wUyn8BYzi**FmvZhm5x@ydZYYW(i40iqFniLlvcvnupD#jI&3dM{~I~v zCQ?wsdlyDJyyjE)HElDRadD5!B*&|ua8PX>LoHsEFPjVEwkI1pxoO-FLsK7TXmdch zS57A$PY7mQM+hdT*^{WYKyR!rSqIf!JPe0vN97bsDxN{mVObehS1_-HJ#F*H!7kpL zSAo<8cdkeOX1`Iw@P0kH+}tNNh7dvS9xoiwhX1Qh*ubxY_afc#Phid?UVhQ+mD$=) z7(o&y2zD~+vcq$aU9n+X=us$20bIZIN1PO%xg{VVlx@${L4+OE z01;8_Qfhpxy~jVPL0^7KfGXWK$wMM2oH~O{$!BdTZGEj zOe4rg8vpq=4^uxpy0^L4PWN4;XV1p>E#PHu1US^Fv@8~{+wzCO9yRx_Co*Kp;r=Qm-HSCdH=-Bu#f?`=u%_*Ogf|2A@=c01HZPm#+N_* zUTOh%HtsD;D?LL~vAoN^`!Y*VtN&YFgqGkT&M3v5X~Y-)T8eb6&*Y@$WMrn(Q-j6D!Q?U?Bt0n@t>WO*1hKDt`wKF$^{GpGr$~JU z@*KG8H0n`5F$yriS1SIO7j(~#(DBUogdO89ewz41G5Pj4y4z^}F7XQVGoWB^bG+Hn zOAc~SK(9yjmudip3G)V*jA2Pxqa+?t{v=i=7d-5!GD1^F@X=#7Koy52HZVkt0e!rm z_M!r5;!AbmG-rz@#kxHyEoKwFSVN?>62~Y4diG1t~(X3j zU=j~{4qCZIp=PsG6e?W!_0!6-sgF;lUyZ^ZlMphM{7Rr@$KuxTM*Qgu6q%z#wbm%3 z`b*23g{?AMn_nQ#oq>mp09)}qd^G?wrGM!jZ?^K!NvuQ~3F0f_uL1+4VLrUe-S4!+ zi$+$pKEV%8;nEes_#r6<=Z6f>X_jv16HGYce1x`)qSrh@+0Z6})zYr{S#bDLl7@_f z?^!o2E>_;UUNxukF8Zk_ptv#~VCR%2ehvHVh>N5ng=o7dWnRfO9I`-w1Z}sGqyrDZ z5zn)QpI$~D+h5y6?};2Azzlh?9&P0 ztx!z03MC&tGdruet^o?Y!_BgY7x|>I|u(OP}m$qZ+F9A@gXC;&&T9~)Md2ox?QiFOB$;RP_GAE z05{&xl(Hf*TH1|Hv3<)XOM1M25GrI+i%nZf1mBivNXSuirc0E%AkEg@Ut0T-beBj& zJKmQ#;tP>XC5wh*)llhy^F%?tP9{*|ATCH7`^@45ZQlzd^@EwaJ2dQY7KsX8O;Qx~ zh~esnf9x72u^~KU4|N47SjdXtqi_GghpXV~6YcW7p?4S6yLoQ(TaTYHH`0tg->z@! zp_WIiml1RV{8M>7$~YCD;yY0lS=Tji6{`Drc#uX&+6{K>R9QPNd<9&4DZby|^Jbfh zbVfgK{m|#=$}mZ?^(j6X$A2A)^YKmkiwRUw;UM1_5c0lDfDVpbKn+IJTnnmrw0d^BUT~hhl8DM;6ET!8{{H9sL)wrhCBL`aS4tUl zRz7d1zVq+9be%}}ncTf>;MSf;Pz&34Qq=YK$ew$iO%(pLFIe$NB)(qy=O`PT^Os&CIYdq0b~PkF5JW5#sWl zt;bmY6`@Cu@ipB$Tz`EGC2OMnE_n{NCDN5SJVXYK45&mqqrH5H+k~ZmNROJ5&mZ&o z0<%r4f7GFiga}?@DY7Dg-n&xToH~Z{ zsC@;L$WTQ~MXPUWTndz!{WZuv``p`JWNJ79kq2Cb%nFt+t8;pe`gX=}&zclX3ndVH z+b{kcS5HK9}vYVMe8&Mn{7XqhSh2|5-j5`;?ElM-w6!5~ITM(Qj z9n|N>Fo%XPZ=TZm6e5~e?H%urPz48_LlUt9ow~zwvFeRIypo~^-?-Kv4;d-erWaMO zN>6)F=j()w``>Suv#8iq#T6?A&01ZuyZ(z9vAouf=NQfHp5k}U^v{|MNlI8}vmF1{ zAK9Vadq4=)mKOdVA}k`l-oAhLQCdQ>V;`}qg7od=G%xw(Q5yE%?Oh0@rukeNQ=DS` zI+u^G$1)r68TgD`N;B z4tQ7{dHbc?nhPA%D>It0Z;bi#1`G00f_Cbk_Gek(JTq1mW?iAcX=N+_T~B0fF{-ej_IBcTaqRg#egI1 zu=kAUHF}n}@o!^yxyp1CR&q_7n|Ys>zPzlQo~?aPn%%a$Ykst8^zk&k`^NqX9fuF* zWEJ$hk=}W1^b0}H8T9DH%bi=Cc+%kGL;GcOIQps8h#KQx3oE5{1$ZZJT_(;2(|sN( zm2{RIgiqbDac8Fmm_%)UX~7#V+l2JW&h)RxW9fc{7ZQ2b#rnLiX^EFfucx&F=-0~x z$mGOk5c|qfXa-hN*gNZ}T zSQC$_F6-g^T+{>jSILIZuPr3VwM5-< zByn|)oj?KTF(RAiM^;LQU9f{lkUZy9<6$? zw}?6+_|Q(6&EfpVq$h~xrtM}uhQ(U`Iup0LH;LD-XNUv6ocCTTwca$J@jmq&cNh;a zBD>&zp1%E?L32hgP94Kxq1)%$zIM$Pg|!)Hb1!Xw-qZhHVQlGo&aD^BA>I&s7o2w3 z&wH^_@AYHyn|(&x>Bnh~l;S3S5%ErcVvZHCp`heOdt|#8OtrCuLtK7+qfts5p7_>Z zzyM&|ONa8b{8DbvBWcE#vap%zghue07WgGRYQVGrN{gl7!)yLJvO_T4tZcrf8uZ6IWkPG<<(QB!$ zvx(vt0Q(=Z+zDO^I7SsX4R$emtiRfaWmm_`9lE5`FBQ#Im9@Yd*nKD-HZaI{^bctB znfA@)IF(N)_w{NOjg)7W{p?RJjf_k?Dr|LosAai7jyIar4Qvumss0NW%aOw|+^}E) zc47=km!qT$H06v8NEVX-C;9&Dcnp^&y>zpcam;7Y7(Vk&snXk!J!_&6E&r8L=!DqXNgx^sK8w7mB%taVVf% zA3BWEoI3i;*uqywNEHOS!!!%ii1m88+1|rX!3!m~LhJ1YI-{zo5Lgl`^qn@mGad@3{}S8e%CKKWZ> zkN6fgY#%snJBbED^uQJs^em+7`tGHb*BRjMIN|gNFUZ?7F*V5xouk`R`$AsQUhT>{ z4}vSZb=dyp-;fCYZ2u5&*&XTyfhmPi)izD3yx)1Y_}Ov5T0=sgw~#)n?(rdYA0*6v zh@ZYnZgRQqBC3&`BDO&PWH@*eTv^nhK+7O3$4H@Vk|HL@3vw!tKjDBCtHwz~(V(}9 z`DGs{1tdZ8bbVu1@jo3w8~twMqH+UOd1v)MWP2M7L%D+c@d07W(m%NAw?mDH;bV}#vh`|QKKt}tA7 zt3Oe!EW7jczlk(sChQT?C%IhYKoS+d4p#Sqmc=bx^NwTV)&+#93<#fsR*D5Gdso*wg^oU;9 zH#R-J(u78FzcsM;<_K9H8R7hxmYp^Q57B1k$e&?cpv{R$>JWHf=jXJF9X&}AcQeDf zoA0-vHkZXV{fl!dY3f5Ij@*t@D_prJsK9e$YF+>z_nnYZK22K)4cDIKn2-{a>!^OZ zM%5_{-(s&cHPy7s9G8?GsomFy$|n3?ZkC}b8ueeHOqNy448Z?D&v#(K=Zm}uWClaOHFZ?8D7h#G?hTqMcKJFXKC4d?ZwSeo zUMM?Zs}RSQ{AB~f+2_rw?4}xnz*zT9*q&SFB!E?Cdwc2R~R(W4?D@ z-sbun0*V+9Ui<5=h(DBG&Xgfb(HfHw<#87g^2pUSVWx1aY(W0ByH~BZpV%Kn1U+5| zE{+HL{=K(@?gzuNMwLf2=Kk|qBm$b6TGNJsZ4UBHu=EqbNzpNq@&yd8-nc3;px#@d zes-wLM-W9Gvzy7+*~OI$;9}KQMrdRJmqtB?y9VfgRyGAMg!w6B9HAak`+Z>vT~NTQ z!-nJhOV+D}6r+0dMV2FC%!-iH?PDM(uR?{1U7gf+k>6&|dHd`3%rgAtWgF>x6aD97 z2szo7=8Ga&{!WkuYX0EZFD{4+V{4PnEDOk$noPt%v)C=o#m~7k&vsn~ zkC~HSENsH0Fq+y?A029a-#&yPv_NZYtfqERzUH1fWfjQV>QTodhFZwlvUE%{RH?M! zkNe9#Tfs&dkHVRKvugoY^G8lk_x|b;ocT$-Q0j8J9|YEHHNB5@R);B#PIc_#|2{9u z+=u_-;`%1>)4JVdtkSerUPEV8NGkD5G$@a!qPz_tA88wcgCUi|6Ts2U(QH-Kh1SWs zWk96th~BkqeK5>+9{X|YKjJ+;#R;jIHXsY;5juVlbBJ*XV~Pr@XI{KN4F%A$C&`#VLWIJ_^og^5FQ~7^T*bV_=9}*z*&&$mzXfJ;B(e&wK(w}C6Z7Fw3>>b zp?8W+c;IMh#V{)mLJow*u>5r&I(2C{&a%iUh^37%6DTAd=It4Lm}L92-t`b{^`amA zbBbZp3;m7ledfI5@{-cgK&I;f+17D7QaE(m%KwKY-1hW=vTONYl~-Y*+fc)*{*TXg zpE9Y-pGDOLVgn0SOzLvUfVK0R@x41~VSK?;28kia)NpB_@jQx2&I1=2RJXz2dpnt5 z`wV%^3Q#R~X19>0m)7I^a9h>>M zyjf$j=$b5aIo>ayKQuXi^jGkO5Ek>mswG`m$3fx7*~UNQfj9lZE=r@Nr@qM7zl8-! z8h5-sQqPm3{UY9bLR95@w$WyCWrZu!&&eXN4=3aKavmbCSbt?ks`I`Z;rGtZiYehR zBh&Mw6rqqubAJe!{s#Toh@4Pf*fWtXX}jFuug`VVkj>I z7~DkP+qGMg@%?`4bB{oT{aUnFVUIKN+JCg`U*^St`2OQ@o&brgk0$u4@{ELGeL=O& zLXZ%N3E`FsX8B-Q?gH0UVEtc}j9&!1sM<`a1^ntkPQ#m91=F6@y$-?LsYo$t8wVR6slM zSyaE(a#TDTN1%PP<+f)!eT14hG6zAgP4c2&Du#fp?7~fN;@c^o^g{Eq&EEFYj}iTrz}hdw25&t)?b3H4bv$LZ$r{mJjI zu2MK%N#pFg4hCM2MUr4!Zt?neRleX~ZEnzicVtExzU_#tvzB1J%yyCOY)ecmFZavz z62J`Sqt6A;8X%$-u<@$&e_i*mC7WQd>O=d(E`guJWt3c|koh zQ`=JefTz86HBLKr!ew*9@RlW9`5YofsL>R-%B|u%e%g`8#;^9LenThANRn6zzi)2} zlKBm|TFA2z@vG*42V~M;9vMYn1I`{g_TtFY6c3jgd)X)?11>e1sm2{())6ssBu7`m zFZUJR6^=wrc`}nq81cj_giTs~f@k|G?9VrgKCRJOzhclp=#kkwXv~O$l@$0yN0R3c zM#hj1-hC&!h*SRT0nLQK?gG;?SX}V>c+dmw78e4LX$4H{KHiy`R4r4R(lBOj0;FQ& z#CH>J#d$r1Y~|h_b@Y5uiK{NU*@J4R!~X+$tBqr(o0hR@;HFSJ*%eS zQAK3_xHt+HGz_TcMA18+iE*wkZ)n5*r$*L)OW_*j$I!N6Iv?e)7IEf=sjm;^q%|+n z-fwZXZGCLBC_(wQjf};HT$>GlTr0=vkPxe%oQ-kHRO$IFtIT~TnyY=`cN=`tl@_aFzcxlO=%UMX7Nvaz3sjkI8L_lX7y z-n_;0FU)C~f^)iWsd^Q*7e=mKSow^YfJj-*3?=2Bejv*Xsnn;*fq^>U-ZW&VHX9tJ?w-(rh;|8UhMwOZ%9$~_yC7!~Q1Jw$8Ty^7c1 z$Nun<>6w$0Y9a@;aE#DbBfgQ~04k&c5)$W<_HsOX1x7L}Bv4XesWaQtk4rJD;y5{A?f3IWrc?FS;V4j2YFS7jrPFjrU_XKC zFqbHm(?zROX((jw3JJRV%xamT+aK`S%ZGw;8N__zR)o zF(-j-nGJ;u$NasBpyAY|on;$LKja~h{_HiU99@sQo53LxJ7sx;kD28HJ*R8U^@Wcl z!IIz1OmCeQZ*jx?`Gh64daa zhp^L`R96>GKFIlwMjiR(CD@ex<(EFdDg-l8zT)FIdFn^5Pb%s}G3a)=QbwvcO%CCH zdwvUgK%0!e=R&(#m*pq4Tgd%zcIV&zjC9~*>_LiI@ktMrOlhWwb`!wVO#ZP!$ z_ql%u)0{a)w0Uwc^f&2=TNIbO%M?-ycIdA`X`Mcq=u1Q-95E@<9Y{3?(ZWOx<5V^O`=8HY3p`*XAYrU&Sn_X*)&fRwexrR8&AjY^$lzP z3ub5MBPr-I(jgTRLam>vU>fZQJLOgK!W)=m62#43d+r>0r1o1op(rAYs@=pWsOa*I zmr=0E_s>-4+Mg@FS0#*Va;D1e>46FGza)Q; zUe4!-0W|Q9X^a1*O>b~Q#r3Zow>i|#u^!&A%!!$-%S6;`Vr?mZ}Q9kmB9a!?BF04iP(hI z7&$7*+2GgXzBq`Ft^ak5n3L2yX(HlYeot8L*ycd~lZJG{z%s>}=4X9DaXHS3Q&{P| z1=Lz@Y>KIrgvV|eKg>O!{tQCKI-zSXG`|wFoE3B{A#@2%i+<;1m#`Jr0 zcdK0shn>W9L2EQAqOgx6Gw$N{YJjcox-aeMQnX|hLkn-El6jJ&WrkKM$>~T_?na0X zLgblZ$4xu&it1w~zHZ&7s!wnyBi6YC-yNH&P|~sw~VR$FkLroS#q9!<}Q^ zw(J36X&ceym}<^8^iijVy!*hb_SE<0uzQ^spemWtiYfw}qzVY2y56fRWC#w_)@|1a z4xn#Qt#tY}GBvxYWaF_*(*@sU+Z2aaib{!`S3lHAU zZo6A_Wsl@0n;qk2DYdhk2fQz&i*o)b%*`qRQQW{7N+?MBqOrL;eLL^>6Dm! zhhz0wv(^)yLM5)WlT%bE71}!OuE7`Mv>7hZk~X`=DYqhUM7#5luai_C;5`q)#ha(Q z;aDfj;gdwzw1*D33c&AUFM$tQtsQGY^u8xKaHyMP>s6>seF81fPQeg#P-j0 z1Rb9_o>7RP9B8~4Wt((c92^Ei^6N4sSfGd#s`X$ z6``N@fX?GR$BD?=6c^L0D{di2I7!@7A?NMLETk~;^5iMCRPpwgF=Nf?K}CQV7Ul@1 zlp0O-5!X$&Ys3{!EyUa8xibJiY5tkoPXu7Oki$g%Fc z>1187028kM%kypCmYH{eu0cRWT0-$qZK7`5r|x-KBv4YarFAM?U+!oQJffpOL(_n-_o<7*D=YF*Ae{}hcZ`~*$dHoydz0Ae5 z#?OxUG2B1Ir!`R52>f3X&0OTruBK3k2EumQ-oJj72$)6z(Wy*G{3_iq-WBzVXsULP8b$?3qYX&>xnfU*mbnG-hn< z`{RyrQ1WR_T8-tFR1L?H1}u|;+b`XV$L<1`0SwUXWST|G5PKbNVQuSqi{lON@vrE* z1T$>~mb3C*3RV~+fzFS<=u>)yf?v~7k`PGyA zmQ_v%1inXdeP)-se-S$L+qjH;EeQD<6T>`xZ4^0|JoU;6t$>c0D=|uA(;#pgg;If{ z0>i>OBfiJKpB${Hn$5$hC-#4j_6s%YnTqsgwD`+9d7E!dc8h6bzy-MqE>&oAXxD_K z4!(=jKNEPh25zp)ymV1OdE4}JBPwVnBD!V-vZCJ9*Y|0ydoHr@|Vl$Dj}=UD6o% zzXV*IPh9;?Sl_9^)SvDLraf+I+}1{RV+t603Ff4uFLsDfn6#~@Sxk*JFSLJs0ZKo; z`7W)0*mOMKf@UuVgOQC+%*2&BtT~%pN)A$y?2!}STB0A+7S2GQH{qf`9~?piJ6aJ= zpJHXUS2lhf82l6eRSORq7FsV93npzT!vJ!Ci@*&rZp+&H>Ke>m7J>(7v-GRL%y-nejTE*k^IgzjE1aOyi%fd1PzuiTQ^{o+Y?zlG1Gk)Z^ z8=9}dZfom4tuN>x>e?>snD~0;G7{wmJQWxqNUJ}PRNK98f$`s8yZ|9wz~2HfXA<*R zDap#RDVT~f)-v0F1ODf1S8?wz&|2^09`|YP;w&&DTtkGR=WNvSbK!9xlcK-6&nTWokT3vvEI&{PU%D#Frbi=}mY&OYmuw znT?}cIMB7gMk|Y8g2T)3gcyy$9 zDI8KPO}TlL5{76MJ7U{f!!}xtknn{2*NsOuyTbMTBmD0O(9nX`>ReR3e1q7;4B*xB zTJI#4$KH_4@8og^*io$`sr3EBsB5|_%76Dl4eNTCdHndc@AwCDuKnH?o%B=x6%{bC zvnGB1#IrEcn&HCJ_5WYFD_g61yW zQx-O%wWRE)VO}!>roNcpNC2m*^2g1XnO42i3{R|F1w_?-tnAMaDKai-i~u(@$olw& zHm(m1k7Yi;af(v_VR7IDNGOBHBOTchVS>8Iyqz!_AJbCfl@V-;rt3I8e~4#!SSJ*E zxv%)LE5&mKI^h4zL|NPcL0^lpQGaFC_QJxz#{<8azL{B!$!Gw45C$N~q|;1T$Joa4 zbL6H92VmNEdj4y`Kh6b$>p68xam_<1YhrUEF(9A0g}dzkc|(!ZXjz5-Bk}#_b5->B z!|;JRBCnWHZ5%^bXr4&BVUClTji8CN;hK{tIHE<1q+dza`-)<1AFQ5-E+0sQLDPTrZc6@uC~<1@m!yxJ3o?b zEs}>l^uCL;kKI^u6Hx?g-__?9cxLWR=&+ywJ)spTv=h*G=9)%Y_hSNW% zy99Bwm*k!jdjBq-w_hL0O8#a436A_G%@TNesHXxs^b*(g9wbO?l&k0v^KpPWx#WM} zS;3`@-lkdZEkHu`-=9g4_2ljA%HE3x&rU@BTVckYN)A=cwV4Or=zOT+3t*i6?<4ai z&>XB!p_I_ZTFG2!SCJl#e}&IR@%#7Fkkr~g5Huh9I|1H+BG9cd9$da8f#*|~7JzN^ zRvwZ`B$ZthIL4(hfZv4d2p}9dduH)pnCpbO7JVo7M+-P#+l`%ZB-muQ6Wh)S=MHt# z?AptUj_S0w)TPr+#guYaR})%f?j6ZdN@+LF{$6g|qx@vbQjH~YO{P7T3%zctsFry! z5ggDC$vxyZ!X+Lmn&dgZpn{@Rxw+T7T;uhD$EY8l`1nwRg9Y*bevF~5bnkB_!V^z3x<(?&QL>EsHSn?8gr}u^zVE~9Ftvpb zf`=<$2vJJ(=2k_lccdpooN&hEYe$&0NHyZ`UQq4h6rkll9MeH2deieN3V2O} zJb0LOa`L+VJM38?e{Gm{YaXr>65C^STK4&xT&&Pg$zG_YMM{Nd&P-J^I;padSHeV` zUCFCN52<%emI|zZRR~(}!r)h{BLA}t1EfFo-+oTfB{ygu-_d!P#vfK%c0H`*L9FfveqIRj)rumAxbvX<3@pNhP4 zi594`dFJeUZ?FzdaPPJ#*8aSlwxWv+uJ@qF@x<@?(u`5&q+%_cd>Yt0{j*8N37jw` zHsPGG3*@Q&3=FVHeg7Xs)v0`-3s(4Nx7j_)D?;*toRwA(nH*42E^ydoJbFt-7Ark( zAOiLQ94l^eyp4pB7{Fpjw}%`vTL&<@R(HV5#rpM{R3LT0n6au zq6!c%f;Ey}r{QW(KE&`z6UDNtF5CV;p1wM$?Y8MUA-GedSn&cyij?A7+@U476?ZA_ z!71)giWQ0_xD@vyEfg(KECg#P?hg5KKkv*plgVGnOtQbd_S!vX_iXeYUc(ziPy`^YtA_q74j?)Xnd6@mQ|&&i7?qM7^D#&@#{t@5n0 zsiw8)yiPCz@7N{b!%~5=jgPkbe{<5{#11FpzJs&UF&w-A6B>}_H{lropc$kPc2or4 zmg#K~R=-83VF`ZE8?SAmxw)i_Tz+$hAl~Ob`P%_CKY=R;n2)E7e4))t5` zolO3g$ev+5OGyi*CbSV!3JMvY7Pv&5M^+#x*3qUuK7z-zfyCgn=66Il0Q^%1z8~8who~i49u;3JP3DHDbjuwNv+yP}Pz@ zyD6a$r(0_egM3H7h=2U=5R&!~o(BrQ93CG1mZYJs(8Dr-brb?}_#41L5?lH%W2g=U zz`T_JK*;O79-_jO=Y&a5yDC#U@Nx5r62XgzSf!2?g09h4GW0N#Pa1#A7C{v zMsX^cCR6vT_}6JSsWOrP2)|KbK4E1k2adx8aq^nQiBx9|O$vth`TrLn33LfSa>p2` zl+Zh36hh`^>`>xyV1Xp`03AYH=@upWxOTdr7F=VEVhl-10x@jFw42(sTirSWVrAis zoE{=y9*Y(Ni|t6XnkOeGOiaNq_HM9|WKo=sQ~Tqy4t^iuN`PY_QiPN^1I__tlOfPQ z?(p#aCCOAND?iohDgo55NM8c6nBiHsiJi|6u*JI|?Az0mrofw7Orppc_IK7zL%b1n z?EQoc4AT&{PsBq_#NnoMiQ_C`xtfQ%i#fH>-E3cJQ3FE5tpD#0heuxzS)f!y9Z%e+ zC1_8yQ7JOm)VM1+;!I{aWicIKL;cC$%fiOh~dzgF5csX#k+9$m`NgrVI&&(mNbdMLAFy zzidd2H;4O1OlY%#kSpDN-WkeZ9}g3<+ATzzQ#aEMQ{e zbS);Baq^oPW<>S+#b>ny_;YNv{s-1H<$l+`pDO|}(LJSzW{r1YR{DlF_~vQ2Gu+u^ z&TO=?OM*73tdOhlu)lZZQ%%M1F>{*@Gj@y@+C_<>%fLRNW3mPXPqi5b@(RsFG1jGh zZT7_y*_4zM^u6THS4rJ*dft5h831r+Sqz)`+{&X3fP|q{(vMCQlgE@Y7voCCIYWS) z<+WQypF?0qk*dqG3UOdZ3|F!x;l?C_oNOiB?R}yDxlU=CEf$>nm)%C!LJ!o9Y#xKJ zIM09XtGBJQ zl1DAZl;3}A`Du7F!c`0tzUvy+oy{E;)lO6Z2b=-;yCKw%urf$d8TNHLVju@gu~2u* z`X|d^=PB#l{YW=@tSRz~nI+dTQ$G!w88VrcNB{fWTH~O;d1r4y|I@KKAOcdSnSKDZDXngJdp99kRo($|SqRhQx{(Dk_D57>3-xB< z=b;){@lq9ka;cNlbbfeeO@$ofDlUS8_>!1Yrb}Jy$xri`P7j*SHpu*8&?R9D*6!0= z&1H-Q85z~o?dRj@`r8eA-_t*C4KA0G{9aPpQ9i#5Xu)6_z$gSbm8=BzOz;Bgt|d$9 zi8x1CP08jt%bYq3^iGTJot=wy!t4?SSXjtZFpN1+qPUp=gsnX|4@*F;Tf1rAM!gW>E}$#$mV$N&-S|7jZH)84V_ER*x8RNsz%Q}uIRIRnYFCa+3?jM zmntfghIlm`gkmP3h$DY6 zMXAl4QG|Zu^vQ)d*@c*+-w!WcE{+~R#-yDBdNKj>!8eoU#Bj5#Mu2h<{Q&pD*2XwvzczW>8jq&Xvy=+|y4PgY< z(NDpd1E!PAJNWW_zD&}HeiPw53tADvmFTX0d32WxonAV&dJ+(f4hGzBx}GBd2P6@3 z+P|>#-Ew7Qjya*P`%=6xgI{3x=_V_0Jy^$2lODYx7&Lq(&>tu;{+8nr4+Kc9OpnLJ zhVTap{?Ge58G5hxWW;VBdmklwhxs0FwL6L)K3a(J4=hlyL_eR3b|MLLlw?qTCs_I} zOG#yE(h6f2ZbM--Bcv4d@#SNNbI5BG(nQFcZN?$8%l3s5xHK2S2E+mZY)X0RlU^iS z8op(?oGy_1uOsjCLS);-+*oeQYn#x}nWIo->4%qJ-)@yI4wxFsXXm80i;cIyu9ZLk zSM1~L^#{1yKTS@ap1xKnD!%0PXRs{8hZneD{4STR17-#s{TPu~inMN=1{~2_MU58D zoQE+J>bnE;$4M>aowaExD^nmw1pl$5C$-AmRJg~kMZE+6Mb}M}oTti)KTF>`RmWEY z6N=NWq$kd-blD8!7o;9C`dI^rsru5{)>FCE<#pTMK_MKn%uvFQC611>uX5|oKXTJ| z>k~HM3iDZdKx8D9TEC^m?&T_f{!?Ifju5`Q#0|Q6GCs+iG`wgDf(y+e%t+~eHl~g* z^J>7NjdDjU+7r#!hTJ6wYHF~R5RaghQcY1w{4=2KO+?6jJW<3rP1~$ ze-;%FB*g`Vn}6ZdwZL5HW+BgQ2niP zccKxaXi}n`JougdI8q2--FK=ECWnjSe8$4;FrKtXZRDRN-K~0xm#D>BH zS&nn}aAcN@(xe0u;wal}GMhix=>LrZ`kyR&pBm-kx)}}-%64P%TLb>@LJXX3ekVHN znE7*~_&XjexH}TPyI!DQhmA|!59_o&^?vWwAIYjWmuNmbQSSBmi&Dbp}W>)oc(sGhKK7oz{7 zr9gssxvL!NF(nkI_q_KJC=+I#6`f{n^CM{?lB;SG=tY^uYipFpQ%ZT-uBU3In!eRO z9$CH^p`)UCFj|D%P$){b58p=qB4@fP2hX+A=J)Z^bVgH>c8sAp0Z;om<*4C>< zegfdWyUAO4cf)x0*huxym*113+K$!Zz}p-#Cy)I{T4&}=K?h5eXFE=Pec1JZLFoE_rAU-R|^dyb=I{OBc?$lO&u65>Lmj2hY>5ffOm(%WiT#Z zDWbwcAHEtzaaaBbN8!}6=jcO(79sHv0#xs*oE2u*K#GL91k%pKd~CXMZTr}tZ%9y>h$3ksqidmq;B;ZZ<9+$Qxe zHAS{jEIP?lb)BcqI7t9A-De_lwt)qFs_95$vf!ubC>znYTruq>_ZLR^?iJn_Fy{Vg zQMOWZlHQgi7Z(Jh%<$p@;uae`keHPv5_q@QpkLfj9Kb-ktdWAh zML!I-tvVZ3tnyQx(ZT*AyFl%67?Fe^q|oQA?l(%2t_w@j|1k+Z^frpw3NU2czleN& zG$Gtr52@Vn^Bv6WTsRY;bw#y*5F5uv z*Ou7F%kK!j70w!4`(F)yqBachW_DXQBB7K9p^3E&%Oe@dj3BG zoyVLDJ>~o@Tn2#6l1?5Ba?#BkgEm7x5||g@I^*>F;b2BlHs%qLu~w3)(E()Lh@xMA zeOopAZ{)Wf`DZgPX!`Gd(jxbbl;q>ipj@0iw5Qv+5kDh59vOM>aA*pEym$s_luhVT z8;<{dSIKuFiIu0x7T@4yh7JQe2PU~mL@V8Q*Ajkc9F$4b^o5|)Yx@(lF358NGb$SN zdI|XS%ZF04(-TsG_ipTHI#aYz#kCg*ApQ0KBUFn8Aj-E-`{DFx-W5o4j^`$w45ciF zMniinvbUpoO7Z>}XX{bU2vz0Z!(X3%)wgSkBkTIj1WhErML`Z7xmx2#{_4iGf(_e zx`SWD5h_j-80%H4G0!Ec?9~zg zf})5r36C*|C_Ld=#=B)arJAq(^|W7esGhP1=DWYftqdVgq^6G$(NTzKde7om~_ z(a?3|Rsk#B<<61&^zyRRZK0j;{B!)WP5R^~Vj3Rqu!F5J<)J+v_u0NN2W!`o5 z+s!t$i`+_%9J|=pFGJ_%X~UPeUr|{8+u(!NAJ3+EdvCTIMcckd5QX!n}L!NdRuOX>P0x z6t#EW`47uH33=1>e?0}r&R>}9Oak)x+5RoEo#J=H(A}RiX1c$YW%cTCzbzNqH3^g% zgi3z`RIL!PIyX>u@71IZyvY z%njJakE>#iDOY?>1n)Bd=8Oz!e9QBB}<9$KEND9SPJZ54#_jZ6* z8i0@Hf~=>M#&-JUz9wO-v@D)Rf96$K$8l@sIv@ymQk5Ui2mjoH|KD@4e z!!bvGHF|{YyO^KYIdS!1jLv4e=A)xA?+EZIXaqIZks&$3%bQw zMjy4|s9(9VsF949Q#H^-={B%G!yLaXd)A^Cd2m2R{!mp(d+}1l}1Y@VvBihvNof2E;HhthauPteo)V zbK$VLaTMw0h@~ykk6w^>YVoo%(w7vJT4*h-gJu!O>XXR3rft`(Gnv4p_AQqGh&f#;e^M{u1U^wD2V13zvV~d6v0xG0 z{%$RUkbhP9D%+x0hFcWy0zxl@8u+FEQtbpJVl1XpsZy&`oVOXGN`LpU;H+xl;X6a{ zhi?-qYX!p(+#rNP7r*&;jk&7vl6A3kxTHN9zo32oXj!IOtFpX4QY!73l*e zkX`+#SQm(zUls957G!+2`^=-hsefYgj{e!c4u#k-Ep1XJ`qi5YdQmMT*OVxd2M zqDCQ-jMfJ(cIcwl+&y?Li3)}6X0}-U(;u+y!Ed!U)lk?^^6<&_g_^xi3zYVSQ+Hqj zRE~qo=t;A*B3L1bnvX^9T8Rrt4?Y5ixQr_-Kis*u>XP+b%M~5<&ixfRB81ZjBR&G< zu!bqgQ^BpxM21J;v6+uf^ZH;=Tub>WaU6F;@!2bCLw5{?OH9nnhB6+h03MqL=7i`` zJXI{fIgd<;bDA$58ntOhw?mr(kjGE;Pt?^%PX$BY16yyX7Z-;Z8FA3km(M3hKHurd z`*0A-mSG(W2QXB|Y=t#zyW3|(77!6%iqH_J=tw#~!A8+0VWV?y{q>>@BFK;Dw*O29 zJw4lHCS3J1%dT>{rbP->?qA5gY=b@u1X?ljyt57XHPjaW4+edF2e1U3lM#c_OI3B& z0e|Fe7}G!s$=t=Mnh*I;J}@#Y;R#<4{PG>b%tyWQLEF>dg>eXO`e@@H&n;rAJk41~ z+bZa{?%jOo5tCx!o>!FdKKZFgHB!HLX!5>zo_QPjag zEh~G#LJh`|{{r2}@65CfFi>zY42kgVjE)Pa@!nY`ecef>EZ~`*n)BRNH(hyvpG>KN z`Ipqmr|Mg=0OSJq2VG3hC*GG5u5nf_c`RODxnnuUt!|bK()fo#Xlgj6^*HEm$C5Pg zwk7!F-2#sG4vHU?8q3_*`cdF*89niitF%qngFNxK`G3!j-euD0+Q__p=MwI3e zmJ0yC$lpuu?kya2%FWg(t*p7dCu9DxynDwFFbwx9bY=QVX}f-*K-t`bpGrSUIXp_i z1Yxx-;^%HQGwYlSJBmfE{Vd!OgO2=cJEZzFdN`(A58#S^x zvot0OB(Tg-rrGU;R8_t$$t#r}ybD)O(OWe5gR>|vx=Vr`0%FAz`t#XDNm^c`k6c!k z+q>87%Uwg$hd44SSDph=a^AVxnVaU;4|?2Ns{aS*P( zyu0`pFmWgQ@DyunTa|8|SLMEPW5jwmHi%xjV+?*9OMf86K8DRyDC9chA`E*BOKhpD z*nZvp=ob$><|apqHVF9Q;m!@X`o$9 zHI-7O1a&W%GVa#Odwj83#pIi5al zG+DsT1R(%j?yK#S3q>@xSzkZWxgJN=f$#rz`(<}PaX@BZ+vZ&sRd5Y=!H;31cM2|2 zYzr<K7?^-m(jgiv!f47EqQPRvTsi`A=}nap>Uy##ieD%#_y0Y+ZT5w$ z3nXFB{A1!C%T<4RLL%ak!m!Th{-rZ$XPr!(8nZ4^ynih7`LPXl@e|BI^?@X%L=s=o zz^;kIzh;-d^EAZ7C%Y;cxppwQCZl(#^4*8tm-o6?s0us4n=fu%P|rCnggs$35`txk zXDGKN=)uYs$^d4vEWHiI5$*95rIyJhfkmNBwK2i6A})Fp-URITqXzuft9R$3d zlUdrnb8Eh?36k%*Qi9>}z&^~C7J=Xf+Z}PH-{xz-s!A?6wB#MM4^_^Y@h91tl!#J+ zpHB{p(_Z@c2Nw^*(->2RZOt=3T|Ksyz!=CX4@iUvJ6DsQ9`wXhSlkyMt!2?bo+3E* zDEs+}$5Tbk6^s=rl zz>owrXYh+Fs$EslqSfYftN@g4$&{^UiLe46T;bI~h!Di@v#z=OZo8u|&4<`xXds;) z?!M*d))?<<-0@a~1?t=9)BeA1ry(NCtGmB^)WK^8+g>ayPug4(jU2y8oF%A_{ff?d zojw1up}twIX_YyioD0zBFjeZ;JbBX3pnMlZ|BRl0|4PY7xCaq$r8x~&n3v6lh+Rkm zR&T@i4hny~xW+oaLnX|=FyHU0!w=n$FXqQs9ERbD_vJ%Nw8}CCX;Vh3;^L~x|0=R+ zOnh#VATNfJqx=2i<1%vDlH*v^$xMbBu!#owU!$*_(|Dso zNSr~W4z2G)iOq7A|8}%R2iVxs^mfFr`Fjg8PVM#k(_=>G6Lg{i!vA9JuGk0lLe)Cy zN&X$VHlR&=Dg0kij6VHwxQ=;KF2d!N=;au0dmm99wHE87@(Rpp zekjKK_Ks|b+b@c^T{F;fab)jlQc^XwVb8xyaLl6UPMjW6-i#1!UI_}n(8m!#+Xdqz zzAs_-^dD#=t|?9r@LHejMjRYw1g63g*QI#<_i4_Ca}f%=wi|U}+8z2iDa`oLWxBn8{S)&8^*prjJwYotXm>9KBBQfj+j@?gne-2*hHOIUm-g)noOZo5dKBHB_YB|~ZkR&c- zD;psOR8WKH;WxjFAxni2zV_C|zAGrVYRkLICw}l47drK2z}O^ zVPmd^q8560X%*6Ug&}7Mt`asvg@qUy_idaP(DYDKN*q`pQMfZkSn)AsYUgI!zG6J8 zeeE7!=JXf$ceG;7a$!Nu5iQ_)Ac@MNOJr*V1w+v&-mJ@XvZTHCz48~WgDybav3puN z+^Pim-moaKX<7ZH%5D$b+q=FOc@V2z4KCUy$Z-%dA_WchYm z)%P+EU$w1s7uRge$&n0R$S5{>0kU1YpIwk2!^^9_E77PE((4aI50$|p)f3w8yhi`B zqw#ugiS?`BjeSMnx9^6wX-Z2$$=^i&gxy0P4txTYJ2Ry@;#tu-Q;k0LeZuBW3-zNU zZ*cBy5%f_CUSNl%ci|eMt(tXjJ&-^3q#g<+{4I_J4{EMI551mzi45!LfsM$wp;Ay< zLxB5=rhQbc0ARBOGqdEJY$xBK7P>0}LeU;4_07ersmbySv#5R^=Y8pUvg`BGqIYO! zNzwS=rCs0-PYkD49G&KjlYOg%h_;{Gm)oF$$3x*#Ihj*9-Ds zZj&hdVQGVvJEH8WJS)*u_pl^bb_c5jy3ys1G%6(IT3S)!pas?$@NZiazh%rP7;F6A z?%@$bBce`0Q=McUKTz`;n9j!T`gKcDRX0E(Dez8Suqs(I{n-38z<2B%qOq!b)%pmM+4opakeiJPQf_xvTs5ljW- zQ0f$}fY54P{G&TW1H4gh`i`2w0MwL67F@lk#}2NAKK3T@n=Mryss7Ot{KGllyjU*L z%d~ofmEJ5?2CU8)G)QDteak{O?bPzg!Vs;ct~4mUIi1Qw_lkj7*Mg0!k%i^kn|iz{ zkZ;2`su6$tZV{PA7HXQt^*_qGLV9z`bFt6JjAVVvc+_Fmnn`g!BpJ(8VdrJ*TF^I)}A2E+CtEkC6rR$U4_jH6fA~d6(;MGnOOi7V z-2V8KAt&oRc*S=Yp-6`2E(?UwZHxwdr3-cM;hph!2>Ip(<-f=;t1+VZh|SsLMuibp zC7hsrnU1mf$hyYXrhb0L^_nRMwq|2Z<6rDaN^j_UX?A-mQf$4?(uduQ(E*6yr*ldx zezAky&*DwfJl38LcviBe2E|ny{0MWW1^hlp@Dqbl${ckceH@j?<3vTo^vf#$dx;Ey zGY~6hP{~>X_UWpV9&(H!JRj!FO7nQdkg*CgsU9<3p^Al2Y4N7XOq~{7w z`~d$8+HQ0F~k{&G|pzO(>IfH`?vx%?Jo1?Ur=*( z(X7ke?lTbJF>sdjR$d)^fvN+DR9*g(IlVGdElm0v=H2%=&mNQ_qJmCVOxfdEO#iXZ z6-s{5c1tWRDH|!0n7aw$-Il^5-^l%EJ>ig0i@+gnk zMrv|pvS0ccz7?7kv(U=0fU}ezVy6Fej!vMN@QkNrThW6OlQgXhJNn2@U~<<2Ys&n_ z8{3B*JJ`YzK0vfe&uW0{$CEE>VM+XQdD2PjXHbfOiRpd@lB3Y9<}|?_#-{qNcmXPd zYz5CZu-O7r$5Jsdgo_ViY}W7ho?JFoDt8psclKjk>%d*9HNR4y-4hK|+*;Qw(FI)J zKt=S!y7h~p?C(7>186A_hfC0!w~9qm9+~AM$LU^a#h_$@+-aSSvbX&n=4lS^%l-L= z$Elr1KY&}8g+|-bG^(0t!+GkjF}x#r7ga2or{5R`*Yl5N>sa?)gD~W2#snjelHthX0?=#CaMhSFA6Hi(qrq%;aGZwstgfg>3{J6nE)}_2LnA+!OB?1z2M1~_R0tRK4fp~C%7{pZf`&2f6PY@bAV*x+jps8A91!A1dk085%b zeOIZq8%gXDvjB*A84uA&Y*6s|#1X%^wB_b}?76FfDP zv)pXl_%2JKomZmLESl*rr0)Cl|5VD3g1hX8a43ezJYA+0B@iF4$~x#9-d66`QoiA+ zj&P}bV&Yu)R55^E^=*V2fzG=lZTELFKLEe`QO%!(CSKS&ax;-?Omf5zyinIo5q=aR z)ky$uik7Up1wg+E*}PYs#~0IQ{-DO!+N`eJ6oq&Z0l<^Dv87xTjTAD$jZfxi8ix~|ANTi0xnkFoU6;2e`2 zQF1Dst5%Nf%5}?Si!Rdq>!%50kM@w?TA#Qo;%lPAC-zb;c<}nFU?5YuEnFFwef=iZ zkke<7$KwSI z-4l?hC}*_Q+$r_51g!-}ynN->)EiRt!y&HeP{@PPz;cW07;O2OKheW&+{LB*%V`HO zMlNS&YV1=WBqb^VIt3F`u%hhxYm6r%2tJoIu|#GJD!;WjwzaP3}T*r>mzK>l_! zbHMQNP$oD5{k@xCYd5(n7>`$L@P>N{``ERE;3S1>m1%gyXiU|=Nwi7pupF$Co=*~Jn7`%H_&y_) zEJr&d6uM*Fr1Rz~$`~SUO^oq%nfcEjray+t;?IOsgA-QaKsSEb49wFN?d8wzO`lV& zW*5p|MHaQK8$mepu#kL_c=r)Gy)tTz(~!qQ_B+2d`>-?lWRg~uS!OvVArse*)t9So z6^(aE<+2wEN2Vv^S@w0ocztV=#MaNWR#(Kjrf`d?f-FWP>TAWv9v2DT50CK3_Hly% z&2Lri=2NLyTtX0|ZY>fm}1xto|>I%fl=GEpNutVR>n>@g8?Gy7(d^yPS>X7RZ;+vmmXHeTi$obBnpwk87U=n<6WN+b*;6p*@{z_=h!Sd0EuAm$q8fIYgGH;-|RA4u8jef$8I^pB%Rri`NLfe`B zg2U-gpO-awl~w1k^zed^CvT33z`naSPIC1!9B#$4>^`Sai+;Rjgz2 zPOr{-T_p)=7#OG4*1q)ijw~&bI0~5scb_nT*hDVY zC*1X|?%ot~jmTV3DzR+Ie$=YK@2Q3Z&orq@pe0P~FScTPyMOdv-SNG)KnqniFDHE^ zQ$~;a42P>QVAc|08fB~J*@0K3g1OEx{{EZoctiyVYoN~Jp`V5a7HtNP-&r3gqS4ic zVe0B8oB4DR`Vn=qh^e2?4pzuGakVYUtGyzZ^5q90mYam@M*$!sbEUhGm5GNXu$S|xRmLv~+r@#r+(ya41Z^L$r_ceU>dDVoQJD!6BT@;Sy2 zUGW&ULN8D6OUa{nQDu6~;KO%b^b2QS0L$e?F3U*fb6dw9#%E8I$R@;2h2Bd_va6G8 zqlzBCr0<68@Y98QDk;1a-!bDAAB)8%C6bc$pL9$aX_rd>oz`ANy%Wqx%Ou4z}EwzukuZ5%nH zt0cKUY!E&OB!tx=6a4O-gD;P&!r#E=plUkA&V*%NUs(uiJ~UIz3L)6DecylFx5mzL z?2LS)TO5#VjC8()aZkCCd3T^Y0T1s3R<_5YBqZ8arS>0tie~&)lw;++)AeNB$&h`H zb67g~R5?^~ee@qnNQ9>7G~l1Pz*w8$L9$3 z3vQOx1|18m5>a6lSxx2$%s0o6FV(@vN5GS@K@na+AFHcfp(kZRk$_Y!!`bezzrz^J zp8uiSdkF^|Ucy6to|NJ<5L9ktRVS6R%2w?EJ|C^63J8Z<<>PuW&g!+|28{e#8gJ-B@Lp0}O zX~t&g2co9@^DyNrX-*@^=3Z8W@RtwMvY&Za z;&a&4MjyQj>*jB2`D%sX6r8p>#Dfe^=qrnV)>b!=?CFL=&qkv*TiuDkKBs>#+-@%m z3hsZw4k9F~wvCZ#FSV$#t9_TN`TQJ)1m?vee%krvZqXBRXq;M6Ri0=5+G}1AQVYxS!81U!oCYoI2T zaGXVqOXz$Kvw<-l%cQpYduPI0a)Oz+U(A?K&4<48z;^QnXfBR^(DsBH__^{_9j)x> zxv0u3(8{{hB%wzP$-_Ol(JQ*ZY@}(B63!ojBmgI=zKkxK-|W)byy`Pm{KwOO*Zrkr zVRO~k-*D$e8)wplyG2Qp?t5cnT69&f13p0l*3An`H$UP4s|@aE9d2(Qyc39u=ibau zlKP5cA}2}~>b^WkuOHSjE(9G(yPZkrAxD?E8oQ#<#Qe1taqoxuw>EeW54^-8GBzkU z4*kjEJ*Ec;p1RVU=PP%{XhTCN`#DQS<6qc{ApSrxpo%t z=1VY+xqy(scS$U3d9a^k9wcpGtfKi00OSVoD2CD9PoRt6#RZ04mFj+(tL$(@j)8u0 zkC0L^<)i2_cxKW^%o2+!$2g}t#G$!~r(vQ2&{sXXjXNgL4{x#*&E|v#y;M47Alt1)B3Pk&^+=@N2B47_J15cUv|;qE1eLcjzJ|XwQteRoc$q zqezm5EDBiTn*e|D3H1tu9#K{q2S7?Wlm143;Yl)f-qtm&e41J9>2(LU>W(Lr&Hm!- zoH@um$aP&eDF9gIy9#u`aEaIl%dLR>4}*QA$F2n-l3U$-zbbi+K;|HL-z2#x<|Wx8 z%ou+!eI(8p^u-wP9LmmU_g9Mh{!d3LWsx@q0fvK!e7YneDJ-PgFSMQ9u%bjO1oHHw zEw*_cxW4w)y_Qc%kk2a&T((Ji1|3 zxmU?MLg@99HUV0sFMTozHG|uUiDPMb~thQjYS>i{u}!9eVBOX{krZYV-IpGY|IOZ<2NFvcw|AZrpI23NCV~Ws{v*A_q$lPlvN_I2G z^vth1F~eY(b!Mlwm}Fm9A%9J>kke2+~M< zGV-PM>cID(?^4fX*vqpp;kKbL;dr$Er+Rghs88mwnttY1S&f?RZ6j6~RNEgf9jv-A z078H<0q=1KnGwsfhl0*zVkTIhwz&|&y8PX5it<1boJSF%QKO+*1x14-FFN#q;Y(HZ z0?KAsBwv$!JWPl8KtILo5OGH8>%{d2z(`h0hzf>H+*VDC)=L(<_HLU^PQ5DDP4B?m zQXygfc`U|rEbg6T;V+IWKoe`5^|Wq(;yj3kYK7#!)3WC-$u+oRyh=Ol+2i76i6 zil^g3io)vD>lVru9rAb1!m{i7jn#EC3wfcz8u2rrzm36Fw!HKWm_~gU-eu&o_V~rAL#uv||h%Eev-cX=GLI518UUP+NN4dUaL&Bd~SpYv7os_#`xlDf=Yt;dSrNeJ{{ zTiD<67T7-2v}^Rls@NayCBHGzTgKNczku7mkIpi!dDrG_`F4#hhPY3xc#mSv21}2LF=Ey2z%a;9$KwDhAawpsufRV<-1<5(y0#Ww>K;3}G>eJtq*%n&RfjDW&!XWC?;Y>u z&_)aDn-6Kn<2IsA@UXSlZ}qKVH85qPAP`eXa=xcink!MyU++2GS40!`!FF77*>-b} z@H*C-?)RG^H1Q1JTrx|W-?-`(KT2^H)2uMv}guU5dkC7N6_#EsCIDbxzyjfv1 zb`~gSD@vq!<}$t3^Q(WJm-w5TfanVIXTk>C_1IhQ<>qDAz*XWJ-?OM0l-&GZb&lR? z^7*-PY{0y3c6JGWs35`%1MqiJUZKlg;o{z_u=Fe_`gehaa>*+I69Fw^4gjdo2!=Xt z3cy__^(nga`w&i9A$5|n{R=>KhV|iBb4mK8lbc*;DA_1K9XFO>3e0}Dv_+Og&&vV4VgB(- z@inOU6)8WTDIv1w$kX>SpkFJbaC;?y9gJXnwSX7S=Sp9>D_4l@EU+{D{>2o%uxv^N zyini;Q`A*3$~Kt2pamoD?}4ooaAXs?wVluJ+p>K6Cqm?;!@3G9$2@PO8n0EeaVRuA z-xr8If3IS`Me(ISCIXMw*huAX+SD)lg8@xte4MlI|L{mHr+Eg6Vlg*A+G8>>Hsl8f z!y7^GtWFap3sMtr6H`cbj^Nw=cT^AEn%J@EB860UZ{+6NXYk*(@;T^GXus)km~dM8 zC3P;zV@rsSE^Yj7gD+U_OAAs5DfbBm=MAnSYx$Jd*@0v+hyg=4&inTI_gK+@r*F>hmrPIkVhmmx=t^c;-8-5rHu#4o5^6FFZZ#-3%YL)mza2gr^ zMJ$ita-``4w!9_Jn~hANv7c;k+_J^EMp*^Df8i@0T721MAJJmn`mh)CwD}3;7gv+q z*ogzUj=wtqUpVas!?kuXyxAEDA98m@lPeZc!R6O%pOJ}p4jSqpPgXlgywTBm&W~LB zER9Ni^{z&AM*18vW%#&p7hbQn6o^!GD&V9J{O5qIkVZbR1qwcrWoTdA;ea%zJag142n6&KG+PP&v^gmx_*~_%I_k zPBqryJZ+oR$tM6z;P<55xt7-x<{bl{nx5{|RiI5;uqLxlrRADgRpl70sq$0LqJxSV!&kCpze)TWUZ1@0XH*Zn?OZb; z3z%xrhOJrmc-4G{(1U<#>eG~RlW1?OW%>YK|A2)doa;mU8~HQ@-%DVUGj{eO-6fP7$JStF3^LCr6sk2Zx_@XueJOFm2`A3{i`uupPLxAMpwBTV5tn| zqq9bRi?edQ$dbRqpH?WYW}2ip9!yeqo0>bVJ*34J&F!kILNS(iQl8}R}QrJW5b z$tX>ov%fTA%9K;3m57gFO~KG$%4E(=vwab*|BnMNMhj1`f{3_eqIH@urYDJyFPI30 zb+BFp&(9(#ZF*il3PXg+hM}aFijT6u4)s-R@aCF)oydj+c6sJ0NM7;%gkkO`<4VXeZKBRvzwNtM-z@lF+|zdXbpZf%OMz#BR|?+f z_nbM;ToUnlqv^(<(tG1Ur9bNp7y&>^a{eqW8b0B)uUxF>;XSw`5%gU2&=2%+iI06E zwYFiGbq^sA?kL|rKR541y5yUQqzt4U9sayLZco@<3cI`cjZ8JJ*Z^tWKB`!}m%x8@ zpuPR9fHAFK0Z>`XhLXwwJhX5~!Pr+fGEyZAEW#6!?Sa5a>iOcnF3?uY-!(p85w z`M%%LsdT3Z(kap@4N8v`22u)AQj#O3QvqotWu$~i4p6$JB{xctu2CD?Z+<_&>)HkX z?cG!7z3=m!``kt&Wi#UALTW}>`uF;QUKc%hCxGGrgiZy&eXF2*N!cdaX9M@!dGX_& zDrcarse{E2-B^FC(%w=)#EH6PF(Cl)0&$D1AXj0ej;3g)R@y%BWVg6Z>5Svk*O^J; z5^Z?->B~zVZgPnuH!vzLqBU)hyr>TdhkPbtg??+ z3r|cI+W8no8K;;5k`VZ!$s8~Q6O?Ur^5^fd9VtNF*sexQ-H(%NQ-*v-hLo(*wQ>6Q zwA@wo@!G~Ddd%Q#26m@Zh$AxzyFToi`5n)nfthG2%GMo{251T#nC>jp;-UlLkq}#4 zk%Xa}gf@%n9um!jMXF;wAN^^5y>srh4PEh7ipy*(fzWW4F*oXeFKyO2&%;MbIQ z4aI5khFHli5eLu^AE=ra$Q7sc60?!I)+0Aq)E$;S5wx(@9Ux|Fxqp;6WCL%6ShviJ zWIHka3Dn2(%$e7zdEN`L^*<(;k%eVIm)fwV&BPZ7;&n0d3RMA8wG2*f-XFwCo8dLv zpPJc9$G*yW*Q5xKrvDlidLE%&?XP9>R8I8+Nv@M2V;swQ{`q;q;X=Y&KN+{L72E~` z&j@45DFSwnSGHdv@BfIxqG)KNZ*-G$5Zm%0{h@!NN9{?fKq_9~y?>tbMZ&DS9@0U#QE)X{k37zHNecH@*)!G*(QQ*&8sLqaNl3GZ)HAGMzHDPJWj=PO}~>TAw@ zpw~Y(phyRBF~tf&==014Q$&XN`x;z8m|>cdk@QlC%9UEM{x|xtu%;qjn1vgqm~v`~ zhyAn7IHAemL|huCj9)LG@~J&=C;lN+oK4`{6t2(Jod2tb+J(ek;=K^!sY)efH{<-? z-inYLD}|0`=%Xk#O>Ch{sy`#!k%ZD3FUys!9qq2oK71+5+}uD7DZ zTiOL#1!kLV4zK9}a9L}_p>Ie&&7d#@ZbrnxIEDm*=h7FCV1`F$zK8(5qKe6=d03?(kzZ( zO6b0Q(-fzUNd`Ahc78_Wi{d!eO@EapQ#p+x;|&Y8*cwM&>&z^@2P`x^G=1EvR>H5O z3eRoBl%?8+jHlPBN=t1tiR8&ITN&9s9?PxqFtMdq(!8?N zKLm-_Pyk>C(Y4&odU6HP0wrFF?Cngn?1|LN$%IP1eFsqQ>}VOB3_}vuyVrPO?8NRc z%IDc=CF~y*MTiv}M5&d=DMGeZMb`g(u`TEJT+lb@^HzLvfh$>o)#M=qX*o3mSUB#PtI%9ag1nNL5AKgoRD@NM=HX{3oe z8t|+tdi`LdaC%_wM%AvXDGHCfYeWZAXeUvjb>2(*pXFq(d2wP7Kk zR>%wcT_i0(7f1>3Pk3Ozg&_83P2Uj@w0xQLpebeAB7uuDl~seUOjxVKx0(5U9b1#c z?^2%zwTGr9Yt*Vu8itE#rOj8zF`@Hz&#`y79|Lu>l61821_pzZ?guCk%Pc))V$a~g zk}u(MC1PA2lCKJeZdrgG&hPr_*8}f!`yE0n(4l0-JffWducfaNwFO`jyXK&zzBJ8h zjmp-s93O`7@3!U4yUz$gck`*>NYS5EyKvX~{$$VGo`4*VBDs z+YJmAOZoE(W07Wo%k|OX0p#ZfqEh734{_f6R7r7+wAEjLibnKe`K)q|C$;JHUbsgL zYjSTve~A|sidU03)Pk;FRZD$;%{*S?Wk|R(h*UcG;$vfyJJ%@mqlAxtw6SsP9-K_R z)P;@3r8ZI(&cTvQ7`VnY>eD#Jfi+*$;QMM3p%B@9FHTSEA#IjZU(S!<8V~=!ZAq5{ zvbkNr60_JZQz75*JZt*tWu2rRuuw2jq++X?D{#Oou&c!|i3%Z!*(~A|vnHLDxYts7 zbDePloAr3m5VYBp%Z-xt{z-*7fm8W~X!3*6M9AgwczFJds7CjC2RSEsv{}dS(txbU zi|&c-`p#a2CyKZp+dCX9Yxq-j=f6YK3l-8ED8;c3@I39M04JuxLKA;<*_;Xekke47 z^-W^Xf{JoMt0BkXN3xX_3$!AiQ5OMF5RV-hMK}RKMtDC=+yCZzf7i00Xo6tNz;S3? zCZkibcZx5))SG&%JaE^71xSqhdHK!vz}bxhxt(k~(_CJteFeR~16ce-w9 zR`f#AA{>m0i(7E$?4@pj@?nqi@v1?;%#&PU zIla*u_x#Q2%>7RPJHbwW1R;YcXy>4R!D3m)pt4n+wt!q~LKbTn;^i3|%(1pLkJU!_ zoeLj@z5DQ^i>=W&Qb2%FSa~#^UV-G+vukVP5 zdb|C;H1)-zv2HBQ+fKpX?uf_q-L3`J)f&bvj3-W$)UM!briYZKY`9d(no(xe^r>_} z%HdGX_>vK+`E+Ns=@50X-#iH{|9t)qovduYlI_($SD!Gi(&g4l9Xh{Q-1-*3NvKL2 z_?|O?Gf9P=i_4e3=Crqai0?e9MElMm>pBUn;3%QsEOCH@7bS~nylCfbE6BZBDm13fNVilcy-@aPf36SfpUOL6?(Hyt&$exzVUY&A4o6+0`zw*05b;(4@ zx1X6x`=W`gCbvK6nZAuFifPj%DD-|}eWSyj#YtZx_6Rb{n*2#dN$~`_+slDcNDw+N zu66c2E8!m3&8XoXB~6$vzI9Z&a{Q+3z*GvUt)H=e`PwPD1#wSm0f|4^WVM%@2lNv5pBJWe4-h}ImAtT z86HqwgON76W1I^`eL9a>1LFYb_kkb*lK_nJ$YzGob$^p8&U7`v{CFATyb<<#egCr7+Ea(BXN!6 zsQ>MIp;2vq_Mbxe1kQjRXdShvtWHY}{L!CS4bjf)W5MYHkp|uAmPBDN2Vhr0)XwdLgWqlr!@t zPTDP3yXW(D@&>@kt`=*LM+a#5`898p6p^{lQujR3Im|G@=fQ;RhD=>gcpe_^_Qe#o z-|_royt<2&IL&IaGypCLQx8Pgax(%W9J8($YQJ|s_;K?(de5tcf?Mf?D1wr3%}loD zkKpwi<=l3T+lQa_&t#~iKnYh13us{tqqK_d4?h^AzIN{@>r}%*&uj9#2C=1vMS$3` zWh*W9WWsT?JhP7HmCH_n2=e_Mk++xAP9mLQnPl~#?Unw85I5Kvsr|+9)WZp@Glhpt zsk zrCIBo$Nu}!KY$H{6A_R)g)1Av4@Q5`BN(LrB`;?8m?Opr%a<)D*qZJH&HqlRdgTE- zXB&49tY`lqqr5w*Ty&2ip`@WvE~VN`LfVOVuYUEStzWKwcHu_+!(1_UZC!nwzN*UM zfmDk{)-Svmns1|FxDITy`;9S0`;=pBXCyorp_8ubUMM|g{OZod(hLWHVRwvqFid(@ zQbS&^WV369j5GD5G}(Ots_b#O^={JXn3*e|d)(L_mi5?W@~ihHE(-&8ayIsBil9Hw zmgKs&>6TX6v6Cm3pnn$}SU97s07n<3en+kcuON3H<#B*}(3g+yO4X)^8Qt9H_IMwv zOP%UsKty42XJ3iV_a0*yLX`S(0YdXH75iH{wigqWQ8So~usiE|AIy;|y=Jd?L)6>d zUy1WKN`Kp3g6tWB>=e3=@VZk9~t^uHE6%>Vcq- z4s`s)PlvQTMiXk-Qsci=(d_9iiRH`j(N7lNa9b+$D3pC5 zI{!n$@HpRs$ddrqGzT{_maS>axVmTZ!bqSVFo`=fi$;7HB$o`4tgHmh)byZw-^Eg~sdp*IFUxFxSEv?CtW5pANdoEn#n8U7lwiIuvjlVUbo)>% z&(Y+!^Y92O4P8YB{N-RvONsrcVI;1;MYj#E9zlVLSJc~hM!c(u&vZt=m`)scnjH=$ z!vCFv77NsFDu~EV;hAB~cPd$`N2YQBAT`i$eyM@JWsYg@WvG;{hweEN)(~nlQb{|KLMk|` zM=qi`Ilm-*&V3GA@ch=%+%bA#Hg6%@G_iDRIgzh8xikEKEH4`lO#FJrx&HIJ^N;6R%+ENzBp&b1~GyOvW+@^PfX$f<6;5|=VBF^{}bka zUbQKiv99Q7e&!h%vvww+H(KqRZT{D+<<6|>IinVZ8sCr^PADo&fmvuRDle0sS(2YEVgI|@Q4Tc7+lCR zV->PX53u`6zrSA1zEu(yP;?ES?2aP`4%fCMH%e|~PJ7@0*yY3Zi$Vu5;E%A=?Isqb zDE~^xdch3jp0{(zrXmd&=e4mScmDY-xZutu@IJOED7JW+tKvt7R7Hids)Z5K=ow@G zPi#GVlSUJ^cH?O3;Bwcu-M52H?w`Il)xSfpX|7`G4R!y$KEBJte0xc{n6Ram8eXyc zNG;YQkEURZNM5V5^ZwD`!J9Q~B}?K|u|Z+^r)e_UD9(m=*$s+RH-KxL6MxP#d&(ha zK8c12y0(_10?hVgS3VO;e3KY3 zWi(KegG%!=m|P8mYWgE-I{GO?GDnR4J`>Osvv&EY+Hs@u znkkAiA?@K?{5Oz2EG7D>4_G<2i8W)jFL+sFz0&#L>b

PwT~ zA$;!LrFU@&vq+e3X-_$@y43jCI2_EbijXp>Vw@<@e!{EOJBc*4#phwfXrwX;ew0c@ zuX6rPMYI#BH0`Q1xY7I4xF{gk3ox2&=+17<#bd@fQfKxC0b!l&m0!I_#- zfRza8WPEhYc((`RADu)tqvGwOG&7mnmY&`tTn+&ntQ z2_@WdR=!!24MAwq>K)M;d7nb(01|eIC1f0X-P>22WY>!Wz7Xv0C~5-%h)B)9=XNOE` zd0fbW%&r)sbv>_Q?eaF!zb9MqdOto~#$aE0pw@RIK*^nGxP4nx$M}(sZk97`xoTwE zm#LCDo6jxHnv_q5nrJI27)AJHfcbK7oci5#K~QX3(J6Fy4Hqic9^@|l=fGErrrKN& zKlSQy{LRaR&>2w67>*Wt&i}97_ScFULKREeDNgcx+KNx!5Ph$Pv__}t;C_A30jX+WviE*LSbd3FwcyKHM4<5SHhS4$Z91j4AFfTVx=->$#q zx(tnyz#+W8bv(-V8DJD27(xBY?GIYiE)HaX+IhT$Z+-d|T_u48~-kjPb=eft1y!X759}bx91r;>Gb*qq`h~2_+s4V(%tdY zj!Hgb3C(+TBX!!j`+=!o=qwm|AN@KvqhjrZca-d`PfUl5u=Jyjvsh4>09C~G8k*+H zl}GJ_JY1uIZnk(LyUjT^C)uZv4tZv3e4I2FWuO!k*9XAYiiZSc;L)x;U6l zMjHxhIUjd9KPHd(OhC_s{$ExRs#AT5Z=r+j3C6^GkBRYAC>%0c`!!uWtC1QnXp=T4 z_iN{;{q+y~w*3;Zag-WU@mHol$CAaALU#>9t2*htv}v^@nZ=VepV7wnn2>Uap4Tta zoR`>1=rE@8Zds=A-wX6Wl|j8V!Jn|hNb)P$!!|25(W5l!iuxkwD3=@Pq2460w|5^P z&;js%SCB+;*+*HHDw@L<^-kVhhB964bX77mMrnlDmuq0FZt7Q2=e+9a%xxd1UDfIq zZ+Bp_^7TXMYdr8D&(kJY_t#hZ*8iQ(uv&c~04yxPQTh9?XG(GltiLT%=u+nXzHg~> z(xu6C(s_NL7CKq9>;)pIzZr}*IM3U+$u^HV{(^VSTOXAZv|IGuF*A0eCWNyI&M}xt zck&?zFxLy^Bb`pTEP6&gGE&Jos{5Wsc`ra=c&Ks1{-P~xWWfrjFJYMB9=9Q`D?up^ zDQETcc{;^)d#w4{al`>YzT_Zb$cUD(RFl?u;&l#P`QyF(I6m*BFK2g<0?z?J(hU@* z6b(h>^^{cpcVxTE=0+9pPBJlnwF=Oq&?fUlB{n)zaO%#Z))7LG;}OK{xnj* z=nJuee13v3%!6o!R=B(qBfcG?$A2s!PmI?m>fJEjgb!d}h~Wi9h*M20@{<(<%R|V+<6C?AHD)Siz2V@G#Mm2w|{>z4lp#QHD6iZ!k_ zvIA#iv6MEFKCTSdV{nrD$;gj9qWj(G+C#WSW-bY%I@br#Edu%hyuTM<;i}b~CvHS3 zw0HX-#-oI-dCtLq>OD`3&@P~vY9fu2J`peT^%9e=En#!Lvy!r@S6F@*vkLH|6mQAF z22XXpFWj#r)2-Ql_3>TU@uoaTvE`@aq^5q4<9(q2qCSw)aB5=)&hcKAAWL8!Mq?}J z#-_1efYvNMZH7T5vueb+bEdpAmQT6;UgvJ+6K-TvoLRLXM?)%7^T=)q){tCy6}`55 zLLk4M7imObEYO26c{7L7=&6n8X zm6yWvl_E5^$w53VHIE2sbVWv#yeKXR)2!Ug6HBl%aI0~`d8xu>JDE{-HwP9qqg(@g zu%~skg2lr^$nWZkO$FR`Z95lYRA=_iOcs4$A zBev3K_|HqlhQO$S{p}*;_SH)3yq!babJq8^YQ-Z{+}p~xm-oUp^2~4M0*;=6mK9o{ zuXg@BI6K~%@1%QzIprZqwSJE#6ZsOjmJaC$@-G6xwm-vLKDn(;e-pY_F8;ku?(!gn zLlTny7Zc#K9eFDsU)_Ew`1avgHbJCH)hOQiTG*3Uk%JWI^GK-Nc|8HRd$qoYF|T^B zuFu&rH&v_D*G*zr*Ug3;e{OMTg~ggE1gUZ|xg&u=Mbz(u1^=**E|xL_-#jEf_&0zH z7QtWcnq;0y|2VY%An^q#0`qP?{anN5r%BErr&Fho1=yTUF+3g_3#bBamyi|{T zBB4T~1>%naCJrMzDLSn`{#pI8In~uG#=pt;2A`{!#Bn2Aqrw+TkOaw6d5}hyfmdGA zlo4)f1?V-3$Ag0Ro1ZBXz`Jn7zJO5?h_%zFW3B(o;Y9};2VC0q=f2Ds(Gqk}W7Q+y zAaz!54;@BiM&B|gk1d2mrOB}?=}{L?{7(Mrm?Q05<-$1Tf<9v`1=ad}ntqoVJhzN? z{YIk1h$>?L?&b05I+*j?AxWoTMiFiUFTzz;M|fn>X?@_99_=!tec$_P8Z}pEU{^4188IaxPM3ewg0xwnyF(0;DC#eV4gTGK6TCj} z1%F%sJxx^hh20%-3}Y6RgO0yXB}r*);Q?*%Y@`M*8ign}1Ski*)fts+Iu>|`(feb{ zlZjPBp6%YFn-~u_;dy)?LfQJY+^&Pl!^8TycdHqa&zX`RaSuygyG*nx7Tt_ego7yX z0xK8X*@~7eM85g+`nPGF@?J}3EFU-tSvhesnCu8YNJ)%F$&lN_LKiXj9lKq0I8CKR|?537Eqs zekr|BgLSr!-_S&D-NbSSr{0jAJrN9iQRhO^lbz;{^GUSj@lFbEL(`nP`j0Bq;dL^HiPJG?xOK2C|(&vFUtqQ_| zi|%4Y&`M~nqZbeB(X1gmK8y4{gY{+C@Z(tBmL+%QjxJ{`6rA*eb|S2M48n_$TP6$n zK9*oGwBog^LB&`6o=?103tcORFXxZ%E~T%#I8a{@tDay7OSlvl9z?DJQi>Hrq&-rl z#Mhw?zyq^t`RY4`I$$dS64k=zbH%P%Q!+b6xsBI+!pQJMMaN^TAc<&f(sdt708xc;icEQh1+$$ z9?yY0_+3@EhJBSNSoBL`rw5;B}gWX*&2vdm}e0+k#jE6dJ{nL>O3%cRP z+$f{O!FMQeUfmAja?^C?r)@94HX@+Q+$dE>nNf6`q#^599d5gm0 zq*_4Y!-PJMhsExAA zIyWx|d!CQJNM|@~6l$f*I$fjxy76mwaG z{`vp&(4unZ!0VOk?oOvgk#zJ+QG~N9?mYyn1}Zche~)w8bVHVZU!_aGc}H%Q*OG*i zikmpDFO7?wqz}OVlNq6em+E%m)@ou^OaG6ImFJoCN$6{tYx7Iv|K-->r|yAkg6kGB zjmiU`xOFycv=(GM9ez66Fy?a6^~NAVoWo<1Bm(dS=V6Z%oTaBa!S=qoevG{gVb%2!Luep^kN3X6DCa-!77b%E7uJo`0 zx)`p}rE}mZS4Uzxup&2n)_J zp!aam;HDyh-GFwa{DMg9GXLw`X-LZDO&(+7H$gu(3zbheN2G7HqB}@udaRhz-cQ)7 z4NwCd3f%_LNG0?>l;z`(d#ee0U74|ODju+iq*XwqBCwZ-GJo>*5)`t9Mu*Px(Is|v zJvc3j(g&e(1=hFJWx?ty_-CCT@IxBQxDxt~D2qjxu~ztBCnhpSU+-z%e6w<2I^25( zwl&Nu_nCMCv{Va;g>p*cAK^oMHY@@nniIl1$)kT+e)!+ZV`pHE`Vb4@eqmRsVLvJS zNzW+ntiiW4QWurr+hZG@?Dr3Kdml&wTdE*C`985WmiJ}n+I>WP>kjne6CGftJLZdB z0HlsSIer8n%(dv~uRLEuW3E>HD&1jh?d=s2W?~I&5sDIpCx9S+P>Ax01;Xef5Pr2F z?9#k!Nr#%zKbg$;5eBZ}+u-Kl9dW+B_nn3BT+O}pk{8A}+ATK+|LLr$XpWvyMvKFc zhn^OTFbiC}v2zG$nK=&|&>O=}_q1{Hi|Rp;xYU&bF%lQ5(P*MMsP70tK$KSA~d zM8NV(R_8;4M=Z4>>(-xP=v;F0PP-197t{vBt-Bi&7v z>M=~qUqZD*YV&QT0R@wKoM6(Vo2~Biai7&I%o6yF8GHtXQl%8hO47ey$M53-h7x=y zeHQ1%O&rnJaC`)2Bwn_%2C1>VU-0k5`Db0TGC z^3W3sY@L`)$|V~TS(1eb=H-2X$frZ%f~zxKb1ST9HP&C`AV=;m_o%^b>8?HFhgSD? z{K3aW%DPabyY)89KhS=9I|xMp0g+~^zeI-g?|*$_RVwvjr*|bNW3~jZM;tD+ONJ{N z^@3o4>VCAn#qr1AZaPnm^}fux&bpH5WKa$owO*iKo!s$dMogevpnPA-glqx?i<_W# zyL%w+FU*)rDNLw%B!);a)@dm%^h3;Vn7*k$fa7sKgZQ1YL_m$ zZigb|BAyBdu&(jH>VL|N6c~Y_Y4Q$Sgs{+&XoUm+StTC-LEE&20vvO~Msh}BvPFnYSTDQUmE||Y>}saR1}^8tVPQJw$5~q_NVNM8T;CMI z6c}oVu%T9sFNC%njpo3Vox)IB^;zT2R(ee@p9Ax_RN2)(YualIlT`6gAgGHh_}l4J9{`mXb_P*sp`2DWmaf7H0Z zCr02o6p~G3T(Dz4hlI$LrfBrL6LKALl1oHScQ22hj~Sag6sCDTCqKFMjatyZx-rjk zC1*8s?E4I(O@~tVpJsCF4D7Xhht{*tfDC+#MYGUBN3?Nw-Fx#zyA@RFRQ?&1mJ zDp3))YaxOLNjR>kF^)|*O0c=moyn5mNEF)c*i-PJ=6clC3@m!>VyU0yTo%?+uVF;1 zVdOl~_6_0&u;z5Tev3(p8~d`?44KF-w_aNMz54F&T+_{jS>k|49+znR#+sy`;0;SP zHeh#}gaqTr;G_t=piDncNa|>09i47AqnEX0o^mape)VW}pCl9!-5pdG+VZK&r`gRu2ftNbiFIeIj*RuneW zq4glKv-rz594rGX+gc4_>26Eau)7a7n(P!v1kS*uegWKVz`+oi;8PimBL+0}@7rN4 z(j_gjKybGWYx{LOz$$QVFCA>DojvgI-!zk^!GbxTBIo^m;;`47s#hAw=ml+PY<0=daNeyrcT1 zJ3nt|Pz9L3_mG6r*u=+yo#y)s#+qg#nqN@@&j8u8yttv=O!Yq1`M5lFa;-%>Ot0lL zovDqgZ&Vc!+!eNoRXkzkML!b+L!0cM9#xJgt!;qfs z%TV_d-&Rug=Sp%sDBGR|#o(LZ$-V5=$H)Q>1`XA8bI;L@^v%@Vs&;q3_RkIXYanNa z(J`*u7)pyO>PTU`03W|rgdS!f@anF5v+OWQL2$S!5_A{^eRZ2h55>ZB2qyN!HTEMBsG9j{rXWCaO>$UwCbJVv;>f1e@(3WVf__&7; z?pHS!JB%B+M~Ax;lJQk~ahKKPU|h%x zNO_EZYs&y`*;~-30a<2YyG>L<1oljyn3n?y5Kij!1nhuwt}$e$@@UU{h*WszZRE<( zXVuW1%Bvgf)L*e7P}#M%JpGZ-fBB#2*MSA^)jK`R=WvLP8SQf12Bo=scN0-#6y zhUpi5stks(xtt2waVuTn_$sVR8!NRIjyEl}296OUwdMmOMoO(1OdH>YGAz(HY^6Z* zxBNLwhh0t?dMsndiC^$jMTPyZ;Jc902Yl`IbMUDfykL36)dc@;&4v8--I~fn7>$uB ziHQpgDrB>sKWf@iKJkRkUnKz212uYbDNNRw)IeTimU@qB@&1p7%$>H?nSZE05aR3k zOuFM3GoY>vR$AS%rn$rG(fLJ^M$ z5$Ug^yZ$KdyttaWcezR(7B5IwIWehw60cUJ`x(OY%WTfZjx8M+5zCoaOaTn!YY=E) z|Kd?9S)gqlL(XT~!Z&IRq?4cY?0$0~zxIjO6o*)Y5BM;Gtf!vyOpp|WCxSCPc=Me@ zvPzU3H?m=AC-q^5Ov${g#P8<--1yRPK2p>%McLIiA6*q(Xd^{X{8QT7El%RTqk6J~ z4h!u|Q(QS~ChBYM9~4Z#&qYTH9RdqD;UE?H36~lyjNDiZ z`xZLkd%rMGH$tspEa99dBy}^v7!4JDI`b#pPJ#N&_|1LAq#K{F*Kjbq7dSud4GXwW z%n1gKzSuMBUj2cF?->EfA{7OL<~$6uyFdnXCs!#HVUj7XSIS5|OkLjZgX6tpZn8OK zImEf!8e{@w?z!KvIf`u5m>c8mbEZSJnl2j73EP>gTX8i*D^wIr?V zJnkU^N>7O&5e>wp#HT!3+`r-wwIljQv>n#_$@48m26Uydv51~toSs}n z(*N>&o|vqz;R`#u6N89C!2O5|a3g7t=xy^^x1-(h?y~;5EhWCXz2CSeqb@CB>cL&W zH)6R#ya%LsghWJ)ER1$uUf6<4PGTw&Kz}Ar-O%tf{kUe7e@B&ur9u!i+&74#M1|R& zuR7wFp=5nz$hVzzTzB9S@Ruhb8Q|Yvj}8F7;*(U(B%o9*5}Wg zxTL0)%WABTqA)*hN~86wwsjQ)WFi`wHym2enXu8Gc#&D$@x`$(ngi#3;egvSrLw1Or&Ex&ukfH=>&*xT>;p!O!TWgv=KG;6S?cnS1u1XF% zVm5Z|cp&15zeP>pL>(hSj0;|($cHFY`r)jeZcQHI7r`SKdRz!@tpUaU|`aw zOi4_easb~xPEM=i>*)NFM9xH-NZrt_nOfesCPJ2q05@HT^hd4CeU6KT4_CNV&=2Y@ zu>xDW-2y6BUG4z_IK=J|&GoaFbNxcdOw85c1_e4BqcXX={Al_4YbSyU+5IKyf6z9GHf1jG}_j#oCwAHqt)u{>mSf_gX>DnCU|IMOyIDy!Bgdbb9eq6P)z@Y z9xH{S9I{6Z!G5UREuwF)QkQ@`*nA-f!|9-9@b>yAlV)ncMo&7;>|Q7m4O`XxV3ym| z*7ajvKT5Odc~d4e{;HA|fq(v9jo>Px(O3F-1uVmp{$_6TQ)%q`8@`<*y@-OKp7HoF z^xSau$}JS;D6S`4c%dnv@U0X2yV2A5zjdr@Rih#_WujT<^P*+kRwKkH_<$q#-hf#L zli20P{`xR570FDV^onmdVmM02eEg-PEj|^z4BKO8aTCPe*_vpe`f=}rMqq%7h-FB7 znp0WHalJ9)|GvBJWN9&M?UU=#T@|JB6-FDu_(K}gKRH^&PmEh4oXp?(nRCu6D?SksRT^znA7?~Q zAaBir{rOJb{<$sXu?HTWhK~H41-cP<-%S0Ozmo~^y?JP?%U2ehdv)-tQ2ZbDa?|K} zl*;)OHz{F=B;*E@14ACO(S7vzi`n`aDDvWtly}nB?xaVxPi8S-*dVLL5@h4-vByr< zWb($nCcT{BX|Zc&VLkR-h~zEN_vE6%qKIVHC;wwH0#-M{Pidb3suG77(IYUbLiiA@ z@)Nczod(q%UX)zW)~CX@cR6IDU436oXl8GN%E3FVmRVmrn#M;q@SKlf_TC=314sAE z_a|n}Q7T11yZh^PoL2<%1l}8-)D6dM4u#_12<*mqwEAzEq5epFs+~e(9rnYVUqwIivKaQOnaHaLS&M8}U9fGs4-|ncwL;m#r{Uoul zqmuj%R3oc$Xx4gEDfYzR+aDLjaE)5nSUFy50i*R=D-` zG)66=Ky#eVc=fy6KKOqRVBkjUk&~AMQKm;J5UpYgJnm$w#3dER(rGsH+q_~PGl*ix zLUMacbXhQI4rG>J78;)v^SOGI_}Ju4eLa@ok~7EYa791~#>`22LhTL_e>E@nU5Kum z{=N^bXZ*(jgZRAZE+`^X08yMRE`DFD_dHL@O5=Lhv5Z3@{D90{HsD5}@{!1O9j4)G zQq_{S+3NYcS=KwT(CnNJX$#BzhwiN*6cN6980(&=Skhp#6~`Zx$EXs4&EFfD69NVJCV$UQVz<@&K z<^9?=rSmk{%^%siafPG^`_o_y9=he?fB-X*j}c4QWnp}Iabl!j&@ptw0PXurmd&IX z^3e(eh3>T))5KDc|33#{`BHlI9X{47$4uG0G4N+9j@>u!XN|XUha^JL%`k zYGHnP1;9W+{?QDx(%!uv1V^xt)Zhh}^WR>DTC==q{)nP$b2u+rc+=$$iuWx3*Y6cy z=Jy4uE-?9le*~7#!SS8EdHXS@zeOhu1MB7j2L?+S%{?fb`UBM;gyQ40@crrO71uB9 z>WQg_{`^TM`u1Xr|2;(twT5>=oBSl9^F)jDuBb5r zb_Gp@T@{(mIRU5jPo)2Qpy>a#cje(wzg>Tfu_lHj*?;z}jD0s0AtBk<2q`~)$dYx; zkS$9oks@2dpg|%gOBBg6k%}y1CriebVYcTxdan0+ulN1?`S1B>?tkW7=X=h5&iy&( zKKFfYg-^dogK9Dg7uk$?mK8vSkeU3uv4s#ZE1qOdp@lKx>9cNeNeURM%DkTvOi$&a zkPNAn+F$DF9iIPFS2Ol!{Gq{`f<>dNrD1g-SZ*tiG6|Um{{mSIwYYN+i$Prv1dptc z!{Vv#)c!=i_svilW3$W5?`0VJRCy0dS|7{Yy_S68g0=x7Iqj6k!sKFgL3?n1eYdHZ z|DJw%yr~UuK+wxqTDpUywSNyxWBXP|z=Ko5Zq7V+O74d3Q-E4jr@E(uaZ{P>El|+< z&BK_u5dlypJp)=EJG8o;P#CaLx~4m5_DBa-j38Q*FWG_YLWWSRAq6m)-a!49s$2Bp z)#ao-kHvuli;Rq{121^Y6Y8f@pU}8REMFd8nr`n|IMZ>6pPKG^v^b5c%Y-l8u4bp+ zM%r`B#eOh4*kg--GJ^|TEmEde`QA>%q)$02ahboeH?}fIwy$mlNP@)8pwJJ>iQN)H z28ah~>3J>WN0?jG4;Wa)0)Jc_g_Hm{d{y5)LRPeG#wdrc3GCS3c6LPo4Th%t!PJj< zo|Q8*ItUt#0b*(Yo#MntJd#d{quI|EJN(f^iq+^Ec`*Jpjubwsy((k$d1?n9vLv*8 zw&OkBMt<((X@%`-QGhDjutYaPK(|J5Ksk;ia2rD@Xz9}psKsQz*pMf(a017LYS|Cr zy`m)7I}L252$B2B^yR$$Mp#gt6zJR?EAV|n#sKZ!oJTkQL!QU%s$<6x;9*)}@9!N< z36dFH2HoSk@olb?9aN2nn$uoUvkV(*Ok3RuV@Z~8sC*#tR?Ttkl;*M1XNf3JJH{FX7wz+SWEHUZ!o-w&Dh46XPPK2_(`|k$EmTM+ zdJ;qK4#v|a{59wR7_og;6CY)}=^pd+!}#f&>l(8CBeXO|IVP7>#q?G6B+=?sOH^j1 z^TI*!@sOc*?Tn*LJQKwFA&}jKOQImjp0|7Ldd($hbhTv z^FCJzj`lw?-2q&AT-1u2TH6d>+bG)hJVYGr^edtG+UIG&)pfSFY?s6voGl&%c>n#h z1T{T~;v@gDbzAUdd6$HoN}V`%bHj>J%+LWh*=Qz(#Bp3Tg2>w2g9~2mlA^OFjvo^e zgm)7@%6bWHlC*rCKmVAj5}^JQvbhv9iKS+p9kP7&x?bAk8R-Q){u`W8WNw+%ktF(C zwW=<6bnWIh|BYkRo+DF9FpZr$LH;VoE2fQRqC&~GKa;<#O2fJTGWX};tSpr^g7V0yAF?oO z!*qIPy=5rKA`9Tw-px}dL zXTL=Zv4N%nV|ts}F}<&W?oVwjmqmZMM`at+-NgTy(wSoX+Ws-HeZ`eSd5~Ot0M+=y ztel-Gi9FmbnRfcL;QYt5F9naaaQT3^QNQ(it)6+U6Kt51lhfw*@#pPwnShs=6bGyh z*y1-S8Tm2IP9Bjn`{W&u?xIv)q7hsZrCI%mcHFc6B1guN^ZO2hqBns}^NdzFxqA>S zRSWj1MuTHl*$tt0AR(88WJXDcTCiL9%jPRi!}q}zzzxvdq<$g&sANVK(<->i7XW6{ z6ZCLn<3DEJ4M+kOtQ<8j3;=FQ`N8QY*yG!!>p2vQVsoH*l1BT_O$`F*#t;7^B`ez( zP)PCdiDLIT8kyFS>voTj)>I>ke}Qb)Pf?+3KD$s;tAd61RjLJAq0dfK;6jM+wIouq zR3bg^xYSbHkHr;)stM}W=(%}%9U1^@wkn`&k%39Sz?<1U|0I^m>YO}Y{+)1JIFbcE zPvb*#p)_L9A`zoF`UKZsL*7d_c^y3snS$KhkrQCh6{aS#T+j+zmz1$8@|~NLvMP#4 z&Cj0z0;hMK1cp+rzgW8|%Ov125??hzED#_4J`Tv3SLM2?tQnOu_}YG3uS`++bKwTQ zM|2O%NcKHR-W1=y|MPnKm+;@xpg$hOZ+qrPwOA`>O@fA@K?JxMeaFkJcDfgElU{4f z;NRO8K(LuMUm>FvyDll=ox;zrLwMXqecvp6XG#qjT+H+l4pZhd2p`K8e84 zSlxL5^w;=S%pu;to%hE!xo$`V7~%e!VkYL zn(!^Z$Zv^H?|b?^5~km`w5l@Lqv2~KZiGzb6>mgi!e6)?bht|~sM?>DsJ+Pk)iG!= zo*qkOjCW8s6|*RENOf*LZUQD60a=9N#n@(`-Lrsv?>+ zo#WnooLmsT{%iW$FX|aSzhCt&?H93y4w;C`)SUJO%<Yv2r()g0am%DhL1ovCRkk!$TbYtO4X4HR3D#q z+Uq4Nx<1R9RuY-q5+WW6=$?%HY#p62?foS6tZGN%1IDc=pt8~Bo zZA3)pC+Z*BOzuML)lT`oVy`hZ@!{11bHp|hm9)auBAT6@3;ZH|a)u>(+2$Y5W+$ey zVqFF4iyl1uUZ1WekhK);J(7xO*63^C4Y!KxgNM!GerqCqQ9!#|b~n@A+`D>}h%>im zN;BdL+5hbtJKRjj#N5t+le?y`Ts&8uS-0sp#-+5JoIXgT#^_R76LD7ng_y}{;Ryl=*C`kSV3AXSQSS(2nU^(O1 zDob!@|F%L`CVkIfD|~4IGL;t114==jum{69Gh$bIE13_&diHZoth{3q$92C~?Hz|g z{@S>n2qcgK*onp`mJMoUVNyo?=t{KV-H$pjrQoZx0_bMs&Akbbt6}oo3)*~$6|F33 z^`R?|=Rh76uS_p86A|-oG21C61l+In?b=XA7P}}mA~QigxcnkGc}t(+UR-Tes4NsX zuq^aYlFi2Ld;(Ih-^>+}5%jYFoMiTyFI&1U5#G~$d1D`M`=$(Si*9|;ZRL(;FhLcg z#9p4-+ZPE^>v3Z0SAJu2#@aZThL1 zQZd#MwE5@RPa~omC;E&cKHS@KuQ9+&QuSy;)Eju6y0XttQoZ-^-c3WT6S;Q4rRh6AB1R>gxVj{YctIbW+qo&vwr8F3`~bYX}eSPq?I`)DGF zR{SmXY#3g(7OD9nAgkjjlzrwl19xPi%8xP!isc%boH(^&H1n8?e2YOV1<$GFA_a~! z6o*RiIAG4(+gG5I(ASArW&yCScmq>Iavg^vo1(4$s3tW~?nee|Xi9fnrz{@cd@Sw{ zn%T*NQrYDNDsMQ|?s6duAVaCv;32T-*L|klbTfCdh8wb|6VFDq^fV=}Q`K$U8Td|$ z$SO(%*ts$U?mZ-<@1oE+v)_{oet^&e-t6s6*!JAo6lwFHLct8P3{GeZa7ntxuu!LrfDgWNc#3tcX4cYQFFL?Dpx zM@l)Y&O$8XK?usNgF-m9svX8^$~9Uk!_D4Cp>Rbmy0qZ=cS0a^ci63z7wTdzl$?u(^ykuK< z1~8Eao3T4?`;><%oCMGC^p;1K0vj14+J@6KFfS|EtN2-PWaRzx-HZ#q=1)i{13Yc^ zxjyg=2tfbepZ}l^4rHnEW1!h%k_QnNK_HM+n2A%Ek5`zlj`uBJU;wGWR8-HvRL>}@ z*{P`NsA%h`Yb(HDIxyG_5)1tQe-Q)*`P{r7_5TS}HU1Ek97c}-1hW6bA?#+LZ)liT eVDSH;QHANK{+o%u9{v}di@AxF@ym0b3I75=PhM02 literal 0 HcmV?d00001 diff --git a/awx/ui/public/static/media/brand-logo.png b/awx/ui/public/static/media/brand-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6a52016f04a191c0b6daaad0d715665279453644 GIT binary patch literal 7491 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 D?NcEH literal 0 HcmV?d00001 diff --git a/awx/ui/public/static/media/brand-logo.svg b/awx/ui/public/static/media/brand-logo.svg new file mode 100644 index 0000000000..6d80915fb6 --- /dev/null +++ b/awx/ui/public/static/media/brand-logo.svg @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awx/ui/public/static/media/brand-logo192.png b/awx/ui/public/static/media/brand-logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..74489717d03fa8c3c170ec3e87e854f6d81bff28 GIT binary patch literal 7854 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 literal 0 HcmV?d00001 diff --git a/awx/ui/public/static/media/favicon.png b/awx/ui/public/static/media/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..170ed20f89248d0ce5cf405c3359cb99439b0181 GIT binary patch literal 3724 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fa3920d3a35c2cd00596ffef1d65811a9bfa93ac Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Fri, 17 Mar 2023 11:11:22 -0400 Subject: [PATCH 015/167] Adding default index_awx.html incase user forgets to build ui-next --- awx/ui_next/build/awx/index_awx.html | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 awx/ui_next/build/awx/index_awx.html diff --git a/awx/ui_next/build/awx/index_awx.html b/awx/ui_next/build/awx/index_awx.html new file mode 100644 index 0000000000..ea339711b4 --- /dev/null +++ b/awx/ui_next/build/awx/index_awx.html @@ -0,0 +1,8 @@ + + UI Next Missing + +
+

Oops... Looks like the UI Next wasn't properly built

+
+ + From f5589575388a859f1a8053ce323c3e546efa3953 Mon Sep 17 00:00:00 2001 From: Kia Lam Date: Fri, 17 Mar 2023 09:40:11 -0700 Subject: [PATCH 016/167] Commit .po files. --- awx/ui/src/locales/en/messages.po | 4530 +++++++++++++++++------------ awx/ui/src/locales/es/messages.po | 1514 ++++++---- awx/ui/src/locales/fr/messages.po | 1329 +++++---- awx/ui/src/locales/ja/messages.po | 1383 +++++---- awx/ui/src/locales/ko/messages.po | 1311 +++++---- awx/ui/src/locales/nl/messages.po | 1359 +++++---- awx/ui/src/locales/zh/messages.po | 1312 +++++---- awx/ui/src/locales/zu/messages.po | 4459 ++++++++++++++++------------ 8 files changed, 9898 insertions(+), 7299 deletions(-) diff --git a/awx/ui/src/locales/en/messages.po b/awx/ui/src/locales/en/messages.po index 11df1f4a99..b5ef29302f 100644 --- a/awx/ui/src/locales/en/messages.po +++ b/awx/ui/src/locales/en/messages.po @@ -18,61 +18,59 @@ msgid "(Limited to first 10)" msgstr "(Limited to first 10)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:154 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(Prompt on launch)" -#: screens/Credential/CredentialDetail/CredentialDetail.js:284 +#: screens/Credential/CredentialDetail/CredentialDetail.js:283 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." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (project root)" -#: components/VerbositySelectField/VerbositySelectField.js:13 -#: constants.js:19 +#: components/VerbositySelectField/VerbositySelectField.js:10 msgid "0 (Normal)" msgstr "0 (Normal)" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:34 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:38 msgid "0 (Warning)" msgstr "0 (Warning)" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:35 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:39 msgid "1 (Info)" msgstr "1 (Info)" -#: components/VerbositySelectField/VerbositySelectField.js:14 -#: constants.js:20 +#: components/VerbositySelectField/VerbositySelectField.js:11 msgid "1 (Verbose)" msgstr "1 (Verbose)" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:36 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:40 msgid "2 (Debug)" msgstr "2 (Debug)" -#: components/VerbositySelectField/VerbositySelectField.js:15 -#: constants.js:21 +#: components/VerbositySelectField/VerbositySelectField.js:12 msgid "2 (More Verbose)" msgstr "2 (More Verbose)" -#: components/VerbositySelectField/VerbositySelectField.js:16 -#: constants.js:22 +#: components/VerbositySelectField/VerbositySelectField.js:13 msgid "3 (Debug)" msgstr "3 (Debug)" -#: components/VerbositySelectField/VerbositySelectField.js:17 -#: constants.js:23 +#: components/VerbositySelectField/VerbositySelectField.js:14 msgid "4 (Connection Debug)" msgstr "4 (Connection Debug)" -#: components/VerbositySelectField/VerbositySelectField.js:18 -#: constants.js:24 +#: components/VerbositySelectField/VerbositySelectField.js:15 msgid "5 (WinRM Debug)" msgstr "5 (WinRM Debug)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -88,29 +86,29 @@ msgid "A subscription manifest is an export of a Red Hat Subscription. To genera msgstr "A subscription manifest is an export of a Red Hat Subscription. To generate a subscription manifest, go to <0>access.redhat.com. For more information, see the <1>User Guide." #: screens/Job/WorkflowOutput/WorkflowOutputNode.js:143 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:299 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:326 msgid "ALL" msgstr "ALL" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:279 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:284 msgid "API Service/Integration Key" msgstr "API Service/Integration Key" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:282 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:291 msgid "API Token" msgstr "API Token" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:297 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:306 msgid "API service/integration key" msgstr "API service/integration key" -#: components/AppContainer/PageHeaderToolbar.js:130 +#: components/AppContainer/PageHeaderToolbar.js:125 msgid "About" msgstr "" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -131,12 +129,12 @@ msgstr "" msgid "Access Token Expiration" msgstr "Access Token Expiration" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:347 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:408 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:352 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:421 msgid "Account SID" msgstr "Account SID" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:383 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:396 msgid "Account token" msgstr "Account token" @@ -146,9 +144,9 @@ msgstr "Action" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 -#: components/Schedule/ScheduleList/ScheduleList.js:171 -#: components/Schedule/ScheduleList/ScheduleListItem.js:114 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 +#: components/Schedule/ScheduleList/ScheduleList.js:172 +#: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 #: components/TemplateList/TemplateList.js:246 #: components/TemplateList/TemplateListItem.js:195 @@ -166,20 +164,21 @@ msgstr "Action" #: screens/Host/HostGroups/HostGroupsList.js:177 #: screens/Host/HostList/HostList.js:172 #: screens/Host/HostList/HostListItem.js:70 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:214 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:260 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:155 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -203,6 +202,8 @@ msgstr "Action" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "Actions" @@ -213,17 +214,17 @@ msgstr "Actions" #: screens/Host/HostList/HostListItem.js:95 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:217 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:50 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:77 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:101 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:33 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:116 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:76 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:100 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:32 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:115 msgid "Activity" msgstr "Activity" #: routeConfig.js:49 #: screens/ActivityStream/ActivityStream.js:43 #: screens/ActivityStream/ActivityStream.js:121 -#: screens/Setting/Settings.js:43 +#: screens/Setting/Settings.js:44 msgid "Activity Stream" msgstr "Activity Stream" @@ -231,7 +232,7 @@ msgstr "Activity Stream" msgid "Activity Stream type selector" msgstr "Activity Stream type selector" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:210 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:169 msgid "Actor" msgstr "Actor" @@ -265,7 +266,7 @@ msgid "Add User Roles" msgstr "" #: components/Workflow/WorkflowStartNode.js:68 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:211 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:238 msgid "Add a new node" msgstr "Add a new node" @@ -273,10 +274,14 @@ msgstr "Add a new node" msgid "Add a new node between these two nodes" msgstr "Add a new node between these two nodes" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:113 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:108 msgid "Add container group" msgstr "Add container group" +#: components/Schedule/shared/ScheduleFormFields.js:171 +msgid "Add exceptions" +msgstr "Add exceptions" + #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:140 msgid "Add existing group" msgstr "Add existing group" @@ -285,7 +290,7 @@ msgstr "Add existing group" msgid "Add existing host" msgstr "Add existing host" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:114 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:109 msgid "Add instance group" msgstr "Add instance group" @@ -325,13 +330,17 @@ msgstr "Add user permissions" msgid "Add workflow template" msgstr "Add workflow template" +#: screens/TopologyView/Legend.js:269 +msgid "Adding" +msgstr "Adding" + #: routeConfig.js:113 #: screens/ActivityStream/ActivityStream.js:190 msgid "Administration" msgstr "" #: components/DataListToolbar/DataListToolbar.js:139 -#: screens/Job/JobOutput/JobOutputSearch.js:137 +#: screens/Job/JobOutput/JobOutputSearch.js:136 msgid "Advanced" msgstr "Advanced" @@ -356,7 +365,7 @@ msgstr "" "before executing job tasks. This is intended for static content,\n" "like the Ansible inventory .ini file format." -#: components/Schedule/shared/FrequencyDetailSubform.js:517 +#: components/Schedule/shared/FrequencyDetailSubform.js:524 msgid "After number of occurrences" msgstr "After number of occurrences" @@ -365,7 +374,7 @@ msgid "Alert modal" msgstr "Alert modal" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:123 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -380,16 +389,16 @@ msgstr "All job types" msgid "All jobs" msgstr "All jobs" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:97 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:101 msgid "Allow Branch Override" msgstr "Allow Branch Override" #: components/PromptDetail/PromptProjectDetail.js:66 -#: screens/Project/ProjectDetail/ProjectDetail.js:120 +#: screens/Project/ProjectDetail/ProjectDetail.js:121 msgid "Allow branch override" msgstr "Allow branch override" -#: screens/Project/shared/Project.helptext.js:122 +#: screens/Project/shared/Project.helptext.js:126 msgid "" "Allow changing the Source Control branch or revision in a job\n" "template that uses this project." @@ -436,13 +445,13 @@ msgstr "Answer type" msgid "Answer variable name" msgstr "Answer variable name" -#: components/PromptDetail/PromptDetail.js:123 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "Any" #: components/Lookup/ApplicationLookup.js:83 -#: screens/User/UserTokenDetail/UserTokenDetail.js:38 +#: screens/User/UserTokenDetail/UserTokenDetail.js:39 #: screens/User/shared/UserTokenForm.js:48 msgid "Application" msgstr "Application" @@ -465,13 +474,13 @@ msgstr "Application name" msgid "Application not found." msgstr "Application not found." -#: components/Lookup/ApplicationLookup.js:95 +#: components/Lookup/ApplicationLookup.js:96 #: routeConfig.js:142 #: screens/Application/Applications.js:26 #: screens/Application/Applications.js:35 #: screens/Application/ApplicationsList/ApplicationsList.js:113 #: screens/Application/ApplicationsList/ApplicationsList.js:148 -#: util/getRelatedResourceDeleteDetails.js:208 +#: util/getRelatedResourceDeleteDetails.js:209 msgid "Applications" msgstr "" @@ -486,17 +495,21 @@ msgstr "Applications & Tokens" msgid "Approval" msgstr "Approval" -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:99 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:106 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:130 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 msgid "Approve" msgstr "Approve" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:115 -msgid "Approve, cancel or deny" -msgstr "Approve, cancel or deny" +#~ msgid "Approve, cancel or deny" +#~ msgstr "Approve, cancel or deny" -#: components/StatusLabel/StatusLabel.js:31 +#: components/StatusLabel/StatusLabel.js:39 msgid "Approved" msgstr "Approved" @@ -508,11 +521,12 @@ msgstr "Approved - {0}. See the Activity Stream for more information." msgid "Approved by {0} - {1}" msgstr "Approved by {0} - {1}" -#: components/Schedule/shared/FrequencyDetailSubform.js:128 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:162 +#: components/Schedule/shared/FrequencyDetailSubform.js:113 msgid "April" msgstr "April" -#: components/JobCancelButton/JobCancelButton.js:89 +#: components/JobCancelButton/JobCancelButton.js:104 msgid "Are you sure you want to cancel this job?" msgstr "Are you sure you want to cancel this job?" @@ -556,7 +570,7 @@ msgstr "" msgid "Are you sure you want to remove {0} access from {username}?" msgstr "" -#: screens/Job/JobOutput/JobOutput.js:771 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "Are you sure you want to submit the request to cancel this job?" @@ -565,11 +579,11 @@ msgstr "Are you sure you want to submit the request to cancel this job?" msgid "Arguments" msgstr "Arguments" -#: screens/Job/JobDetail/JobDetail.js:541 +#: screens/Job/JobDetail/JobDetail.js:559 msgid "Artifacts" msgstr "Artifacts" -#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "Associate" @@ -583,11 +597,12 @@ msgstr "Associate role error" msgid "Association modal" msgstr "Association modal" -#: components/LaunchPrompt/steps/SurveyStep.js:166 +#: components/LaunchPrompt/steps/SurveyStep.js:168 msgid "At least one value must be selected for this field." msgstr "At least one value must be selected for this field." -#: components/Schedule/shared/FrequencyDetailSubform.js:148 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:166 +#: components/Schedule/shared/FrequencyDetailSubform.js:133 msgid "August" msgstr "August" @@ -599,15 +614,17 @@ msgstr "" msgid "Authorization Code Expiration" msgstr "Authorization Code Expiration" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:80 -#: screens/Application/shared/ApplicationForm.js:84 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:81 +#: screens/Application/shared/ApplicationForm.js:85 msgid "Authorization grant type" msgstr "Authorization grant type" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:208 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:159 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -620,7 +637,11 @@ msgstr "Automation Analytics" msgid "Automation Analytics dashboard" msgstr "Automation Analytics dashboard" -#: screens/Setting/Settings.js:46 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:175 +msgid "Automation controller version" +msgstr "Automation controller version" + +#: screens/Setting/Settings.js:47 msgid "Azure AD" msgstr "Azure AD" @@ -628,18 +649,18 @@ msgstr "Azure AD" msgid "Azure AD settings" msgstr "Azure AD settings" -#: components/AdHocCommands/AdHocCommandsWizard.js:50 +#: components/AdHocCommands/AdHocCommandsWizard.js:49 #: components/AddRole/AddResourceRole.js:267 -#: components/LaunchPrompt/LaunchPrompt.js:128 -#: components/Schedule/shared/SchedulePromptableFields.js:132 +#: components/LaunchPrompt/LaunchPrompt.js:158 +#: components/Schedule/shared/SchedulePromptableFields.js:125 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:90 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:70 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:152 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:155 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:154 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:157 msgid "Back" msgstr "Back" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "Back to Credentials" @@ -662,8 +683,9 @@ msgstr "Back to Hosts" msgid "Back to Instance Groups" msgstr "Back to Instance Groups" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:171 -#: screens/Instances/Instance.js:18 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 +#: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "Back to Instances" @@ -672,7 +694,7 @@ msgstr "Back to Instances" msgid "Back to Inventories" msgstr "Back to Inventories" -#: screens/Job/Job.js:110 +#: screens/Job/Job.js:123 msgid "Back to Jobs" msgstr "Back to Jobs" @@ -699,10 +721,11 @@ msgstr "Back to Schedules" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:25 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:34 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:49 #: screens/Setting/UI/UIDetail/UIDetail.js:59 msgid "Back to Settings" @@ -765,7 +788,7 @@ msgstr "" "Together the base path and selected playbook directory provide the full\n" "path used to locate playbooks." -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:433 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:448 msgid "Basic auth password" msgstr "Basic auth password" @@ -781,6 +804,14 @@ msgstr "" "commit hashes and refs may not be available unless you also\n" "provide a custom refspec." +#: screens/Template/shared/JobTemplate.helptext.js:27 +msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." + +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." + #: components/About/About.js:45 msgid "Brand Image" msgstr "" @@ -803,32 +834,34 @@ msgid "By default, we collect and transmit analytics data on the service usage t msgstr "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." #: screens/TopologyView/Legend.js:74 -msgid "C" -msgstr "C" +#~ msgid "C" +#~ msgstr "C" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:171 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" -#: components/PromptDetail/PromptInventorySourceDetail.js:113 -#: components/PromptDetail/PromptProjectDetail.js:136 -#: screens/Project/ProjectDetail/ProjectDetail.js:250 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:114 +#: components/PromptDetail/PromptInventorySourceDetail.js:102 +#: components/PromptDetail/PromptProjectDetail.js:151 +#: screens/Project/ProjectDetail/ProjectDetail.js:268 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:118 msgid "Cache Timeout" msgstr "Cache Timeout" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "Cache timeout" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:114 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:106 msgid "Cache timeout (seconds)" msgstr "Cache timeout (seconds)" -#: components/AdHocCommands/AdHocCommandsWizard.js:51 +#: components/AdHocCommands/AdHocCommandsWizard.js:50 #: components/AddRole/AddResourceRole.js:268 #: components/AssociateModal/AssociateModal.js:114 #: components/AssociateModal/AssociateModal.js:119 @@ -838,20 +871,21 @@ msgstr "Cache timeout (seconds)" #: components/DisassociateButton/DisassociateButton.js:142 #: components/FormActionGroup/FormActionGroup.js:23 #: components/FormActionGroup/FormActionGroup.js:29 -#: components/LaunchPrompt/LaunchPrompt.js:129 -#: components/Lookup/HostFilterLookup.js:387 -#: components/Lookup/Lookup.js:203 +#: components/LaunchPrompt/LaunchPrompt.js:159 +#: components/Lookup/HostFilterLookup.js:388 +#: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:462 -#: components/Schedule/shared/ScheduleForm.js:467 -#: components/Schedule/shared/ScheduleForm.js:678 -#: components/Schedule/shared/ScheduleForm.js:683 -#: components/Schedule/shared/SchedulePromptableFields.js:133 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 +#: components/Schedule/shared/SchedulePromptableFields.js:126 +#: components/Schedule/shared/UnsupportedScheduleForm.js:22 +#: components/Schedule/shared/UnsupportedScheduleForm.js:27 #: screens/Credential/shared/CredentialForm.js:343 #: screens/Credential/shared/CredentialForm.js:348 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:100 #: screens/Credential/shared/ExternalTestModal.js:98 +#: screens/Instances/Shared/RemoveInstanceButton.js:174 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:111 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:63 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:66 @@ -872,38 +906,44 @@ msgstr "Cache timeout (seconds)" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:39 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:45 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeDeleteModal.js:50 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:162 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:165 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:164 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:167 #: screens/User/UserRoles/UserRolesList.js:224 #: screens/User/UserRoles/UserRolesList.js:227 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:84 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:92 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:104 msgid "Cancel" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "Cancel Inventory Source Sync" -#: components/JobCancelButton/JobCancelButton.js:55 -#: screens/Job/JobOutput/JobOutput.js:747 -#: screens/Job/JobOutput/JobOutput.js:748 +#: components/JobCancelButton/JobCancelButton.js:69 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "Cancel Job" -#: screens/Project/ProjectDetail/ProjectDetail.js:303 +#: screens/Project/ProjectDetail/ProjectDetail.js:321 #: screens/Project/ProjectList/ProjectListItem.js:230 msgid "Cancel Project Sync" msgstr "Cancel Project Sync" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:318 -#: screens/Project/ProjectDetail/ProjectDetail.js:305 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 +#: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "Cancel Sync" -#: screens/Job/JobOutput/JobOutput.js:755 -#: screens/Job/JobOutput/JobOutput.js:758 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:322 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:327 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:95 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:101 +msgid "Cancel Workflow" +msgstr "Cancel Workflow" + +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "Cancel job" @@ -915,7 +955,7 @@ msgstr "Cancel link changes" msgid "Cancel link removal" msgstr "Cancel link removal" -#: components/Lookup/Lookup.js:201 +#: components/Lookup/Lookup.js:207 msgid "Cancel lookup" msgstr "Cancel lookup" @@ -941,22 +981,22 @@ msgid "Cancel subscription edit" msgstr "Cancel subscription edit" #: components/JobList/JobListItem.js:113 -#: screens/Job/JobDetail/JobDetail.js:582 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobDetail/JobDetail.js:600 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "Cancel {0}" #: components/JobList/JobList.js:234 -#: components/StatusLabel/StatusLabel.js:46 +#: components/StatusLabel/StatusLabel.js:54 #: components/Workflow/WorkflowNodeHelp.js:111 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:253 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:212 msgid "Canceled" msgstr "Canceled" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:58 -msgid "Cannot approve, cancel or deny completed workflow approvals" -msgstr "Cannot approve, cancel or deny completed workflow approvals" +#~ msgid "Cannot approve, cancel or deny completed workflow approvals" +#~ msgstr "Cannot approve, cancel or deny completed workflow approvals" #: screens/Setting/Logging/LoggingEdit/LoggingEdit.js:129 msgid "" @@ -966,21 +1006,23 @@ msgstr "" "Cannot enable log aggregator without providing\n" "logging aggregator host and logging aggregator type." -#: screens/Instances/InstanceList/InstanceList.js:148 +#: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "Cannot run health check on hop nodes." -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:213 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:199 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:74 +#: screens/TopologyView/Tooltip.js:312 msgid "Capacity" msgstr "Capacity" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 -#: screens/InstanceGroup/Instances/InstanceList.js:258 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:168 -#: screens/Instances/InstanceList/InstanceList.js:153 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "Capacity Adjustment" @@ -1012,7 +1054,7 @@ msgstr "" "Change PROJECTS_ROOT when deploying\n" "{brandName} to change this location." -#: components/StatusLabel/StatusLabel.js:47 +#: components/StatusLabel/StatusLabel.js:55 #: screens/Job/JobOutput/shared/HostStatusBar.js:43 msgid "Changed" msgstr "Changed" @@ -1021,13 +1063,13 @@ msgstr "Changed" msgid "Changes" msgstr "Changes" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:253 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:257 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:258 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:266 msgid "Channel" msgstr "Channel" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:103 -#: screens/Template/shared/JobTemplateForm.js:214 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:138 +#: screens/Template/shared/JobTemplateForm.js:218 msgid "Check" msgstr "Check" @@ -1047,20 +1089,20 @@ msgstr "Choose a .json file" msgid "Choose a Notification Type" msgstr "Choose a Notification Type" -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:24 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:25 msgid "Choose a Playbook Directory" msgstr "Choose a Playbook Directory" -#: screens/Project/shared/ProjectForm.js:224 +#: screens/Project/shared/ProjectForm.js:268 msgid "Choose a Source Control Type" msgstr "Choose a Source Control Type" -#: screens/Template/shared/WebhookSubForm.js:99 +#: screens/Template/shared/WebhookSubForm.js:100 msgid "Choose a Webhook Service" msgstr "Choose a Webhook Service" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:96 -#: screens/Template/shared/JobTemplateForm.js:207 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:131 +#: screens/Template/shared/JobTemplateForm.js:211 msgid "Choose a job type" msgstr "Choose a job type" @@ -1072,7 +1114,7 @@ msgstr "Choose a module" msgid "Choose a source" msgstr "Choose a source" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:475 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:490 msgid "Choose an HTTP method" msgstr "Choose an HTTP method" @@ -1098,7 +1140,7 @@ msgstr "Choose the resources that will be receiving new roles. You'll be able t msgid "Choose the type of resource that will be receiving new roles. For example, if you'd like to add new roles to a set of users please choose Users and click Next. You'll be able to select the specific resources in the next step." msgstr "Choose the type of resource that will be receiving new roles. For example, if you'd like to add new roles to a set of users please choose Users and click Next. You'll be able to select the specific resources in the next step." -#: screens/Project/shared/ProjectSubForms/SharedFields.js:70 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:74 msgid "Clean" msgstr "Clean" @@ -1108,7 +1150,7 @@ msgid "Clear" msgstr "Clear" #: components/DataListToolbar/DataListToolbar.js:95 -#: screens/Job/JobOutput/JobOutputSearch.js:145 +#: screens/Job/JobOutput/JobOutputSearch.js:144 msgid "Clear all filters" msgstr "Clear all filters" @@ -1124,7 +1166,7 @@ msgstr "Clear subscription selection" msgid "Click an available node to create a new link. Click outside the graph to cancel." msgstr "Click an available node to create a new link. Click outside the graph to cancel." -#: screens/TopologyView/Tooltip.js:60 +#: screens/TopologyView/Tooltip.js:191 msgid "Click on a node icon to display the details." msgstr "Click on a node icon to display the details." @@ -1136,10 +1178,15 @@ msgstr "Click the Edit button below to reconfigure the node." msgid "Click this button to verify connection to the secret management system using the selected credential and specified inputs." msgstr "Click this button to verify connection to the secret management system using the selected credential and specified inputs." -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:152 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:179 msgid "Click to create a new link to this node." msgstr "Click to create a new link to this node." +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 +msgid "Click to download bundle" +msgstr "Click to download bundle" + #: screens/Template/Survey/SurveyToolbar.js:64 msgid "Click to rearrange the order of the survey questions" msgstr "Click to rearrange the order of the survey questions" @@ -1152,16 +1199,16 @@ msgstr "Click to toggle default value" msgid "Click to view job details" msgstr "Click to view job details" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:88 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:89 #: screens/Application/Applications.js:84 msgid "Client ID" msgstr "Client ID" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:284 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:289 msgid "Client Identifier" msgstr "Client Identifier" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:305 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:314 msgid "Client identifier" msgstr "Client identifier" @@ -1169,8 +1216,8 @@ msgstr "Client identifier" msgid "Client secret" msgstr "Client secret" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:99 -#: screens/Application/shared/ApplicationForm.js:126 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:100 +#: screens/Application/shared/ApplicationForm.js:127 msgid "Client type" msgstr "Client type" @@ -1206,26 +1253,26 @@ msgid "Command" msgstr "Command" #: components/Schedule/shared/ScheduleForm.js:453 -msgid "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." -msgstr "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." +#~ msgid "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." +#~ msgstr "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:49 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:66 msgid "Compliant" msgstr "Compliant" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:130 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 -#: screens/Template/shared/JobTemplateForm.js:539 +#: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" msgstr "Concurrent Jobs" -#: screens/Template/shared/JobTemplate.helptext.js:35 +#: screens/Template/shared/JobTemplate.helptext.js:38 msgid "Concurrent jobs: If enabled, simultaneous runs of this job template will be allowed." msgstr "Concurrent jobs: If enabled, simultaneous runs of this job template will be allowed." -#: screens/Template/shared/WorkflowJobTemplate.helptext.js:23 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:25 msgid "Concurrent jobs: If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "Concurrent jobs: If enabled, simultaneous runs of this workflow job template will be allowed." @@ -1248,11 +1295,11 @@ msgstr "Confirm Disable Local Authorization" msgid "Confirm Password" msgstr "Confirm Password" -#: components/JobCancelButton/JobCancelButton.js:71 +#: components/JobCancelButton/JobCancelButton.js:86 msgid "Confirm cancel job" msgstr "Confirm cancel job" -#: components/JobCancelButton/JobCancelButton.js:75 +#: components/JobCancelButton/JobCancelButton.js:90 msgid "Confirm cancellation" msgstr "Confirm cancellation" @@ -1276,6 +1323,10 @@ msgstr "Confirm node removal" msgid "Confirm removal of all nodes" msgstr "Confirm removal of all nodes" +#: screens/Instances/Shared/RemoveInstanceButton.js:160 +msgid "Confirm remove" +msgstr "Confirm remove" + #: screens/Setting/shared/RevertAllAlert.js:20 msgid "Confirm revert all" msgstr "Confirm revert all" @@ -1284,11 +1335,11 @@ msgstr "Confirm revert all" msgid "Confirm selection" msgstr "Confirm selection" -#: screens/Job/JobDetail/JobDetail.js:361 +#: screens/Job/JobDetail/JobDetail.js:366 msgid "Container Group" msgstr "Container Group" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1298,17 +1349,23 @@ msgstr "Container group" msgid "Container group not found." msgstr "Container group not found." -#: components/LaunchPrompt/LaunchPrompt.js:123 -#: components/Schedule/shared/SchedulePromptableFields.js:127 +#: components/LaunchPrompt/LaunchPrompt.js:153 +#: components/Schedule/shared/SchedulePromptableFields.js:120 msgid "Content Loading" msgstr "Content Loading" +#: components/PromptDetail/PromptProjectDetail.js:130 +#: screens/Project/ProjectDetail/ProjectDetail.js:240 +#: screens/Project/shared/ProjectForm.js:290 +msgid "Content Signature Validation Credential" +msgstr "Content Signature Validation Credential" + #: components/AppContainer/AppContainer.js:142 msgid "Continue" msgstr "Continue" -#: screens/InstanceGroup/Instances/InstanceList.js:196 -#: screens/Instances/InstanceList/InstanceList.js:116 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "Control" @@ -1325,12 +1382,12 @@ msgstr "" "will produce for inventory source update jobs." #: components/LaunchPrompt/steps/OtherPromptsStep.js:139 -msgid "" -"Control the level of output ansible\n" -"will produce as the playbook executes." -msgstr "" -"Control the level of output ansible\n" -"will produce as the playbook executes." +#~ msgid "" +#~ "Control the level of output ansible\n" +#~ "will produce as the playbook executes." +#~ msgstr "" +#~ "Control the level of output ansible\n" +#~ "will produce as the playbook executes." #: screens/Template/shared/JobTemplateForm.js:464 #~ msgid "" @@ -1340,16 +1397,16 @@ msgstr "" #~ "Control the level of output ansible will\n" #~ "produce as the playbook executes." -#: screens/Job/Job.helptext.js:14 -#: screens/Template/shared/JobTemplate.helptext.js:15 +#: screens/Job/Job.helptext.js:15 +#: screens/Template/shared/JobTemplate.helptext.js:16 msgid "Control the level of output ansible will produce as the playbook executes." msgstr "Control the level of output ansible will produce as the playbook executes." -#: screens/Job/JobDetail/JobDetail.js:346 +#: screens/Job/JobDetail/JobDetail.js:351 msgid "Controller Node" msgstr "Controller Node" -#: components/PromptDetail/PromptDetail.js:121 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "Convergence" @@ -1391,7 +1448,7 @@ msgstr "Copy Project" msgid "Copy Template" msgstr "Copy Template" -#: screens/Project/ProjectDetail/ProjectDetail.js:201 +#: screens/Project/ProjectDetail/ProjectDetail.js:202 #: screens/Project/ProjectList/ProjectListItem.js:98 msgid "Copy full revision to clipboard." msgstr "Copy full revision to clipboard." @@ -1400,11 +1457,12 @@ msgstr "Copy full revision to clipboard." msgid "Copyright" msgstr "Copyright" +#: components/LaunchPrompt/steps/OtherPromptsStep.js:231 #: components/MultiSelect/TagMultiSelect.js:62 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:66 -#: screens/Inventory/shared/InventoryForm.js:83 -#: screens/Template/shared/JobTemplateForm.js:387 -#: screens/Template/shared/WorkflowJobTemplateForm.js:197 +#: screens/Inventory/shared/InventoryForm.js:91 +#: screens/Template/shared/JobTemplateForm.js:396 +#: screens/Template/shared/WorkflowJobTemplateForm.js:204 msgid "Create" msgstr "Create" @@ -1467,8 +1525,12 @@ msgstr "Create New Workflow Template" msgid "Create a new Smart Inventory with the applied filter" msgstr "Create a new Smart Inventory with the applied filter" -#: screens/InstanceGroup/InstanceGroups.js:47 -#: screens/InstanceGroup/InstanceGroups.js:57 +#: screens/Instances/Instances.js:14 +msgid "Create new Instance" +msgstr "Create new Instance" + +#: screens/InstanceGroup/InstanceGroups.js:18 +#: screens/InstanceGroup/InstanceGroups.js:28 msgid "Create new container group" msgstr "Create new container group" @@ -1495,8 +1557,8 @@ msgstr "Create new group" msgid "Create new host" msgstr "Create new host" -#: screens/InstanceGroup/InstanceGroups.js:46 -#: screens/InstanceGroup/InstanceGroups.js:56 +#: screens/InstanceGroup/InstanceGroups.js:17 +#: screens/InstanceGroup/InstanceGroups.js:27 msgid "Create new instance group" msgstr "Create new instance group" @@ -1516,34 +1578,34 @@ msgstr "Create new source" msgid "Create user token" msgstr "Create user token" -#: components/Lookup/ApplicationLookup.js:114 -#: components/PromptDetail/PromptDetail.js:145 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:270 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:104 +#: components/Lookup/ApplicationLookup.js:115 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:102 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 -#: screens/Host/HostDetail/HostDetail.js:84 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:134 +#: screens/Host/HostDetail/HostDetail.js:86 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:82 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:293 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47 -#: screens/Job/JobDetail/JobDetail.js:516 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:388 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 -#: screens/Project/ProjectDetail/ProjectDetail.js:274 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Job/JobDetail/JobDetail.js:534 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 +#: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:339 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:188 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 -#: screens/User/UserTokenDetail/UserTokenDetail.js:60 +#: screens/User/UserTokenDetail/UserTokenDetail.js:61 #: screens/User/UserTokenList/UserTokenList.js:150 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:240 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199 msgid "Created" msgstr "" @@ -1551,17 +1613,17 @@ msgstr "" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 -#: components/Lookup/CredentialLookup.js:193 -#: components/Lookup/InventoryLookup.js:161 -#: components/Lookup/InventoryLookup.js:216 -#: components/Lookup/MultiCredentialsLookup.js:193 -#: components/Lookup/OrganizationLookup.js:133 -#: components/Lookup/ProjectLookup.js:150 +#: components/Lookup/CredentialLookup.js:194 +#: components/Lookup/InventoryLookup.js:152 +#: components/Lookup/InventoryLookup.js:207 +#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/OrganizationLookup.js:134 +#: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 -#: components/Schedule/ScheduleList/ScheduleList.js:197 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 +#: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:58 @@ -1585,7 +1647,7 @@ msgstr "" #: screens/Organization/OrganizationList/OrganizationList.js:131 #: screens/Project/ProjectList/ProjectList.js:213 #: screens/Team/TeamList/TeamList.js:130 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:163 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:161 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:108 msgid "Created By (Username)" @@ -1599,29 +1661,30 @@ msgstr "Created by (username)" #: components/AdHocCommands/AdHocPreviewStep.js:54 #: components/AdHocCommands/useAdHocCredentialStep.js:24 -#: components/PromptDetail/PromptInventorySourceDetail.js:119 +#: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:274 -#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:83 -#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:35 -#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:37 -#: util/getRelatedResourceDeleteDetails.js:166 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 +#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 +#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 +#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 +#: util/getRelatedResourceDeleteDetails.js:167 msgid "Credential" msgstr "Credential" -#: util/getRelatedResourceDeleteDetails.js:73 +#: util/getRelatedResourceDeleteDetails.js:74 msgid "Credential Input Sources" msgstr "Credential Input Sources" +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:83 #: components/Lookup/InstanceGroupsLookup.js:108 msgid "Credential Name" msgstr "Credential Name" @@ -1646,7 +1709,7 @@ msgstr "" msgid "Credential copied successfully" msgstr "Credential copied successfully" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "Credential not found." @@ -1655,7 +1718,7 @@ msgstr "Credential not found." msgid "Credential passwords" msgstr "Credential passwords" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Credential to authenticate with Kubernetes or OpenShift" @@ -1672,25 +1735,25 @@ msgid "Credential type not found." msgstr "Credential type not found." #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:210 -#: components/PromptDetail/PromptDetail.js:183 -#: components/PromptDetail/PromptJobTemplateDetail.js:186 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:324 -#: components/TemplateList/TemplateListItem.js:322 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 +#: components/PromptDetail/PromptJobTemplateDetail.js:191 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 +#: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 #: screens/ActivityStream/ActivityStream.js:167 #: screens/Credential/CredentialList/CredentialList.js:195 #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 -#: screens/Job/JobDetail/JobDetail.js:414 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:360 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:51 -#: screens/Template/shared/JobTemplateForm.js:365 -#: util/getRelatedResourceDeleteDetails.js:90 +#: screens/Job/JobDetail/JobDetail.js:429 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 +#: screens/Template/shared/JobTemplateForm.js:372 +#: util/getRelatedResourceDeleteDetails.js:91 msgid "Credentials" msgstr "" @@ -1702,11 +1765,11 @@ msgstr "Credentials that require passwords on launch are not permitted. Please msgid "Current page" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "Custom Kubernetes or OpenShift Pod specification." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "Custom pod spec" @@ -1728,18 +1791,18 @@ msgstr "Custom virtual environment {virtualEnvironment} must be replaced by an e msgid "Customize messages…" msgstr "Customize messages…" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Customize pod specification" #: screens/Job/WorkflowOutput/WorkflowOutputNode.js:109 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:185 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:212 msgid "DELETED" msgstr "DELETED" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "" @@ -1755,14 +1818,21 @@ msgstr "Data retention period" msgid "Date" msgstr "Date" -#: components/Schedule/shared/FrequencyDetailSubform.js:349 -#: components/Schedule/shared/FrequencyDetailSubform.js:453 -#: components/Schedule/shared/ScheduleForm.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 +#: components/Schedule/shared/FrequencyDetailSubform.js:177 +#: components/Schedule/shared/FrequencyDetailSubform.js:356 +#: components/Schedule/shared/FrequencyDetailSubform.js:460 +#: components/Schedule/shared/ScheduleFormFields.js:127 +#: components/Schedule/shared/ScheduleFormFields.js:187 msgid "Day" msgstr "Day" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:266 -#: components/Schedule/shared/ScheduleForm.js:167 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:130 +msgid "Day {0}" +msgstr "Day {0}" + +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 +#: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "Days of Data to Keep" @@ -1770,7 +1840,7 @@ msgstr "Days of Data to Keep" msgid "Days of data to be retained" msgstr "Days of data to be retained" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:105 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:167 msgid "Days remaining" msgstr "Days remaining" @@ -1778,11 +1848,12 @@ msgstr "Days remaining" msgid "Days to keep" msgstr "Days to keep" -#: screens/Job/JobOutput/JobOutputSearch.js:103 +#: screens/Job/JobOutput/JobOutputSearch.js:102 msgid "Debug" msgstr "Debug" -#: components/Schedule/shared/FrequencyDetailSubform.js:168 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:170 +#: components/Schedule/shared/FrequencyDetailSubform.js:153 msgid "December" msgstr "December" @@ -1809,7 +1880,7 @@ msgstr "Default Execution Environment" msgid "Default answer" msgstr "Default answer" -#: screens/Setting/SettingList.js:99 +#: screens/Setting/SettingList.js:103 msgid "Define system-level features and functions" msgstr "Define system-level features and functions" @@ -1824,35 +1895,35 @@ msgstr "Define system-level features and functions" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:127 -#: screens/Credential/CredentialDetail/CredentialDetail.js:307 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:128 +#: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:133 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:162 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:332 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:176 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:78 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 -#: screens/Job/JobDetail/JobDetail.js:594 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:431 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 -#: screens/Project/ProjectDetail/ProjectDetail.js:322 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:76 +#: screens/Job/JobDetail/JobDetail.js:612 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 +#: screens/Project/ProjectDetail/ProjectDetail.js:340 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:528 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:271 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 #: screens/User/UserDetail/UserDetail.js:107 -#: screens/User/UserTokenDetail/UserTokenDetail.js:77 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:365 +#: screens/User/UserTokenDetail/UserTokenDetail.js:78 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:340 msgid "Delete" msgstr "" @@ -1860,42 +1931,42 @@ msgstr "" msgid "Delete All Groups and Hosts" msgstr "Delete All Groups and Hosts" -#: screens/Credential/CredentialDetail/CredentialDetail.js:301 +#: screens/Credential/CredentialDetail/CredentialDetail.js:300 msgid "Delete Credential" msgstr "Delete Credential" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:126 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:127 msgid "Delete Execution Environment" msgstr "Delete Execution Environment" -#: screens/Host/HostDetail/HostDetail.js:112 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:110 +#: screens/Host/HostDetail/HostDetail.js:114 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109 msgid "Delete Host" msgstr "Delete Host" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:157 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "Delete Inventory" -#: screens/Job/JobDetail/JobDetail.js:590 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobDetail/JobDetail.js:608 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "Delete Job" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:522 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "Delete Job Template" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:427 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:432 msgid "Delete Notification" msgstr "Delete Notification" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "Delete Organization" -#: screens/Project/ProjectDetail/ProjectDetail.js:316 +#: screens/Project/ProjectDetail/ProjectDetail.js:334 msgid "Delete Project" msgstr "Delete Project" @@ -1903,7 +1974,7 @@ msgstr "Delete Project" msgid "Delete Questions" msgstr "Delete Questions" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:415 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "Delete Schedule" @@ -1919,15 +1990,15 @@ msgstr "Delete Team" msgid "Delete User" msgstr "Delete User" -#: screens/User/UserTokenDetail/UserTokenDetail.js:73 +#: screens/User/UserTokenDetail/UserTokenDetail.js:74 msgid "Delete User Token" msgstr "Delete User Token" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:361 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:336 msgid "Delete Workflow Approval" msgstr "Delete Workflow Approval" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:265 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:263 msgid "Delete Workflow Job Template" msgstr "Delete Workflow Job Template" @@ -1936,7 +2007,7 @@ msgstr "Delete Workflow Job Template" msgid "Delete all nodes" msgstr "Delete all nodes" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:123 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:124 msgid "Delete application" msgstr "Delete application" @@ -1948,16 +2019,16 @@ msgstr "Delete credential type" msgid "Delete error" msgstr "Delete error" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "Delete instance group" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:326 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "Delete inventory source" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:172 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "Delete smart inventory" @@ -1965,7 +2036,7 @@ msgstr "Delete smart inventory" msgid "Delete survey question" msgstr "Delete survey question" -#: screens/Project/shared/Project.helptext.js:110 +#: screens/Project/shared/Project.helptext.js:114 msgid "" "Delete the local repository in its entirety prior to\n" "performing an update. Depending on the size of the\n" @@ -1978,7 +2049,7 @@ msgstr "" "of time required to complete an update." #: components/PromptDetail/PromptProjectDetail.js:51 -#: screens/Project/ProjectDetail/ProjectDetail.js:99 +#: screens/Project/ProjectDetail/ProjectDetail.js:100 msgid "Delete the project before syncing" msgstr "Delete the project before syncing" @@ -1986,7 +2057,7 @@ msgstr "Delete the project before syncing" msgid "Delete this link" msgstr "Delete this link" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:247 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:274 msgid "Delete this node" msgstr "Delete this node" @@ -1997,9 +2068,9 @@ msgstr "Delete {pluralizedItemName}?" #: components/DetailList/DeletedDetail.js:19 #: components/Workflow/WorkflowNodeHelp.js:157 #: components/Workflow/WorkflowNodeHelp.js:193 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:272 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:40 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:51 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:231 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:49 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:60 msgid "Deleted" msgstr "Deleted" @@ -2012,11 +2083,11 @@ msgstr "Deletion Error" #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:202 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:227 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:233 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:219 msgid "Deletion error" msgstr "Deletion error" -#: components/StatusLabel/StatusLabel.js:32 +#: components/StatusLabel/StatusLabel.js:40 msgid "Denied" msgstr "Denied" @@ -2028,125 +2099,141 @@ msgstr "Denied - {0}. See the Activity Stream for more information." msgid "Denied by {0} - {1}" msgstr "Denied by {0} - {1}" -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:72 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:80 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 msgid "Deny" msgstr "Deny" -#: screens/Job/JobOutput/JobOutputSearch.js:104 +#: screens/Job/JobOutput/JobOutputSearch.js:103 msgid "Deprecated" msgstr "Deprecated" +#: components/StatusLabel/StatusLabel.js:60 +#: screens/TopologyView/Legend.js:164 +msgid "Deprovisioning" +msgstr "Deprovisioning" + +#: components/StatusLabel/StatusLabel.js:63 +msgid "Deprovisioning fail" +msgstr "Deprovisioning fail" + #: components/HostForm/HostForm.js:104 -#: components/Lookup/ApplicationLookup.js:104 -#: components/Lookup/ApplicationLookup.js:122 -#: components/Lookup/HostFilterLookup.js:422 +#: components/Lookup/ApplicationLookup.js:105 +#: components/Lookup/ApplicationLookup.js:123 +#: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:110 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:253 -#: components/Schedule/ScheduleList/ScheduleList.js:193 -#: components/Schedule/shared/ScheduleForm.js:115 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 +#: components/Schedule/ScheduleList/ScheduleList.js:194 +#: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 #: components/TemplateList/TemplateListItem.js:271 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:64 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:65 #: screens/Application/ApplicationsList/ApplicationsList.js:123 -#: screens/Application/shared/ApplicationForm.js:61 +#: screens/Application/shared/ApplicationForm.js:62 #: screens/Credential/CredentialDetail/CredentialDetail.js:223 #: screens/Credential/CredentialList/CredentialList.js:146 #: screens/Credential/shared/CredentialForm.js:169 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:72 #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:128 #: screens/CredentialType/shared/CredentialTypeForm.js:29 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:59 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:60 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:159 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:126 -#: screens/Host/HostDetail/HostDetail.js:73 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:127 +#: screens/Host/HostDetail/HostDetail.js:75 #: screens/Host/HostList/HostList.js:153 #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 +#: screens/Instances/Shared/InstanceForm.js:26 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:213 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:37 -#: screens/Inventory/shared/InventoryForm.js:50 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 +#: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 #: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:108 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 -#: screens/Project/ProjectDetail/ProjectDetail.js:176 +#: screens/Project/ProjectDetail/ProjectDetail.js:177 #: screens/Project/ProjectList/ProjectList.js:190 #: screens/Project/ProjectList/ProjectListItem.js:281 -#: screens/Project/shared/ProjectForm.js:178 +#: screens/Project/shared/ProjectForm.js:222 #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:180 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 -#: screens/Template/shared/JobTemplateForm.js:247 -#: screens/Template/shared/WorkflowJobTemplateForm.js:112 +#: screens/Template/shared/JobTemplateForm.js:251 +#: screens/Template/shared/WorkflowJobTemplateForm.js:117 #: screens/User/UserOrganizations/UserOrganizationList.js:80 #: screens/User/UserOrganizations/UserOrganizationListItem.js:18 #: screens/User/UserTeams/UserTeamList.js:182 #: screens/User/UserTeams/UserTeamListItem.js:32 -#: screens/User/UserTokenDetail/UserTokenDetail.js:44 +#: screens/User/UserTokenDetail/UserTokenDetail.js:45 #: screens/User/UserTokenList/UserTokenList.js:128 #: screens/User/UserTokenList/UserTokenList.js:138 #: screens/User/UserTokenList/UserTokenList.js:188 #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:205 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:320 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:325 msgid "Destination Channels" msgstr "Destination Channels" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:228 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:233 msgid "Destination Channels or Users" msgstr "Destination Channels or Users" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:341 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:346 msgid "Destination SMS Number(s)" msgstr "Destination SMS Number(s)" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:399 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:412 msgid "Destination SMS number(s)" msgstr "Destination SMS number(s)" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:353 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:364 msgid "Destination channels" msgstr "Destination channels" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:222 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:231 msgid "Destination channels or users" msgstr "Destination channels or users" #: components/AdHocCommands/useAdHocDetailsStep.js:35 -#: components/ErrorDetail/ErrorDetail.js:80 +#: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2155,12 +2242,12 @@ msgstr "Destination channels or users" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:178 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 -#: screens/InstanceGroup/InstanceGroups.js:59 -#: screens/InstanceGroup/InstanceGroups.js:67 -#: screens/Instances/Instance.js:25 -#: screens/Instances/Instances.js:22 +#: screens/InstanceGroup/InstanceGroups.js:30 +#: screens/InstanceGroup/InstanceGroups.js:38 +#: screens/Instances/Instance.js:29 +#: screens/Instances/Instances.js:24 #: screens/Inventory/Inventories.js:61 #: screens/Inventory/Inventories.js:87 #: screens/Inventory/Inventory.js:64 @@ -2169,8 +2256,8 @@ msgstr "Destination channels or users" #: screens/Inventory/InventorySource/InventorySource.js:83 #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 -#: screens/Job/Job.js:117 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/Job.js:130 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2184,33 +2271,35 @@ msgstr "Destination channels or users" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 -#: screens/Setting/Settings.js:44 -#: screens/Setting/Settings.js:47 -#: screens/Setting/Settings.js:51 -#: screens/Setting/Settings.js:54 -#: screens/Setting/Settings.js:57 -#: screens/Setting/Settings.js:60 -#: screens/Setting/Settings.js:63 -#: screens/Setting/Settings.js:66 -#: screens/Setting/Settings.js:69 -#: screens/Setting/Settings.js:72 -#: screens/Setting/Settings.js:81 -#: screens/Setting/Settings.js:82 -#: screens/Setting/Settings.js:83 -#: screens/Setting/Settings.js:84 +#: screens/Setting/Settings.js:45 +#: screens/Setting/Settings.js:48 +#: screens/Setting/Settings.js:52 +#: screens/Setting/Settings.js:55 +#: screens/Setting/Settings.js:58 +#: screens/Setting/Settings.js:61 +#: screens/Setting/Settings.js:64 +#: screens/Setting/Settings.js:67 +#: screens/Setting/Settings.js:70 +#: screens/Setting/Settings.js:73 +#: screens/Setting/Settings.js:76 #: screens/Setting/Settings.js:85 #: screens/Setting/Settings.js:86 -#: screens/Setting/Settings.js:94 -#: screens/Setting/Settings.js:97 -#: screens/Setting/Settings.js:100 -#: screens/Setting/Settings.js:103 -#: screens/Setting/Settings.js:106 -#: screens/Setting/Settings.js:109 -#: screens/Setting/Settings.js:112 -#: screens/Setting/Settings.js:115 +#: screens/Setting/Settings.js:87 +#: screens/Setting/Settings.js:88 +#: screens/Setting/Settings.js:89 +#: screens/Setting/Settings.js:90 +#: screens/Setting/Settings.js:98 +#: screens/Setting/Settings.js:101 +#: screens/Setting/Settings.js:104 +#: screens/Setting/Settings.js:107 +#: screens/Setting/Settings.js:110 +#: screens/Setting/Settings.js:113 +#: screens/Setting/Settings.js:116 +#: screens/Setting/Settings.js:119 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:56 #: screens/Setting/UI/UIDetail/UIDetail.js:66 #: screens/Team/Team.js:57 @@ -2218,9 +2307,9 @@ msgstr "Destination channels or users" #: screens/Template/Template.js:135 #: screens/Template/Templates.js:43 #: screens/Template/WorkflowJobTemplate.js:117 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:140 -#: screens/TopologyView/Tooltip.js:56 -#: screens/TopologyView/Tooltip.js:70 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:138 +#: screens/TopologyView/Tooltip.js:187 +#: screens/TopologyView/Tooltip.js:213 #: screens/User/User.js:64 #: screens/User/UserToken/UserToken.js:54 #: screens/User/Users.js:30 @@ -2230,7 +2319,7 @@ msgstr "Destination channels or users" msgid "Details" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "Details tab" @@ -2238,24 +2327,24 @@ msgstr "Details tab" msgid "Direct Keys" msgstr "Direct Keys" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:204 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:263 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:308 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:366 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:209 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:268 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:313 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:371 msgid "Disable SSL Verification" msgstr "Disable SSL Verification" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:180 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:231 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:270 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:341 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:446 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:187 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:240 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:279 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:350 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:461 msgid "Disable SSL verification" msgstr "Disable SSL verification" #: components/InstanceToggle/InstanceToggle.js:56 -#: components/StatusLabel/StatusLabel.js:45 -#: screens/TopologyView/Legend.js:133 +#: components/StatusLabel/StatusLabel.js:53 +#: screens/TopologyView/Legend.js:233 msgid "Disabled" msgstr "Disabled" @@ -2278,8 +2367,8 @@ msgstr "Disassociate group from host?" msgid "Disassociate host from group?" msgstr "Disassociate host from group?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:289 -#: screens/InstanceGroup/Instances/InstanceList.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "Disassociate instance from instance group?" @@ -2306,7 +2395,7 @@ msgid "Disassociate?" msgstr "Disassociate?" #: components/PromptDetail/PromptProjectDetail.js:46 -#: screens/Project/ProjectDetail/ProjectDetail.js:93 +#: screens/Project/ProjectDetail/ProjectDetail.js:94 msgid "Discard local changes before syncing" msgstr "Discard local changes before syncing" @@ -2320,8 +2409,8 @@ msgstr "Discard local changes before syncing" #~ "into the specified number of job slices, each running the\n" #~ "same tasks against a portion of the inventory." -#: screens/Job/Job.helptext.js:15 -#: screens/Template/shared/JobTemplate.helptext.js:16 +#: screens/Job/Job.helptext.js:16 +#: screens/Template/shared/JobTemplate.helptext.js:17 msgid "Divide the work done by this job template into the specified number of job slices, each running the same tasks against a portion of the inventory." msgstr "Divide the work done by this job template into the specified number of job slices, each running the same tasks against a portion of the inventory." @@ -2336,11 +2425,19 @@ msgstr "Documentation." msgid "Done" msgstr "Done" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/TopologyView/Tooltip.js:251 +msgid "Download Bundle" +msgstr "Download Bundle" + +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "Download Output" +#: screens/TopologyView/Tooltip.js:247 +msgid "Download bundle" +msgstr "Download bundle" + #: screens/Credential/shared/CredentialFormFields/CredentialField.js:93 #: screens/Credential/shared/CredentialFormFields/CredentialField.js:114 msgid "Drag a file here or browse to upload" @@ -2367,8 +2464,8 @@ msgid "E-mail" msgstr "E-mail" #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:121 -msgid "E-mail options" -msgstr "E-mail options" +#~ msgid "E-mail options" +#~ msgstr "E-mail options" #: screens/Inventory/shared/Inventory.helptext.js:113 msgid "" @@ -2380,7 +2477,7 @@ msgstr "" "refresh the inventory from the selected source before\n" "executing job tasks." -#: screens/Project/shared/Project.helptext.js:120 +#: screens/Project/shared/Project.helptext.js:124 msgid "" "Each time a job runs using this project, update the\n" "revision of the project prior to starting the job." @@ -2388,29 +2485,29 @@ msgstr "" "Each time a job runs using this project, update the\n" "revision of the project prior to starting the job." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:405 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:409 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:114 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:116 -#: screens/Credential/CredentialDetail/CredentialDetail.js:294 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:115 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:117 +#: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:120 -#: screens/Host/HostDetail/HostDetail.js:106 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:151 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 +#: screens/Host/HostDetail/HostDetail.js:108 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:104 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:166 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:413 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:415 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 -#: screens/Project/ProjectDetail/ProjectDetail.js:295 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 +#: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:148 @@ -2425,24 +2522,26 @@ msgstr "" #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:103 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:86 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:90 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:169 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:199 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:103 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:108 #: screens/Setting/UI/UIDetail/UIDetail.js:105 #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:497 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:499 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:243 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:241 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 #: screens/User/UserDetail/UserDetail.js:96 msgid "Edit" msgstr "" @@ -2465,30 +2564,31 @@ msgstr "Edit Credential Plugin Configuration" #: screens/Organization/Organizations.js:29 #: screens/Project/Projects.js:25 #: screens/Project/Projects.js:35 -#: screens/Setting/Settings.js:45 -#: screens/Setting/Settings.js:48 -#: screens/Setting/Settings.js:52 -#: screens/Setting/Settings.js:55 -#: screens/Setting/Settings.js:58 -#: screens/Setting/Settings.js:61 -#: screens/Setting/Settings.js:64 -#: screens/Setting/Settings.js:67 -#: screens/Setting/Settings.js:70 -#: screens/Setting/Settings.js:73 -#: screens/Setting/Settings.js:87 -#: screens/Setting/Settings.js:88 -#: screens/Setting/Settings.js:89 -#: screens/Setting/Settings.js:90 +#: screens/Setting/Settings.js:46 +#: screens/Setting/Settings.js:49 +#: screens/Setting/Settings.js:53 +#: screens/Setting/Settings.js:56 +#: screens/Setting/Settings.js:59 +#: screens/Setting/Settings.js:62 +#: screens/Setting/Settings.js:65 +#: screens/Setting/Settings.js:68 +#: screens/Setting/Settings.js:71 +#: screens/Setting/Settings.js:74 +#: screens/Setting/Settings.js:77 #: screens/Setting/Settings.js:91 #: screens/Setting/Settings.js:92 +#: screens/Setting/Settings.js:93 +#: screens/Setting/Settings.js:94 #: screens/Setting/Settings.js:95 -#: screens/Setting/Settings.js:98 -#: screens/Setting/Settings.js:101 -#: screens/Setting/Settings.js:104 -#: screens/Setting/Settings.js:107 -#: screens/Setting/Settings.js:110 -#: screens/Setting/Settings.js:113 -#: screens/Setting/Settings.js:116 +#: screens/Setting/Settings.js:96 +#: screens/Setting/Settings.js:99 +#: screens/Setting/Settings.js:102 +#: screens/Setting/Settings.js:105 +#: screens/Setting/Settings.js:108 +#: screens/Setting/Settings.js:111 +#: screens/Setting/Settings.js:114 +#: screens/Setting/Settings.js:117 +#: screens/Setting/Settings.js:120 #: screens/Team/Teams.js:28 #: screens/Template/Templates.js:44 #: screens/User/Users.js:29 @@ -2529,7 +2629,7 @@ msgid "Edit Login redirect override URL" msgstr "Edit Login redirect override URL" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeEditModal.js:64 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:238 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:257 msgid "Edit Node" msgstr "Edit Node" @@ -2555,8 +2655,8 @@ msgstr "Edit Project" msgid "Edit Question" msgstr "Edit Question" -#: components/Schedule/ScheduleList/ScheduleListItem.js:118 -#: components/Schedule/ScheduleList/ScheduleListItem.js:122 +#: components/Schedule/ScheduleList/ScheduleListItem.js:132 +#: components/Schedule/ScheduleList/ScheduleListItem.js:136 #: screens/Template/Templates.js:55 msgid "Edit Schedule" msgstr "Edit Schedule" @@ -2598,8 +2698,8 @@ msgstr "Edit credential type" #: screens/CredentialType/CredentialTypes.js:25 #: screens/ExecutionEnvironment/ExecutionEnvironments.js:25 -#: screens/InstanceGroup/InstanceGroups.js:64 -#: screens/InstanceGroup/InstanceGroups.js:69 +#: screens/InstanceGroup/InstanceGroups.js:35 +#: screens/InstanceGroup/InstanceGroups.js:40 #: screens/Inventory/Inventories.js:63 #: screens/Inventory/Inventories.js:68 #: screens/Inventory/Inventories.js:77 @@ -2612,7 +2712,8 @@ msgstr "Edit details" msgid "Edit group" msgstr "Edit group" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "Edit host" @@ -2630,7 +2731,7 @@ msgstr "Edit login redirect override URL" msgid "Edit this link" msgstr "Edit this link" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:221 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:248 msgid "Edit this node" msgstr "Edit this node" @@ -2639,16 +2740,16 @@ msgid "Edit workflow" msgstr "Edit workflow" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:257 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "Elapsed" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "Elapsed Time" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "Elapsed time that the job ran" @@ -2660,15 +2761,16 @@ msgstr "Elapsed time that the job ran" msgid "Email" msgstr "Email" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:175 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:177 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:125 msgid "Email Options" msgstr "Email Options" -#: screens/Template/shared/WorkflowJobTemplateForm.js:232 +#: screens/Template/shared/WorkflowJobTemplateForm.js:263 msgid "Enable Concurrent Jobs" msgstr "Enable Concurrent Jobs" -#: screens/Template/shared/JobTemplateForm.js:545 +#: screens/Template/shared/JobTemplateForm.js:597 msgid "Enable Fact Storage" msgstr "Enable Fact Storage" @@ -2676,10 +2778,14 @@ msgstr "Enable Fact Storage" msgid "Enable HTTPS certificate verification" msgstr "Enable HTTPS certificate verification" -#: screens/Template/shared/JobTemplateForm.js:521 -#: screens/Template/shared/JobTemplateForm.js:524 -#: screens/Template/shared/WorkflowJobTemplateForm.js:213 -#: screens/Template/shared/WorkflowJobTemplateForm.js:216 +#: screens/Instances/Shared/InstanceForm.js:58 +msgid "Enable Instance" +msgstr "Enable Instance" + +#: screens/Template/shared/JobTemplateForm.js:573 +#: screens/Template/shared/JobTemplateForm.js:576 +#: screens/Template/shared/WorkflowJobTemplateForm.js:244 +#: screens/Template/shared/WorkflowJobTemplateForm.js:247 msgid "Enable Webhook" msgstr "Enable Webhook" @@ -2687,6 +2793,18 @@ msgstr "Enable Webhook" msgid "Enable Webhook for this workflow job template." msgstr "Enable Webhook for this workflow job template." +#: screens/Project/shared/Project.helptext.js:108 +msgid "" +"Enable content signing to verify that the content \n" +"has remained secure when a project is synced. \n" +"If the content has been tampered with, the \n" +"job will not run." +msgstr "" +"Enable content signing to verify that the content \n" +"has remained secure when a project is synced. \n" +"If the content has been tampered with, the \n" +"job will not run." + #: screens/Setting/Logging/LoggingEdit/LoggingEdit.js:136 msgid "Enable external logging" msgstr "Enable external logging" @@ -2708,35 +2826,37 @@ msgstr "Enable privilege escalation" msgid "Enable simplified login for your {brandName} applications" msgstr "Enable simplified login for your {brandName} applications" -#: screens/Template/shared/JobTemplate.helptext.js:30 +#: screens/Template/shared/JobTemplate.helptext.js:31 msgid "Enable webhook for this template." msgstr "Enable webhook for this template." #: components/InstanceToggle/InstanceToggle.js:55 #: components/Lookup/HostFilterLookup.js:110 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 +#: screens/TopologyView/Legend.js:205 msgid "Enabled" msgstr "Enabled" -#: components/PromptDetail/PromptInventorySourceDetail.js:183 -#: components/PromptDetail/PromptJobTemplateDetail.js:182 -#: components/PromptDetail/PromptProjectDetail.js:130 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:97 -#: screens/Credential/CredentialDetail/CredentialDetail.js:269 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:281 -#: screens/Project/ProjectDetail/ProjectDetail.js:284 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:351 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:200 +#: components/PromptDetail/PromptInventorySourceDetail.js:171 +#: components/PromptDetail/PromptJobTemplateDetail.js:187 +#: components/PromptDetail/PromptProjectDetail.js:145 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:99 +#: screens/Credential/CredentialDetail/CredentialDetail.js:268 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 +#: screens/Project/ProjectDetail/ProjectDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "Enabled Options" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:267 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:135 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "Enabled Value" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:262 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:125 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "Enabled Variable" @@ -2776,7 +2896,7 @@ msgstr "" #~ "and request a configuration update using this job\n" #~ "template." -#: screens/Template/shared/JobTemplate.helptext.js:28 +#: screens/Template/shared/JobTemplate.helptext.js:29 msgid "Enables creation of a provisioning callback URL. Using the URL a host can contact {brandName} and request a configuration update using this job template." msgstr "Enables creation of a provisioning callback URL. Using the URL a host can contact {brandName} and request a configuration update using this job template." @@ -2785,7 +2905,8 @@ msgstr "Enables creation of a provisioning callback URL. Using the URL a host ca msgid "Encrypted" msgstr "Encrypted" -#: components/Schedule/shared/FrequencyDetailSubform.js:500 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:109 +#: components/Schedule/shared/FrequencyDetailSubform.js:507 msgid "End" msgstr "End" @@ -2797,13 +2918,17 @@ msgstr "End User License Agreement" msgid "End date" msgstr "End date" -#: components/Schedule/shared/FrequencyDetailSubform.js:555 +#: components/Schedule/shared/FrequencyDetailSubform.js:561 msgid "End date/time" msgstr "End date/time" #: components/Schedule/shared/buildRuleObj.js:97 -msgid "End did not match an expected value" -msgstr "End did not match an expected value" +#~ msgid "End did not match an expected value" +#~ msgstr "End did not match an expected value" + +#: components/Schedule/shared/buildRuleObj.js:110 +msgid "End did not match an expected value ({0})" +msgstr "End did not match an expected value ({0})" #: components/Schedule/shared/DateTimePicker.js:61 msgid "End time" @@ -2826,18 +2951,22 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Controller documentation for example syntax." #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." #: screens/Inventory/shared/InventoryForm.js:65 -msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" -msgstr "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" +#~ msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" +#~ msgstr "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:181 #~ msgid "Enter one Annotation Tag per line, without commas." @@ -2954,17 +3083,17 @@ msgid "Environment variables or extra variables that specify the values a creden msgstr "Environment variables or extra variables that specify the values a credential type can inject." #: components/JobList/JobList.js:233 -#: components/StatusLabel/StatusLabel.js:38 +#: components/StatusLabel/StatusLabel.js:46 #: components/Workflow/WorkflowNodeHelp.js:108 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:133 #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:142 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:236 -#: screens/Job/JobOutput/JobOutputSearch.js:105 -#: screens/TopologyView/Legend.js:124 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 +#: screens/Job/JobOutput/JobOutputSearch.js:104 +#: screens/TopologyView/Legend.js:178 msgid "Error" msgstr "Error" @@ -2972,18 +3101,18 @@ msgstr "Error" msgid "Error fetching updated project" msgstr "Error fetching updated project" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:496 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:501 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:141 msgid "Error message" msgstr "Error message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:505 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:510 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:150 msgid "Error message body" msgstr "Error message body" -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:617 -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:619 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:709 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:711 msgid "Error saving the workflow!" msgstr "Error saving the workflow!" @@ -2994,88 +3123,90 @@ msgstr "Error saving the workflow!" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:162 -#: components/LaunchPrompt/LaunchPrompt.js:66 +#: components/LaunchButton/LaunchButton.js:196 +#: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:427 -#: components/Schedule/ScheduleList/ScheduleList.js:238 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 +#: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 -#: components/Schedule/shared/SchedulePromptableFields.js:70 +#: components/Schedule/shared/SchedulePromptableFields.js:63 #: components/TemplateList/TemplateList.js:299 #: contexts/Config.js:94 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:135 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:136 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:155 #: screens/Application/ApplicationsList/ApplicationsList.js:185 -#: screens/Credential/CredentialDetail/CredentialDetail.js:315 +#: screens/Credential/CredentialDetail/CredentialDetail.js:314 #: screens/Credential/CredentialList/CredentialList.js:214 #: screens/Host/HostDetail/HostDetail.js:56 -#: screens/Host/HostDetail/HostDetail.js:121 +#: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:303 -#: screens/InstanceGroup/Instances/InstanceList.js:297 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 -#: screens/Instances/InstanceList/InstanceList.js:178 -#: screens/Instances/InstanceList/InstanceListItem.js:234 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:171 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 +#: screens/Instances/Shared/RemoveInstanceButton.js:104 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:119 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:339 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:185 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 -#: screens/Login/Login.js:217 +#: screens/Login/Login.js:239 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:125 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:439 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 -#: screens/Project/ProjectDetail/ProjectDetail.js:330 +#: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 #: screens/Project/ProjectList/ProjectList.js:303 -#: screens/Project/shared/ProjectSyncButton.js:59 +#: screens/Project/shared/ProjectSyncButton.js:60 #: screens/Team/TeamDetail/TeamDetail.js:78 #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:537 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:279 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:178 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:193 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:318 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:346 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:357 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 +#: screens/TopologyView/MeshGraph.js:406 +#: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 #: screens/User/UserRoles/UserRolesList.js:243 #: screens/User/UserRoles/UserRolesList.js:254 #: screens/User/UserTeams/UserTeamList.js:259 -#: screens/User/UserTokenDetail/UserTokenDetail.js:84 +#: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:373 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:384 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:395 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:406 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:277 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:288 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:299 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:310 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" msgstr "Error!" @@ -3083,14 +3214,18 @@ msgstr "Error!" msgid "Error:" msgstr "Error:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "Errors" +#: screens/TopologyView/Legend.js:253 +msgid "Established" +msgstr "Established" + #: screens/ActivityStream/ActivityStream.js:265 #: screens/ActivityStream/ActivityStreamListItem.js:46 -#: screens/Job/JobOutput/JobOutputSearch.js:100 +#: screens/Job/JobOutput/JobOutputSearch.js:99 msgid "Event" msgstr "Event" @@ -3110,22 +3245,30 @@ msgstr "Event summary not available" msgid "Events" msgstr "Events" +#: screens/Job/JobOutput/JobOutput.js:725 +msgid "Events processing complete." +msgstr "Events processing complete." + #: components/Schedule/ScheduleDetail/ScheduleDetail.js:144 -msgid "Every minute for {0} times" -msgstr "Every minute for {0} times" +#~ msgid "Every minute for {0} times" +#~ msgstr "Every minute for {0} times" #: screens/TopologyView/Legend.js:82 -msgid "Ex" -msgstr "Ex" +#~ msgid "Ex" +#~ msgstr "Ex" #: components/Search/LookupTypeInput.js:39 msgid "Exact match (default lookup if not specified)." msgstr "Exact match (default lookup if not specified)." -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "Exact search on id field." +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "Exact search on name field." + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "Example URLs for GIT Source Control include:" @@ -3146,6 +3289,14 @@ msgstr "Examples include:" msgid "Examples:" msgstr "Examples:" +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 +msgid "Exception Frequency" +msgstr "Exception Frequency" + +#: components/Schedule/shared/ScheduleFormFields.js:160 +msgid "Exceptions" +msgstr "Exceptions" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:47 msgid "Execute regardless of the parent node's final state." msgstr "Execute regardless of the parent node's final state." @@ -3158,8 +3309,8 @@ msgstr "Execute when the parent node results in a failure state." msgid "Execute when the parent node results in a successful state." msgstr "Execute when the parent node results in a successful state." -#: screens/InstanceGroup/Instances/InstanceList.js:197 -#: screens/Instances/InstanceList/InstanceList.js:117 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "Execution" @@ -3169,9 +3320,12 @@ msgstr "Execution" #: components/AdHocCommands/useAdHocExecutionEnvironmentStep.js:15 #: components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js:41 #: components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js:105 -#: components/Lookup/ExecutionEnvironmentLookup.js:155 -#: components/Lookup/ExecutionEnvironmentLookup.js:186 -#: components/Lookup/ExecutionEnvironmentLookup.js:201 +#: components/LaunchPrompt/steps/useExecutionEnvironmentStep.js:29 +#: components/Lookup/ExecutionEnvironmentLookup.js:159 +#: components/Lookup/ExecutionEnvironmentLookup.js:191 +#: components/Lookup/ExecutionEnvironmentLookup.js:208 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "Execution Environment" @@ -3181,6 +3335,7 @@ msgid "Execution Environment Missing" msgstr "Execution Environment Missing" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:103 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:107 #: routeConfig.js:147 #: screens/ActivityStream/ActivityStream.js:217 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:129 @@ -3190,12 +3345,12 @@ msgstr "Execution Environment Missing" #: screens/Organization/Organization.js:127 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:78 #: screens/Organization/Organizations.js:34 -#: util/getRelatedResourceDeleteDetails.js:80 -#: util/getRelatedResourceDeleteDetails.js:187 +#: util/getRelatedResourceDeleteDetails.js:81 +#: util/getRelatedResourceDeleteDetails.js:188 msgid "Execution Environments" msgstr "Execution Environments" -#: screens/Job/JobDetail/JobDetail.js:340 +#: screens/Job/JobDetail/JobDetail.js:345 msgid "Execution Node" msgstr "Execution Node" @@ -3249,20 +3404,20 @@ msgstr "Expected at least one of client_email, project_id or private_key to be p #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:34 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:148 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:172 -#: screens/User/UserTokenDetail/UserTokenDetail.js:55 +#: screens/User/UserTokenDetail/UserTokenDetail.js:56 #: screens/User/UserTokenList/UserTokenList.js:146 #: screens/User/UserTokenList/UserTokenList.js:190 #: screens/User/UserTokenList/UserTokenListItem.js:35 #: screens/User/UserTokens/UserTokens.js:89 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:192 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:151 msgid "Expires" msgstr "Expires" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:84 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:146 msgid "Expires on" msgstr "Expires on" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:94 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:156 msgid "Expires on UTC" msgstr "Expires on UTC" @@ -3270,8 +3425,8 @@ msgstr "Expires on UTC" msgid "Expires on {0}" msgstr "Expires on {0}" -#: components/JobList/JobListItem.js:306 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222 +#: components/JobList/JobListItem.js:307 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181 msgid "Explanation" msgstr "Explanation" @@ -3285,7 +3440,7 @@ msgid "Extra variables" msgstr "Extra variables" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:179 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3293,11 +3448,11 @@ msgid "FINISHED:" msgstr "FINISHED:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:135 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "Fact Storage" -#: screens/Template/shared/JobTemplate.helptext.js:36 +#: screens/Template/shared/JobTemplate.helptext.js:39 msgid "Fact storage: If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime.." msgstr "Fact storage: If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime.." @@ -3311,24 +3466,25 @@ msgid "Facts" msgstr "Facts" #: components/JobList/JobList.js:232 -#: components/StatusLabel/StatusLabel.js:37 +#: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "Failed" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "Failed Host Count" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "Failed Hosts" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "Failed hosts" @@ -3336,14 +3492,18 @@ msgstr "Failed hosts" msgid "Failed jobs" msgstr "Failed jobs" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:291 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 msgid "Failed to approve one or more workflow approval." msgstr "Failed to approve one or more workflow approval." #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:387 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:398 -msgid "Failed to approve workflow approval." -msgstr "Failed to approve workflow approval." +#~ msgid "Failed to approve workflow approval." +#~ msgstr "Failed to approve workflow approval." + +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 +msgid "Failed to approve {0}." +msgstr "Failed to approve {0}." #: components/ResourceAccessList/ResourceAccessList.js:281 msgid "Failed to assign roles properly" @@ -3355,7 +3515,7 @@ msgid "Failed to associate role" msgstr "Failed to associate role" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:300 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3363,12 +3523,12 @@ msgstr "Failed to associate role" msgid "Failed to associate." msgstr "Failed to associate." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:317 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "Failed to cancel Inventory Source Sync" -#: screens/Project/ProjectDetail/ProjectDetail.js:304 +#: screens/Project/ProjectDetail/ProjectDetail.js:322 #: screens/Project/ProjectList/ProjectListItem.js:232 msgid "Failed to cancel Project Sync" msgstr "Failed to cancel Project Sync" @@ -3378,12 +3538,12 @@ msgid "Failed to cancel one or more jobs." msgstr "Failed to cancel one or more jobs." #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:302 -msgid "Failed to cancel one or more workflow approval." -msgstr "Failed to cancel one or more workflow approval." +#~ msgid "Failed to cancel one or more workflow approval." +#~ msgstr "Failed to cancel one or more workflow approval." #: components/JobList/JobListItem.js:114 -#: screens/Job/JobDetail/JobDetail.js:583 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobDetail/JobDetail.js:601 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "Failed to cancel {0}" @@ -3409,11 +3569,11 @@ msgstr "Failed to copy project." msgid "Failed to copy template." msgstr "Failed to copy template." -#: screens/Application/ApplicationDetails/ApplicationDetails.js:138 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:139 msgid "Failed to delete application." msgstr "Failed to delete application." -#: screens/Credential/CredentialDetail/CredentialDetail.js:318 +#: screens/Credential/CredentialDetail/CredentialDetail.js:317 msgid "Failed to delete credential." msgstr "Failed to delete credential." @@ -3421,24 +3581,24 @@ msgstr "Failed to delete credential." msgid "Failed to delete group {0}." msgstr "Failed to delete group {0}." -#: screens/Host/HostDetail/HostDetail.js:124 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:122 +#: screens/Host/HostDetail/HostDetail.js:126 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121 msgid "Failed to delete host." msgstr "Failed to delete host." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:343 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "Failed to delete inventory source {name}." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:174 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "Failed to delete inventory." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:540 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "Failed to delete job template." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:443 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:448 msgid "Failed to delete notification." msgstr "Failed to delete notification." @@ -3463,11 +3623,11 @@ msgid "Failed to delete one or more groups." msgstr "Failed to delete one or more groups." #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "Failed to delete one or more hosts." -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:239 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:225 msgid "Failed to delete one or more instance groups." msgstr "Failed to delete one or more instance groups." @@ -3479,7 +3639,7 @@ msgstr "Failed to delete one or more inventories." msgid "Failed to delete one or more inventory sources." msgstr "Failed to delete one or more inventory sources." -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "Failed to delete one or more job templates." @@ -3499,7 +3659,7 @@ msgstr "Failed to delete one or more organizations." msgid "Failed to delete one or more projects." msgstr "Failed to delete one or more projects." -#: components/Schedule/ScheduleList/ScheduleList.js:241 +#: components/Schedule/ScheduleList/ScheduleList.js:242 msgid "Failed to delete one or more schedules." msgstr "Failed to delete one or more schedules." @@ -3523,15 +3683,15 @@ msgstr "Failed to delete one or more user tokens." msgid "Failed to delete one or more users." msgstr "Failed to delete one or more users." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:280 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "Failed to delete one or more workflow approval." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "Failed to delete organization." -#: screens/Project/ProjectDetail/ProjectDetail.js:333 +#: screens/Project/ProjectDetail/ProjectDetail.js:351 msgid "Failed to delete project." msgstr "Failed to delete project." @@ -3544,11 +3704,11 @@ msgstr "Failed to delete role" msgid "Failed to delete role." msgstr "Failed to delete role." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "Failed to delete schedule." -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:188 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "Failed to delete smart inventory." @@ -3560,11 +3720,11 @@ msgstr "Failed to delete team." msgid "Failed to delete user." msgstr "Failed to delete user." -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:376 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:351 msgid "Failed to delete workflow approval." msgstr "Failed to delete workflow approval." -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:282 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:280 msgid "Failed to delete workflow job template." msgstr "Failed to delete workflow job template." @@ -3573,13 +3733,17 @@ msgstr "Failed to delete workflow job template." msgid "Failed to delete {name}." msgstr "Failed to delete {name}." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:313 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 msgid "Failed to deny one or more workflow approval." msgstr "Failed to deny one or more workflow approval." #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:409 -msgid "Failed to deny workflow approval." -msgstr "Failed to deny workflow approval." +#~ msgid "Failed to deny workflow approval." +#~ msgstr "Failed to deny workflow approval." + +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 +msgid "Failed to deny {0}." +msgstr "Failed to deny {0}." #: screens/Host/HostGroups/HostGroupsList.js:249 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:266 @@ -3591,9 +3755,9 @@ msgstr "Failed to disassociate one or more groups." msgid "Failed to disassociate one or more hosts." msgstr "Failed to disassociate one or more hosts." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:308 -#: screens/InstanceGroup/Instances/InstanceList.js:302 -#: screens/Instances/InstanceDetail/InstanceDetail.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "Failed to disassociate one or more instances." @@ -3601,7 +3765,7 @@ msgstr "Failed to disassociate one or more instances." msgid "Failed to disassociate one or more teams." msgstr "Failed to disassociate one or more teams." -#: screens/Login/Login.js:221 +#: screens/Login/Login.js:243 msgid "Failed to fetch custom login configuration settings. System defaults will be shown instead." msgstr "Failed to fetch custom login configuration settings. System defaults will be shown instead." @@ -3609,26 +3773,39 @@ msgstr "Failed to fetch custom login configuration settings. System defaults wi msgid "Failed to fetch the updated project data." msgstr "Failed to fetch the updated project data." +#: screens/TopologyView/MeshGraph.js:410 +msgid "Failed to get instance." +msgstr "Failed to get instance." + #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:165 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "Failed to launch job." +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "Failed to load related groups." + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 +msgid "Failed to remove one or more instances." +msgstr "Failed to remove one or more instances." + #: contexts/Config.js:98 msgid "Failed to retrieve configuration." msgstr "Failed to retrieve configuration." -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:349 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:376 msgid "Failed to retrieve full node resource object." msgstr "Failed to retrieve full node resource object." #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:360 -msgid "Failed to retrieve node credentials." -msgstr "Failed to retrieve node credentials." +#~ msgid "Failed to retrieve node credentials." +#~ msgstr "Failed to retrieve node credentials." -#: screens/InstanceGroup/Instances/InstanceList.js:304 -#: screens/Instances/InstanceList/InstanceList.js:181 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "Failed to run a health check on one or more instances." @@ -3640,7 +3817,7 @@ msgstr "Failed to send test notification." msgid "Failed to sync inventory source." msgstr "Failed to sync inventory source." -#: screens/Project/shared/ProjectSyncButton.js:62 +#: screens/Project/shared/ProjectSyncButton.js:63 msgid "Failed to sync project." msgstr "Failed to sync project." @@ -3664,18 +3841,22 @@ msgstr "Failed to toggle notification." msgid "Failed to toggle schedule." msgstr "Failed to toggle schedule." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:307 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:253 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "Failed to update capacity adjustment." +#: screens/TopologyView/Tooltip.js:204 +msgid "Failed to update instance." +msgstr "Failed to update instance." + #: screens/Template/TemplateSurvey.js:133 msgid "Failed to update survey." msgstr "Failed to update survey." -#: screens/User/UserTokenDetail/UserTokenDetail.js:87 +#: screens/User/UserTokenDetail/UserTokenDetail.js:88 msgid "Failed to user token." msgstr "Failed to user token." @@ -3684,17 +3865,22 @@ msgstr "Failed to user token." msgid "Failure" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:205 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:235 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:265 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:310 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:368 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:80 +#: screens/Job/JobOutput/EmptyOutput.js:45 +msgid "Failure Explanation:" +msgstr "Failure Explanation:" + +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:66 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:210 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:240 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:270 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:315 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:142 msgid "False" msgstr "False" -#: components/Schedule/shared/FrequencyDetailSubform.js:118 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:160 +#: components/Schedule/shared/FrequencyDetailSubform.js:103 msgid "February" msgstr "February" @@ -3706,7 +3892,7 @@ msgstr "Field contains value." msgid "Field ends with value." msgstr "Field ends with value." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "Field for passing a custom Kubernetes or OpenShift Pod specification." @@ -3718,11 +3904,11 @@ msgstr "Field matches the given regular expression." msgid "Field starts with value." msgstr "Field starts with value." -#: components/Schedule/shared/FrequencyDetailSubform.js:409 +#: components/Schedule/shared/FrequencyDetailSubform.js:416 msgid "Fifth" msgstr "Fifth" -#: screens/Job/JobOutput/JobOutputSearch.js:106 +#: screens/Job/JobOutput/JobOutputSearch.js:105 msgid "File Difference" msgstr "File Difference" @@ -3739,17 +3925,25 @@ msgstr "File, directory or script" msgid "Filter By {name}" msgstr "Filter By {name}" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +msgid "Filter by failed jobs" +msgstr "Filter by failed jobs" + +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 +msgid "Filter by successful jobs" +msgstr "Filter by successful jobs" + #: components/JobList/JobList.js:248 #: components/JobList/JobListItem.js:100 msgid "Finish Time" msgstr "Finish Time" -#: screens/Job/JobDetail/JobDetail.js:206 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:249 +#: screens/Job/JobDetail/JobDetail.js:226 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208 msgid "Finished" msgstr "Finished" -#: components/Schedule/shared/FrequencyDetailSubform.js:397 +#: components/Schedule/shared/FrequencyDetailSubform.js:404 msgid "First" msgstr "" @@ -3764,7 +3958,7 @@ msgstr "" msgid "First Name" msgstr "First Name" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:255 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "First Run" @@ -3791,7 +3985,7 @@ msgstr "Fit to screen" msgid "Float" msgstr "Float" -#: screens/Job/JobOutput/JobOutputSearch.js:184 +#: screens/Job/JobOutput/JobOutputSearch.js:183 msgid "Follow" msgstr "Follow" @@ -3808,17 +4002,17 @@ msgstr "Follow" #~ "executing the playbook." #: components/LaunchPrompt/steps/OtherPromptsStep.js:114 -msgid "" -"For job templates, select run to execute the playbook.\n" -"Select check to only check playbook syntax, test environment setup,\n" -"and report problems without executing the playbook." -msgstr "" -"For job templates, select run to execute the playbook.\n" -"Select check to only check playbook syntax, test environment setup,\n" -"and report problems without executing the playbook." +#~ msgid "" +#~ "For job templates, select run to execute the playbook.\n" +#~ "Select check to only check playbook syntax, test environment setup,\n" +#~ "and report problems without executing the playbook." +#~ msgstr "" +#~ "For job templates, select run to execute the playbook.\n" +#~ "Select check to only check playbook syntax, test environment setup,\n" +#~ "and report problems without executing the playbook." #: screens/Job/Job.helptext.js:5 -#: screens/Template/shared/JobTemplate.helptext.js:5 +#: screens/Template/shared/JobTemplate.helptext.js:6 msgid "For job templates, select run to execute the playbook. Select check to only check playbook syntax, test environment setup, and report problems without executing the playbook." msgstr "For job templates, select run to execute the playbook. Select check to only check playbook syntax, test environment setup, and report problems without executing the playbook." @@ -3828,36 +4022,49 @@ msgstr "For more information, refer to the" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 -#: components/PromptDetail/PromptJobTemplateDetail.js:147 -#: screens/Job/JobDetail/JobDetail.js:384 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:252 -#: screens/Template/shared/JobTemplateForm.js:403 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:55 +#: components/PromptDetail/PromptDetail.js:332 +#: components/PromptDetail/PromptJobTemplateDetail.js:150 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 +#: screens/Job/JobDetail/JobDetail.js:389 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 +#: screens/Template/shared/JobTemplateForm.js:409 +#: screens/TopologyView/Tooltip.js:282 msgid "Forks" msgstr "Forks" -#: components/Schedule/shared/FrequencyDetailSubform.js:407 +#: components/Schedule/shared/FrequencyDetailSubform.js:414 msgid "Fourth" msgstr "Fourth" -#: components/Schedule/shared/ScheduleForm.js:177 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 +#: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "Frequency Details" -#: components/Schedule/shared/FrequencyDetailSubform.js:201 -#: components/Schedule/shared/buildRuleObj.js:71 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 +msgid "Frequency Exception Details" +msgstr "Frequency Exception Details" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:72 +#: components/Schedule/shared/FrequencyDetailSubform.js:185 +#: components/Schedule/shared/FrequencyDetailSubform.js:206 +#: components/Schedule/shared/buildRuleObj.js:91 msgid "Frequency did not match an expected value" msgstr "Frequency did not match an expected value" -#: components/Schedule/shared/FrequencyDetailSubform.js:303 +#: components/Schedule/shared/FrequencyDetailSubform.js:310 msgid "Fri" msgstr "Fri" -#: components/Schedule/shared/FrequencyDetailSubform.js:308 -#: components/Schedule/shared/FrequencyDetailSubform.js:446 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:81 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:187 +#: components/Schedule/shared/FrequencyDetailSubform.js:315 +#: components/Schedule/shared/FrequencyDetailSubform.js:453 msgid "Friday" msgstr "Friday" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "Fuzzy search on id, name or description fields." @@ -3865,7 +4072,11 @@ msgstr "Fuzzy search on id, name or description fields." msgid "Fuzzy search on name field." msgstr "Fuzzy search on name field." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: components/CredentialChip/CredentialChip.js:13 +msgid "GPG Public Key" +msgstr "GPG Public Key" + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Galaxy Credentials" @@ -3874,10 +4085,18 @@ msgstr "Galaxy Credentials" msgid "Galaxy credentials must be owned by an Organization." msgstr "Galaxy credentials must be owned by an Organization." -#: screens/Job/JobOutput/JobOutputSearch.js:107 +#: screens/Job/JobOutput/JobOutputSearch.js:106 msgid "Gathering Facts" msgstr "Gathering Facts" +#: screens/Setting/Settings.js:72 +msgid "Generic OIDC" +msgstr "Generic OIDC" + +#: screens/Setting/SettingList.js:85 +msgid "Generic OIDC settings" +msgstr "Generic OIDC settings" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:222 msgid "Get subscription" msgstr "Get subscription" @@ -3886,47 +4105,47 @@ msgstr "Get subscription" msgid "Get subscriptions" msgstr "Get subscriptions" -#: components/Lookup/ProjectLookup.js:135 +#: components/Lookup/ProjectLookup.js:136 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:89 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:158 -#: screens/Job/JobDetail/JobDetail.js:74 +#: screens/Job/JobDetail/JobDetail.js:75 #: screens/Project/ProjectList/ProjectList.js:198 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:97 msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:305 -#: screens/Template/shared/WebhookSubForm.js:105 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 +#: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:85 -#: screens/Setting/Settings.js:50 +#: screens/Setting/Settings.js:51 msgid "GitHub Default" msgstr "GitHub Default" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:100 -#: screens/Setting/Settings.js:59 +#: screens/Setting/Settings.js:60 msgid "GitHub Enterprise" msgstr "GitHub Enterprise" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:105 -#: screens/Setting/Settings.js:62 +#: screens/Setting/Settings.js:63 msgid "GitHub Enterprise Organization" msgstr "GitHub Enterprise Organization" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:110 -#: screens/Setting/Settings.js:65 +#: screens/Setting/Settings.js:66 msgid "GitHub Enterprise Team" msgstr "GitHub Enterprise Team" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:90 -#: screens/Setting/Settings.js:53 +#: screens/Setting/Settings.js:54 msgid "GitHub Organization" msgstr "GitHub Organization" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:95 -#: screens/Setting/Settings.js:56 +#: screens/Setting/Settings.js:57 msgid "GitHub Team" msgstr "GitHub Team" @@ -3934,8 +4153,8 @@ msgstr "GitHub Team" msgid "GitHub settings" msgstr "GitHub settings" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:305 -#: screens/Template/shared/WebhookSubForm.js:111 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 +#: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3943,12 +4162,12 @@ msgstr "GitLab" #~ msgid "Global Default Execution Environment" #~ msgstr "Global Default Execution Environment" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:78 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:79 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:84 msgid "Globally Available" msgstr "Globally Available" -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:133 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:134 msgid "Globally available execution environment can not be reassigned to a specific Organization" msgstr "Globally available execution environment can not be reassigned to a specific Organization" @@ -3976,7 +4195,7 @@ msgstr "Google Compute Engine" msgid "Google OAuth 2 settings" msgstr "Google OAuth 2 settings" -#: screens/Setting/Settings.js:68 +#: screens/Setting/Settings.js:69 msgid "Google OAuth2" msgstr "Google OAuth2" @@ -3985,12 +4204,12 @@ msgstr "Google OAuth2" msgid "Grafana" msgstr "Grafana" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:153 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:160 msgid "Grafana API key" msgstr "Grafana API key" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:182 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:144 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:187 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:151 msgid "Grafana URL" msgstr "Grafana URL" @@ -4024,17 +4243,17 @@ msgstr "Group type" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:248 #: screens/Inventory/InventoryList/InventoryListItem.js:127 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:251 -#: util/getRelatedResourceDeleteDetails.js:118 +#: util/getRelatedResourceDeleteDetails.js:119 msgid "Groups" msgstr "Groups" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:378 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:453 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:383 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:468 msgid "HTTP Headers" msgstr "HTTP Headers" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:466 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:378 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:481 msgid "HTTP Method" msgstr "HTTP Method" @@ -4045,12 +4264,28 @@ msgstr "HTTP Method" #~ msgid "Health Check" #~ msgstr "Health Check" -#: components/StatusLabel/StatusLabel.js:34 -#: screens/TopologyView/Legend.js:118 +#: components/HealthCheckAlert/HealthCheckAlert.js:22 +msgid "Health check request(s) submitted. Please wait and reload the page." +msgstr "Health check request(s) submitted. Please wait and reload the page." + +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "Health checks are asynchronous tasks. See the" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "Health checks can only be run on execution nodes." + +#: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "Healthy" -#: components/AppContainer/PageHeaderToolbar.js:121 +#: components/AppContainer/PageHeaderToolbar.js:116 msgid "Help" msgstr "" @@ -4058,8 +4293,8 @@ msgstr "" msgid "Hide" msgstr "Hide" -#: components/LaunchPrompt/LaunchPrompt.js:105 -#: components/Schedule/shared/SchedulePromptableFields.js:109 +#: components/LaunchPrompt/LaunchPrompt.js:135 +#: components/Schedule/shared/SchedulePromptableFields.js:102 msgid "Hide description" msgstr "Hide description" @@ -4068,7 +4303,7 @@ msgstr "Hide description" msgid "Hipchat" msgstr "Hipchat" -#: screens/Instances/InstanceList/InstanceList.js:119 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "Hop" @@ -4076,73 +4311,77 @@ msgstr "Hop" msgid "Hop node" msgstr "Hop node" -#: screens/Job/JobOutput/HostEventModal.js:109 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:148 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:76 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" msgstr "Host" -#: screens/Job/JobOutput/JobOutputSearch.js:108 +#: screens/Job/JobOutput/JobOutputSearch.js:107 msgid "Host Async Failure" msgstr "Host Async Failure" -#: screens/Job/JobOutput/JobOutputSearch.js:109 +#: screens/Job/JobOutput/JobOutputSearch.js:108 msgid "Host Async OK" msgstr "Host Async OK" -#: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:290 -#: screens/Template/shared/JobTemplateForm.js:575 +#: components/PromptDetail/PromptJobTemplateDetail.js:159 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 +#: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "Host Config Key" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "Host Count" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "Host Details" -#: screens/Job/JobOutput/JobOutputSearch.js:110 +#: screens/Job/JobOutput/JobOutputSearch.js:109 msgid "Host Failed" msgstr "Host Failed" -#: screens/Job/JobOutput/JobOutputSearch.js:111 +#: screens/Job/JobOutput/JobOutputSearch.js:110 msgid "Host Failure" msgstr "Host Failure" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:257 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "Host Filter" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:196 -#: screens/Instances/InstanceDetail/InstanceDetail.js:144 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 +#: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "Host Name" -#: screens/Job/JobOutput/JobOutputSearch.js:112 +#: screens/Job/JobOutput/JobOutputSearch.js:111 msgid "Host OK" msgstr "Host OK" -#: screens/Job/JobOutput/JobOutputSearch.js:113 +#: screens/Job/JobOutput/JobOutputSearch.js:112 msgid "Host Polling" msgstr "Host Polling" -#: screens/Job/JobOutput/JobOutputSearch.js:114 +#: screens/Job/JobOutput/JobOutputSearch.js:113 msgid "Host Retry" msgstr "Host Retry" -#: screens/Job/JobOutput/JobOutputSearch.js:115 +#: screens/Job/JobOutput/JobOutputSearch.js:114 msgid "Host Skipped" msgstr "Host Skipped" -#: screens/Job/JobOutput/JobOutputSearch.js:116 +#: screens/Job/JobOutput/JobOutputSearch.js:115 msgid "Host Started" msgstr "Host Started" -#: screens/Job/JobOutput/JobOutputSearch.js:117 +#: screens/Job/JobOutput/JobOutputSearch.js:116 msgid "Host Unreachable" msgstr "Host Unreachable" @@ -4150,7 +4389,7 @@ msgstr "Host Unreachable" msgid "Host details" msgstr "Host details" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "Host details modal" @@ -4165,7 +4404,7 @@ msgstr "Host status information for this job is unavailable." #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4177,41 +4416,44 @@ msgstr "Host status information for this job is unavailable." #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 -#: util/getRelatedResourceDeleteDetails.js:122 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "Hosts" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:132 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:92 msgid "Hosts automated" msgstr "Hosts automated" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:114 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:121 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:118 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:125 msgid "Hosts available" msgstr "Hosts available" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:127 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:107 msgid "Hosts imported" msgstr "Hosts imported" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:145 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:112 msgid "Hosts remaining" msgstr "Hosts remaining" -#: components/Schedule/shared/ScheduleForm.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 +#: components/Schedule/shared/FrequencyDetailSubform.js:175 +#: components/Schedule/shared/ScheduleFormFields.js:126 +#: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "Hour" #: screens/TopologyView/Legend.js:92 -msgid "Hy" -msgstr "Hy" +#~ msgid "Hy" +#~ msgstr "Hy" -#: screens/InstanceGroup/Instances/InstanceList.js:198 -#: screens/Instances/InstanceList/InstanceList.js:118 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "Hybrid" @@ -4225,59 +4467,63 @@ msgstr "Hybrid node" msgid "ID" msgstr "ID" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:188 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:193 msgid "ID of the Dashboard" msgstr "ID of the Dashboard" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:193 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:198 msgid "ID of the Panel" msgstr "ID of the Panel" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:160 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:167 msgid "ID of the dashboard (optional)" msgstr "ID of the dashboard (optional)" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:166 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:173 msgid "ID of the panel (optional)" msgstr "ID of the panel (optional)" +#: screens/TopologyView/Tooltip.js:265 +msgid "IP address" +msgstr "IP address" + #: components/NotificationList/NotificationList.js:196 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:137 msgid "IRC" msgstr "IRC" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:223 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:228 msgid "IRC Nick" msgstr "IRC Nick" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:218 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:223 msgid "IRC Server Address" msgstr "IRC Server Address" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:213 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:218 msgid "IRC Server Port" msgstr "IRC Server Port" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:214 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:223 msgid "IRC nick" msgstr "IRC nick" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:206 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:215 msgid "IRC server address" msgstr "IRC server address" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:192 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:201 msgid "IRC server password" msgstr "IRC server password" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:197 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:206 msgid "IRC server port" msgstr "IRC server port" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:258 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:303 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:263 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:334 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:263 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:308 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:272 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:343 msgid "Icon URL" msgstr "Icon URL" @@ -4317,11 +4563,11 @@ msgstr "" #~ "If enabled, run this playbook as an\n" #~ "administrator." -#: screens/Template/shared/JobTemplate.helptext.js:29 +#: screens/Template/shared/JobTemplate.helptext.js:30 msgid "If enabled, run this playbook as an administrator." msgstr "If enabled, run this playbook as an administrator." -#: components/LaunchPrompt/steps/OtherPromptsStep.js:156 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:184 msgid "" "If enabled, show the changes made\n" "by Ansible tasks, where supported. This is equivalent to Ansible’s\n" @@ -4341,7 +4587,7 @@ msgstr "" #~ "Ansible tasks, where supported. This is equivalent\n" #~ "to Ansible's --diff mode." -#: screens/Template/shared/JobTemplate.helptext.js:18 +#: screens/Template/shared/JobTemplate.helptext.js:19 msgid "If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansible's --diff mode." msgstr "If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansible's --diff mode." @@ -4357,7 +4603,7 @@ msgstr "If enabled, show the changes made by Ansible tasks, where supported. Thi #~ "If enabled, simultaneous runs of this job\n" #~ "template will be allowed." -#: screens/Template/shared/JobTemplate.helptext.js:31 +#: screens/Template/shared/JobTemplate.helptext.js:32 msgid "If enabled, simultaneous runs of this job template will be allowed." msgstr "If enabled, simultaneous runs of this job template will be allowed." @@ -4365,6 +4611,22 @@ msgstr "If enabled, simultaneous runs of this job template will be allowed." msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "If enabled, simultaneous runs of this workflow job template will be allowed." +#: screens/Inventory/shared/Inventory.helptext.js:195 +msgid "" +"If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." +msgstr "" +"If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." + +#: screens/Template/shared/JobTemplate.helptext.js:33 +msgid "" +"If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." +msgstr "" +"If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." + #: screens/Template/shared/JobTemplateForm.js:611 #~ msgid "" #~ "If enabled, this will store gathered facts so they can\n" @@ -4375,7 +4637,7 @@ msgstr "If enabled, simultaneous runs of this workflow job template will be allo #~ "be viewed at the host level. Facts are persisted and\n" #~ "injected into the fact cache at runtime." -#: screens/Template/shared/JobTemplate.helptext.js:32 +#: screens/Template/shared/JobTemplate.helptext.js:35 msgid "If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime." msgstr "If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime." @@ -4383,7 +4645,7 @@ msgstr "If enabled, this will store gathered facts so they can be viewed at the msgid "If specified, this field will be shown on the node instead of the resource name when viewing the workflow" msgstr "If specified, this field will be shown on the node instead of the resource name when viewing the workflow" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:150 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:180 msgid "If you are ready to upgrade or renew, please <0>contact us." msgstr "If you are ready to upgrade or renew, please <0>contact us." @@ -4408,19 +4670,22 @@ msgstr "" "If you want the Inventory Source to update on\n" "launch and on project update, click on Update on launch, and also go to" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:53 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:80 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:91 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:101 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:54 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:141 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:147 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:166 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:75 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:97 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:98 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:89 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:108 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:21 msgid "Image" msgstr "Image" -#: screens/Job/JobOutput/JobOutputSearch.js:118 +#: screens/Job/JobOutput/JobOutputSearch.js:117 msgid "Including File" msgstr "Including File" @@ -4434,7 +4699,7 @@ msgstr "" "jobs. For hosts that are part of an external inventory, this may be\n" "reset by the inventory sync process." -#: components/AppContainer/PageHeaderToolbar.js:108 +#: components/AppContainer/PageHeaderToolbar.js:103 msgid "Info" msgstr "" @@ -4483,31 +4748,49 @@ msgstr "Insights Credential" msgid "Insights system ID" msgstr "Insights system ID" +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +msgid "Install Bundle" +msgstr "Install Bundle" + +#: components/StatusLabel/StatusLabel.js:58 +#: screens/TopologyView/Legend.js:136 +msgid "Installed" +msgstr "Installed" + #: screens/Metrics/Metrics.js:187 msgid "Instance" msgstr "Instance" -#: components/PromptDetail/PromptInventorySourceDetail.js:147 +#: components/PromptDetail/PromptInventorySourceDetail.js:135 msgid "Instance Filters" msgstr "Instance Filters" -#: screens/Job/JobDetail/JobDetail.js:353 +#: screens/Job/JobDetail/JobDetail.js:358 msgid "Instance Group" msgstr "Instance Group" -#: components/Lookup/InstanceGroupsLookup.js:69 -#: components/Lookup/InstanceGroupsLookup.js:75 +#: components/InstanceDetails.js/InstanceDetails.js:263 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 +#: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 +#: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 -#: components/PromptDetail/PromptJobTemplateDetail.js:222 +#: components/Lookup/InstanceGroupsLookup.js:141 +#: components/Lookup/InstanceGroupsLookup.js:151 +#: components/PromptDetail/PromptDetail.js:228 +#: components/PromptDetail/PromptJobTemplateDetail.js:228 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:111 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:193 -#: screens/InstanceGroup/InstanceGroups.js:45 -#: screens/InstanceGroup/InstanceGroups.js:55 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:85 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:407 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 +#: screens/InstanceGroup/InstanceGroups.js:16 +#: screens/InstanceGroup/InstanceGroups.js:26 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 +#: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "" @@ -4515,7 +4798,15 @@ msgstr "" msgid "Instance ID" msgstr "Instance ID" -#: screens/InstanceGroup/InstanceGroups.js:62 +#: screens/Instances/Shared/InstanceForm.js:32 +msgid "Instance State" +msgstr "Instance State" + +#: screens/Instances/Shared/InstanceForm.js:48 +msgid "Instance Type" +msgstr "Instance Type" + +#: screens/InstanceGroup/InstanceGroups.js:33 msgid "Instance details" msgstr "Instance details" @@ -4528,26 +4819,35 @@ msgstr "Instance group" msgid "Instance group not found." msgstr "Instance group not found." -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "Instance group used capacity" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:124 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:122 +#: screens/TopologyView/Tooltip.js:273 msgid "Instance groups" msgstr "Instance groups" +#: screens/TopologyView/Tooltip.js:234 +msgid "Instance status" +msgstr "Instance status" + +#: screens/TopologyView/Tooltip.js:240 +msgid "Instance type" +msgstr "Instance type" + #: routeConfig.js:137 #: screens/ActivityStream/ActivityStream.js:203 #: screens/InstanceGroup/InstanceGroup.js:74 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:212 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 -#: screens/InstanceGroup/InstanceGroups.js:60 -#: screens/InstanceGroup/Instances/InstanceList.js:181 -#: screens/InstanceGroup/Instances/InstanceList.js:279 -#: screens/Instances/InstanceList/InstanceList.js:101 -#: screens/Instances/Instances.js:12 -#: screens/Instances/Instances.js:20 +#: screens/InstanceGroup/InstanceGroups.js:31 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/Instances.js:13 +#: screens/Instances/Instances.js:22 msgid "Instances" msgstr "Instances" @@ -4567,7 +4867,7 @@ msgstr "Invalid file format. Please upload a valid Red Hat Subscription Manifest #~ msgid "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." #~ msgstr "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:151 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:178 msgid "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." msgstr "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." @@ -4575,19 +4875,19 @@ msgstr "Invalid link target. Unable to link to children or ancestor nodes. Graph msgid "Invalid time format" msgstr "Invalid time format" -#: screens/Login/Login.js:142 +#: screens/Login/Login.js:153 msgid "Invalid username or password. Please try again." msgstr "" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 -#: util/getRelatedResourceDeleteDetails.js:201 -#: util/getRelatedResourceDeleteDetails.js:269 +#: util/getRelatedResourceDeleteDetails.js:202 +#: util/getRelatedResourceDeleteDetails.js:270 msgid "Inventories" msgstr "" @@ -4599,38 +4899,38 @@ msgstr "Inventories with sources cannot be copied" #: components/JobList/JobListItem.js:223 #: components/LaunchPrompt/steps/InventoryStep.js:105 #: components/LaunchPrompt/steps/useInventoryStep.js:48 -#: components/Lookup/HostFilterLookup.js:423 +#: components/Lookup/HostFilterLookup.js:424 #: components/Lookup/HostListItem.js:10 -#: components/Lookup/InventoryLookup.js:129 -#: components/Lookup/InventoryLookup.js:138 -#: components/Lookup/InventoryLookup.js:178 -#: components/Lookup/InventoryLookup.js:193 -#: components/Lookup/InventoryLookup.js:233 -#: components/PromptDetail/PromptDetail.js:205 -#: components/PromptDetail/PromptInventorySourceDetail.js:87 -#: components/PromptDetail/PromptJobTemplateDetail.js:117 -#: components/PromptDetail/PromptJobTemplateDetail.js:127 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:77 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:290 -#: components/TemplateList/TemplateListItem.js:284 -#: components/TemplateList/TemplateListItem.js:294 -#: screens/Host/HostDetail/HostDetail.js:75 +#: components/Lookup/InventoryLookup.js:119 +#: components/Lookup/InventoryLookup.js:128 +#: components/Lookup/InventoryLookup.js:169 +#: components/Lookup/InventoryLookup.js:184 +#: components/Lookup/InventoryLookup.js:224 +#: components/PromptDetail/PromptDetail.js:215 +#: components/PromptDetail/PromptInventorySourceDetail.js:76 +#: components/PromptDetail/PromptJobTemplateDetail.js:119 +#: components/PromptDetail/PromptJobTemplateDetail.js:129 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:79 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 +#: components/TemplateList/TemplateListItem.js:285 +#: components/TemplateList/TemplateListItem.js:295 +#: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:39 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:113 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:41 -#: screens/Job/JobDetail/JobDetail.js:106 -#: screens/Job/JobDetail/JobDetail.js:121 -#: screens/Job/JobDetail/JobDetail.js:128 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:207 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:217 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:142 +#: screens/Job/JobDetail/JobDetail.js:107 +#: screens/Job/JobDetail/JobDetail.js:122 +#: screens/Job/JobDetail/JobDetail.js:129 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:293 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 msgid "Inventory" msgstr "Inventory" @@ -4638,7 +4938,7 @@ msgstr "Inventory" msgid "Inventory (Name)" msgstr "Inventory (Name)" -#: components/PromptDetail/PromptInventorySourceDetail.js:110 +#: components/PromptDetail/PromptInventorySourceDetail.js:99 msgid "Inventory File" msgstr "Inventory File" @@ -4646,27 +4946,27 @@ msgstr "Inventory File" msgid "Inventory ID" msgstr "Inventory ID" -#: screens/Job/JobDetail/JobDetail.js:262 +#: screens/Job/JobDetail/JobDetail.js:282 msgid "Inventory Source" msgstr "Inventory Source" #: screens/Job/JobDetail/JobDetail.js:285 -msgid "Inventory Source Project" -msgstr "Inventory Source Project" +#~ msgid "Inventory Source Project" +#~ msgstr "Inventory Source Project" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:73 msgid "Inventory Source Sync" msgstr "Inventory Source Sync" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:315 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "Inventory Source Sync Error" #: screens/Inventory/InventorySources/InventorySourceList.js:176 #: screens/Inventory/InventorySources/InventorySourceList.js:193 -#: util/getRelatedResourceDeleteDetails.js:66 -#: util/getRelatedResourceDeleteDetails.js:146 +#: util/getRelatedResourceDeleteDetails.js:67 +#: util/getRelatedResourceDeleteDetails.js:147 msgid "Inventory Sources" msgstr "Inventory Sources" @@ -4674,7 +4974,7 @@ msgstr "Inventory Sources" #: components/JobList/JobListItem.js:43 #: components/Schedule/ScheduleList/ScheduleListItem.js:36 #: components/Workflow/WorkflowLegend.js:100 -#: screens/Job/JobDetail/JobDetail.js:65 +#: screens/Job/JobDetail/JobDetail.js:66 msgid "Inventory Sync" msgstr "Inventory Sync" @@ -4690,8 +4990,8 @@ msgstr "Inventory Update" msgid "Inventory copied successfully" msgstr "Inventory copied successfully" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:241 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:108 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "Inventory file" @@ -4703,7 +5003,7 @@ msgstr "Inventory not found." msgid "Inventory sync" msgstr "Inventory sync" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "Inventory sync failures" @@ -4715,15 +5015,15 @@ msgstr "Is expanded" msgid "Is not expanded" msgstr "Is not expanded" -#: screens/Job/JobOutput/JobOutputSearch.js:119 +#: screens/Job/JobOutput/JobOutputSearch.js:118 msgid "Item Failed" msgstr "Item Failed" -#: screens/Job/JobOutput/JobOutputSearch.js:120 +#: screens/Job/JobOutput/JobOutputSearch.js:119 msgid "Item OK" msgstr "Item OK" -#: screens/Job/JobOutput/JobOutputSearch.js:121 +#: screens/Job/JobOutput/JobOutputSearch.js:120 msgid "Item Skipped" msgstr "Item Skipped" @@ -4737,18 +5037,18 @@ msgid "Items per page" msgstr "" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:172 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "JOB ID:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "JSON tab" @@ -4756,7 +5056,8 @@ msgstr "JSON tab" msgid "JSON:" msgstr "JSON:" -#: components/Schedule/shared/FrequencyDetailSubform.js:113 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:159 +#: components/Schedule/shared/FrequencyDetailSubform.js:98 msgid "January" msgstr "January" @@ -4766,21 +5067,21 @@ msgstr "January" #~ msgstr "Job" #: components/JobList/JobListItem.js:112 -#: screens/Job/JobDetail/JobDetail.js:581 -#: screens/Job/JobOutput/JobOutput.js:790 -#: screens/Job/JobOutput/JobOutput.js:791 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobDetail/JobDetail.js:599 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "Job Cancel Error" -#: screens/Job/JobDetail/JobDetail.js:603 -#: screens/Job/JobOutput/JobOutput.js:779 -#: screens/Job/JobOutput/JobOutput.js:780 +#: screens/Job/JobDetail/JobDetail.js:621 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "Job Delete Error" -#: screens/Job/JobDetail/JobDetail.js:184 +#: screens/Job/JobDetail/JobDetail.js:206 msgid "Job ID" msgstr "Job ID" @@ -4788,19 +5089,22 @@ msgstr "Job ID" msgid "Job Runs" msgstr "Job Runs" -#: components/JobList/JobListItem.js:313 -#: screens/Job/JobDetail/JobDetail.js:369 +#: components/JobList/JobListItem.js:314 +#: screens/Job/JobDetail/JobDetail.js:374 msgid "Job Slice" msgstr "Job Slice" -#: components/JobList/JobListItem.js:318 -#: screens/Job/JobDetail/JobDetail.js:377 +#: components/JobList/JobListItem.js:319 +#: screens/Job/JobDetail/JobDetail.js:382 msgid "Job Slice Parent" msgstr "Job Slice Parent" -#: components/PromptDetail/PromptJobTemplateDetail.js:153 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:282 -#: screens/Template/shared/JobTemplateForm.js:435 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:76 +#: components/PromptDetail/PromptDetail.js:336 +#: components/PromptDetail/PromptJobTemplateDetail.js:158 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 +#: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "Job Slicing" @@ -4808,14 +5112,15 @@ msgstr "Job Slicing" msgid "Job Status" msgstr "Job Status" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:57 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:58 -#: components/PromptDetail/PromptDetail.js:228 -#: components/PromptDetail/PromptJobTemplateDetail.js:241 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:346 -#: screens/Job/JobDetail/JobDetail.js:458 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:434 -#: screens/Template/shared/JobTemplateForm.js:469 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:97 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:98 +#: components/PromptDetail/PromptDetail.js:254 +#: components/PromptDetail/PromptJobTemplateDetail.js:247 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 +#: screens/Job/JobDetail/JobDetail.js:474 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 +#: screens/Template/shared/JobTemplateForm.js:521 +#: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" msgstr "Job Tags" @@ -4825,7 +5130,7 @@ msgstr "Job Tags" #: components/Workflow/WorkflowNodeHelp.js:59 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:97 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:19 -#: screens/Job/JobDetail/JobDetail.js:213 +#: screens/Job/JobDetail/JobDetail.js:233 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:79 msgid "Job Template" msgstr "Job Template" @@ -4834,16 +5139,16 @@ msgstr "Job Template" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 #: screens/Inventory/SmartInventory.js:74 #: screens/Project/Project.js:107 #: screens/Project/Projects.js:29 -#: util/getRelatedResourceDeleteDetails.js:55 -#: util/getRelatedResourceDeleteDetails.js:100 -#: util/getRelatedResourceDeleteDetails.js:132 +#: util/getRelatedResourceDeleteDetails.js:56 +#: util/getRelatedResourceDeleteDetails.js:101 +#: util/getRelatedResourceDeleteDetails.js:133 msgid "Job Templates" msgstr "Job Templates" @@ -4851,32 +5156,32 @@ msgstr "Job Templates" msgid "Job Templates with a missing inventory or project cannot be selected when creating or editing nodes. Select another template or fix the missing fields to proceed." msgstr "Job Templates with a missing inventory or project cannot be selected when creating or editing nodes. Select another template or fix the missing fields to proceed." -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js:316 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js:357 msgid "Job Templates with credentials that prompt for passwords cannot be selected when creating or editing nodes" msgstr "Job Templates with credentials that prompt for passwords cannot be selected when creating or editing nodes" #: components/JobList/JobList.js:208 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:111 -#: components/PromptDetail/PromptDetail.js:176 -#: components/PromptDetail/PromptJobTemplateDetail.js:100 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:286 -#: screens/Job/JobDetail/JobDetail.js:247 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:139 -#: screens/Template/shared/JobTemplateForm.js:252 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:146 +#: components/PromptDetail/PromptDetail.js:186 +#: components/PromptDetail/PromptJobTemplateDetail.js:102 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 +#: screens/Job/JobDetail/JobDetail.js:267 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 +#: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "Job Type" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "Job status" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "Job status graph tab" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "Job templates" @@ -4890,8 +5195,8 @@ msgstr "Job templates" #: screens/Host/Hosts.js:30 #: screens/InstanceGroup/ContainerGroup.js:71 #: screens/InstanceGroup/InstanceGroup.js:79 -#: screens/InstanceGroup/InstanceGroups.js:63 -#: screens/InstanceGroup/InstanceGroups.js:68 +#: screens/InstanceGroup/InstanceGroups.js:34 +#: screens/InstanceGroup/InstanceGroups.js:39 #: screens/Inventory/Inventories.js:60 #: screens/Inventory/Inventories.js:70 #: screens/Inventory/Inventory.js:70 @@ -4899,23 +5204,25 @@ msgstr "Job templates" #: screens/Inventory/SmartInventory.js:70 #: screens/Job/Jobs.js:22 #: screens/Job/Jobs.js:32 -#: screens/Setting/SettingList.js:87 -#: screens/Setting/Settings.js:71 +#: screens/Setting/SettingList.js:91 +#: screens/Setting/Settings.js:75 #: screens/Template/Template.js:155 #: screens/Template/Templates.js:47 #: screens/Template/WorkflowJobTemplate.js:141 msgid "Jobs" msgstr "" -#: screens/Setting/SettingList.js:92 +#: screens/Setting/SettingList.js:96 msgid "Jobs settings" msgstr "Jobs settings" -#: components/Schedule/shared/FrequencyDetailSubform.js:143 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:165 +#: components/Schedule/shared/FrequencyDetailSubform.js:128 msgid "July" msgstr "July" -#: components/Schedule/shared/FrequencyDetailSubform.js:138 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:164 +#: components/Schedule/shared/FrequencyDetailSubform.js:123 msgid "June" msgstr "June" @@ -4940,27 +5247,27 @@ msgstr "Keyword" msgid "LDAP" msgstr "LDAP" -#: screens/Setting/Settings.js:76 +#: screens/Setting/Settings.js:80 msgid "LDAP 1" msgstr "LDAP 1" -#: screens/Setting/Settings.js:77 +#: screens/Setting/Settings.js:81 msgid "LDAP 2" msgstr "LDAP 2" -#: screens/Setting/Settings.js:78 +#: screens/Setting/Settings.js:82 msgid "LDAP 3" msgstr "LDAP 3" -#: screens/Setting/Settings.js:79 +#: screens/Setting/Settings.js:83 msgid "LDAP 4" msgstr "LDAP 4" -#: screens/Setting/Settings.js:80 +#: screens/Setting/Settings.js:84 msgid "LDAP 5" msgstr "LDAP 5" -#: screens/Setting/Settings.js:75 +#: screens/Setting/Settings.js:79 msgid "LDAP Default" msgstr "LDAP Default" @@ -4988,7 +5295,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "Label" @@ -4997,36 +5304,42 @@ msgstr "Label" msgid "Label Name" msgstr "Label Name" -#: components/JobList/JobListItem.js:283 -#: components/PromptDetail/PromptJobTemplateDetail.js:203 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:114 -#: components/TemplateList/TemplateListItem.js:345 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:110 -#: screens/Inventory/shared/InventoryForm.js:75 -#: screens/Job/JobDetail/JobDetail.js:437 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:386 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:208 -#: screens/Template/shared/JobTemplateForm.js:379 -#: screens/Template/shared/WorkflowJobTemplateForm.js:189 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:315 +#: components/JobList/JobListItem.js:284 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:223 +#: components/PromptDetail/PromptDetail.js:310 +#: components/PromptDetail/PromptJobTemplateDetail.js:209 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:116 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/TemplateList/TemplateListItem.js:347 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 +#: screens/Inventory/shared/InventoryForm.js:83 +#: screens/Job/JobDetail/JobDetail.js:453 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 +#: screens/Template/shared/JobTemplateForm.js:387 +#: screens/Template/shared/WorkflowJobTemplateForm.js:195 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:273 msgid "Labels" msgstr "Labels" -#: components/Schedule/shared/FrequencyDetailSubform.js:410 +#: components/Schedule/shared/FrequencyDetailSubform.js:417 msgid "Last" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:213 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:164 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:47 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "Last Health Check" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 -#: screens/Project/ProjectDetail/ProjectDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 +#: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "Last Job Status" @@ -5034,30 +5347,30 @@ msgstr "Last Job Status" msgid "Last Login" msgstr "Last Login" -#: components/PromptDetail/PromptDetail.js:152 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:275 -#: components/TemplateList/TemplateListItem.js:315 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:105 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 +#: components/TemplateList/TemplateListItem.js:316 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 #: screens/Application/ApplicationsList/ApplicationsList.js:159 #: screens/Credential/CredentialDetail/CredentialDetail.js:263 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:107 -#: screens/Host/HostDetail/HostDetail.js:87 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:139 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 +#: screens/Host/HostDetail/HostDetail.js:89 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85 -#: screens/Job/JobDetail/JobDetail.js:520 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 -#: screens/Project/ProjectDetail/ProjectDetail.js:279 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 +#: screens/Job/JobDetail/JobDetail.js:538 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 +#: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:344 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 -#: screens/User/UserTokenDetail/UserTokenDetail.js:65 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 +#: screens/User/UserTokenDetail/UserTokenDetail.js:66 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 msgid "Last Modified" msgstr "" @@ -5077,7 +5390,7 @@ msgstr "" msgid "Last Ran" msgstr "Last Ran" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:262 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "Last Run" @@ -5085,10 +5398,11 @@ msgstr "Last Run" msgid "Last job" msgstr "Last job" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:296 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:153 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:50 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 +#: screens/TopologyView/Tooltip.js:331 msgid "Last modified" msgstr "Last modified" @@ -5097,6 +5411,10 @@ msgstr "Last modified" msgid "Last name" msgstr "Last name" +#: screens/TopologyView/Tooltip.js:337 +msgid "Last seen" +msgstr "Last seen" + #: screens/Project/ProjectList/ProjectListItem.js:313 msgid "Last used" msgstr "Last used" @@ -5105,10 +5423,10 @@ msgstr "Last used" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:503 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:512 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:256 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" msgstr "Launch" @@ -5138,7 +5456,7 @@ msgstr "Launch template" msgid "Launch workflow" msgstr "Launch workflow" -#: components/LaunchPrompt/LaunchPrompt.js:100 +#: components/LaunchPrompt/LaunchPrompt.js:130 msgid "Launch | {0}" msgstr "Launch | {0}" @@ -5158,14 +5476,14 @@ msgstr "Learn more about Automation Analytics" #~ msgid "Learn more about Insights for Ansible Automation Platform" #~ msgstr "Learn more about Insights for Ansible Automation Platform" -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:68 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:69 msgid "Leave this field blank to make the execution environment globally available." msgstr "Leave this field blank to make the execution environment globally available." #: components/Workflow/WorkflowLegend.js:86 #: screens/Metrics/LineChart.js:120 #: screens/TopologyView/Header.js:102 -#: screens/TopologyView/Legend.js:65 +#: screens/TopologyView/Legend.js:67 msgid "Legend" msgstr "Legend" @@ -5180,25 +5498,33 @@ msgstr "Less than or equal to comparison." #: components/AdHocCommands/AdHocDetailsStep.js:140 #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:36 -#: components/PromptDetail/PromptDetail.js:216 -#: components/PromptDetail/PromptJobTemplateDetail.js:148 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:88 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:314 -#: screens/Job/JobDetail/JobDetail.js:320 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:258 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:152 -#: screens/Template/shared/JobTemplateForm.js:408 -#: screens/Template/shared/WorkflowJobTemplateForm.js:153 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:279 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:65 +#: components/PromptDetail/PromptDetail.js:242 +#: components/PromptDetail/PromptJobTemplateDetail.js:153 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:90 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 +#: screens/Job/JobDetail/JobDetail.js:325 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 +#: screens/Template/shared/JobTemplateForm.js:429 +#: screens/Template/shared/WorkflowJobTemplateForm.js:159 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238 msgid "Limit" msgstr "Limit" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:234 +#: screens/TopologyView/Legend.js:237 +msgid "Link state types" +msgstr "Link state types" + +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:261 msgid "Link to an available node" msgstr "Link to an available node" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:334 +#: screens/Instances/Shared/InstanceForm.js:40 +msgid "Listener Port" +msgstr "Listener Port" + +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:353 msgid "Loading" msgstr "Loading" @@ -5206,34 +5532,34 @@ msgstr "Loading" msgid "Local" msgstr "Local" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:263 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "Local Time Zone" -#: components/Schedule/shared/ScheduleForm.js:132 +#: components/Schedule/shared/ScheduleFormFields.js:95 msgid "Local time zone" msgstr "Local time zone" -#: screens/Login/Login.js:195 +#: screens/Login/Login.js:217 msgid "Log In" msgstr "Log In" -#: screens/Setting/Settings.js:93 +#: screens/Setting/Settings.js:97 msgid "Logging" msgstr "Logging" -#: screens/Setting/SettingList.js:111 +#: screens/Setting/SettingList.js:115 msgid "Logging settings" msgstr "Logging settings" #: components/AppContainer/AppContainer.js:81 #: components/AppContainer/AppContainer.js:150 -#: components/AppContainer/PageHeaderToolbar.js:174 +#: components/AppContainer/PageHeaderToolbar.js:169 msgid "Logout" msgstr "" -#: components/Lookup/HostFilterLookup.js:366 -#: components/Lookup/Lookup.js:181 +#: components/Lookup/HostFilterLookup.js:367 +#: components/Lookup/Lookup.js:187 msgid "Lookup modal" msgstr "Lookup modal" @@ -5249,7 +5575,7 @@ msgstr "Lookup type" msgid "Lookup typeahead" msgstr "Lookup typeahead" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:170 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5259,11 +5585,11 @@ msgstr "MOST RECENT SYNC" #: components/AdHocCommands/AdHocCredentialStep.js:97 #: components/AdHocCommands/AdHocCredentialStep.js:98 #: components/AdHocCommands/AdHocCredentialStep.js:112 -#: screens/Job/JobDetail/JobDetail.js:392 +#: screens/Job/JobDetail/JobDetail.js:407 msgid "Machine Credential" msgstr "Machine Credential" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:64 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 msgid "Managed" msgstr "Managed" @@ -5277,7 +5603,7 @@ msgstr "Managed nodes" #: components/Schedule/ScheduleList/ScheduleListItem.js:39 #: components/Workflow/WorkflowLegend.js:108 #: components/Workflow/WorkflowNodeHelp.js:79 -#: screens/Job/JobDetail/JobDetail.js:68 +#: screens/Job/JobDetail/JobDetail.js:69 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:102 msgid "Management Job" msgstr "Management Job" @@ -5304,23 +5630,26 @@ msgstr "Management job not found." msgid "Management jobs" msgstr "Management jobs" -#: components/Lookup/ProjectLookup.js:134 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:208 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:159 -#: screens/Instances/InstanceList/InstanceListItem.js:219 -#: screens/Job/JobDetail/JobDetail.js:73 -#: screens/Project/ProjectDetail/ProjectDetail.js:191 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:83 +#: screens/Job/JobDetail/JobDetail.js:74 +#: screens/Project/ProjectDetail/ProjectDetail.js:192 #: screens/Project/ProjectList/ProjectList.js:197 #: screens/Project/ProjectList/ProjectListItem.js:219 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:96 msgid "Manual" msgstr "Manual" -#: components/Schedule/shared/FrequencyDetailSubform.js:123 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:161 +#: components/Schedule/shared/FrequencyDetailSubform.js:108 msgid "March" msgstr "March" @@ -5329,11 +5658,25 @@ msgstr "March" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "Max Hosts" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "Max concurrent jobs" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "Max forks" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "Maximum" @@ -5342,7 +5685,30 @@ msgstr "Maximum" msgid "Maximum length" msgstr "Maximum length" -#: components/Schedule/shared/FrequencyDetailSubform.js:133 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 +#: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" msgstr "May" @@ -5393,28 +5759,31 @@ msgstr "" "Minimum percentage of all instances that will be automatically\n" "assigned to this group when new instances come online." -#: components/Schedule/shared/ScheduleForm.js:154 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 +#: components/Schedule/shared/FrequencyDetailSubform.js:173 +#: components/Schedule/shared/ScheduleFormFields.js:125 +#: components/Schedule/shared/ScheduleFormFields.js:185 msgid "Minute" msgstr "Minute" -#: screens/Setting/Settings.js:96 +#: screens/Setting/Settings.js:100 msgid "Miscellaneous Authentication" msgstr "Miscellaneous Authentication" -#: screens/Setting/SettingList.js:107 +#: screens/Setting/SettingList.js:111 msgid "Miscellaneous Authentication settings" msgstr "Miscellaneous Authentication settings" -#: screens/Setting/Settings.js:99 +#: screens/Setting/Settings.js:103 msgid "Miscellaneous System" msgstr "Miscellaneous System" -#: screens/Setting/SettingList.js:103 +#: screens/Setting/SettingList.js:107 msgid "Miscellaneous System settings" msgstr "Miscellaneous System settings" #: components/Workflow/WorkflowNodeHelp.js:120 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:86 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:87 msgid "Missing" msgstr "Missing" @@ -5423,7 +5792,7 @@ msgstr "Missing" msgid "Missing resource" msgstr "Missing resource" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:193 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:192 #: screens/User/UserTokenList/UserTokenList.js:154 msgid "Modified" msgstr "" @@ -5432,17 +5801,17 @@ msgstr "" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 -#: components/Lookup/CredentialLookup.js:197 -#: components/Lookup/InventoryLookup.js:165 -#: components/Lookup/InventoryLookup.js:220 -#: components/Lookup/MultiCredentialsLookup.js:197 -#: components/Lookup/OrganizationLookup.js:137 -#: components/Lookup/ProjectLookup.js:146 +#: components/Lookup/CredentialLookup.js:198 +#: components/Lookup/InventoryLookup.js:156 +#: components/Lookup/InventoryLookup.js:211 +#: components/Lookup/MultiCredentialsLookup.js:202 +#: components/Lookup/OrganizationLookup.js:138 +#: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 -#: components/Schedule/ScheduleList/ScheduleList.js:201 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 +#: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:62 @@ -5466,7 +5835,7 @@ msgstr "" #: screens/Organization/OrganizationList/OrganizationList.js:135 #: screens/Project/ProjectList/ProjectList.js:209 #: screens/Team/TeamList/TeamList.js:134 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:167 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:165 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:108 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:112 msgid "Modified By (Username)" @@ -5479,28 +5848,33 @@ msgid "Modified by (username)" msgstr "Modified by (username)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "Module" -#: screens/Job/JobDetail/JobDetail.js:512 +#: screens/Job/JobDetail/JobDetail.js:530 msgid "Module Arguments" msgstr "Module Arguments" -#: screens/Job/JobDetail/JobDetail.js:506 +#: screens/Job/JobDetail/JobDetail.js:524 msgid "Module Name" msgstr "Module Name" -#: components/Schedule/shared/FrequencyDetailSubform.js:259 +#: components/Schedule/shared/FrequencyDetailSubform.js:266 msgid "Mon" msgstr "Mon" -#: components/Schedule/shared/FrequencyDetailSubform.js:264 -#: components/Schedule/shared/FrequencyDetailSubform.js:426 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:77 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:183 +#: components/Schedule/shared/FrequencyDetailSubform.js:271 +#: components/Schedule/shared/FrequencyDetailSubform.js:433 msgid "Monday" msgstr "Monday" -#: components/Schedule/shared/ScheduleForm.js:158 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/shared/FrequencyDetailSubform.js:181 +#: components/Schedule/shared/ScheduleFormFields.js:129 +#: components/Schedule/shared/ScheduleFormFields.js:189 msgid "Month" msgstr "Month" @@ -5546,45 +5920,50 @@ msgstr "Multiple Choice Options" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:78 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:89 #: components/LaunchPrompt/steps/InventoryStep.js:84 #: components/LaunchPrompt/steps/InventoryStep.js:99 -#: components/Lookup/ApplicationLookup.js:99 -#: components/Lookup/ApplicationLookup.js:110 -#: components/Lookup/CredentialLookup.js:188 -#: components/Lookup/CredentialLookup.js:203 -#: components/Lookup/ExecutionEnvironmentLookup.js:172 -#: components/Lookup/ExecutionEnvironmentLookup.js:179 +#: components/Lookup/ApplicationLookup.js:100 +#: components/Lookup/ApplicationLookup.js:111 +#: components/Lookup/CredentialLookup.js:189 +#: components/Lookup/CredentialLookup.js:204 +#: components/Lookup/ExecutionEnvironmentLookup.js:177 +#: components/Lookup/ExecutionEnvironmentLookup.js:184 #: components/Lookup/HostFilterLookup.js:93 -#: components/Lookup/HostFilterLookup.js:421 +#: components/Lookup/HostFilterLookup.js:422 #: components/Lookup/HostListItem.js:8 #: components/Lookup/InstanceGroupsLookup.js:103 #: components/Lookup/InstanceGroupsLookup.js:114 -#: components/Lookup/InventoryLookup.js:156 -#: components/Lookup/InventoryLookup.js:171 -#: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/InventoryLookup.js:226 -#: components/Lookup/MultiCredentialsLookup.js:188 -#: components/Lookup/MultiCredentialsLookup.js:203 -#: components/Lookup/OrganizationLookup.js:128 -#: components/Lookup/OrganizationLookup.js:143 -#: components/Lookup/ProjectLookup.js:126 -#: components/Lookup/ProjectLookup.js:156 +#: components/Lookup/InventoryLookup.js:147 +#: components/Lookup/InventoryLookup.js:162 +#: components/Lookup/InventoryLookup.js:202 +#: components/Lookup/InventoryLookup.js:217 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 +#: components/Lookup/OrganizationLookup.js:129 +#: components/Lookup/OrganizationLookup.js:144 +#: components/Lookup/ProjectLookup.js:127 +#: components/Lookup/ProjectLookup.js:157 #: components/NotificationList/NotificationList.js:181 #: components/NotificationList/NotificationList.js:218 #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:105 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:252 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 -#: components/Schedule/ScheduleList/ScheduleList.js:188 -#: components/Schedule/ScheduleList/ScheduleListItem.js:80 -#: components/Schedule/shared/ScheduleForm.js:107 +#: components/Schedule/ScheduleList/ScheduleList.js:189 +#: components/Schedule/ScheduleList/ScheduleListItem.js:86 +#: components/Schedule/shared/ScheduleFormFields.js:72 #: components/TemplateList/TemplateList.js:205 #: components/TemplateList/TemplateList.js:242 #: components/TemplateList/TemplateListItem.js:142 @@ -5600,7 +5979,7 @@ msgstr "Multiple Choice Options" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:179 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:191 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:206 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:59 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:60 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:109 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:135 #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:28 @@ -5608,7 +5987,7 @@ msgstr "Multiple Choice Options" #: screens/Application/ApplicationsList/ApplicationListItem.js:33 #: screens/Application/ApplicationsList/ApplicationsList.js:118 #: screens/Application/ApplicationsList/ApplicationsList.js:155 -#: screens/Application/shared/ApplicationForm.js:53 +#: screens/Application/shared/ApplicationForm.js:54 #: screens/Credential/CredentialDetail/CredentialDetail.js:217 #: screens/Credential/CredentialList/CredentialList.js:141 #: screens/Credential/CredentialList/CredentialList.js:164 @@ -5621,14 +6000,14 @@ msgstr "Multiple Choice Options" #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:176 #: screens/CredentialType/CredentialTypeList/CredentialTypeListItem.js:33 #: screens/CredentialType/shared/CredentialTypeForm.js:21 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:48 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:49 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:136 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:165 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:69 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:89 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:115 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:12 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:88 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:89 #: screens/Host/HostDetail/HostDetail.js:69 #: screens/Host/HostGroups/HostGroupItem.js:28 #: screens/Host/HostGroups/HostGroupsList.js:159 @@ -5636,23 +6015,27 @@ msgstr "Multiple Choice Options" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:175 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:208 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:188 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:255 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 #: screens/InstanceGroup/Instances/InstanceList.js:288 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:108 -#: screens/Instances/InstanceList/InstanceList.js:125 -#: screens/Instances/InstanceList/InstanceList.js:150 -#: screens/Instances/InstanceList/InstanceListItem.js:128 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:67 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 +#: screens/Instances/InstancePeers/InstancePeerList.js:80 +#: screens/Instances/InstancePeers/InstancePeerList.js:87 +#: screens/Instances/InstancePeers/InstancePeerList.js:96 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:37 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5664,7 +6047,7 @@ msgstr "Multiple Choice Options" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5674,7 +6057,7 @@ msgstr "Multiple Choice Options" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:196 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5682,19 +6065,19 @@ msgstr "Multiple Choice Options" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:76 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:111 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 -#: screens/Inventory/shared/InventoryForm.js:42 +#: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 #: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:67 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:106 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:122 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5705,18 +6088,18 @@ msgstr "Multiple Choice Options" #: screens/Organization/OrganizationTeams/OrganizationTeamList.js:85 #: screens/Organization/OrganizationTeams/OrganizationTeamListItem.js:14 #: screens/Organization/shared/OrganizationForm.js:56 -#: screens/Project/ProjectDetail/ProjectDetail.js:175 +#: screens/Project/ProjectDetail/ProjectDetail.js:176 #: screens/Project/ProjectList/ProjectList.js:185 #: screens/Project/ProjectList/ProjectList.js:221 #: screens/Project/ProjectList/ProjectListItem.js:179 -#: screens/Project/shared/ProjectForm.js:170 +#: screens/Project/shared/ProjectForm.js:214 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:146 #: screens/Team/TeamDetail/TeamDetail.js:37 #: screens/Team/TeamList/TeamList.js:117 #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:178 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5726,8 +6109,8 @@ msgstr "Multiple Choice Options" #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:111 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:69 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:88 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:122 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:154 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:120 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:152 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:178 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:68 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:88 @@ -5735,8 +6118,8 @@ msgstr "Multiple Choice Options" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/SystemJobTemplatesList.js:94 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:75 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:95 -#: screens/Template/shared/JobTemplateForm.js:239 -#: screens/Template/shared/WorkflowJobTemplateForm.js:104 +#: screens/Template/shared/JobTemplateForm.js:243 +#: screens/Template/shared/WorkflowJobTemplateForm.js:109 #: screens/User/UserOrganizations/UserOrganizationList.js:75 #: screens/User/UserOrganizations/UserOrganizationList.js:79 #: screens/User/UserOrganizations/UserOrganizationListItem.js:13 @@ -5746,10 +6129,10 @@ msgstr "Multiple Choice Options" #: screens/User/UserTeams/UserTeamList.js:232 #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:200 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:251 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:34 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "" @@ -5761,7 +6144,8 @@ msgstr "" msgid "Navigation" msgstr "Navigation" -#: components/Schedule/shared/FrequencyDetailSubform.js:505 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:221 +#: components/Schedule/shared/FrequencyDetailSubform.js:512 #: screens/Dashboard/shared/ChartTooltip.js:106 #: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:57 msgid "Never" @@ -5780,24 +6164,24 @@ msgstr "Never expires" msgid "New" msgstr "New" -#: components/AdHocCommands/AdHocCommandsWizard.js:52 +#: components/AdHocCommands/AdHocCommandsWizard.js:51 #: components/AdHocCommands/useAdHocCredentialStep.js:29 #: components/AdHocCommands/useAdHocDetailsStep.js:40 #: components/AdHocCommands/useAdHocExecutionEnvironmentStep.js:22 #: components/AddRole/AddResourceRole.js:196 #: components/AddRole/AddResourceRole.js:231 -#: components/LaunchPrompt/LaunchPrompt.js:130 -#: components/Schedule/shared/SchedulePromptableFields.js:134 +#: components/LaunchPrompt/LaunchPrompt.js:160 +#: components/Schedule/shared/SchedulePromptableFields.js:127 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:66 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:59 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:130 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:132 msgid "Next" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:259 -#: components/Schedule/ScheduleList/ScheduleList.js:170 -#: components/Schedule/ScheduleList/ScheduleListItem.js:104 -#: components/Schedule/ScheduleList/ScheduleListItem.js:108 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 +#: components/Schedule/ScheduleList/ScheduleList.js:171 +#: components/Schedule/ScheduleList/ScheduleListItem.js:118 +#: components/Schedule/ScheduleList/ScheduleListItem.js:122 msgid "Next Run" msgstr "Next Run" @@ -5805,16 +6189,16 @@ msgstr "Next Run" msgid "No" msgstr "No" -#: screens/Job/JobOutput/JobOutputSearch.js:122 +#: screens/Job/JobOutput/JobOutputSearch.js:121 msgid "No Hosts Matched" msgstr "No Hosts Matched" +#: screens/Job/JobOutput/JobOutputSearch.js:122 #: screens/Job/JobOutput/JobOutputSearch.js:123 -#: screens/Job/JobOutput/JobOutputSearch.js:124 msgid "No Hosts Remaining" msgstr "No Hosts Remaining" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "No JSON Available" @@ -5842,17 +6226,17 @@ msgstr "No items found." msgid "No job data available" msgstr "No job data available" -#: screens/Job/JobOutput/EmptyOutput.js:25 +#: screens/Job/JobOutput/EmptyOutput.js:52 msgid "No output found for this job." msgstr "No output found for this job." -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "No result found" -#: components/LabelSelect/LabelSelect.js:102 -#: components/LaunchPrompt/steps/SurveyStep.js:134 -#: components/LaunchPrompt/steps/SurveyStep.js:193 +#: components/LabelSelect/LabelSelect.js:130 +#: components/LaunchPrompt/steps/SurveyStep.js:136 +#: components/LaunchPrompt/steps/SurveyStep.js:195 #: components/MultiSelect/TagMultiSelect.js:60 #: components/Search/AdvancedSearch.js:151 #: components/Search/AdvancedSearch.js:266 @@ -5865,10 +6249,10 @@ msgstr "No result found" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "No results found" @@ -5881,6 +6265,10 @@ msgstr "No subscriptions found" msgid "No survey questions found." msgstr "No survey questions found." +#: screens/Job/JobDetail/JobDetail.js:399 +msgid "No timeout specified" +msgstr "No timeout specified" + #: components/PaginatedTable/PaginatedTable.js:80 msgid "No {pluralizedItemName} Found" msgstr "No {pluralizedItemName} Found" @@ -5892,36 +6280,47 @@ msgstr "No {pluralizedItemName} Found" msgid "Node Alias" msgstr "Node Alias" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:216 -#: screens/InstanceGroup/Instances/InstanceList.js:193 -#: screens/InstanceGroup/Instances/InstanceList.js:257 -#: screens/InstanceGroup/Instances/InstanceList.js:289 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:154 -#: screens/Instances/InstanceList/InstanceList.js:113 -#: screens/Instances/InstanceList/InstanceList.js:152 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 +#: screens/Instances/InstancePeers/InstancePeerList.js:98 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 msgid "Node Type" msgstr "Node Type" +#: screens/TopologyView/Legend.js:107 +msgid "Node state types" +msgstr "Node state types" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/useNodeTypeStep.js:75 msgid "Node type" msgstr "Node type" -#: screens/TopologyView/Legend.js:68 +#: screens/TopologyView/Legend.js:70 msgid "Node types" msgstr "Node types" +#: components/Schedule/shared/ScheduleFormFields.js:180 +#: components/Schedule/shared/ScheduleFormFields.js:184 #: components/Workflow/WorkflowNodeHelp.js:123 msgid "None" msgstr "None" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:136 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "None (Run Once)" -#: components/Schedule/shared/ScheduleForm.js:153 +#: components/Schedule/shared/ScheduleFormFields.js:120 +#: components/Schedule/shared/ScheduleFormFields.js:124 msgid "None (run once)" msgstr "None (run once)" @@ -5995,7 +6394,7 @@ msgstr "" "read only protocol (git://) does not use username or\n" "password information." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:326 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:331 msgid "Notification Color" msgstr "Notification Color" @@ -6009,15 +6408,15 @@ msgstr "Notification Template not found." #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:171 #: screens/NotificationTemplate/NotificationTemplates.js:14 #: screens/NotificationTemplate/NotificationTemplates.js:21 -#: util/getRelatedResourceDeleteDetails.js:180 +#: util/getRelatedResourceDeleteDetails.js:181 msgid "Notification Templates" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:133 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:134 msgid "Notification Type" msgstr "Notification Type" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:369 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:380 msgid "Notification color" msgstr "Notification color" @@ -6025,7 +6424,7 @@ msgstr "Notification color" msgid "Notification sent successfully" msgstr "Notification sent successfully" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:449 msgid "Notification test failed." msgstr "Notification test failed." @@ -6054,11 +6453,12 @@ msgstr "Notification type" msgid "Notifications" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:163 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:169 +#: components/Schedule/shared/FrequencyDetailSubform.js:148 msgid "November" msgstr "November" -#: components/StatusLabel/StatusLabel.js:36 +#: components/StatusLabel/StatusLabel.js:44 #: components/Workflow/WorkflowNodeHelp.js:117 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:35 @@ -6066,43 +6466,44 @@ msgid "OK" msgstr "OK" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:42 -#: components/Schedule/shared/FrequencyDetailSubform.js:542 +#: components/Schedule/shared/FrequencyDetailSubform.js:549 msgid "Occurrences" msgstr "Occurrences" -#: components/Schedule/shared/FrequencyDetailSubform.js:158 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:168 +#: components/Schedule/shared/FrequencyDetailSubform.js:143 msgid "October" msgstr "October" #: components/AdHocCommands/AdHocDetailsStep.js:189 #: components/HostToggle/HostToggle.js:61 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:164 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:167 -#: components/PromptDetail/PromptDetail.js:284 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:318 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:192 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:195 +#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 -#: screens/Template/shared/JobTemplateForm.js:455 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 +#: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "Off" #: components/AdHocCommands/AdHocDetailsStep.js:188 #: components/HostToggle/HostToggle.js:60 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:164 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:166 -#: components/PromptDetail/PromptDetail.js:284 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:318 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:192 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:194 +#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 -#: screens/Template/shared/JobTemplateForm.js:455 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 +#: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "On" @@ -6120,11 +6521,12 @@ msgstr "On Failure" msgid "On Success" msgstr "On Success" -#: components/Schedule/shared/FrequencyDetailSubform.js:529 +#: components/Schedule/shared/FrequencyDetailSubform.js:536 msgid "On date" msgstr "On date" -#: components/Schedule/shared/FrequencyDetailSubform.js:244 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:99 +#: components/Schedule/shared/FrequencyDetailSubform.js:251 msgid "On days" msgstr "On days" @@ -6136,7 +6538,7 @@ msgstr "" "One Slack channel per line. The pound symbol (#)\n" "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" -#: components/PromptDetail/PromptInventorySourceDetail.js:166 +#: components/PromptDetail/PromptInventorySourceDetail.js:154 msgid "Only Group By" msgstr "Only Group By" @@ -6144,7 +6546,7 @@ msgstr "Only Group By" msgid "OpenStack" msgstr "OpenStack" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:107 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:111 msgid "Option Details" msgstr "Option Details" @@ -6159,21 +6561,31 @@ msgstr "" "inventories and completed jobs." #: screens/Template/shared/WorkflowJobTemplate.helptext.js:11 -msgid "" -"Optional labels that describe this job template,\n" -"such as 'dev' or 'test'. Labels can be used to group and filter\n" -"job templates and completed jobs." -msgstr "" -"Optional labels that describe this job template,\n" -"such as 'dev' or 'test'. Labels can be used to group and filter\n" -"job templates and completed jobs." +#~ msgid "" +#~ "Optional labels that describe this job template,\n" +#~ "such as 'dev' or 'test'. Labels can be used to group and filter\n" +#~ "job templates and completed jobs." +#~ msgstr "" +#~ "Optional labels that describe this job template,\n" +#~ "such as 'dev' or 'test'. Labels can be used to group and filter\n" +#~ "job templates and completed jobs." -#: screens/Job/Job.helptext.js:11 -#: screens/Template/shared/JobTemplate.helptext.js:12 +#: screens/Job/Job.helptext.js:12 +#: screens/Template/shared/JobTemplate.helptext.js:13 msgid "Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs." msgstr "Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs." -#: screens/Template/shared/JobTemplate.helptext.js:25 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:11 +msgid "" +"Optional labels that describe this workflow job template,\n" +"such as 'dev' or 'test'. Labels can be used to group and filter\n" +"workflow job templates and completed jobs." +msgstr "" +"Optional labels that describe this workflow job template,\n" +"such as 'dev' or 'test'. Labels can be used to group and filter\n" +"workflow job templates and completed jobs." + +#: screens/Template/shared/JobTemplate.helptext.js:26 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:19 msgid "Optionally select the credential to use to send status updates back to the webhook service." msgstr "Optionally select the credential to use to send status updates back to the webhook service." @@ -6181,10 +6593,12 @@ msgstr "Optionally select the credential to use to send status updates back to t #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:65 -#: screens/Template/shared/JobTemplateForm.js:493 -#: screens/Template/shared/WorkflowJobTemplateForm.js:210 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 +#: screens/Instances/Shared/InstanceForm.js:54 +#: screens/Inventory/shared/InventoryForm.js:94 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:69 +#: screens/Template/shared/JobTemplateForm.js:545 +#: screens/Template/shared/WorkflowJobTemplateForm.js:241 msgid "Options" msgstr "Options" @@ -6194,44 +6608,44 @@ msgstr "Options" msgid "Order" msgstr "Order" -#: components/Lookup/ApplicationLookup.js:118 +#: components/Lookup/ApplicationLookup.js:119 #: components/Lookup/OrganizationLookup.js:101 #: components/Lookup/OrganizationLookup.js:107 -#: components/Lookup/OrganizationLookup.js:123 -#: components/PromptDetail/PromptInventorySourceDetail.js:73 -#: components/PromptDetail/PromptInventorySourceDetail.js:83 -#: components/PromptDetail/PromptJobTemplateDetail.js:103 -#: components/PromptDetail/PromptJobTemplateDetail.js:113 +#: components/Lookup/OrganizationLookup.js:124 +#: components/PromptDetail/PromptInventorySourceDetail.js:62 +#: components/PromptDetail/PromptInventorySourceDetail.js:72 +#: components/PromptDetail/PromptJobTemplateDetail.js:105 +#: components/PromptDetail/PromptJobTemplateDetail.js:115 #: components/PromptDetail/PromptProjectDetail.js:77 #: components/PromptDetail/PromptProjectDetail.js:88 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:65 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:67 #: components/TemplateList/TemplateList.js:244 #: components/TemplateList/TemplateListItem.js:185 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:69 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:70 #: screens/Application/ApplicationsList/ApplicationListItem.js:38 #: screens/Application/ApplicationsList/ApplicationsList.js:157 #: screens/Credential/CredentialDetail/CredentialDetail.js:230 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:69 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:70 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:74 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:108 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:120 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:130 -#: screens/Project/ProjectDetail/ProjectDetail.js:179 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 +#: screens/Project/ProjectDetail/ProjectDetail.js:180 #: screens/Project/ProjectList/ProjectListItem.js:287 #: screens/Project/ProjectList/ProjectListItem.js:298 #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:203 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:121 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 #: screens/User/UserTeams/UserTeamListItem.js:23 @@ -6260,52 +6674,52 @@ msgstr "Organization not found." #: screens/User/User.js:66 #: screens/User/UserOrganizations/UserOrganizationList.js:72 #: screens/User/Users.js:33 -#: util/getRelatedResourceDeleteDetails.js:231 -#: util/getRelatedResourceDeleteDetails.js:265 +#: util/getRelatedResourceDeleteDetails.js:232 +#: util/getRelatedResourceDeleteDetails.js:266 msgid "Organizations" msgstr "" -#: components/LaunchPrompt/steps/useOtherPromptsStep.js:85 +#: components/LaunchPrompt/steps/useOtherPromptsStep.js:90 msgid "Other prompts" msgstr "Other prompts" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:57 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:79 msgid "Out of compliance" msgstr "Out of compliance" -#: screens/Job/Job.js:118 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/Job.js:131 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "Output" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "Output tab" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:76 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:80 msgid "Overwrite" msgstr "Overwrite" -#: components/PromptDetail/PromptInventorySourceDetail.js:47 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:126 +#: components/PromptDetail/PromptInventorySourceDetail.js:41 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "Overwrite local groups and hosts from remote inventory source" -#: components/PromptDetail/PromptInventorySourceDetail.js:52 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:132 +#: components/PromptDetail/PromptInventorySourceDetail.js:46 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "Overwrite local variables from remote inventory source" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:82 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:86 msgid "Overwrite variables" msgstr "Overwrite variables" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:478 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:493 msgid "POST" msgstr "POST" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:479 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:494 msgid "PUT" msgstr "PUT" @@ -6314,11 +6728,11 @@ msgstr "PUT" msgid "Pagerduty" msgstr "Pagerduty" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:274 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:279 msgid "Pagerduty Subdomain" msgstr "Pagerduty Subdomain" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:289 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:298 msgid "Pagerduty subdomain" msgstr "Pagerduty subdomain" @@ -6358,17 +6772,17 @@ msgstr "Pass extra command line changes. There are two ansible command line para #~ "Provide key/value pairs using either YAML or JSON. Refer to the\n" #~ "documentation for example syntax." -#: screens/Template/shared/WorkflowJobTemplateForm.js:215 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the Ansible Controller documentation for example syntax." msgstr "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the Ansible Controller documentation for example syntax." -#: screens/Job/Job.helptext.js:12 -#: screens/Template/shared/JobTemplate.helptext.js:13 +#: screens/Job/Job.helptext.js:13 +#: screens/Template/shared/JobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the documentation for example syntax." msgstr "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the documentation for example syntax." -#: screens/Login/Login.js:205 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:71 +#: screens/Login/Login.js:227 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:73 #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:101 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:212 #: screens/Template/Survey/SurveyQuestionForm.js:82 @@ -6392,13 +6806,18 @@ msgstr "Past two weeks" msgid "Past week" msgstr "Past week" +#: screens/Instances/Instance.js:51 +#: screens/Instances/InstancePeers/InstancePeerList.js:74 +msgid "Peers" +msgstr "Peers" + #: components/JobList/JobList.js:228 -#: components/StatusLabel/StatusLabel.js:41 +#: components/StatusLabel/StatusLabel.js:49 #: components/Workflow/WorkflowNodeHelp.js:93 msgid "Pending" msgstr "Pending" -#: components/AppContainer/PageHeaderToolbar.js:83 +#: components/AppContainer/PageHeaderToolbar.js:76 msgid "Pending Workflow Approvals" msgstr "Pending Workflow Approvals" @@ -6406,11 +6825,11 @@ msgstr "Pending Workflow Approvals" msgid "Pending delete" msgstr "Pending delete" -#: components/Lookup/HostFilterLookup.js:369 +#: components/Lookup/HostFilterLookup.js:370 msgid "Perform a search to define a host filter" msgstr "Perform a search to define a host filter" -#: screens/User/UserTokenDetail/UserTokenDetail.js:72 +#: screens/User/UserTokenDetail/UserTokenDetail.js:73 #: screens/User/UserTokenList/UserTokenList.js:105 msgid "Personal Access Token" msgstr "Personal Access Token" @@ -6419,57 +6838,57 @@ msgstr "Personal Access Token" msgid "Personal access token" msgstr "Personal access token" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "Play" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "Play Count" -#: screens/Job/JobOutput/JobOutputSearch.js:125 +#: screens/Job/JobOutput/JobOutputSearch.js:124 msgid "Play Started" msgstr "Play Started" -#: components/PromptDetail/PromptJobTemplateDetail.js:146 -#: screens/Job/JobDetail/JobDetail.js:314 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:246 +#: components/PromptDetail/PromptJobTemplateDetail.js:148 +#: screens/Job/JobDetail/JobDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 -#: screens/Template/shared/JobTemplateForm.js:350 +#: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" msgstr "Playbook" #: components/JobList/JobListItem.js:44 -#: screens/Job/JobDetail/JobDetail.js:66 +#: screens/Job/JobDetail/JobDetail.js:67 msgid "Playbook Check" msgstr "Playbook Check" -#: screens/Job/JobOutput/JobOutputSearch.js:126 +#: screens/Job/JobOutput/JobOutputSearch.js:125 msgid "Playbook Complete" msgstr "Playbook Complete" -#: components/PromptDetail/PromptProjectDetail.js:150 -#: screens/Project/ProjectDetail/ProjectDetail.js:270 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:71 +#: components/PromptDetail/PromptProjectDetail.js:165 +#: screens/Project/ProjectDetail/ProjectDetail.js:288 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:72 msgid "Playbook Directory" msgstr "Playbook Directory" #: components/JobList/JobList.js:213 #: components/JobList/JobListItem.js:44 #: components/Schedule/ScheduleList/ScheduleListItem.js:37 -#: screens/Job/JobDetail/JobDetail.js:66 +#: screens/Job/JobDetail/JobDetail.js:67 msgid "Playbook Run" msgstr "Playbook Run" -#: screens/Job/JobOutput/JobOutputSearch.js:127 +#: screens/Job/JobOutput/JobOutputSearch.js:126 msgid "Playbook Started" msgstr "Playbook Started" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:159 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:157 msgid "Playbook name" msgstr "Playbook name" @@ -6477,7 +6896,7 @@ msgstr "Playbook name" msgid "Playbook run" msgstr "Playbook run" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "Plays" @@ -6501,6 +6920,10 @@ msgstr "Please add {pluralizedItemName} to populate this list" msgid "Please click the Start button to begin." msgstr "Please click the Start button to begin." +#: components/Schedule/shared/ScheduleForm.js:414 +msgid "Please enter a number of occurrences." +msgstr "Please enter a number of occurrences." + #: util/validators.js:160 msgid "Please enter a valid URL" msgstr "Please enter a valid URL" @@ -6509,7 +6932,7 @@ msgstr "Please enter a valid URL" msgid "Please enter a value." msgstr "Please enter a value." -#: screens/Login/Login.js:169 +#: screens/Login/Login.js:191 msgid "Please log in" msgstr "Please log in" @@ -6517,23 +6940,23 @@ msgstr "Please log in" msgid "Please run a job to populate this list." msgstr "Please run a job to populate this list." -#: components/Schedule/shared/ScheduleForm.js:622 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "Please select a day number between 1 and 31." -#: screens/Template/shared/JobTemplateForm.js:170 +#: screens/Template/shared/JobTemplateForm.js:174 msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "Please select an Inventory or check the Prompt on Launch option" -#: components/Schedule/shared/ScheduleForm.js:614 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "Please select an end date/time that comes after the start date/time." -#: components/Lookup/HostFilterLookup.js:358 +#: components/Lookup/HostFilterLookup.js:359 msgid "Please select an organization before editing the host filter" msgstr "Please select an organization before editing the host filter" -#: screens/Job/JobOutput/EmptyOutput.js:20 +#: screens/Job/JobOutput/EmptyOutput.js:32 msgid "Please try another search using the filter above" msgstr "Please try another search using the filter above" @@ -6541,14 +6964,16 @@ msgstr "Please try another search using the filter above" msgid "Please wait until the topology view is populated..." msgstr "Please wait until the topology view is populated..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Pod spec override" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:207 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:158 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "Policy Type" @@ -6581,7 +7006,7 @@ msgstr "Populate field from an external secret management system" #~ "examples. Refer to the Ansible Tower documentation for further syntax and\n" #~ "examples." -#: components/Lookup/HostFilterLookup.js:348 +#: components/Lookup/HostFilterLookup.js:349 msgid "" "Populate the hosts for this inventory by using a search\n" "filter. Example: ansible_facts__ansible_distribution:\"RedHat\".\n" @@ -6595,8 +7020,8 @@ msgstr "" "examples. Refer to the Ansible Controller documentation for further syntax and\n" "examples." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:164 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:102 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:165 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:104 msgid "Port" msgstr "Port" @@ -6628,6 +7053,23 @@ msgstr "" "Press enter to confirm the drag, or any other key to\n" "cancel the drag operation." +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 +#: screens/Inventory/shared/InventoryForm.js:99 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 +#: screens/Template/shared/JobTemplateForm.js:603 +msgid "Prevent Instance Group Fallback" +msgstr "Prevent Instance Group Fallback" + +#: screens/Inventory/shared/Inventory.helptext.js:198 +msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." +msgstr "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." + +#: screens/Template/shared/JobTemplate.helptext.js:43 +msgid "Prevent Instance Group Fallback: If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on." +msgstr "Prevent Instance Group Fallback: If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on." + #: components/AdHocCommands/useAdHocPreviewStep.js:17 #: components/LaunchPrompt/steps/usePreviewStep.js:23 msgid "Preview" @@ -6638,8 +7080,8 @@ msgid "Private key passphrase" msgstr "Private key passphrase" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:120 -#: screens/Template/shared/JobTemplateForm.js:499 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 +#: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "Privilege Escalation" @@ -6647,30 +7089,30 @@ msgstr "Privilege Escalation" msgid "Privilege escalation password" msgstr "Privilege escalation password" -#: screens/Template/shared/JobTemplate.helptext.js:37 +#: screens/Template/shared/JobTemplate.helptext.js:40 msgid "Privilege escalation: If enabled, run this playbook as an administrator." msgstr "Privilege escalation: If enabled, run this playbook as an administrator." #: components/JobList/JobListItem.js:239 #: components/Lookup/ProjectLookup.js:104 #: components/Lookup/ProjectLookup.js:109 -#: components/Lookup/ProjectLookup.js:165 -#: components/PromptDetail/PromptInventorySourceDetail.js:98 -#: components/PromptDetail/PromptJobTemplateDetail.js:131 -#: components/PromptDetail/PromptJobTemplateDetail.js:139 -#: components/TemplateList/TemplateListItem.js:299 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:231 -#: screens/Job/JobDetail/JobDetail.js:158 -#: screens/Job/JobDetail/JobDetail.js:176 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:222 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:232 +#: components/Lookup/ProjectLookup.js:166 +#: components/PromptDetail/PromptInventorySourceDetail.js:87 +#: components/PromptDetail/PromptJobTemplateDetail.js:133 +#: components/PromptDetail/PromptJobTemplateDetail.js:141 +#: components/TemplateList/TemplateListItem.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 +#: screens/Job/JobDetail/JobDetail.js:172 +#: screens/Job/JobDetail/JobDetail.js:198 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "Project" -#: components/PromptDetail/PromptProjectDetail.js:143 -#: screens/Project/ProjectDetail/ProjectDetail.js:263 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:60 +#: components/PromptDetail/PromptProjectDetail.js:158 +#: screens/Project/ProjectDetail/ProjectDetail.js:281 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:61 msgid "Project Base Path" msgstr "Project Base Path" @@ -6683,7 +7125,7 @@ msgstr "Project Base Path" msgid "Project Sync" msgstr "Project Sync" -#: screens/Project/ProjectDetail/ProjectDetail.js:302 +#: screens/Project/ProjectDetail/ProjectDetail.js:320 #: screens/Project/ProjectList/ProjectListItem.js:229 msgid "Project Sync Error" msgstr "Project Sync Error" @@ -6692,11 +7134,11 @@ msgstr "Project Sync Error" msgid "Project Update" msgstr "Project Update" -#: screens/Job/JobDetail/JobDetail.js:164 +#: screens/Job/JobDetail/JobDetail.js:180 msgid "Project Update Status" msgstr "Project Update Status" -#: screens/Job/Job.helptext.js:21 +#: screens/Job/Job.helptext.js:22 msgid "Project checkout results" msgstr "Project checkout results" @@ -6708,21 +7150,21 @@ msgstr "Project copied successfully" msgid "Project not found." msgstr "Project not found." -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "Project sync failures" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 #: screens/Project/Projects.js:22 -#: util/getRelatedResourceDeleteDetails.js:59 -#: util/getRelatedResourceDeleteDetails.js:194 -#: util/getRelatedResourceDeleteDetails.js:224 +#: util/getRelatedResourceDeleteDetails.js:60 +#: util/getRelatedResourceDeleteDetails.js:195 +#: util/getRelatedResourceDeleteDetails.js:225 msgid "Projects" msgstr "" @@ -6730,12 +7172,12 @@ msgstr "" msgid "Promote Child Groups and Hosts" msgstr "Promote Child Groups and Hosts" -#: components/Schedule/shared/ScheduleForm.js:670 -#: components/Schedule/shared/ScheduleForm.js:673 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "Prompt" -#: components/PromptDetail/PromptDetail.js:173 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "Prompt Overrides" @@ -6745,12 +7187,12 @@ msgstr "Prompt Overrides" msgid "Prompt on launch" msgstr "Prompt on launch" -#: components/Schedule/shared/SchedulePromptableFields.js:104 +#: components/Schedule/shared/SchedulePromptableFields.js:97 msgid "Prompt | {0}" msgstr "Prompt | {0}" -#: components/PromptDetail/PromptDetail.js:171 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:282 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "Prompted Values" @@ -6767,19 +7209,19 @@ msgstr "" "documentation for more information and examples on patterns." #: components/LaunchPrompt/steps/OtherPromptsStep.js:37 -msgid "" -"Provide a host pattern to further constrain the list\n" -"of hosts that will be managed or affected by the playbook. Multiple\n" -"patterns are allowed. Refer to Ansible documentation for more\n" -"information and examples on patterns." -msgstr "" -"Provide a host pattern to further constrain the list\n" -"of hosts that will be managed or affected by the playbook. Multiple\n" -"patterns are allowed. Refer to Ansible documentation for more\n" -"information and examples on patterns." +#~ msgid "" +#~ "Provide a host pattern to further constrain the list\n" +#~ "of hosts that will be managed or affected by the playbook. Multiple\n" +#~ "patterns are allowed. Refer to Ansible documentation for more\n" +#~ "information and examples on patterns." +#~ msgstr "" +#~ "Provide a host pattern to further constrain the list\n" +#~ "of hosts that will be managed or affected by the playbook. Multiple\n" +#~ "patterns are allowed. Refer to Ansible documentation for more\n" +#~ "information and examples on patterns." -#: screens/Job/Job.helptext.js:13 -#: screens/Template/shared/JobTemplate.helptext.js:14 +#: screens/Job/Job.helptext.js:14 +#: screens/Template/shared/JobTemplate.helptext.js:15 msgid "Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns are allowed. Refer to Ansible documentation for more information and examples on patterns." msgstr "Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns are allowed. Refer to Ansible documentation for more information and examples on patterns." @@ -6815,29 +7257,38 @@ msgstr "Provide your Red Hat or Red Hat Satellite credentials to enable Automati #~ msgid "Provide your Red Hat or Red Hat Satellite credentials to enable Insights for Ansible Automation Platform." #~ msgstr "Provide your Red Hat or Red Hat Satellite credentials to enable Insights for Ansible Automation Platform." -#: components/PromptDetail/PromptJobTemplateDetail.js:157 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:295 -#: screens/Template/shared/JobTemplateForm.js:562 +#: components/StatusLabel/StatusLabel.js:59 +#: screens/TopologyView/Legend.js:150 +msgid "Provisioning" +msgstr "Provisioning" + +#: components/PromptDetail/PromptJobTemplateDetail.js:162 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 +#: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "Provisioning Callback URL" -#: screens/Template/shared/JobTemplateForm.js:557 +#: screens/Template/shared/JobTemplateForm.js:615 msgid "Provisioning Callback details" msgstr "Provisioning Callback details" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:125 -#: screens/Template/shared/JobTemplateForm.js:503 -#: screens/Template/shared/JobTemplateForm.js:506 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 +#: screens/Template/shared/JobTemplateForm.js:555 +#: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" msgstr "Provisioning Callbacks" -#: screens/Template/shared/JobTemplate.helptext.js:38 +#: screens/Template/shared/JobTemplate.helptext.js:41 msgid "Provisioning callbacks: Enables creation of a provisioning callback URL. Using the URL a host can contact Ansible AWX and request a configuration update using this job template." msgstr "Provisioning callbacks: Enables creation of a provisioning callback URL. Using the URL a host can contact Ansible AWX and request a configuration update using this job template." -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:85 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:113 +#: components/StatusLabel/StatusLabel.js:62 +msgid "Provisioning fail" +msgstr "Provisioning fail" + +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:86 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:114 msgid "Pull" msgstr "Pull" @@ -6845,7 +7296,7 @@ msgstr "Pull" msgid "Question" msgstr "Question" -#: screens/Setting/Settings.js:102 +#: screens/Setting/Settings.js:106 msgid "RADIUS" msgstr "RADIUS" @@ -6853,10 +7304,12 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "RADIUS settings" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:187 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 +#: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6864,33 +7317,38 @@ msgstr "RAM {0}" msgid "Read" msgstr "Read" -#: screens/Dashboard/Dashboard.js:133 +#: components/StatusLabel/StatusLabel.js:57 +#: screens/TopologyView/Legend.js:122 +msgid "Ready" +msgstr "Ready" + +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "Recent Jobs" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "Recent Jobs list tab" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "Recent Templates" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "Recent Templates list tab" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" msgstr "Recent jobs" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:153 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:154 msgid "Recipient List" msgstr "Recipient List" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:84 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:86 msgid "Recipient list" msgstr "Recipient list" @@ -6898,10 +7356,10 @@ msgstr "Recipient list" msgid "Red Hat Ansible Automation Platform" msgstr "Red Hat Ansible Automation Platform" -#: components/Lookup/ProjectLookup.js:138 +#: components/Lookup/ProjectLookup.js:139 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161 -#: screens/Job/JobDetail/JobDetail.js:76 +#: screens/Job/JobDetail/JobDetail.js:77 #: screens/Project/ProjectList/ProjectList.js:201 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:100 msgid "Red Hat Insights" @@ -6923,8 +7381,8 @@ msgstr "Red Hat subscription manifest" msgid "Red Hat, Inc." msgstr "Red Hat, Inc." -#: screens/Application/ApplicationDetails/ApplicationDetails.js:93 -#: screens/Application/shared/ApplicationForm.js:106 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:94 +#: screens/Application/shared/ApplicationForm.js:107 msgid "Redirect URIs" msgstr "Redirect URIs" @@ -6941,6 +7399,7 @@ msgid "Redirecting to subscription detail" msgstr "Redirecting to subscription detail" #: screens/Template/Survey/SurveyQuestionForm.js:261 +#: screens/Template/shared/JobTemplate.helptext.js:55 msgid "Refer to the" msgstr "Refer to the" @@ -6952,8 +7411,8 @@ msgstr "Refer to the" #~ "Refer to the Ansible documentation for details\n" #~ "about the configuration file." -#: screens/Job/Job.helptext.js:26 -#: screens/Template/shared/JobTemplate.helptext.js:46 +#: screens/Job/Job.helptext.js:27 +#: screens/Template/shared/JobTemplate.helptext.js:50 msgid "Refer to the Ansible documentation for details about the configuration file." msgstr "Refer to the Ansible documentation for details about the configuration file." @@ -6973,21 +7432,24 @@ msgstr "Refresh for revision" msgid "Refresh project revision" msgstr "Refresh project revision" -#: components/PromptDetail/PromptInventorySourceDetail.js:128 +#: components/PromptDetail/PromptInventorySourceDetail.js:116 msgid "Regions" msgstr "Regions" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:91 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:142 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:92 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:143 msgid "Registry credential" msgstr "Registry credential" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "Related Groups" @@ -6996,6 +7458,11 @@ msgstr "Related Groups" msgid "Related Keys" msgstr "Related Keys" +#: components/Schedule/ScheduleList/ScheduleList.js:169 +#: components/Schedule/ScheduleList/ScheduleListItem.js:105 +msgid "Related resource" +msgstr "Related resource" + #: components/Search/RelatedLookupTypeInput.js:16 #: components/Search/RelatedLookupTypeInput.js:24 msgid "Related search type" @@ -7007,14 +7474,14 @@ msgstr "Related search type typeahead" #: components/JobList/JobListItem.js:146 #: components/LaunchButton/ReLaunchDropDown.js:82 -#: screens/Job/JobDetail/JobDetail.js:562 -#: screens/Job/JobDetail/JobDetail.js:570 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobDetail/JobDetail.js:580 +#: screens/Job/JobDetail/JobDetail.js:588 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "Relaunch" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "Relaunch Job" @@ -7032,20 +7499,37 @@ msgid "Relaunch on" msgstr "Relaunch on" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "Relaunch using host parameters" -#: components/Lookup/ProjectLookup.js:137 +#: components/HealthCheckAlert/HealthCheckAlert.js:27 +msgid "Reload" +msgstr "Reload" + +#: screens/Job/JobOutput/JobOutput.js:735 +msgid "Reload output" +msgstr "Reload output" + +#: components/Lookup/ProjectLookup.js:138 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:91 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:160 -#: screens/Job/JobDetail/JobDetail.js:77 +#: screens/Job/JobDetail/JobDetail.js:78 #: screens/Project/ProjectList/ProjectList.js:200 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:99 msgid "Remote Archive" msgstr "Remote Archive" +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 +msgid "Removal Error" +msgstr "Removal Error" + #: components/SelectedList/DraggableSelectedList.js:105 +#: screens/Instances/Shared/RemoveInstanceButton.js:75 +#: screens/Instances/Shared/RemoveInstanceButton.js:129 +#: screens/Instances/Shared/RemoveInstanceButton.js:143 +#: screens/Instances/Shared/RemoveInstanceButton.js:163 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/DeleteAllNodesModal.js:21 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:29 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeDeleteModal.js:40 @@ -7056,6 +7540,10 @@ msgstr "Remove" msgid "Remove All Nodes" msgstr "Remove All Nodes" +#: screens/Instances/Shared/RemoveInstanceButton.js:152 +msgid "Remove Instances" +msgstr "Remove Instances" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:17 msgid "Remove Link" msgstr "Remove Link" @@ -7068,7 +7556,7 @@ msgstr "Remove Link" msgid "Remove Node {nodeName}" msgstr "Remove Node {nodeName}" -#: screens/Project/shared/Project.helptext.js:109 +#: screens/Project/shared/Project.helptext.js:113 msgid "Remove any local modifications prior to performing an update." msgstr "Remove any local modifications prior to performing an update." @@ -7084,6 +7572,10 @@ msgstr "" msgid "Remove {0} chip" msgstr "Remove {0} chip" +#: screens/TopologyView/Legend.js:285 +msgid "Removing" +msgstr "Removing" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:48 msgid "Removing this link will orphan the rest of the branch and cause it to be executed immediately on launch." msgstr "Removing this link will orphan the rest of the branch and cause it to be executed immediately on launch." @@ -7092,10 +7584,14 @@ msgstr "Removing this link will orphan the rest of the branch and cause it to be msgid "Reorder" msgstr "Reorder" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:264 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "Repeat Frequency" +#: components/Schedule/shared/ScheduleFormFields.js:113 +msgid "Repeat frequency" +msgstr "Repeat frequency" + #: screens/Credential/shared/CredentialFormFields/CredentialField.js:52 msgid "Replace" msgstr "Replace" @@ -7126,10 +7622,15 @@ msgstr "Reset zoom" msgid "Resource Name" msgstr "Resource Name" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:227 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:246 msgid "Resource deleted" msgstr "Resource deleted" +#: components/Schedule/ScheduleList/ScheduleList.js:170 +#: components/Schedule/ScheduleList/ScheduleListItem.js:111 +msgid "Resource type" +msgstr "Resource type" + #: routeConfig.js:61 #: screens/ActivityStream/ActivityStream.js:159 msgid "Resources" @@ -7151,15 +7652,19 @@ msgstr "" "Retrieve the enabled state from the given dict of host variables.\n" "The enabled variable may be specified using dot notation, e.g: 'foo.bar'" -#: components/JobCancelButton/JobCancelButton.js:81 -#: components/JobCancelButton/JobCancelButton.js:85 +#: components/JobCancelButton/JobCancelButton.js:96 +#: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:764 -#: screens/Job/JobOutput/JobOutput.js:767 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "Return" +#: screens/Job/JobOutput/EmptyOutput.js:40 +msgid "Return to" +msgstr "Return to" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:129 msgid "Return to subscription management." msgstr "Return to subscription management." @@ -7203,13 +7708,13 @@ msgstr "Revert settings" msgid "Revert to factory default." msgstr "Revert to factory default." -#: screens/Job/JobDetail/JobDetail.js:309 +#: screens/Job/JobDetail/JobDetail.js:314 #: screens/Project/ProjectList/ProjectList.js:224 #: screens/Project/ProjectList/ProjectListItem.js:221 msgid "Revision" msgstr "Revision" -#: screens/Project/shared/ProjectSubForms/SvnSubForm.js:20 +#: screens/Project/shared/ProjectSubForms/SvnSubForm.js:22 msgid "Revision #" msgstr "Revision #" @@ -7240,12 +7745,12 @@ msgstr "Role" msgid "Roles" msgstr "Roles" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:99 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:134 #: components/Workflow/WorkflowLinkHelp.js:39 #: screens/Credential/shared/ExternalTestModal.js:89 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:49 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:23 -#: screens/Template/shared/JobTemplateForm.js:210 +#: screens/Template/shared/JobTemplateForm.js:214 msgid "Run" msgstr "Run" @@ -7253,12 +7758,13 @@ msgstr "Run" #: components/AdHocCommands/AdHocCommands.js:135 #: components/AdHocCommands/AdHocCommands.js:141 #: components/AdHocCommands/AdHocCommands.js:145 -#: screens/Job/JobDetail/JobDetail.js:67 +#: screens/Job/JobDetail/JobDetail.js:68 msgid "Run Command" msgstr "Run Command" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:225 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "Run a health check on the instance" @@ -7266,26 +7772,32 @@ msgstr "Run a health check on the instance" msgid "Run ad hoc command" msgstr "Run ad hoc command" -#: components/AdHocCommands/AdHocCommandsWizard.js:49 +#: components/AdHocCommands/AdHocCommandsWizard.js:48 msgid "Run command" msgstr "Run command" -#: components/Schedule/shared/FrequencyDetailSubform.js:216 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:93 +#: components/Schedule/shared/FrequencyDetailSubform.js:223 msgid "Run every" msgstr "Run every" #: components/Schedule/shared/ScheduleForm.js:148 -msgid "Run frequency" -msgstr "Run frequency" +#~ msgid "Run frequency" +#~ msgstr "Run frequency" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 -#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "Run health check" -#: components/Schedule/shared/FrequencyDetailSubform.js:337 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:129 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:138 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:175 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:197 +#: components/Schedule/shared/FrequencyDetailSubform.js:344 msgid "Run on" msgstr "Run on" @@ -7294,26 +7806,36 @@ msgid "Run type" msgstr "Run type" #: components/JobList/JobList.js:230 -#: components/StatusLabel/StatusLabel.js:40 +#: components/StatusLabel/StatusLabel.js:48 #: components/TemplateList/TemplateListItem.js:118 #: components/Workflow/WorkflowNodeHelp.js:99 msgid "Running" msgstr "Running" -#: screens/Job/JobOutput/JobOutputSearch.js:128 +#: screens/Job/JobOutput/JobOutputSearch.js:127 msgid "Running Handlers" msgstr "Running Handlers" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:210 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:161 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "Running Jobs" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:232 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "Running health check" @@ -7321,7 +7843,7 @@ msgstr "Running health check" msgid "Running jobs" msgstr "Running jobs" -#: screens/Setting/Settings.js:105 +#: screens/Setting/Settings.js:109 msgid "SAML" msgstr "SAML" @@ -7342,29 +7864,31 @@ msgstr "SOCIAL" msgid "SSH password" msgstr "SSH password" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:234 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:239 msgid "SSL Connection" msgstr "SSL Connection" #: components/Workflow/WorkflowStartNode.js:60 -#: components/Workflow/workflowReducer.js:413 +#: components/Workflow/workflowReducer.js:419 msgid "START" msgstr "START" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:175 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 msgid "STATUS:" msgstr "STATUS:" -#: components/Schedule/shared/FrequencyDetailSubform.js:314 +#: components/Schedule/shared/FrequencyDetailSubform.js:321 msgid "Sat" msgstr "Sat" -#: components/Schedule/shared/FrequencyDetailSubform.js:319 -#: components/Schedule/shared/FrequencyDetailSubform.js:451 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:82 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:188 +#: components/Schedule/shared/FrequencyDetailSubform.js:326 +#: components/Schedule/shared/FrequencyDetailSubform.js:458 msgid "Saturday" msgstr "Saturday" @@ -7373,9 +7897,9 @@ msgstr "Saturday" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:656 -#: components/Schedule/shared/ScheduleForm.js:662 -#: components/Schedule/shared/useSchedulePromptSteps.js:45 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 +#: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 #: screens/Credential/shared/CredentialForm.js:323 @@ -7383,7 +7907,7 @@ msgstr "Saturday" #: screens/Setting/shared/RevertFormActionGroup.js:18 #: screens/Template/Survey/SurveyReorderModal.js:205 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:35 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:129 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.js:158 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.js:162 msgid "Save" @@ -7412,7 +7936,7 @@ msgstr "Schedule" msgid "Schedule Details" msgstr "Schedule Details" -#: components/Schedule/shared/ScheduleForm.js:455 +#: components/Schedule/shared/UnsupportedScheduleForm.js:15 msgid "Schedule Rules" msgstr "Schedule Rules" @@ -7428,7 +7952,7 @@ msgstr "Schedule is active" msgid "Schedule is inactive" msgstr "Schedule is inactive" -#: components/Schedule/shared/ScheduleForm.js:566 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "Schedule is missing rrule" @@ -7437,7 +7961,7 @@ msgid "Schedule not found." msgstr "Schedule not found." #: components/Schedule/ScheduleList/ScheduleList.js:163 -#: components/Schedule/ScheduleList/ScheduleList.js:228 +#: components/Schedule/ScheduleList/ScheduleList.js:229 #: routeConfig.js:44 #: screens/ActivityStream/ActivityStream.js:153 #: screens/Inventory/Inventories.js:89 @@ -7455,7 +7979,7 @@ msgstr "" #: screens/Application/ApplicationTokens/ApplicationTokenList.js:136 #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:33 -#: screens/User/UserTokenDetail/UserTokenDetail.js:49 +#: screens/User/UserTokenDetail/UserTokenDetail.js:50 #: screens/User/UserTokenList/UserTokenList.js:142 #: screens/User/UserTokenList/UserTokenList.js:189 #: screens/User/UserTokenList/UserTokenListItem.js:32 @@ -7483,12 +8007,12 @@ msgstr "Scroll next" msgid "Scroll previous" msgstr "Scroll previous" -#: components/Lookup/HostFilterLookup.js:289 -#: components/Lookup/Lookup.js:137 +#: components/Lookup/HostFilterLookup.js:290 +#: components/Lookup/Lookup.js:143 msgid "Search" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:152 +#: screens/Job/JobOutput/JobOutputSearch.js:151 msgid "Search is disabled while the job is running" msgstr "Search is disabled while the job is running" @@ -7501,28 +8025,32 @@ msgstr "Search submit button" msgid "Search text input" msgstr "" -#: components/Lookup/HostFilterLookup.js:397 +#: components/Lookup/HostFilterLookup.js:398 msgid "Searching by ansible_facts requires special syntax. Refer to the" msgstr "Searching by ansible_facts requires special syntax. Refer to the" -#: components/Schedule/shared/FrequencyDetailSubform.js:401 +#: components/Schedule/shared/FrequencyDetailSubform.js:408 msgid "Second" msgstr "Second" -#: components/PromptDetail/PromptInventorySourceDetail.js:114 -#: components/PromptDetail/PromptProjectDetail.js:138 -#: screens/Project/ProjectDetail/ProjectDetail.js:251 +#: components/PromptDetail/PromptInventorySourceDetail.js:103 +#: components/PromptDetail/PromptProjectDetail.js:153 +#: screens/Project/ProjectDetail/ProjectDetail.js:269 msgid "Seconds" msgstr "Seconds" +#: screens/NotificationTemplate/shared/Notifications.helptext.js:34 +msgid "See Django" +msgstr "See Django" + #: components/AdHocCommands/AdHocPreviewStep.js:35 -#: components/LaunchPrompt/steps/PreviewStep.js:63 +#: components/LaunchPrompt/steps/PreviewStep.js:61 msgid "See errors on the left" msgstr "See errors on the left" #: components/JobList/JobListItem.js:84 -#: components/Lookup/HostFilterLookup.js:379 -#: components/Lookup/Lookup.js:194 +#: components/Lookup/HostFilterLookup.js:380 +#: components/Lookup/Lookup.js:200 #: components/Pagination/Pagination.js:33 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:98 msgid "Select" @@ -7546,7 +8074,7 @@ msgstr "Select Hosts" msgid "Select Input" msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:284 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "Select Instances" @@ -7558,7 +8086,7 @@ msgstr "Select Items" msgid "Select Items from List" msgstr "Select Items from List" -#: components/LabelSelect/LabelSelect.js:99 +#: components/LabelSelect/LabelSelect.js:127 msgid "Select Labels" msgstr "Select Labels" @@ -7591,11 +8119,10 @@ msgstr "Select a Resource Type" #~ "all job template nodes that prompt for a branch." #: components/LaunchPrompt/steps/OtherPromptsStep.js:48 -msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" -msgstr "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" +#~ msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" +#~ msgstr "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" -#: screens/Job/Job.helptext.js:20 -#: screens/Template/shared/JobTemplate.helptext.js:26 +#: screens/Job/Job.helptext.js:21 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:10 msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch." msgstr "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch." @@ -7625,7 +8152,7 @@ msgstr "Select a module" msgid "Select a playbook" msgstr "Select a playbook" -#: screens/Template/shared/JobTemplateForm.js:319 +#: screens/Template/shared/JobTemplateForm.js:323 msgid "Select a project before editing the execution environment." msgstr "Select a project before editing the execution environment." @@ -7633,62 +8160,67 @@ msgstr "Select a project before editing the execution environment." msgid "Select a question to delete" msgstr "Select a question to delete" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:19 -#~ msgid "Select a row to approve" -#~ msgstr "Select a row to approve" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "Select a row to approve" #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:19 -#~ msgid "Select a row to deny" -#~ msgstr "Select a row to deny" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "Select a row to deny" #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "Select a row to disassociate" +#: screens/Instances/Shared/RemoveInstanceButton.js:77 +msgid "Select a row to remove" +msgstr "Select a row to remove" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:87 msgid "Select a subscription" msgstr "Select a subscription" #: components/HostForm/HostForm.js:39 -#: components/Schedule/shared/FrequencyDetailSubform.js:59 -#: components/Schedule/shared/FrequencyDetailSubform.js:87 -#: components/Schedule/shared/FrequencyDetailSubform.js:91 -#: components/Schedule/shared/FrequencyDetailSubform.js:99 -#: components/Schedule/shared/ScheduleForm.js:95 -#: components/Schedule/shared/ScheduleForm.js:99 +#: components/Schedule/shared/FrequencyDetailSubform.js:71 +#: components/Schedule/shared/FrequencyDetailSubform.js:78 +#: components/Schedule/shared/FrequencyDetailSubform.js:88 +#: components/Schedule/shared/ScheduleFormFields.js:33 +#: components/Schedule/shared/ScheduleFormFields.js:37 +#: components/Schedule/shared/ScheduleFormFields.js:61 #: screens/Credential/shared/CredentialForm.js:44 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:78 -#: screens/Inventory/shared/InventoryForm.js:64 -#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:96 -#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:43 -#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:45 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:79 +#: screens/Inventory/shared/InventoryForm.js:72 +#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 +#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 +#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:67 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:24 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:61 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:421 -#: screens/Project/shared/ProjectForm.js:190 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:436 +#: screens/Project/shared/ProjectForm.js:234 #: screens/Project/shared/ProjectSubForms/InsightsSubForm.js:39 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:36 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:37 #: screens/Team/shared/TeamForm.js:49 #: screens/Template/Survey/SurveyQuestionForm.js:30 -#: screens/Template/shared/WorkflowJobTemplateForm.js:125 +#: screens/Template/shared/WorkflowJobTemplateForm.js:130 #: screens/User/shared/UserForm.js:139 +#: util/validators.js:201 msgid "Select a value for this field" msgstr "Select a value for this field" -#: screens/Template/shared/JobTemplate.helptext.js:22 +#: screens/Template/shared/JobTemplate.helptext.js:23 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:20 msgid "Select a webhook service." msgstr "Select a webhook service." @@ -7711,7 +8243,7 @@ msgstr "Select an instance" msgid "Select an instance and a metric to show chart" msgstr "Select an instance and a metric to show chart" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "Select an instance to run a health check." @@ -7719,11 +8251,11 @@ msgstr "Select an instance to run a health check." msgid "Select an inventory for the workflow. This inventory is applied to all workflow nodes that prompt for an inventory." msgstr "Select an inventory for the workflow. This inventory is applied to all workflow nodes that prompt for an inventory." -#: components/LaunchPrompt/steps/SurveyStep.js:129 +#: components/LaunchPrompt/steps/SurveyStep.js:131 msgid "Select an option" msgstr "Select an option" -#: screens/Project/shared/ProjectForm.js:201 +#: screens/Project/shared/ProjectForm.js:245 msgid "Select an organization before editing the default execution environment." msgstr "Select an organization before editing the default execution environment." @@ -7741,11 +8273,16 @@ msgstr "Select an organization before editing the default execution environment. #~ "credential at run time. If you select credentials and check \"Prompt on launch\", the selected\n" #~ "credential(s) become the defaults that can be updated at run time." -#: screens/Job/Job.helptext.js:10 -#: screens/Template/shared/JobTemplate.helptext.js:11 +#: screens/Job/Job.helptext.js:11 +#: screens/Template/shared/JobTemplate.helptext.js:12 msgid "Select credentials for accessing the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking \"Prompt on launch\" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check \"Prompt on launch\", the selected credential(s) become the defaults that can be updated at run time." msgstr "Select credentials for accessing the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking \"Prompt on launch\" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check \"Prompt on launch\", the selected credential(s) become the defaults that can be updated at run time." +#: components/Schedule/shared/ScheduleFormFields.js:120 +#: components/Schedule/shared/ScheduleFormFields.js:179 +msgid "Select frequency" +msgstr "Select frequency" + #: screens/Project/shared/Project.helptext.js:18 msgid "" "Select from the list of directories found in\n" @@ -7761,15 +8298,15 @@ msgid "Select items from list" msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:55 -msgid "Select items to approve, deny, or cancel" -msgstr "Select items to approve, deny, or cancel" +#~ msgid "Select items to approve, deny, or cancel" +#~ msgstr "Select items to approve, deny, or cancel" #: screens/Dashboard/DashboardGraph.js:124 #: screens/Dashboard/DashboardGraph.js:125 msgid "Select job type" msgstr "Select job type" -#: components/LaunchPrompt/steps/SurveyStep.js:177 +#: components/LaunchPrompt/steps/SurveyStep.js:179 msgid "Select option(s)" msgstr "Select option(s)" @@ -7783,9 +8320,9 @@ msgstr "Select period" msgid "Select roles to apply" msgstr "Select roles to apply" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:127 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "Select source path" @@ -7814,8 +8351,8 @@ msgstr "Select the Instance Groups for this Inventory to run on." #~ "Select the Instance Groups for this Job Template\n" #~ "to run on." -#: screens/Job/Job.helptext.js:17 -#: screens/Template/shared/JobTemplate.helptext.js:19 +#: screens/Job/Job.helptext.js:18 +#: screens/Template/shared/JobTemplate.helptext.js:20 msgid "Select the Instance Groups for this Job Template to run on." msgstr "Select the Instance Groups for this Job Template to run on." @@ -7844,10 +8381,10 @@ msgid "Select the credential you want to use when accessing the remote hosts to msgstr "Select the credential you want to use when accessing the remote hosts to run the command. Choose the credential containing the username and SSH key or password that Ansible will need to log into the remote hosts." #: screens/Template/shared/JobTemplate.helptext.js:8 -msgid "Select the execution environment for this job template." -msgstr "Select the execution environment for this job template." +#~ msgid "Select the execution environment for this job template." +#~ msgstr "Select the execution environment for this job template." -#: components/Lookup/InventoryLookup.js:133 +#: components/Lookup/InventoryLookup.js:123 msgid "" "Select the inventory containing the hosts\n" "you want this job to manage." @@ -7856,7 +8393,7 @@ msgstr "" "you want this job to manage." #: screens/Job/Job.helptext.js:6 -#: screens/Template/shared/JobTemplate.helptext.js:6 +#: screens/Template/shared/JobTemplate.helptext.js:7 msgid "Select the inventory containing the hosts you want this job to manage." msgstr "Select the inventory containing the hosts you want this job to manage." @@ -7875,11 +8412,15 @@ msgstr "Select the inventory containing the hosts you want this job to manage." msgid "Select the inventory that this host will belong to." msgstr "Select the inventory that this host will belong to." -#: screens/Job/Job.helptext.js:9 -#: screens/Template/shared/JobTemplate.helptext.js:10 +#: screens/Job/Job.helptext.js:10 +#: screens/Template/shared/JobTemplate.helptext.js:11 msgid "Select the playbook to be executed by this job." msgstr "Select the playbook to be executed by this job." +#: screens/Instances/Shared/InstanceForm.js:43 +msgid "Select the port that Receptor will listen on for incoming connections. Default is 27199." +msgstr "Select the port that Receptor will listen on for incoming connections. Default is 27199." + #: screens/Template/shared/JobTemplateForm.js:300 #~ msgid "" #~ "Select the project containing the playbook\n" @@ -7888,8 +8429,7 @@ msgstr "Select the playbook to be executed by this job." #~ "Select the project containing the playbook\n" #~ "you want this job to execute." -#: screens/Job/Job.helptext.js:7 -#: screens/Template/shared/JobTemplate.helptext.js:7 +#: screens/Template/shared/JobTemplate.helptext.js:8 msgid "Select the project containing the playbook you want this job to execute." msgstr "Select the project containing the playbook you want this job to execute." @@ -7897,7 +8437,7 @@ msgstr "Select the project containing the playbook you want this job to execute. msgid "Select your Ansible Automation Platform subscription to use." msgstr "Select your Ansible Automation Platform subscription to use." -#: components/Lookup/Lookup.js:180 +#: components/Lookup/Lookup.js:186 msgid "Select {0}" msgstr "Select {0}" @@ -7908,7 +8448,7 @@ msgstr "Select {0}" #: components/CheckboxListItem/CheckboxListItem.js:44 #: components/Lookup/InstanceGroupsLookup.js:87 #: components/OptionsList/OptionsList.js:74 -#: components/Schedule/ScheduleList/ScheduleListItem.js:78 +#: components/Schedule/ScheduleList/ScheduleListItem.js:84 #: components/TemplateList/TemplateListItem.js:140 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:107 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:125 @@ -7920,8 +8460,8 @@ msgstr "Select {0}" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7933,31 +8473,32 @@ msgstr "Select {0}" #: screens/Team/TeamList/TeamListItem.js:31 #: screens/Template/Survey/SurveyListItem.js:34 #: screens/User/UserTokenList/UserTokenListItem.js:19 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:32 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:41 msgid "Selected" msgstr "" #: components/LaunchPrompt/steps/CredentialsStep.js:142 #: components/LaunchPrompt/steps/CredentialsStep.js:147 -#: components/Lookup/MultiCredentialsLookup.js:161 -#: components/Lookup/MultiCredentialsLookup.js:166 +#: components/Lookup/MultiCredentialsLookup.js:162 +#: components/Lookup/MultiCredentialsLookup.js:167 msgid "Selected Category" msgstr "Selected Category" -#: components/Schedule/shared/ScheduleForm.js:605 -#: components/Schedule/shared/ScheduleForm.js:606 +#: components/Schedule/shared/ScheduleForm.js:445 +#: components/Schedule/shared/ScheduleForm.js:446 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "Selected date range must have at least 1 schedule occurrence." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:159 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:160 msgid "Sender Email" msgstr "Sender Email" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:94 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:96 msgid "Sender e-mail" msgstr "Sender e-mail" -#: components/Schedule/shared/FrequencyDetailSubform.js:153 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:167 +#: components/Schedule/shared/FrequencyDetailSubform.js:138 msgid "September" msgstr "September" @@ -7966,7 +8507,7 @@ msgid "Service account JSON file" msgstr "Service account JSON file" #: screens/Inventory/shared/InventorySourceForm.js:46 -#: screens/Project/shared/ProjectForm.js:94 +#: screens/Project/shared/ProjectForm.js:112 msgid "Set a value for this field" msgstr "Set a value for this field" @@ -7974,15 +8515,16 @@ msgstr "Set a value for this field" msgid "Set how many days of data should be retained." msgstr "Set how many days of data should be retained." -#: screens/Setting/SettingList.js:118 +#: screens/Setting/SettingList.js:122 msgid "Set preferences for data collection, logos, and logins" msgstr "Set preferences for data collection, logos, and logins" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "Set source path to" #: components/InstanceToggle/InstanceToggle.js:48 +#: screens/Instances/Shared/InstanceForm.js:59 msgid "Set the instance enabled or disabled. If disabled, jobs will not be assigned to this instance." msgstr "Set the instance enabled or disabled. If disabled, jobs will not be assigned to this instance." @@ -8014,6 +8556,14 @@ msgstr "Set type typeahead" msgid "Set zoom to 100% and center graph" msgstr "Set zoom to 100% and center graph" +#: screens/Instances/Shared/InstanceForm.js:35 +msgid "Sets the current life cycle stage of this instance. Default is \"installed.\"" +msgstr "Sets the current life cycle stage of this instance. Default is \"installed.\"" + +#: screens/Instances/Shared/InstanceForm.js:51 +msgid "Sets the role that this instance will play within mesh topology. Default is \"execution.\"" +msgstr "Sets the role that this instance will play within mesh topology. Default is \"execution.\"" + #: screens/ActivityStream/ActivityStreamDetailButton.js:46 msgid "Setting category" msgstr "Setting category" @@ -8030,7 +8580,7 @@ msgstr "Setting name" #: routeConfig.js:163 #: screens/ActivityStream/ActivityStream.js:220 #: screens/ActivityStream/ActivityStream.js:222 -#: screens/Setting/Settings.js:42 +#: screens/Setting/Settings.js:43 msgid "Settings" msgstr "" @@ -8038,12 +8588,12 @@ msgstr "" msgid "Show" msgstr "Show" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:154 -#: components/PromptDetail/PromptDetail.js:283 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:317 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:276 -#: screens/Template/shared/JobTemplateForm.js:448 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:182 +#: components/PromptDetail/PromptDetail.js:348 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 +#: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "Show Changes" @@ -8056,8 +8606,8 @@ msgstr "Show Changes" msgid "Show changes" msgstr "Show changes" -#: components/LaunchPrompt/LaunchPrompt.js:105 -#: components/Schedule/shared/SchedulePromptableFields.js:109 +#: components/LaunchPrompt/LaunchPrompt.js:135 +#: components/Schedule/shared/SchedulePromptableFields.js:102 msgid "Show description" msgstr "Show description" @@ -8069,43 +8619,47 @@ msgstr "Show less" msgid "Show only root groups" msgstr "Show only root groups" -#: screens/Login/Login.js:240 +#: screens/Login/Login.js:262 msgid "Sign in with Azure AD" msgstr "Sign in with Azure AD" -#: screens/Login/Login.js:254 +#: screens/Login/Login.js:276 msgid "Sign in with GitHub" msgstr "Sign in with GitHub" -#: screens/Login/Login.js:296 +#: screens/Login/Login.js:318 msgid "Sign in with GitHub Enterprise" msgstr "Sign in with GitHub Enterprise" -#: screens/Login/Login.js:311 +#: screens/Login/Login.js:333 msgid "Sign in with GitHub Enterprise Organizations" msgstr "Sign in with GitHub Enterprise Organizations" -#: screens/Login/Login.js:327 +#: screens/Login/Login.js:349 msgid "Sign in with GitHub Enterprise Teams" msgstr "Sign in with GitHub Enterprise Teams" -#: screens/Login/Login.js:268 +#: screens/Login/Login.js:290 msgid "Sign in with GitHub Organizations" msgstr "Sign in with GitHub Organizations" -#: screens/Login/Login.js:282 +#: screens/Login/Login.js:304 msgid "Sign in with GitHub Teams" msgstr "Sign in with GitHub Teams" -#: screens/Login/Login.js:342 +#: screens/Login/Login.js:364 msgid "Sign in with Google" msgstr "Sign in with Google" -#: screens/Login/Login.js:361 +#: screens/Login/Login.js:378 +msgid "Sign in with OIDC" +msgstr "Sign in with OIDC" + +#: screens/Login/Login.js:397 msgid "Sign in with SAML" msgstr "Sign in with SAML" -#: screens/Login/Login.js:360 +#: screens/Login/Login.js:396 msgid "Sign in with SAML {samlIDP}" msgstr "Sign in with SAML {samlIDP}" @@ -8114,17 +8668,23 @@ msgstr "Sign in with SAML {samlIDP}" msgid "Simple key select" msgstr "Simple key select" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:69 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:70 -#: components/PromptDetail/PromptDetail.js:256 -#: components/PromptDetail/PromptJobTemplateDetail.js:260 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:369 -#: screens/Job/JobDetail/JobDetail.js:483 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:459 -#: screens/Template/shared/JobTemplateForm.js:481 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:106 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:107 +#: components/PromptDetail/PromptDetail.js:282 +#: components/PromptDetail/PromptJobTemplateDetail.js:267 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 +#: screens/Job/JobDetail/JobDetail.js:500 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 +#: screens/Template/shared/JobTemplateForm.js:533 +#: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" msgstr "Skip Tags" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:93 +#: components/Schedule/shared/FrequencyDetailSubform.js:223 +msgid "Skip every" +msgstr "Skip every" + #: screens/Template/shared/JobTemplateForm.js:538 #~ msgid "" #~ "Skip tags are useful when you have a\n" @@ -8140,19 +8700,20 @@ msgstr "Skip Tags" #~ "of tags." #: components/LaunchPrompt/steps/OtherPromptsStep.js:71 -msgid "" -"Skip tags are useful when you have a large\n" -"playbook, and you want to skip specific parts of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." -msgstr "" -"Skip tags are useful when you have a large\n" -"playbook, and you want to skip specific parts of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." +#~ msgid "" +#~ "Skip tags are useful when you have a large\n" +#~ "playbook, and you want to skip specific parts of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." +#~ msgstr "" +#~ "Skip tags are useful when you have a large\n" +#~ "playbook, and you want to skip specific parts of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." -#: screens/Job/Job.helptext.js:19 -#: screens/Template/shared/JobTemplate.helptext.js:21 +#: screens/Job/Job.helptext.js:20 +#: screens/Template/shared/JobTemplate.helptext.js:22 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:22 msgid "Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." msgstr "Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." @@ -8160,7 +8721,7 @@ msgstr "Skip tags are useful when you have a large playbook, and you want to ski msgid "Skipped" msgstr "Skipped" -#: components/StatusLabel/StatusLabel.js:42 +#: components/StatusLabel/StatusLabel.js:50 msgid "Skipped'" msgstr "Skipped'" @@ -8181,17 +8742,17 @@ msgstr "Smart Inventory" msgid "Smart Inventory not found." msgstr "Smart Inventory not found." -#: components/Lookup/HostFilterLookup.js:344 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:117 +#: components/Lookup/HostFilterLookup.js:345 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:116 msgid "Smart host filter" msgstr "Smart host filter" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:106 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 msgid "Smart inventory" msgstr "Smart inventory" #: components/AdHocCommands/AdHocPreviewStep.js:32 -#: components/LaunchPrompt/steps/PreviewStep.js:60 +#: components/LaunchPrompt/steps/PreviewStep.js:58 msgid "Some of the previous step(s) have errors" msgstr "Some of the previous step(s) have errors" @@ -8216,37 +8777,40 @@ msgstr "" #~ msgid "Sort question order" #~ msgstr "Sort question order" -#: components/JobList/JobListItem.js:170 -#: components/PromptDetail/PromptInventorySourceDetail.js:95 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:214 +#: components/JobList/JobListItem.js:169 +#: components/PromptDetail/PromptInventorySourceDetail.js:84 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 #: screens/Inventory/shared/InventorySourceForm.js:131 -#: screens/Job/JobDetail/JobDetail.js:274 +#: screens/Job/JobDetail/JobDetail.js:172 +#: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 msgid "Source" msgstr "Source" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:47 -#: components/PromptDetail/PromptDetail.js:211 -#: components/PromptDetail/PromptJobTemplateDetail.js:145 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:44 +#: components/PromptDetail/PromptDetail.js:237 +#: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:87 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:312 -#: screens/Job/JobDetail/JobDetail.js:302 -#: screens/Project/ProjectDetail/ProjectDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:241 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:134 -#: screens/Template/shared/JobTemplateForm.js:328 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:286 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:89 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Job/JobDetail/JobDetail.js:307 +#: screens/Project/ProjectDetail/ProjectDetail.js:230 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 +#: screens/Template/shared/JobTemplateForm.js:335 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "Source Control Branch" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "Source Control Branch/Tag/Commit" #: components/PromptDetail/PromptProjectDetail.js:117 -#: screens/Project/ProjectDetail/ProjectDetail.js:239 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:53 +#: screens/Project/ProjectDetail/ProjectDetail.js:256 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:56 msgid "Source Control Credential" msgstr "Source Control Credential" @@ -8255,27 +8819,27 @@ msgstr "Source Control Credential" #~ msgstr "Source Control Credential Type" #: components/PromptDetail/PromptProjectDetail.js:111 -#: screens/Project/ProjectDetail/ProjectDetail.js:234 +#: screens/Project/ProjectDetail/ProjectDetail.js:235 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:32 msgid "Source Control Refspec" msgstr "Source Control Refspec" -#: screens/Project/ProjectDetail/ProjectDetail.js:194 +#: screens/Project/ProjectDetail/ProjectDetail.js:195 msgid "Source Control Revision" msgstr "Source Control Revision" #: components/PromptDetail/PromptProjectDetail.js:96 -#: screens/Job/JobDetail/JobDetail.js:253 -#: screens/Project/ProjectDetail/ProjectDetail.js:190 -#: screens/Project/shared/ProjectForm.js:215 +#: screens/Job/JobDetail/JobDetail.js:273 +#: screens/Project/ProjectDetail/ProjectDetail.js:191 +#: screens/Project/shared/ProjectForm.js:259 msgid "Source Control Type" msgstr "Source Control Type" -#: components/Lookup/ProjectLookup.js:142 +#: components/Lookup/ProjectLookup.js:143 #: components/PromptDetail/PromptProjectDetail.js:101 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:96 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:165 -#: screens/Project/ProjectDetail/ProjectDetail.js:224 +#: screens/Project/ProjectDetail/ProjectDetail.js:225 #: screens/Project/ProjectList/ProjectList.js:205 #: screens/Project/shared/ProjectSubForms/SharedFields.js:16 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:104 @@ -8285,24 +8849,24 @@ msgstr "Source Control URL" #: components/JobList/JobList.js:211 #: components/JobList/JobListItem.js:42 #: components/Schedule/ScheduleList/ScheduleListItem.js:38 -#: screens/Job/JobDetail/JobDetail.js:64 +#: screens/Job/JobDetail/JobDetail.js:65 msgid "Source Control Update" msgstr "Source Control Update" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:335 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:340 msgid "Source Phone Number" msgstr "Source Phone Number" -#: components/PromptDetail/PromptInventorySourceDetail.js:188 +#: components/PromptDetail/PromptInventorySourceDetail.js:176 msgid "Source Variables" msgstr "Source Variables" #: components/JobList/JobListItem.js:213 -#: screens/Job/JobDetail/JobDetail.js:237 +#: screens/Job/JobDetail/JobDetail.js:257 msgid "Source Workflow Job" msgstr "Source Workflow Job" -#: screens/Template/shared/WorkflowJobTemplateForm.js:172 +#: screens/Template/shared/WorkflowJobTemplateForm.js:177 msgid "Source control branch" msgstr "Source control branch" @@ -8310,12 +8874,12 @@ msgstr "Source control branch" msgid "Source details" msgstr "Source details" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:390 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:403 msgid "Source phone number" msgstr "Source phone number" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:285 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:19 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "Source variables" @@ -8352,7 +8916,7 @@ msgstr "" msgid "Specify the conditions under which this node should be executed" msgstr "Specify the conditions under which this node should be executed" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "Standard Error" @@ -8360,7 +8924,7 @@ msgstr "Standard Error" #~ msgid "Standard Out" #~ msgstr "Standard Out" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "Standard error tab" @@ -8384,16 +8948,16 @@ msgstr "Start Time" msgid "Start date" msgstr "Start date" -#: components/Schedule/shared/ScheduleForm.js:122 +#: components/Schedule/shared/ScheduleFormFields.js:87 msgid "Start date/time" msgstr "Start date/time" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:460 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:465 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:105 msgid "Start message" msgstr "Start message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:469 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:474 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:114 msgid "Start message body" msgstr "Start message body" @@ -8410,45 +8974,46 @@ msgstr "Start sync source" msgid "Start time" msgstr "Start time" -#: screens/Job/JobDetail/JobDetail.js:200 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:253 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:54 +#: screens/Job/JobDetail/JobDetail.js:220 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "Started" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/InstanceGroup/Instances/InstanceList.js:256 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:149 -#: screens/Instances/InstanceList/InstanceList.js:151 -#: screens/Instances/InstanceList/InstanceListItem.js:134 -#: screens/Inventory/InventoryList/InventoryList.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: screens/Instances/InstancePeers/InstancePeerList.js:97 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 -#: screens/Job/JobDetail/JobDetail.js:188 -#: screens/Job/JobOutput/HostEventModal.js:118 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:114 +#: screens/Job/JobDetail/JobDetail.js:210 +#: screens/Job/JobOutput/HostEventModal.js:119 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 #: screens/Project/ProjectList/ProjectList.js:222 #: screens/Project/ProjectList/ProjectListItem.js:197 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:45 -#: screens/TopologyView/Tooltip.js:98 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:254 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:57 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "Status" #: screens/TopologyView/Legend.js:107 -msgid "Status types" -msgstr "Status types" +#~ msgid "Status types" +#~ msgstr "Status types" -#: screens/Job/JobOutput/JobOutputSearch.js:92 +#: screens/Job/JobOutput/JobOutputSearch.js:91 msgid "Stdout" msgstr "Stdout" @@ -8458,7 +9023,7 @@ msgstr "Stdout" msgid "Submit" msgstr "Submit" -#: screens/Project/shared/Project.helptext.js:114 +#: screens/Project/shared/Project.helptext.js:118 msgid "" "Submodules will track the latest commit on\n" "their master branch (or other branch specified in\n" @@ -8474,14 +9039,14 @@ msgstr "" "This is equivalent to specifying the --remote\n" "flag to git submodule update." -#: screens/Setting/SettingList.js:128 -#: screens/Setting/Settings.js:108 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:74 +#: screens/Setting/SettingList.js:132 +#: screens/Setting/Settings.js:112 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:136 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:195 msgid "Subscription" msgstr "Subscription" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:32 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:41 msgid "Subscription Details" msgstr "Subscription Details" @@ -8497,11 +9062,11 @@ msgstr "Subscription manifest" msgid "Subscription selection modal" msgstr "Subscription selection modal" -#: screens/Setting/SettingList.js:133 +#: screens/Setting/SettingList.js:137 msgid "Subscription settings" msgstr "Subscription settings" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:69 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:131 msgid "Subscription type" msgstr "Subscription type" @@ -8509,10 +9074,10 @@ msgstr "Subscription type" msgid "Subscriptions table" msgstr "Subscriptions table" -#: components/Lookup/ProjectLookup.js:136 +#: components/Lookup/ProjectLookup.js:137 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:90 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:159 -#: screens/Job/JobDetail/JobDetail.js:75 +#: screens/Job/JobDetail/JobDetail.js:76 #: screens/Project/ProjectList/ProjectList.js:199 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:98 msgid "Subversion" @@ -8520,23 +9085,24 @@ msgstr "Subversion" #: components/NotificationList/NotificationListItem.js:71 #: components/NotificationList/NotificationListItem.js:72 -#: components/StatusLabel/StatusLabel.js:33 +#: components/StatusLabel/StatusLabel.js:41 msgid "Success" msgstr "Success" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:478 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:483 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:123 msgid "Success message" msgstr "Success message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:487 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:492 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:132 msgid "Success message body" msgstr "Success message body" #: components/JobList/JobList.js:231 -#: components/StatusLabel/StatusLabel.js:35 +#: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "" @@ -8545,17 +9111,27 @@ msgstr "" msgid "Successful jobs" msgstr "Successful jobs" -#: screens/Project/ProjectDetail/ProjectDetail.js:200 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:28 +msgid "Successfully Approved" +msgstr "Successfully Approved" + +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:25 +msgid "Successfully Denied" +msgstr "Successfully Denied" + +#: screens/Project/ProjectDetail/ProjectDetail.js:201 #: screens/Project/ProjectList/ProjectListItem.js:97 msgid "Successfully copied to clipboard!" msgstr "Successfully copied to clipboard!" -#: components/Schedule/shared/FrequencyDetailSubform.js:248 +#: components/Schedule/shared/FrequencyDetailSubform.js:255 msgid "Sun" msgstr "Sun" -#: components/Schedule/shared/FrequencyDetailSubform.js:253 -#: components/Schedule/shared/FrequencyDetailSubform.js:421 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:83 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:182 +#: components/Schedule/shared/FrequencyDetailSubform.js:260 +#: components/Schedule/shared/FrequencyDetailSubform.js:428 msgid "Sunday" msgstr "Sunday" @@ -8600,17 +9176,21 @@ msgstr "Survey preview modal" #: screens/Inventory/InventorySources/InventorySourceListItem.js:120 #: screens/Inventory/shared/InventorySourceSyncButton.js:41 -#: screens/Project/shared/ProjectSyncButton.js:40 -#: screens/Project/shared/ProjectSyncButton.js:52 +#: screens/Project/shared/ProjectSyncButton.js:41 +#: screens/Project/shared/ProjectSyncButton.js:53 msgid "Sync" msgstr "Sync" #: screens/Project/ProjectList/ProjectListItem.js:238 -#: screens/Project/shared/ProjectSyncButton.js:36 -#: screens/Project/shared/ProjectSyncButton.js:47 +#: screens/Project/shared/ProjectSyncButton.js:37 +#: screens/Project/shared/ProjectSyncButton.js:48 msgid "Sync Project" msgstr "Sync Project" +#: screens/Inventory/InventoryList/InventoryList.js:219 +msgid "Sync Status" +msgstr "Sync Status" + #: components/PaginatedTable/ToolbarSyncSourceButton.js:19 #: components/PaginatedTable/ToolbarSyncSourceButton.js:29 #: components/PaginatedTable/ToolbarSyncSourceButton.js:32 @@ -8625,7 +9205,7 @@ msgstr "Sync all sources" msgid "Sync error" msgstr "Sync error" -#: screens/Project/ProjectDetail/ProjectDetail.js:212 +#: screens/Project/ProjectDetail/ProjectDetail.js:213 #: screens/Project/ProjectList/ProjectListItem.js:109 msgid "Sync for revision" msgstr "Sync for revision" @@ -8634,7 +9214,7 @@ msgstr "Sync for revision" msgid "Syncing" msgstr "Syncing" -#: screens/Setting/SettingList.js:98 +#: screens/Setting/SettingList.js:102 #: screens/User/UserRoles/UserRolesListItem.js:18 msgid "System" msgstr "" @@ -8653,7 +9233,7 @@ msgstr "System Administrator" msgid "System Auditor" msgstr "System Auditor" -#: screens/Job/JobOutput/JobOutputSearch.js:129 +#: screens/Job/JobOutput/JobOutputSearch.js:128 msgid "System Warning" msgstr "System Warning" @@ -8662,7 +9242,7 @@ msgstr "System Warning" msgid "System administrators have unrestricted access to all resources." msgstr "System administrators have unrestricted access to all resources." -#: screens/Setting/Settings.js:111 +#: screens/Setting/Settings.js:115 msgid "TACACS+" msgstr "TACACS+" @@ -8670,8 +9250,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "TACACS+ settings" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "Tabs" @@ -8690,52 +9270,53 @@ msgstr "Tabs" #~ "the usage of tags." #: components/LaunchPrompt/steps/OtherPromptsStep.js:59 -msgid "" -"Tags are useful when you have a large\n" -"playbook, and you want to run a specific part of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." -msgstr "" -"Tags are useful when you have a large\n" -"playbook, and you want to run a specific part of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." +#~ msgid "" +#~ "Tags are useful when you have a large\n" +#~ "playbook, and you want to run a specific part of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." +#~ msgstr "" +#~ "Tags are useful when you have a large\n" +#~ "playbook, and you want to run a specific part of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." -#: screens/Job/Job.helptext.js:18 -#: screens/Template/shared/JobTemplate.helptext.js:20 +#: screens/Job/Job.helptext.js:19 +#: screens/Template/shared/JobTemplate.helptext.js:21 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:21 msgid "Tags are useful when you have a large playbook, and you want to run a specific part of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." msgstr "Tags are useful when you have a large playbook, and you want to run a specific part of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:198 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:203 msgid "Tags for the Annotation" msgstr "Tags for the Annotation" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:172 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:179 msgid "Tags for the annotation (optional)" msgstr "Tags for the annotation (optional)" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:243 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:293 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:361 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:243 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:320 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:438 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:248 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:298 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:366 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:252 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:329 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:453 msgid "Target URL" msgstr "Target URL" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "Task" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "Task Count" -#: screens/Job/JobOutput/JobOutputSearch.js:130 +#: screens/Job/JobOutput/JobOutputSearch.js:129 msgid "Task Started" msgstr "Task Started" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "Tasks" @@ -8743,7 +9324,7 @@ msgstr "Tasks" msgid "Team" msgstr "" -#: components/ResourceAccessList/ResourceAccessListItem.js:87 +#: components/ResourceAccessList/ResourceAccessListItem.js:85 #: screens/Team/TeamRoles/TeamRolesList.js:144 msgid "Team Roles" msgstr "" @@ -8769,7 +9350,7 @@ msgstr "Team not found." #: screens/User/UserTeams/UserTeamList.js:175 #: screens/User/UserTeams/UserTeamList.js:246 #: screens/User/Users.js:32 -#: util/getRelatedResourceDeleteDetails.js:173 +#: util/getRelatedResourceDeleteDetails.js:174 msgid "Teams" msgstr "" @@ -8777,7 +9358,7 @@ msgstr "" msgid "Template" msgstr "Template" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "Template copied successfully" @@ -8794,15 +9375,15 @@ msgstr "Template not found." #: screens/ExecutionEnvironment/ExecutionEnvironment.js:70 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:83 #: screens/Template/Templates.js:17 -#: util/getRelatedResourceDeleteDetails.js:217 -#: util/getRelatedResourceDeleteDetails.js:274 +#: util/getRelatedResourceDeleteDetails.js:218 +#: util/getRelatedResourceDeleteDetails.js:275 msgid "Templates" msgstr "" #: screens/Credential/shared/CredentialForm.js:331 #: screens/Credential/shared/CredentialForm.js:337 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:80 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:421 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:426 msgid "Test" msgstr "Test" @@ -8835,11 +9416,11 @@ msgstr "Text Area" msgid "Textarea" msgstr "Textarea" -#: components/Lookup/Lookup.js:62 +#: components/Lookup/Lookup.js:63 msgid "That value was not found. Please enter or select a valid value." msgstr "That value was not found. Please enter or select a valid value." -#: components/Schedule/shared/FrequencyDetailSubform.js:391 +#: components/Schedule/shared/FrequencyDetailSubform.js:398 msgid "The" msgstr "The" @@ -8855,10 +9436,15 @@ msgstr "The" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "The Grant type the user must use to acquire tokens for this application" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "The Instance Groups for this Organization to run on." +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 +msgid "The Instance Groups to which this instance belongs." +msgstr "The Instance Groups to which this instance belongs." + #: screens/NotificationTemplate/shared/Notifications.helptext.js:6 msgid "" "The amount of time (in seconds) before the email\n" @@ -8879,8 +9465,8 @@ msgstr "" #~ "before the job is canceled. Defaults to 0 for no job\n" #~ "timeout." -#: screens/Job/Job.helptext.js:16 -#: screens/Template/shared/JobTemplate.helptext.js:17 +#: screens/Job/Job.helptext.js:17 +#: screens/Template/shared/JobTemplate.helptext.js:18 msgid "The amount of time (in seconds) to run before the job is canceled. Defaults to 0 for no job timeout." msgstr "The amount of time (in seconds) to run before the job is canceled. Defaults to 0 for no job timeout." @@ -8898,7 +9484,11 @@ msgstr "" "/api/annotations endpoint will be added automatically to the base\n" "Grafana URL." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Template/shared/JobTemplate.helptext.js:9 +msgid "The container image to be used for execution." +msgstr "The container image to be used for execution." + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8928,8 +9518,8 @@ msgstr "The execution environment that will be used for jobs that use this proje #~ "this job template. The resolved execution environment can be overridden by\n" #~ "explicitly assigning a different one to this job template." -#: screens/Job/Job.helptext.js:8 -#: screens/Template/shared/JobTemplate.helptext.js:9 +#: screens/Job/Job.helptext.js:9 +#: screens/Template/shared/JobTemplate.helptext.js:10 msgid "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." msgstr "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." @@ -8944,14 +9534,14 @@ msgstr "" "the branch needs to be \"pull/62/head\"." #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:66 -msgid "The following selected items are complete and cannot be acted on: {completedItems}" -msgstr "The following selected items are complete and cannot be acted on: {completedItems}" +#~ msgid "The following selected items are complete and cannot be acted on: {completedItems}" +#~ msgstr "The following selected items are complete and cannot be acted on: {completedItems}" #: screens/ExecutionEnvironment/shared/ExecutionEnvironment.helptext.js:7 msgid "The full image location, including the container registry, image name, and version tag." msgstr "The full image location, including the container registry, image name, and version tag." -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8961,11 +9551,19 @@ msgstr "" "to be synced by this source. You can select from\n" "the dropdown or enter a file within the input." -#: screens/Host/HostDetail/HostDetail.js:77 +#: screens/Host/HostDetail/HostDetail.js:79 msgid "The inventory that this host belongs to." msgstr "The inventory that this host belongs to." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:141 +msgid "The last {dayOfWeek}" +msgstr "The last {dayOfWeek}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:200 +msgid "The last {weekday} of {month}" +msgstr "The last {weekday} of {month}" + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8993,6 +9591,10 @@ msgstr "" "The number associated with the \"Messaging\n" "Service\" in Twilio with the format +18005550199." +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:69 +msgid "The number of hosts you have automated against is below your subscription count." +msgstr "The number of hosts you have automated against is below your subscription count." + #: screens/Template/shared/JobTemplateForm.js:427 #~ msgid "" #~ "The number of parallel or simultaneous\n" @@ -9007,8 +9609,8 @@ msgstr "" #~ "usually 5. The default number of forks can be overwritten\n" #~ "with a change to" -#: screens/Job/Job.helptext.js:24 -#: screens/Template/shared/JobTemplate.helptext.js:44 +#: screens/Job/Job.helptext.js:25 +#: screens/Template/shared/JobTemplate.helptext.js:48 msgid "The number of parallel or simultaneous processes to use while executing the playbook. An empty value, or a value less than 1 will use the Ansible default which is usually 5. The default number of forks can be overwritten with a change to" msgstr "The number of parallel or simultaneous processes to use while executing the playbook. An empty value, or a value less than 1 will use the Ansible default which is usually 5. The default number of forks can be overwritten with a change to" @@ -9017,7 +9619,7 @@ msgid "The number of parallel or simultaneous processes to use while executing t msgstr "The number of parallel or simultaneous processes to use while executing the playbook. Inputting no value will use the default value from the ansible configuration file. You can find more information" #: components/ContentError/ContentError.js:41 -#: screens/Job/Job.js:138 +#: screens/Job/Job.js:161 msgid "The page you requested could not be found." msgstr "The page you requested could not be found." @@ -9025,11 +9627,19 @@ msgstr "The page you requested could not be found." msgid "The pattern used to target hosts in the inventory. Leaving the field blank, all, and * will all target all hosts in the inventory. You can find more information about Ansible's host patterns" msgstr "The pattern used to target hosts in the inventory. Leaving the field blank, all, and * will all target all hosts in the inventory. You can find more information about Ansible's host patterns" +#: screens/Job/Job.helptext.js:7 +msgid "The project containing the playbook this job will execute." +msgstr "The project containing the playbook this job will execute." + +#: screens/Job/Job.helptext.js:8 +msgid "The project from which this inventory update is sourced." +msgstr "The project from which this inventory update is sourced." + #: screens/Project/ProjectList/ProjectListItem.js:120 msgid "The project is currently syncing and the revision will be available after the sync is complete." msgstr "The project is currently syncing and the revision will be available after the sync is complete." -#: screens/Project/ProjectDetail/ProjectDetail.js:210 +#: screens/Project/ProjectDetail/ProjectDetail.js:211 #: screens/Project/ProjectList/ProjectListItem.js:107 msgid "The project must be synced before a revision is available." msgstr "The project must be synced before a revision is available." @@ -9043,7 +9653,7 @@ msgstr "The project revision is currently out of date. Please refresh to fetch msgid "The resource associated with this node has been deleted." msgstr "The resource associated with this node has been deleted." -#: screens/Job/JobOutput/EmptyOutput.js:19 +#: screens/Job/JobOutput/EmptyOutput.js:31 msgid "The search filter did not produce any results…" msgstr "The search filter did not produce any results…" @@ -9073,7 +9683,7 @@ msgstr "" #~ "or have {0} directly retrieve your playbooks from\n" #~ "source control using the Source Control Type option above." -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:49 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:50 msgid "" "There are no available playbook directories in {project_base_dir}.\n" "Either that directory is empty, or all of the contents are already\n" @@ -9093,7 +9703,7 @@ msgstr "" msgid "There must be a value in at least one input" msgstr "There must be a value in at least one input" -#: screens/Login/Login.js:144 +#: screens/Login/Login.js:155 msgid "There was a problem logging in. Please try again." msgstr "There was a problem logging in. Please try again." @@ -9105,7 +9715,7 @@ msgstr "There was an error loading this content. Please reload the page." msgid "There was an error parsing the file. Please check the file formatting and try again." msgstr "There was an error parsing the file. Please check the file formatting and try again." -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:621 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:713 msgid "There was an error saving the workflow." msgstr "There was an error saving the workflow." @@ -9122,7 +9732,7 @@ msgid "These are the verbosity levels for standard out of the command run that a msgstr "These are the verbosity levels for standard out of the command run that are supported." #: components/AdHocCommands/AdHocDetailsStep.js:122 -#: screens/Job/Job.helptext.js:42 +#: screens/Job/Job.helptext.js:43 msgid "These arguments are used with the specified module." msgstr "These arguments are used with the specified module." @@ -9130,15 +9740,15 @@ msgstr "These arguments are used with the specified module." msgid "These arguments are used with the specified module. You can find information about {0} by clicking" msgstr "These arguments are used with the specified module. You can find information about {0} by clicking" -#: screens/Job/Job.helptext.js:32 +#: screens/Job/Job.helptext.js:33 msgid "These arguments are used with the specified module. You can find information about {moduleName} by clicking" msgstr "These arguments are used with the specified module. You can find information about {moduleName} by clicking" -#: components/Schedule/shared/FrequencyDetailSubform.js:403 +#: components/Schedule/shared/FrequencyDetailSubform.js:410 msgid "Third" msgstr "Third" -#: screens/Template/shared/JobTemplateForm.js:153 +#: screens/Template/shared/JobTemplateForm.js:157 msgid "This Project needs to be updated" msgstr "This Project needs to be updated" @@ -9160,11 +9770,15 @@ msgstr "This action will disassociate the following role from {0}:" msgid "This action will disassociate the following:" msgstr "This action will disassociate the following:" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/Instances/Shared/RemoveInstanceButton.js:178 +msgid "This action will remove the following instances:" +msgstr "This action will remove the following instances:" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 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:305 +#: screens/Credential/CredentialDetail/CredentialDetail.js:304 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?" @@ -9202,7 +9816,7 @@ msgstr "" "future releases of the Tower Software and help\n" "streamline customer experience and success." -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:131 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132 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?" @@ -9211,7 +9825,7 @@ msgstr "This execution environment is currently being used by other resources. A msgid "This feature is deprecated and will be removed in a future release." msgstr "This feature is deprecated and will be removed in a future release." -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." @@ -9252,8 +9866,8 @@ msgstr "This field must be a number and have a value less than {max}" msgid "This field must be a regular expression" msgstr "This field must be a regular expression" -#: components/Schedule/shared/FrequencyDetailSubform.js:52 #: util/validators.js:111 +#: util/validators.js:194 msgid "This field must be an integer" msgstr "This field must be an integer" @@ -9265,13 +9879,13 @@ msgstr "This field must be at least {0} characters" msgid "This field must be at least {min} characters" msgstr "This field must be at least {min} characters" -#: components/Schedule/shared/FrequencyDetailSubform.js:55 +#: util/validators.js:197 msgid "This field must be greater than 0" msgstr "This field must be greater than 0" #: components/AdHocCommands/useAdHocDetailsStep.js:52 #: components/LaunchPrompt/steps/useSurveyStep.js:111 -#: screens/Template/shared/JobTemplateForm.js:150 +#: screens/Template/shared/JobTemplateForm.js:154 #: screens/User/shared/UserForm.js:92 #: screens/User/shared/UserForm.js:103 #: util/validators.js:5 @@ -9299,7 +9913,13 @@ msgstr "" 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." -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:104 +msgid "This has already been acted on" +msgstr "This has already been acted on" + +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "This instance group is currently being by other resources. Are you sure you want to delete it?" @@ -9307,11 +9927,11 @@ msgstr "This instance group is currently being by other resources. Are you sure msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:160 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "This inventory is currently being used by other resources. Are you sure you want to delete it?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" @@ -9323,15 +9943,19 @@ msgstr "This is the only time the client secret will be shown." msgid "This is the only time the token value and associated refresh token value will be shown." msgstr "This is the only time the token value and associated refresh token value will be shown." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:526 +#: screens/Job/JobOutput/EmptyOutput.js:37 +msgid "This job failed and has no output." +msgstr "This job failed and has no output." + +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "This job template is currently being used by other resources. Are you sure you want to delete it?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "This organization is currently being by other resources. Are you sure you want to delete it?" -#: screens/Project/ProjectDetail/ProjectDetail.js:320 +#: screens/Project/ProjectDetail/ProjectDetail.js:338 msgid "This project is currently being used by other resources. Are you sure you want to delete it?" msgstr "This project is currently being used by other resources. Are you sure you want to delete it?" @@ -9339,6 +9963,10 @@ msgstr "This project is currently being used by other resources. Are you sure yo msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "This project is currently on sync and cannot be clicked until sync process completed" +#: components/Schedule/shared/ScheduleForm.js:459 +msgid "This schedule has no occurrences due to the selected exceptions." +msgstr "This schedule has no occurrences due to the selected exceptions." + #: components/Schedule/ScheduleList/ScheduleList.js:122 msgid "This schedule is missing an Inventory" msgstr "This schedule is missing an Inventory" @@ -9347,6 +9975,14 @@ msgstr "This schedule is missing an Inventory" msgid "This schedule is missing required survey values" msgstr "This schedule is missing required survey values" +#: components/Schedule/shared/UnsupportedScheduleForm.js:12 +msgid "" +"This schedule uses complex rules that are not supported in the\n" +"UI. Please use the API to manage this schedule." +msgstr "" +"This schedule uses complex rules that are not supported in the\n" +"UI. Please use the API to manage this schedule." + #: components/LaunchPrompt/steps/StepName.js:26 msgid "This step contains errors" msgstr "This step contains errors" @@ -9355,17 +9991,25 @@ msgstr "This step contains errors" msgid "This value does not match the password you entered previously. Please confirm that password." msgstr "This value does not match the password you entered previously. Please confirm that password." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:106 +msgid "This will cancel all subsequent nodes in this workflow" +msgstr "This will cancel all subsequent nodes in this workflow" + +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:328 +msgid "This will cancel all subsequent nodes in this workflow." +msgstr "This will cancel all subsequent nodes in this workflow." + #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:90 -msgid "This will cancel the workflow and no subsequent nodes will execute." -msgstr "This will cancel the workflow and no subsequent nodes will execute." +#~ msgid "This will cancel the workflow and no subsequent nodes will execute." +#~ msgstr "This will cancel the workflow and no subsequent nodes will execute." #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:105 -msgid "This will continue the workflow" -msgstr "This will continue the workflow" +#~ msgid "This will continue the workflow" +#~ msgstr "This will continue the workflow" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:78 -msgid "This will continue the workflow along failure and always paths." -msgstr "This will continue the workflow along failure and always paths." +#~ msgid "This will continue the workflow along failure and always paths." +#~ msgstr "This will continue the workflow along failure and always paths." #: screens/Setting/shared/RevertAllAlert.js:36 msgid "" @@ -9379,16 +10023,23 @@ msgstr "" msgid "This workflow does not have any nodes configured." msgstr "This workflow does not have any nodes configured." -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:43 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 +msgid "This workflow has already been acted on" +msgstr "This workflow has already been acted on" + +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:267 msgid "This workflow job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "This workflow job template is currently being used by other resources. Are you sure you want to delete it?" -#: components/Schedule/shared/FrequencyDetailSubform.js:292 +#: components/Schedule/shared/FrequencyDetailSubform.js:299 msgid "Thu" msgstr "Thu" -#: components/Schedule/shared/FrequencyDetailSubform.js:297 -#: components/Schedule/shared/FrequencyDetailSubform.js:441 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:80 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:186 +#: components/Schedule/shared/FrequencyDetailSubform.js:304 +#: components/Schedule/shared/FrequencyDetailSubform.js:448 msgid "Thursday" msgstr "Thursday" @@ -9399,7 +10050,7 @@ msgstr "Thursday" msgid "Time" msgstr "Time" -#: screens/Project/shared/Project.helptext.js:124 +#: screens/Project/shared/Project.helptext.js:128 msgid "" "Time in seconds to consider a project\n" "to be current. During job runs and callbacks the task\n" @@ -9429,16 +10080,20 @@ msgstr "" "Cache Timeout, it is not considered current, and a new\n" "inventory sync will be performed." -#: components/StatusLabel/StatusLabel.js:43 +#: components/StatusLabel/StatusLabel.js:51 msgid "Timed out" msgstr "Timed out" -#: components/PromptDetail/PromptDetail.js:127 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:169 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:112 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:270 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:86 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 +#: screens/Job/JobDetail/JobDetail.js:397 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 -#: screens/Template/shared/JobTemplateForm.js:443 +#: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" msgstr "Timeout" @@ -9514,7 +10169,7 @@ msgstr "Toggle schedule" msgid "Toggle tools" msgstr "Toggle tools" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:362 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:373 #: screens/User/UserTokens/UserTokens.js:64 msgid "Token" msgstr "Token" @@ -9547,15 +10202,17 @@ msgstr "Tools" #~ msgstr "Top Pagination" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "Topology View" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:211 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:211 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:162 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "Total Jobs" @@ -9564,8 +10221,8 @@ msgstr "Total Jobs" msgid "Total Nodes" msgstr "Total Nodes" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:81 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:120 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "Total hosts" @@ -9573,38 +10230,40 @@ msgstr "Total hosts" msgid "Total jobs" msgstr "Total jobs" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:83 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:87 msgid "Track submodules" msgstr "Track submodules" #: components/PromptDetail/PromptProjectDetail.js:56 -#: screens/Project/ProjectDetail/ProjectDetail.js:108 +#: screens/Project/ProjectDetail/ProjectDetail.js:109 msgid "Track submodules latest commit on branch" msgstr "Track submodules latest commit on branch" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:79 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:141 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:168 msgid "Trial" msgstr "Trial" -#: components/JobList/JobListItem.js:318 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 -#: screens/Job/JobDetail/JobDetail.js:378 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:205 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:235 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:265 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:310 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:368 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:80 +#: components/JobList/JobListItem.js:319 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:66 +#: screens/Job/JobDetail/JobDetail.js:383 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:210 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:240 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:270 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:315 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:142 msgid "True" msgstr "True" -#: components/Schedule/shared/FrequencyDetailSubform.js:270 +#: components/Schedule/shared/FrequencyDetailSubform.js:277 msgid "Tue" msgstr "Tue" -#: components/Schedule/shared/FrequencyDetailSubform.js:275 -#: components/Schedule/shared/FrequencyDetailSubform.js:431 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:78 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:184 +#: components/Schedule/shared/FrequencyDetailSubform.js:282 +#: components/Schedule/shared/FrequencyDetailSubform.js:438 msgid "Tuesday" msgstr "Tuesday" @@ -9615,13 +10274,11 @@ msgstr "Twilio" #: components/JobList/JobList.js:246 #: components/JobList/JobListItem.js:98 -#: components/Lookup/ProjectLookup.js:131 +#: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:115 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 -#: components/Schedule/ScheduleList/ScheduleList.js:169 -#: components/Schedule/ScheduleList/ScheduleListItem.js:97 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9634,16 +10291,16 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:209 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 #: screens/Inventory/InventorySources/InventorySourceListItem.js:100 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:106 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:180 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:120 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:68 @@ -9656,7 +10313,6 @@ msgstr "Twilio" #: screens/Template/Survey/SurveyList.js:103 #: screens/Template/Survey/SurveyListItem.js:60 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:93 -#: screens/TopologyView/Tooltip.js:92 #: screens/User/UserDetail/UserDetail.js:75 #: screens/User/UserRoles/UserRolesList.js:156 #: screens/User/UserRoles/UserRolesListItem.js:21 @@ -9664,8 +10320,8 @@ msgid "Type" msgstr "Type" #: screens/Credential/shared/TypeInputsSubForm.js:25 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:46 -#: screens/Project/shared/ProjectForm.js:247 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:47 +#: screens/Project/shared/ProjectForm.js:298 msgid "Type Details" msgstr "Type Details" @@ -9689,12 +10345,15 @@ msgstr "Unable to change inventory on a host" msgid "Unable to load last job update" msgstr "Unable to load last job update" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: components/InstanceDetails.js/InstanceDetails.js:367 +#: components/StatusLabel/StatusLabel.js:61 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:205 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 +#: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "Unavailable" @@ -9707,25 +10366,25 @@ msgstr "Unavailable" msgid "Undo" msgstr "Undo" -#: screens/Job/JobOutput/JobOutputSearch.js:184 +#: screens/Job/JobOutput/JobOutputSearch.js:183 msgid "Unfollow" msgstr "Unfollow" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:122 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:126 msgid "Unlimited" msgstr "Unlimited" -#: components/StatusLabel/StatusLabel.js:39 +#: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "Unreachable" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "Unreachable Host Count" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "Unreachable Hosts" @@ -9737,28 +10396,28 @@ msgstr "Unrecognized day string" msgid "Unsaved changes modal" msgstr "Unsaved changes modal" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:90 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:94 msgid "Update Revision on Launch" msgstr "Update Revision on Launch" -#: components/PromptDetail/PromptInventorySourceDetail.js:57 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:138 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:89 +#: components/PromptDetail/PromptInventorySourceDetail.js:51 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "Update on launch" #: components/PromptDetail/PromptInventorySourceDetail.js:62 #: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:148 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:97 -msgid "Update on project update" -msgstr "Update on project update" +#~ msgid "Update on project update" +#~ msgstr "Update on project update" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:71 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:75 msgid "Update options" msgstr "Update options" #: components/PromptDetail/PromptProjectDetail.js:61 -#: screens/Project/ProjectDetail/ProjectDetail.js:114 +#: screens/Project/ProjectDetail/ProjectDetail.js:115 msgid "Update revision on job launch" msgstr "Update revision on job launch" @@ -9766,11 +10425,11 @@ msgstr "Update revision on job launch" #~ msgid "Update settings pertaining to Jobs within {0}" #~ msgstr "Update settings pertaining to Jobs within {0}" -#: screens/Setting/SettingList.js:88 +#: screens/Setting/SettingList.js:92 msgid "Update settings pertaining to Jobs within {brandName}" msgstr "Update settings pertaining to Jobs within {brandName}" -#: screens/Template/shared/WebhookSubForm.js:187 +#: screens/Template/shared/WebhookSubForm.js:188 msgid "Update webhook key" msgstr "Update webhook key" @@ -9786,13 +10445,13 @@ msgstr "Upload a .zip file" msgid "Upload a Red Hat Subscription Manifest containing your subscription. To generate your subscription manifest, go to <0>subscription allocations on the Red Hat Customer Portal." msgstr "Upload a Red Hat Subscription Manifest containing your subscription. To generate your subscription manifest, go to <0>subscription allocations on the Red Hat Customer Portal." -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:52 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:126 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:53 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:132 msgid "Use SSL" msgstr "Use SSL" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:57 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:131 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:58 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:137 msgid "Use TLS" msgstr "Use TLS" @@ -9832,22 +10491,26 @@ msgstr "" "Use one phone number per line to specify where to\n" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 -#: screens/InstanceGroup/Instances/InstanceList.js:259 -#: screens/Instances/InstanceDetail/InstanceDetail.js:192 -#: screens/Instances/InstanceList/InstanceList.js:154 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "Used Capacity" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:246 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceDetail/InstanceDetail.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 +#: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "Used capacity" @@ -9855,20 +10518,20 @@ msgstr "Used capacity" msgid "User" msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:165 +#: components/AppContainer/PageHeaderToolbar.js:160 msgid "User Details" msgstr "" -#: screens/Setting/SettingList.js:117 -#: screens/Setting/Settings.js:114 +#: screens/Setting/SettingList.js:121 +#: screens/Setting/Settings.js:118 msgid "User Interface" msgstr "" -#: screens/Setting/SettingList.js:122 +#: screens/Setting/SettingList.js:126 msgid "User Interface settings" msgstr "User Interface settings" -#: components/ResourceAccessList/ResourceAccessListItem.js:73 +#: components/ResourceAccessList/ResourceAccessListItem.js:72 #: screens/User/UserRoles/UserRolesList.js:142 msgid "User Roles" msgstr "" @@ -9893,7 +10556,7 @@ msgstr "User and Automation Analytics" #~ msgid "User and Insights analytics" #~ msgstr "User and Insights analytics" -#: components/AppContainer/PageHeaderToolbar.js:159 +#: components/AppContainer/PageHeaderToolbar.js:154 msgid "User details" msgstr "User details" @@ -9909,15 +10572,15 @@ msgstr "User tokens" #: components/AddRole/AddResourceRole.js:38 #: components/ResourceAccessList/ResourceAccessList.js:173 #: components/ResourceAccessList/ResourceAccessList.js:226 -#: screens/Login/Login.js:208 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:143 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:248 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:298 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:356 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:65 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:251 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:328 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:427 +#: screens/Login/Login.js:230 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:144 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:253 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:303 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:361 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:67 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:260 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:337 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:442 #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:92 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:204 #: screens/User/UserDetail/UserDetail.js:68 @@ -9950,31 +10613,31 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:81 -#: components/PromptDetail/PromptDetail.js:159 -#: components/PromptDetail/PromptDetail.js:291 -#: components/PromptDetail/PromptJobTemplateDetail.js:278 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:132 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:393 -#: screens/Host/HostDetail/HostDetail.js:91 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:126 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:115 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 +#: components/PromptDetail/PromptJobTemplateDetail.js:286 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:135 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 +#: screens/Host/HostDetail/HostDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:54 -#: screens/Inventory/shared/InventoryForm.js:90 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 +#: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 -#: screens/Job/JobDetail/JobDetail.js:528 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:484 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:228 -#: screens/Template/shared/JobTemplateForm.js:393 -#: screens/Template/shared/WorkflowJobTemplateForm.js:205 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:335 +#: screens/Job/JobDetail/JobDetail.js:546 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 +#: screens/Template/shared/JobTemplateForm.js:402 +#: screens/Template/shared/WorkflowJobTemplateForm.js:212 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:293 msgid "Variables" msgstr "Variables" -#: screens/Job/JobOutput/JobOutputSearch.js:131 +#: screens/Job/JobOutput/JobOutputSearch.js:130 msgid "Variables Prompted" msgstr "Variables Prompted" @@ -9982,7 +10645,7 @@ msgstr "Variables Prompted" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." @@ -9994,34 +10657,34 @@ msgstr "Vault password" msgid "Vault password | {credId}" msgstr "Vault password | {credId}" -#: screens/Job/JobOutput/JobOutputSearch.js:132 +#: screens/Job/JobOutput/JobOutputSearch.js:131 msgid "Verbose" msgstr "Verbose" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:221 -#: components/PromptDetail/PromptInventorySourceDetail.js:111 -#: components/PromptDetail/PromptJobTemplateDetail.js:149 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:309 -#: components/VerbositySelectField/VerbositySelectField.js:47 -#: components/VerbositySelectField/VerbositySelectField.js:58 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:43 -#: screens/Job/JobDetail/JobDetail.js:326 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:264 +#: components/PromptDetail/PromptDetail.js:247 +#: components/PromptDetail/PromptInventorySourceDetail.js:100 +#: components/PromptDetail/PromptJobTemplateDetail.js:154 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 +#: components/VerbositySelectField/VerbositySelectField.js:34 +#: components/VerbositySelectField/VerbositySelectField.js:45 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 +#: screens/Job/JobDetail/JobDetail.js:331 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "Verbosity" #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:64 -msgid "Version" -msgstr "Version" +#~ msgid "Version" +#~ msgstr "Version" #: screens/Setting/AzureAD/AzureAD.js:25 msgid "View Azure AD settings" msgstr "View Azure AD settings" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "View Credential Details" @@ -10041,11 +10704,11 @@ msgstr "View Google OAuth 2.0 settings" msgid "View Host Details" msgstr "View Host Details" -#: screens/Instances/Instance.js:41 +#: screens/Instances/Instance.js:78 msgid "View Instance Details" msgstr "View Instance Details" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -10063,7 +10726,7 @@ msgstr "View Inventory Host Details" msgid "View JSON examples at <0>www.json.org" msgstr "View JSON examples at <0>www.json.org" -#: screens/Job/Job.js:183 +#: screens/Job/Job.js:212 msgid "View Job Details" msgstr "View Job Details" @@ -10087,6 +10750,10 @@ msgstr "View Miscellaneous Authentication settings" msgid "View Miscellaneous System settings" msgstr "View Miscellaneous System settings" +#: screens/Setting/OIDC/OIDC.js:25 +msgid "View OIDC settings" +msgstr "View OIDC settings" + #: screens/Organization/Organization.js:225 msgid "View Organization Details" msgstr "View Organization Details" @@ -10142,7 +10809,7 @@ msgstr "View User Details" msgid "View User Interface settings" msgstr "View User Interface settings" -#: screens/WorkflowApproval/WorkflowApproval.js:102 +#: screens/WorkflowApproval/WorkflowApproval.js:105 msgid "View Workflow Approval Details" msgstr "View Workflow Approval Details" @@ -10155,7 +10822,7 @@ msgstr "View YAML examples at <0>docs.ansible.com" msgid "View activity stream" msgstr "View activity stream" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "View all Credentials." @@ -10176,7 +10843,7 @@ msgstr "View all Inventory Hosts." msgid "View all Jobs" msgstr "View all Jobs" -#: screens/Job/Job.js:139 +#: screens/Job/Job.js:162 msgid "View all Jobs." msgstr "View all Jobs." @@ -10231,7 +10898,7 @@ msgstr "View all instance groups" msgid "View all management jobs" msgstr "View all management jobs" -#: screens/Setting/Settings.js:197 +#: screens/Setting/Settings.js:204 msgid "View all settings" msgstr "View all settings" @@ -10239,7 +10906,7 @@ msgstr "View all settings" msgid "View all tokens." msgstr "View all tokens." -#: screens/Setting/SettingList.js:129 +#: screens/Setting/SettingList.js:133 msgid "View and edit your subscription information" msgstr "View and edit your subscription information" @@ -10256,7 +10923,7 @@ msgstr "View inventory source details" msgid "View job {0}" msgstr "View job {0}" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:193 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:220 msgid "View node details" msgstr "View node details" @@ -10275,22 +10942,22 @@ msgstr "" msgid "Visualizer" msgstr "Visualizer" -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:43 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:44 msgid "WARNING:" msgstr "WARNING:" #: components/JobList/JobList.js:229 -#: components/StatusLabel/StatusLabel.js:44 +#: components/StatusLabel/StatusLabel.js:52 #: components/Workflow/WorkflowNodeHelp.js:96 msgid "Waiting" msgstr "Waiting" -#: screens/Job/JobOutput/EmptyOutput.js:23 +#: screens/Job/JobOutput/EmptyOutput.js:35 msgid "Waiting for job output…" msgstr "Waiting for job output…" #: components/Workflow/WorkflowLegend.js:118 -#: screens/Job/JobOutput/JobOutputSearch.js:133 +#: screens/Job/JobOutput/JobOutputSearch.js:132 msgid "Warning" msgstr "Warning" @@ -10298,6 +10965,10 @@ msgstr "Warning" msgid "Warning: Unsaved Changes" msgstr "Warning: Unsaved Changes" +#: components/Schedule/shared/ScheduleFormFields.js:43 +msgid "Warning: {selectedValue} is a link to {0} and will be saved as that." +msgstr "Warning: {selectedValue} is a link to {0} and will be saved as that." + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:119 msgid "We were unable to locate licenses associated with this account." msgstr "We were unable to locate licenses associated with this account." @@ -10312,90 +10983,95 @@ msgstr "We were unable to locate subscriptions associated with this account." msgid "Webhook" msgstr "Webhook" -#: components/PromptDetail/PromptJobTemplateDetail.js:172 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:101 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 -#: screens/Template/shared/WebhookSubForm.js:198 +#: components/PromptDetail/PromptJobTemplateDetail.js:177 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:103 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 +#: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Webhook Credential" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:176 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:175 msgid "Webhook Credentials" msgstr "Webhook Credentials" -#: components/PromptDetail/PromptJobTemplateDetail.js:168 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:169 -#: screens/Template/shared/WebhookSubForm.js:172 +#: components/PromptDetail/PromptJobTemplateDetail.js:173 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:92 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 +#: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" msgstr "Webhook Key" -#: components/PromptDetail/PromptJobTemplateDetail.js:161 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:304 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:157 -#: screens/Template/shared/WebhookSubForm.js:128 +#: components/PromptDetail/PromptJobTemplateDetail.js:166 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:91 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 +#: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" msgstr "Webhook Service" -#: components/PromptDetail/PromptJobTemplateDetail.js:164 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:93 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:163 -#: screens/Template/shared/WebhookSubForm.js:160 -#: screens/Template/shared/WebhookSubForm.js:166 +#: components/PromptDetail/PromptJobTemplateDetail.js:169 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:95 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 +#: screens/Template/shared/WebhookSubForm.js:161 +#: screens/Template/shared/WebhookSubForm.js:167 msgid "Webhook URL" msgstr "Webhook URL" -#: screens/Template/shared/JobTemplateForm.js:588 -#: screens/Template/shared/WorkflowJobTemplateForm.js:240 +#: screens/Template/shared/JobTemplateForm.js:646 +#: screens/Template/shared/WorkflowJobTemplateForm.js:271 msgid "Webhook details" msgstr "Webhook details" -#: screens/Template/shared/JobTemplate.helptext.js:23 +#: screens/Template/shared/JobTemplate.helptext.js:24 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:17 msgid "Webhook services can launch jobs with this workflow job template by making a POST request to this URL." msgstr "Webhook services can launch jobs with this workflow job template by making a POST request to this URL." -#: screens/Template/shared/JobTemplate.helptext.js:24 +#: screens/Template/shared/JobTemplate.helptext.js:25 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:18 msgid "Webhook services can use this as a shared secret." msgstr "Webhook services can use this as a shared secret." #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:140 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhooks" -#: screens/Template/shared/WorkflowJobTemplate.helptext.js:24 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:26 msgid "Webhooks: Enable Webhook for this workflow job template." msgstr "Webhooks: Enable Webhook for this workflow job template." -#: screens/Template/shared/JobTemplate.helptext.js:39 +#: screens/Template/shared/JobTemplate.helptext.js:42 msgid "Webhooks: Enable webhook for this template." msgstr "Webhooks: Enable webhook for this template." -#: components/Schedule/shared/FrequencyDetailSubform.js:281 +#: components/Schedule/shared/FrequencyDetailSubform.js:288 msgid "Wed" msgstr "Wed" -#: components/Schedule/shared/FrequencyDetailSubform.js:286 -#: components/Schedule/shared/FrequencyDetailSubform.js:436 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:79 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:185 +#: components/Schedule/shared/FrequencyDetailSubform.js:293 +#: components/Schedule/shared/FrequencyDetailSubform.js:443 msgid "Wednesday" msgstr "Wednesday" -#: components/Schedule/shared/ScheduleForm.js:157 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 +#: components/Schedule/shared/FrequencyDetailSubform.js:179 +#: components/Schedule/shared/ScheduleFormFields.js:128 +#: components/Schedule/shared/ScheduleFormFields.js:188 msgid "Week" msgstr "Week" -#: components/Schedule/shared/FrequencyDetailSubform.js:457 +#: components/Schedule/shared/FrequencyDetailSubform.js:464 msgid "Weekday" msgstr "Weekday" -#: components/Schedule/shared/FrequencyDetailSubform.js:462 +#: components/Schedule/shared/FrequencyDetailSubform.js:469 msgid "Weekend day" msgstr "Weekend day" @@ -10407,7 +11083,7 @@ msgstr "" "Welcome to Red Hat Ansible Automation Platform!\n" "Please complete the steps below to activate your subscription." -#: screens/Login/Login.js:168 +#: screens/Login/Login.js:190 msgid "Welcome to {brandName}!" msgstr "Welcome to {brandName}!" @@ -10445,8 +11121,8 @@ msgstr "Workflow Approval not found." #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:195 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:233 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10455,29 +11131,33 @@ msgstr "Workflow Approvals" #: components/JobList/JobList.js:216 #: components/JobList/JobListItem.js:47 #: components/Schedule/ScheduleList/ScheduleListItem.js:40 -#: screens/Job/JobDetail/JobDetail.js:69 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:265 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:252 +#: screens/Job/JobDetail/JobDetail.js:70 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "Workflow Job" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 +msgid "Workflow Job 1/{0}" +msgstr "Workflow Job 1/{0}" + #: components/JobList/JobListItem.js:201 #: components/Workflow/WorkflowNodeHelp.js:63 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:20 -#: screens/Job/JobDetail/JobDetail.js:224 +#: screens/Job/JobDetail/JobDetail.js:244 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:91 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227 -#: util/getRelatedResourceDeleteDetails.js:104 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186 +#: util/getRelatedResourceDeleteDetails.js:105 msgid "Workflow Job Template" msgstr "Workflow Job Template" -#: util/getRelatedResourceDeleteDetails.js:114 -#: util/getRelatedResourceDeleteDetails.js:156 -#: util/getRelatedResourceDeleteDetails.js:259 +#: util/getRelatedResourceDeleteDetails.js:115 +#: util/getRelatedResourceDeleteDetails.js:157 +#: util/getRelatedResourceDeleteDetails.js:260 msgid "Workflow Job Template Nodes" msgstr "Workflow Job Template Nodes" -#: util/getRelatedResourceDeleteDetails.js:139 +#: util/getRelatedResourceDeleteDetails.js:140 msgid "Workflow Job Templates" msgstr "Workflow Job Templates" @@ -10485,27 +11165,35 @@ msgstr "Workflow Job Templates" msgid "Workflow Link" msgstr "Workflow Link" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 +msgid "Workflow Nodes" +msgstr "Workflow Nodes" + +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 +msgid "Workflow Statuses" +msgstr "Workflow Statuses" + #: components/TemplateList/TemplateList.js:218 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:98 msgid "Workflow Template" msgstr "Workflow Template" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:514 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:519 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:159 msgid "Workflow approved message" msgstr "Workflow approved message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:526 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:531 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:168 msgid "Workflow approved message body" msgstr "Workflow approved message body" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:538 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:543 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:177 msgid "Workflow denied message" msgstr "Workflow denied message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:550 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:555 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:186 msgid "Workflow denied message body" msgstr "Workflow denied message body" @@ -10515,7 +11203,7 @@ msgstr "Workflow denied message body" msgid "Workflow documentation" msgstr "Workflow documentation" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:261 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:220 msgid "Workflow job details" msgstr "Workflow job details" @@ -10527,26 +11215,26 @@ msgstr "Workflow job templates" msgid "Workflow link modal" msgstr "Workflow link modal" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:228 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:247 msgid "Workflow node view modal" msgstr "Workflow node view modal" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:562 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:567 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:195 msgid "Workflow pending message" msgstr "Workflow pending message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:574 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:579 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:204 msgid "Workflow pending message body" msgstr "Workflow pending message body" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:586 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:591 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:213 msgid "Workflow timed out message" msgstr "Workflow timed out message" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:598 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:603 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:222 msgid "Workflow timed out message body" msgstr "Workflow timed out message body" @@ -10559,7 +11247,10 @@ msgstr "Write" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/shared/ScheduleForm.js:159 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/shared/FrequencyDetailSubform.js:183 +#: components/Schedule/shared/ScheduleFormFields.js:130 +#: components/Schedule/shared/ScheduleFormFields.js:190 msgid "Year" msgstr "Year" @@ -10567,15 +11258,15 @@ msgstr "Year" msgid "Yes" msgstr "Yes" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:28 -#~ msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" -#~ msgstr "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:28 -#~ msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" -#~ msgstr "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" -#: components/Lookup/MultiCredentialsLookup.js:154 +#: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." @@ -10591,6 +11282,14 @@ msgstr "You do not have permission to delete {pluralizedItemName}: {itemsUnableT msgid "You do not have permission to disassociate the following: {itemsUnableToDisassociate}" msgstr "You do not have permission to disassociate the following: {itemsUnableToDisassociate}" +#: screens/Instances/Shared/RemoveInstanceButton.js:72 +msgid "You do not have permission to remove instances: {itemsUnableToremove}" +msgstr "You do not have permission to remove instances: {itemsUnableToremove}" + +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:82 +msgid "You have automated against more hosts than your subscription allows." +msgstr "You have automated against more hosts than your subscription allows." + #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:87 msgid "" "You may apply a number of possible variables in the\n" @@ -10599,7 +11298,7 @@ msgstr "" "You may apply a number of possible variables in the\n" "message. For more information, refer to the" -#: screens/Login/Login.js:176 +#: screens/Login/Login.js:198 msgid "Your session has expired. Please log in to continue where you left off." msgstr "Your session has expired. Please log in to continue where you left off." @@ -10625,13 +11324,13 @@ msgstr "Zoom in" msgid "Zoom out" msgstr "Zoom out" -#: screens/Template/shared/JobTemplateForm.js:685 -#: screens/Template/shared/WebhookSubForm.js:149 +#: screens/Template/shared/JobTemplateForm.js:754 +#: screens/Template/shared/WebhookSubForm.js:150 msgid "a new webhook key will be generated on save." msgstr "a new webhook key will be generated on save." -#: screens/Template/shared/JobTemplateForm.js:682 -#: screens/Template/shared/WebhookSubForm.js:139 +#: screens/Template/shared/JobTemplateForm.js:751 +#: screens/Template/shared/WebhookSubForm.js:140 msgid "a new webhook url will be generated on save." msgstr "a new webhook url will be generated on save." @@ -10661,6 +11360,14 @@ msgstr "" msgid "cancel edit login redirect" msgstr "cancel edit login redirect" +#: screens/Instances/Shared/RemoveInstanceButton.js:169 +msgid "cancel remove" +msgstr "cancel remove" + +#: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:34 +msgid "canceled" +msgstr "canceled" + #: components/AdHocCommands/AdHocDetailsStep.js:217 msgid "command" msgstr "command" @@ -10683,35 +11390,51 @@ msgstr "confirm edit login redirect" msgid "content-loading-in-progress" msgstr "content-loading-in-progress" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:189 +msgid "day" +msgstr "day" + #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:151 msgid "deletion error" msgstr "deletion error" #: screens/ActivityStream/ActivityStreamDescription.js:513 +#: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:37 msgid "denied" msgstr "denied" +#: screens/Job/JobOutput/EmptyOutput.js:41 +msgid "details." +msgstr "details." + #: components/DisassociateButton/DisassociateButton.js:91 msgid "disassociate" msgstr "disassociate" -#: components/Lookup/HostFilterLookup.js:405 +#: components/InstanceDetails.js/InstanceDetails.js:301 +#: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 +#: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:239 +#: screens/Template/shared/JobTemplate.helptext.js:61 msgid "documentation" msgstr "documentation" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:116 -#: screens/Host/HostDetail/HostDetail.js:102 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:100 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:163 -#: screens/Project/ProjectDetail/ProjectDetail.js:291 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:165 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 +#: screens/Host/HostDetail/HostDetail.js:104 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 +#: screens/Project/ProjectDetail/ProjectDetail.js:309 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 msgid "edit" msgstr "edit" @@ -10725,19 +11448,26 @@ msgstr "edit" msgid "encrypted" msgstr "encrypted" -#: components/Lookup/HostFilterLookup.js:407 +#: components/InstanceDetails.js/InstanceDetails.js:303 +#: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "for more info." #: screens/NotificationTemplate/shared/Notifications.helptext.js:21 +#: screens/NotificationTemplate/shared/Notifications.helptext.js:40 #: screens/Template/Survey/SurveyQuestionForm.js:271 +#: screens/Template/shared/JobTemplate.helptext.js:63 msgid "for more information." msgstr "for more information." #: screens/TopologyView/Legend.js:100 -msgid "h" -msgstr "h" +#~ msgid "h" +#~ msgstr "h" #: components/AdHocCommands/AdHocDetailsStep.js:150 msgid "here" @@ -10745,7 +11475,7 @@ msgstr "here" #: components/AdHocCommands/AdHocDetailsStep.js:118 #: components/AdHocCommands/AdHocDetailsStep.js:170 -#: screens/Job/Job.helptext.js:38 +#: screens/Job/Job.helptext.js:39 msgid "here." msgstr "here." @@ -10757,7 +11487,7 @@ msgstr "host-description-{0}" msgid "host-name-{0}" msgstr "host-name-{0}" -#: components/Lookup/HostFilterLookup.js:417 +#: components/Lookup/HostFilterLookup.js:418 msgid "hosts" msgstr "hosts" @@ -10790,11 +11520,11 @@ msgid "new choice" msgstr "new choice" #: screens/TopologyView/Tooltip.js:94 -msgid "node" -msgstr "node" +#~ msgid "node" +#~ msgstr "node" #: components/Pagination/Pagination.js:36 -#: components/Schedule/shared/FrequencyDetailSubform.js:473 +#: components/Schedule/shared/FrequencyDetailSubform.js:480 msgid "of" msgstr "of" @@ -10823,7 +11553,7 @@ msgstr "relaunch jobs" msgid "sec" msgstr "sec" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "seconds" @@ -10836,15 +11566,15 @@ msgstr "select module" #~ msgstr "select verbosity" #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:135 -msgid "since" -msgstr "since" +#~ msgid "since" +#~ msgstr "since" #: screens/User/UserList/UserListItem.js:49 msgid "social login" msgstr "social login" -#: screens/Template/shared/JobTemplateForm.js:339 -#: screens/Template/shared/WorkflowJobTemplateForm.js:183 +#: screens/Template/shared/JobTemplateForm.js:346 +#: screens/Template/shared/WorkflowJobTemplateForm.js:188 msgid "source control branch" msgstr "source control branch" @@ -10864,7 +11594,15 @@ msgstr "toggle changes" msgid "updated" msgstr "updated" -#: screens/Template/shared/WebhookSubForm.js:180 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:190 +msgid "weekday" +msgstr "weekday" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:191 +msgid "weekend day" +msgstr "weekend day" + +#: screens/Template/shared/WebhookSubForm.js:181 msgid "workflow job template webhook key" msgstr "workflow job template webhook key" @@ -10900,7 +11638,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:239 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10916,10 +11654,14 @@ msgstr "{0, plural, one {This credential type is currently being used by some cr msgid "{0, plural, one {This execution environment is currently being used by other resources. Are you sure you want to delete it?} other {These execution environments could be in use by other resources that rely on them. Are you sure you want to delete them anyway?}}" msgstr "{0, plural, one {This execution environment is currently being used by other resources. Are you sure you want to delete it?} other {These execution environments could be in use by other resources that rely on them. Are you sure you want to delete them anyway?}}" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:182 msgid "{0, plural, one {This instance group is currently being by other resources. Are you sure you want to delete it?} other {Deleting these instance groups could impact other resources that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This instance group is currently being by other resources. Are you sure you want to delete it?} other {Deleting these instance groups could impact other resources that rely on them. Are you sure you want to delete anyway?}}" +#: screens/Instances/Shared/RemoveInstanceButton.js:85 +msgid "{0, plural, one {This intance is currently being used by other resources. Are you sure you want to delete it?} other {Deprovisioning these instances could impact other resources that rely on them. Are you sure you want to delete anyway?}}" +msgstr "{0, plural, one {This intance is currently being used by other resources. Are you sure you want to delete it?} other {Deprovisioning these instances could impact other resources that rely on them. Are you sure you want to delete anyway?}}" + #: screens/Inventory/InventoryList/InventoryList.js:240 msgid "{0, plural, one {This inventory is currently being used by some templates. Are you sure you want to delete it?} other {Deleting these inventories could impact some templates that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This inventory is currently being used by some templates. Are you sure you want to delete it?} other {Deleting these inventories could impact some templates that rely on them. Are you sure you want to delete anyway?}}" @@ -10940,7 +11682,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10953,6 +11695,14 @@ msgstr "{0, plural, one {You cannot cancel the following job because it is not r msgid "{0, plural, one {You do not have permission to cancel the following job:} other {You do not have permission to cancel the following jobs:}}" msgstr "{0, plural, one {You do not have permission to cancel the following job:} other {You do not have permission to cancel the following jobs:}}" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:143 +msgid "{0, selectordinal, one {The first {dayOfWeek}} two {The second {dayOfWeek}} =3 {The third {dayOfWeek}} =4 {The fourth {dayOfWeek}} =5 {The fifth {dayOfWeek}}}" +msgstr "{0, selectordinal, one {The first {dayOfWeek}} two {The second {dayOfWeek}} =3 {The third {dayOfWeek}} =4 {The fourth {dayOfWeek}} =5 {The fifth {dayOfWeek}}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:202 +msgid "{0, selectordinal, one {The first {weekday} of {month}} two {The second {weekday} of {month}} =3 {The third {weekday} of {month}} =4 {The fourth {weekday} of {month}} =5 {The fifth {weekday} of {month}}}" +msgstr "{0, selectordinal, one {The first {weekday} of {month}} two {The second {weekday} of {month}} =3 {The third {weekday} of {month}} =4 {The fourth {weekday} of {month}} =5 {The fifth {weekday} of {month}}}" + #: screens/ActivityStream/ActivityStreamListItem.js:28 msgid "{0} (deleted)" msgstr "{0} (deleted)" @@ -10961,6 +11711,10 @@ msgstr "{0} (deleted)" msgid "{0} more" msgstr "{0} more" +#: screens/Job/JobDetail/JobDetail.js:399 +msgid "{0} seconds" +msgstr "{0} seconds" + #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:138 #~ msgid "{0} since {1}" #~ msgstr "{0} since {1}" @@ -10969,6 +11723,10 @@ msgstr "{0} more" #~ msgid "{0} sources with sync failures." #~ msgstr "{0} sources with sync failures." +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:95 +msgid "{automatedInstancesCount} since {automatedInstancesSinceDateTime}" +msgstr "{automatedInstancesCount} since {automatedInstancesSinceDateTime}" + #: components/AppContainer/AppContainer.js:55 msgid "{brandName} logo" msgstr "{brandName} logo" @@ -10977,10 +11735,12 @@ msgstr "{brandName} logo" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} by <0>{username}" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:174 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 +#: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10988,27 +11748,51 @@ msgstr "{forks, plural, one {# fork} other {# forks}}" #~ msgid "{hopNodeSelected, plural, one {Cannot run health check on a hop node. Deselect the hop node to run a health check.} other {Cannot run health check on hop nodes. Deselect the hop nodes to run health checks.}}" #~ msgstr "{hopNodeSelected, plural, one {Cannot run health check on a hop node. Deselect the hop node to run a health check.} other {Cannot run health check on hop nodes. Deselect the hop nodes to run health checks.}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:193 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:41 +msgid "{interval, plural, one {{interval} day} other {{interval} days}}" +msgstr "{interval, plural, one {{interval} day} other {{interval} days}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:33 +msgid "{interval, plural, one {{interval} hour} other {{interval} hours}}" +msgstr "{interval, plural, one {{interval} hour} other {{interval} hours}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:25 +msgid "{interval, plural, one {{interval} minute} other {{interval} minutes}}" +msgstr "{interval, plural, one {{interval} minute} other {{interval} minutes}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:57 +msgid "{interval, plural, one {{interval} month} other {{interval} months}}" +msgstr "{interval, plural, one {{interval} month} other {{interval} months}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:49 +msgid "{interval, plural, one {{interval} week} other {{interval} weeks}}" +msgstr "{interval, plural, one {{interval} week} other {{interval} weeks}}" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:65 +msgid "{interval, plural, one {{interval} year} other {{interval} years}}" +msgstr "{interval, plural, one {{interval} year} other {{interval} years}}" + +#: components/Schedule/shared/FrequencyDetailSubform.js:198 msgid "{intervalValue, plural, one {day} other {days}}" msgstr "{intervalValue, plural, one {day} other {days}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:191 +#: components/Schedule/shared/FrequencyDetailSubform.js:196 msgid "{intervalValue, plural, one {hour} other {hours}}" msgstr "{intervalValue, plural, one {hour} other {hours}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:189 +#: components/Schedule/shared/FrequencyDetailSubform.js:194 msgid "{intervalValue, plural, one {minute} other {minutes}}" msgstr "{intervalValue, plural, one {minute} other {minutes}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:197 +#: components/Schedule/shared/FrequencyDetailSubform.js:202 msgid "{intervalValue, plural, one {month} other {months}}" msgstr "{intervalValue, plural, one {month} other {months}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:195 +#: components/Schedule/shared/FrequencyDetailSubform.js:200 msgid "{intervalValue, plural, one {week} other {weeks}}" msgstr "{intervalValue, plural, one {week} other {weeks}}" -#: components/Schedule/shared/FrequencyDetailSubform.js:199 +#: components/Schedule/shared/FrequencyDetailSubform.js:204 msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" @@ -11020,7 +11804,7 @@ msgstr "{intervalValue, plural, one {year} other {years}}" #~ msgid "{label} time" #~ msgstr "{label} time" -#: components/PromptDetail/PromptDetail.js:41 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} min {seconds} sec" @@ -11036,6 +11820,10 @@ msgstr "{numJobsToCancel, plural, one {This action will cancel the following job msgid "{numJobsToCancel, plural, one {{0}} other {{1}}}" msgstr "{numJobsToCancel, plural, one {{0}} other {{1}}}" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:226 +msgid "{numOccurrences, plural, one {After {numOccurrences} occurrence} other {After {numOccurrences} occurrences}}" +msgstr "{numOccurrences, plural, one {After {numOccurrences} occurrence} other {After {numOccurrences} occurrences}}" + #: components/DetailList/NumberSinceDetail.js:19 #~ msgid "{number} since {dateStr}" #~ msgstr "{number} since {dateStr}" @@ -11044,7 +11832,7 @@ msgstr "{numJobsToCancel, plural, one {{0}} other {{1}}}" msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} List" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" diff --git a/awx/ui/src/locales/es/messages.po b/awx/ui/src/locales/es/messages.po index 3521e3b94d..b2159124f9 100644 --- a/awx/ui/src/locales/es/messages.po +++ b/awx/ui/src/locales/es/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(Limitado a los primeros 10)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(Preguntar al ejecutar)" @@ -25,7 +26,7 @@ msgstr "(Preguntar al ejecutar)" 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." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (raíz del proyecto)" @@ -65,6 +66,10 @@ msgstr "4 (Depuración de la conexión)" msgid "5 (WinRM Debug)" msgstr "5 (Depuración de WinRM)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -99,7 +104,7 @@ msgstr "Acerca de" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -135,7 +140,7 @@ msgstr "Acción" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -157,18 +162,19 @@ msgstr "Acción" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -192,7 +198,7 @@ msgstr "Acción" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "Acciones" @@ -360,7 +366,7 @@ msgid "Alert modal" msgstr "Modal de alerta" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -388,7 +394,8 @@ msgstr "Permitir la invalidación de la rama" msgid "" "Allow changing the Source Control branch or revision in a job\n" "template that uses this project." -msgstr "Permitir el cambio de la rama o revisión de la fuente de control\n" +msgstr "" +"Permitir el cambio de la rama o revisión de la fuente de control\n" "en una plantilla de trabajo que utilice este proyecto." #: screens/Application/shared/Application.helptext.js:6 @@ -426,7 +433,7 @@ msgstr "Tipo de respuesta" msgid "Answer variable name" msgstr "Nombre de la variable de respuesta" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "Cualquiera" @@ -476,6 +483,10 @@ msgstr "Aplicaciones y tokens" msgid "Approval" msgstr "Aprobación" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -543,7 +554,7 @@ msgstr "¿Está seguro de que desea eliminar el acceso de {0} a {1}? Esto afecta msgid "Are you sure you want to remove {0} access from {username}?" msgstr "¿Está seguro de que quiere eliminar el acceso de {0} a {username}?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "¿Está seguro de que desea enviar la solicitud para cancelar este trabajo?" @@ -556,7 +567,7 @@ msgstr "Argumentos" msgid "Artifacts" msgstr "Artefactos" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "Asociar" @@ -592,10 +603,11 @@ msgstr "Expiración del código de autorización" msgid "Authorization grant type" msgstr "Tipo de autorización" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -632,7 +644,7 @@ msgstr "Configuración de Azure AD" msgid "Back" msgstr "Volver" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "Volver a Credenciales" @@ -655,7 +667,8 @@ msgstr "Volver a Hosts" msgid "Back to Instance Groups" msgstr "Volver a los grupos de instancias" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "Volver a las instancias" @@ -692,7 +705,7 @@ msgstr "Volver a Programaciones" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -765,7 +778,8 @@ msgid "" "you can input tags, commit hashes, and arbitrary refs. Some\n" "commit hashes and refs may not be available unless you also\n" "provide a custom refspec." -msgstr "Rama para realizar la comprobación. Además de las ramas, puede\n" +msgstr "" +"Rama para realizar la comprobación. Además de las ramas, puede\n" "introducir etiquetas, hashes de commit y referencias arbitrarias. Es posible\n" "que algunos hashes y referencias de commit no estén disponibles,\n" "a menos que usted también proporcione un refspec personalizado." @@ -774,6 +788,10 @@ msgstr "Rama para realizar la comprobación. Además de las ramas, puede\n" msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "Rama para usar en la ejecución del trabajo. Se utiliza el proyecto predeterminado si está en blanco. Solo se permite si el campo allow_override del proyecto se establece en true." +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "Imagen de marca" @@ -791,10 +809,11 @@ msgstr "Navegar" msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "Por defecto, recopilamos y transmitimos a Red Hat datos analíticos sobre el uso del servicio. Hay dos categorías de datos recogidos por el servicio. Para más información, consulte <0>esta página de documentación de Tower. Desmarque las siguientes casillas para desactivar esta función." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -806,7 +825,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "Tiempo de espera de la caché" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "Tiempo de espera de la caché" @@ -829,8 +848,8 @@ msgstr "Tiempo de espera de la caché (segundos)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -867,14 +886,14 @@ msgstr "Tiempo de espera de la caché (segundos)" msgid "Cancel" msgstr "Cancelar" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "Cancelar sincronización de la fuente del inventario" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "Cancelar tarea" @@ -883,7 +902,7 @@ msgstr "Cancelar tarea" msgid "Cancel Project Sync" msgstr "Cancelar sincronización del proyecto" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "Cancelar sincronización" @@ -895,8 +914,8 @@ msgstr "Cancelar sincronización" msgid "Cancel Workflow" msgstr "Cancelar el flujo de trabajo" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "Cancelar tarea" @@ -935,7 +954,7 @@ msgstr "Cancelar modificación de la suscripción" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "Cancelar {0}" @@ -951,10 +970,10 @@ msgstr "Cancelado" msgid "" "Cannot enable log aggregator without providing\n" "logging aggregator host and logging aggregator type." -msgstr "No se puede habilitar la agregación de registros sin proporcionar\n" +msgstr "" +"No se puede habilitar la agregación de registros sin proporcionar\n" "el host y el tipo de agregación de registros." -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "No se puede ejecutar la comprobación de estado en los nodos de salto." @@ -965,12 +984,13 @@ msgstr "No se puede ejecutar la comprobación de estado en los nodos de salto." msgid "Capacity" msgstr "Capacidad" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "Ajuste de la capacidad" @@ -998,7 +1018,8 @@ msgstr "Versión de startswith que no distingue mayúsculas de minúsculas." msgid "" "Change PROJECTS_ROOT when deploying\n" "{brandName} to change this location." -msgstr "Cambie PROJECTS_ROOT al implementar {brandName}\n" +msgstr "" +"Cambie PROJECTS_ROOT al implementar {brandName}\n" "para cambiar esta ubicación." #: components/StatusLabel/StatusLabel.js:55 @@ -1057,7 +1078,7 @@ msgstr "Seleccionar un tipo de tarea" msgid "Choose a module" msgstr "Elegir un módulo" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "Elegir una fuente" @@ -1126,7 +1147,8 @@ msgstr "Haga clic en este botón para verificar la conexión con el sistema de g msgid "Click to create a new link to this node." msgstr "Haga clic para crear un nuevo enlace a este nodo." -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "Haga clic para descargar el paquete" @@ -1201,7 +1223,7 @@ msgstr "Compatible" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1209,7 +1231,8 @@ msgstr "Tareas concurrentes" #: screens/Template/shared/JobTemplate.helptext.js:38 msgid "Concurrent jobs: If enabled, simultaneous runs of this job template will be allowed." -msgstr "Si se habilita esta opción, se permitirá la ejecución\n" +msgstr "" +"Si se habilita esta opción, se permitirá la ejecución\n" "simultánea de esta plantilla de trabajo." #: screens/Template/shared/WorkflowJobTemplate.helptext.js:25 @@ -1279,7 +1302,7 @@ msgstr "Confirmar selección" msgid "Container Group" msgstr "Grupo de contenedores" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1304,8 +1327,8 @@ msgstr "Credencial de validación de la firma del contenido" msgid "Continue" msgstr "Continuar" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "Control" @@ -1328,7 +1351,7 @@ msgstr "Controlar el nivel de salida que ansible producirá al ejecutar playbook msgid "Controller Node" msgstr "Nombre del controlador" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "Convergencia" @@ -1501,28 +1524,28 @@ msgid "Create user token" msgstr "Crear token de usuario" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1535,16 +1558,16 @@ msgstr "Creado" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1585,16 +1608,16 @@ msgstr "Creado por (nombre de usuario)" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1631,7 +1654,7 @@ msgstr "Tipos de credencial" msgid "Credential copied successfully" msgstr "La credencial se copió correctamente" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "No se encontró la credencial." @@ -1640,7 +1663,7 @@ msgstr "No se encontró la credencial." msgid "Credential passwords" msgstr "Contraseñas de credenciales" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Credencial para autenticarse con Kubernetes u OpenShift" @@ -1657,13 +1680,13 @@ msgid "Credential type not found." msgstr "No se encontró el tipo de credencial." #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1672,7 +1695,7 @@ msgstr "No se encontró el tipo de credencial." #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1687,11 +1710,11 @@ msgstr "No se permiten las credenciales que requieran contraseñas al iniciarse. msgid "Current page" msgstr "Página actual" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "Campo para pasar una especificación personalizada de Kubernetes u OpenShift Pod." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "Especificaciones del pod personalizado" @@ -1713,8 +1736,8 @@ msgstr "El entorno virtual personalizado {virtualEnvironment} debe ser sustituid msgid "Customize messages…" msgstr "Personalizar mensajes." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Personalizar especificaciones del pod" @@ -1724,7 +1747,7 @@ msgid "DELETED" msgstr "ELIMINADO" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "Panel de control" @@ -1740,7 +1763,7 @@ msgstr "Período de conservación de datos" msgid "Date" msgstr "Fecha" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1753,7 +1776,7 @@ msgstr "Día" msgid "Day {0}" msgstr "Día {0}" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "Días de datos para mantener" @@ -1817,17 +1840,17 @@ msgstr "Defina características y funciones a nivel del sistema" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1835,11 +1858,11 @@ msgstr "Defina características y funciones a nivel del sistema" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1866,17 +1889,17 @@ msgstr "Eliminar entorno de ejecución" msgid "Delete Host" msgstr "Borrar un host" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "Eliminar inventario" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "Eliminar tarea" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "Eliminar plantilla de trabajo" @@ -1884,7 +1907,7 @@ msgstr "Eliminar plantilla de trabajo" msgid "Delete Notification" msgstr "Eliminar notificación" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "Eliminar organización" @@ -1896,7 +1919,7 @@ msgstr "Eliminar proyecto" msgid "Delete Questions" msgstr "Eliminar pregunta" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "Eliminar planificación" @@ -1941,16 +1964,16 @@ msgstr "Eliminar tipo de credencial" msgid "Delete error" msgstr "Eliminar el error" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "Eliminar grupo de instancias" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "Eliminar fuente de inventario" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "Eliminar inventario inteligente" @@ -1964,7 +1987,8 @@ msgid "" "performing an update. Depending on the size of the\n" "repository this may significantly increase the amount\n" "of time required to complete an update." -msgstr "Elimine el repositorio local por completo antes de realizar\n" +msgstr "" +"Elimine el repositorio local por completo antes de realizar\n" "una actualización. Según el tamaño del repositorio, esto\n" "podría incrementar significativamente el tiempo necesario\n" "para completar una actualización." @@ -2020,6 +2044,10 @@ msgstr "Denegado: {0}. Consulte el flujo de actividad para obtener más informac msgid "Denied by {0} - {1}" msgstr "Denegado por {0} - {1}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2045,8 +2073,8 @@ msgstr "Fallo de desaprovisionamiento" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2068,28 +2096,28 @@ msgstr "Fallo de desaprovisionamiento" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2099,7 +2127,7 @@ msgstr "Fallo de desaprovisionamiento" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2116,7 +2144,7 @@ msgstr "Fallo de desaprovisionamiento" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "Descripción" @@ -2146,10 +2174,11 @@ msgstr "Usuarios o canales destinatarios" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2158,7 +2187,7 @@ msgstr "Usuarios o canales destinatarios" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2173,7 +2202,7 @@ msgstr "Usuarios o canales destinatarios" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2187,7 +2216,7 @@ msgstr "Usuarios o canales destinatarios" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2235,7 +2264,7 @@ msgstr "Usuarios o canales destinatarios" msgid "Details" msgstr "Detalles" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "Pestaña de detalles" @@ -2283,8 +2312,8 @@ msgstr "¿Disociar grupo del host?" msgid "Disassociate host from group?" msgstr "¿Disociar host del grupo?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "¿Disociar instancia del grupo de instancias?" @@ -2335,8 +2364,8 @@ msgstr "Finalizado" msgid "Download Bundle" msgstr "Descargar paquete" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "Descargar salida" @@ -2374,7 +2403,8 @@ msgid "" "Each time a job runs using this inventory,\n" "refresh the inventory from the selected source before\n" "executing job tasks." -msgstr "Cada vez que se ejecute una tarea con este inventario,\n" +msgstr "" +"Cada vez que se ejecute una tarea con este inventario,\n" "actualice el inventario de la fuente seleccionada antes\n" "de ejecutar tareas de trabajo." @@ -2382,31 +2412,32 @@ msgstr "Cada vez que se ejecute una tarea con este inventario,\n" msgid "" "Each time a job runs using this project, update the\n" "revision of the project prior to starting the job." -msgstr "Cada vez que una tarea se ejecute con este proyecto,\n" +msgstr "" +"Cada vez que una tarea se ejecute con este proyecto,\n" "actualice la revisión del proyecto antes de iniciar dicha tarea." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2422,8 +2453,8 @@ msgstr "Cada vez que una tarea se ejecute con este proyecto,\n" #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2437,8 +2468,8 @@ msgstr "Cada vez que una tarea se ejecute con este proyecto,\n" #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2612,7 +2643,8 @@ msgstr "Modificar detalles" msgid "Edit group" msgstr "Editar grupo" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "Editar el servidor" @@ -2639,16 +2671,16 @@ msgid "Edit workflow" msgstr "Editar el flujo de trabajo" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "Tiempo transcurrido" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "Tiempo transcurrido" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "Tiempo transcurrido de la ejecución de la tarea " @@ -2698,7 +2730,8 @@ msgid "" "has remained secure when a project is synced. \n" "If the content has been tampered with, the \n" "job will not run." -msgstr "Habilitar la firma de contenidos para verificar que el contenido \n" +msgstr "" +"Habilitar la firma de contenidos para verificar que el contenido \n" "ha permanecido seguro cuando se sincroniza un proyecto. \n" "Si el contenido ha sido manipulado, el trabajo \n" "trabajo no se ejecutará." @@ -2736,20 +2769,20 @@ msgstr "Habilitado" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "Opciones habilitadas" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "Valor habilitado" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "Variable habilitada" @@ -2760,12 +2793,14 @@ msgid "" "callback URL. Using the URL a host can contact {brandName}\n" "and request a configuration update using this job\n" "template" -msgstr "Permite la creación de una URL de\n" +msgstr "" +"Permite la creación de una URL de\n" "de aprovisionamiento. A través de esta URL, un host puede ponerse en contacto con {brandName} y solicitar una actualización de la configuración utilizando esta plantilla" #: screens/Template/shared/JobTemplate.helptext.js:29 msgid "Enables creation of a provisioning callback URL. Using the URL a host can contact {brandName} and request a configuration update using this job template." -msgstr "Permite la creación de una URL de\n" +msgstr "" +"Permite la creación de una URL de\n" "de aprovisionamiento. A través de esta URL, un host puede ponerse en contacto con {brandName} y solicitar una actualización de la configuración utilizando esta plantilla de trabajo." #: screens/Credential/CredentialDetail/CredentialDetail.js:160 @@ -2815,13 +2850,18 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "Ingrese entradas a través de la sintaxis JSON o YAML. Consulte la documentación de Ansible Tower para ver la sintaxis de ejemplo." #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "Ingrese variables de inventario mediante el uso de la sintaxis JSON o YAML.\n" -"Utilice el botón de selección para alternar entre las dos opciones. Consulte la\n" -"documentación de Ansible Tower para acceder a ejemplos de sintaxis." +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "" +#~ "Ingrese variables de inventario mediante el uso de la sintaxis JSON o YAML.\n" +#~ "Utilice el botón de selección para alternar entre las dos opciones. Consulte la\n" +#~ "documentación de Ansible Tower para acceder a ejemplos de sintaxis." + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2834,8 +2874,8 @@ msgstr "Variables de entorno o variables extra que especifican los valores que u #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2868,14 +2908,14 @@ msgstr "Error al guardar el flujo de trabajo" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2890,29 +2930,30 @@ msgstr "Error al guardar el flujo de trabajo" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2920,7 +2961,7 @@ msgstr "Error al guardar el flujo de trabajo" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2930,14 +2971,14 @@ msgstr "Error al guardar el flujo de trabajo" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2947,7 +2988,8 @@ msgstr "Error al guardar el flujo de trabajo" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2957,8 +2999,8 @@ msgstr "¡Error!" msgid "Error:" msgstr "Error:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "Errores" @@ -2988,7 +3030,7 @@ msgstr "Resumen del evento no disponible." msgid "Events" msgstr "Eventos" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "Procesamiento de eventos completo." @@ -2996,10 +3038,14 @@ msgstr "Procesamiento de eventos completo." msgid "Exact match (default lookup if not specified)." msgstr "Coincidencia exacta (búsqueda predeterminada si no se especifica)." -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "Búsqueda exacta en el campo de identificación." +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "A continuación, se incluyen algunos ejemplos de URL para la fuente de control de GIT:" @@ -3020,7 +3066,7 @@ msgstr "Los ejemplos incluyen:" msgid "Examples:" msgstr "Ejemplos:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "Frecuencia de las excepciones" @@ -3040,8 +3086,8 @@ msgstr "Ejecutar cuando el nodo primario se encuentre en estado de error." msgid "Execute when the parent node results in a successful state." msgstr "Ejecutar cuando el nodo primario se encuentre en estado correcto." -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "Ejecución" @@ -3055,8 +3101,8 @@ msgstr "Ejecución" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "Entorno de ejecución" @@ -3171,7 +3217,7 @@ msgid "Extra variables" msgstr "Variables adicionales" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3179,13 +3225,14 @@ msgid "FINISHED:" msgstr "FINALIZADO:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "Almacenamiento de datos" #: screens/Template/shared/JobTemplate.helptext.js:39 msgid "Fact storage: If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime.." -msgstr "Si se habilita esta opción, se almacenarán los eventos recopilados para que estén visibles en el nivel de host. Los eventos persisten y\n" +msgstr "" +"Si se habilita esta opción, se almacenarán los eventos recopilados para que estén visibles en el nivel de host. Los eventos persisten y\n" "se insertan en la caché de eventos en tiempo de ejecución." #: screens/Host/Host.js:63 @@ -3200,23 +3247,23 @@ msgstr "Eventos" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "Fallido" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "Recuento de hosts fallidos" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "Servidores fallidos" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "Hosts fallidos" @@ -3224,6 +3271,10 @@ msgstr "Hosts fallidos" msgid "Failed jobs" msgstr "Tareas fallidas" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "No se aprueba {0}." @@ -3238,7 +3289,7 @@ msgid "Failed to associate role" msgstr "No se pudo asociar el rol" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3246,7 +3297,7 @@ msgstr "No se pudo asociar el rol" msgid "Failed to associate." msgstr "No se pudo asociar." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "No se pudo cancelar la sincronización de fuentes de inventario" @@ -3262,7 +3313,7 @@ msgstr "No se pudo cancelar una o varias tareas." #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "No se ha podido cancelar {0}" @@ -3305,15 +3356,15 @@ msgstr "No se pudo eliminar el grupo {0}." msgid "Failed to delete host." msgstr "No se pudo eliminar el host." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "No se pudo eliminar la fuente del inventario {name}." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "No se pudo eliminar el inventario." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "No se pudo eliminar la plantilla de trabajo." @@ -3342,7 +3393,7 @@ msgid "Failed to delete one or more groups." msgstr "No se pudo eliminar uno o varios grupos." #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "No se pudo eliminar uno o más hosts." @@ -3358,7 +3409,7 @@ msgstr "No se pudo eliminar uno o más inventarios." msgid "Failed to delete one or more inventory sources." msgstr "No se pudo eliminar una o más fuentes de inventario." -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "No se pudo eliminar una o más plantillas de trabajo." @@ -3402,11 +3453,11 @@ msgstr "No se pudo eliminar uno o más tokens de usuario." msgid "Failed to delete one or more users." msgstr "No se pudo eliminar uno o más usuarios." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "No se pudo eliminar una o más aprobaciones del flujo de trabajo." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "No se pudo eliminar la organización." @@ -3423,11 +3474,11 @@ msgstr "No se pudo eliminar el rol" msgid "Failed to delete role." msgstr "No se pudo eliminar el rol." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "No se pudo eliminar la programación." -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "No se pudo eliminar el inventario inteligente." @@ -3452,6 +3503,10 @@ msgstr "No se pudo eliminar la plantilla de trabajo del flujo de trabajo." msgid "Failed to delete {name}." msgstr "No se pudo eliminar {name}." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "No se pudo eliminar {0}." @@ -3466,9 +3521,9 @@ msgstr "No se pudo disociar uno o más grupos." msgid "Failed to disassociate one or more hosts." msgstr "No se pudo disociar uno o más hosts." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "No se pudo disociar una o más instancias." @@ -3484,18 +3539,22 @@ msgstr "No se pudo obtener la configuración de inicio de sesión personalizada. msgid "Failed to fetch the updated project data." msgstr "No se han podido obtener los datos actualizados del proyecto." -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "No se pudo obtener el tablero:" #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "No se pudo ejecutar la tarea." -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "No se pudo disociar una o más instancias." @@ -3507,8 +3566,8 @@ msgstr "No se pudo recuperar la configuración." msgid "Failed to retrieve full node resource object." msgstr "No se pudo recuperar el objeto de recurso de nodo completo." -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "No se ha podido ejecutar una comprobación de estado en una o más instancias." @@ -3544,10 +3603,10 @@ msgstr "No se pudo alternar la notificación." msgid "Failed to toggle schedule." msgstr "No se pudo alternar la programación." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "No se pudo actualizar el ajuste de capacidad." @@ -3595,7 +3654,7 @@ msgstr "El campo contiene un valor." msgid "Field ends with value." msgstr "El campo termina con un valor." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "Campo para pasar una especificación personalizada de Kubernetes u OpenShift Pod." @@ -3628,11 +3687,11 @@ msgstr "Archivo, directorio o script" msgid "Filter By {name}" msgstr "Filtrar por {name}" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "Filtrar por trabajos fallidos" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "Trabajos exitosos recientes" @@ -3661,7 +3720,7 @@ msgstr "Primero" msgid "First Name" msgstr "Nombre" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "Primera ejecución" @@ -3704,11 +3763,11 @@ msgstr "Para obtener más información, consulte la" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3718,12 +3777,12 @@ msgstr "Forks" msgid "Fourth" msgstr "Cuarto" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "Información sobre la frecuencia" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "Frecuencia Detalles de la excepción" @@ -3745,7 +3804,7 @@ msgstr "Vie" msgid "Friday" msgstr "Viernes" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "Búsqueda difusa en los campos id, nombre o descripción." @@ -3757,7 +3816,7 @@ msgstr "Búsqueda difusa en el campo del nombre." msgid "GPG Public Key" msgstr "Clave pública GPG" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Credenciales de Galaxy" @@ -3795,7 +3854,7 @@ msgstr "Obtener suscripciones" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3834,7 +3893,7 @@ msgstr "Equipo GitHub" msgid "GitHub settings" msgstr "Configuración de GitHub" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3938,6 +3997,19 @@ msgstr "Método HTTP" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "Solicitudes de chequeo enviadas. Por favor, espere y recargue la página." +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "Saludable" @@ -3960,7 +4032,7 @@ msgstr "Ocultar descripción" msgid "Hipchat" msgstr "HipChat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "Salto" @@ -3968,8 +4040,9 @@ msgstr "Salto" msgid "Hop node" msgstr "Nodo de salto" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3984,16 +4057,16 @@ msgid "Host Async OK" msgstr "Servidor Async OK" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "Clave de configuración del servidor" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "Recuento de hosts" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "Detalles del host" @@ -4005,13 +4078,14 @@ msgstr "Servidor fallido" msgid "Host Failure" msgstr "Fallo del servidor" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "Filtro de host" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "Nombre de Host" @@ -4044,7 +4118,7 @@ msgstr "Servidor no alcanzable" msgid "Host details" msgstr "Detalles del host" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "Modal de detalles del host" @@ -4059,7 +4133,7 @@ msgstr "La información de estado del host para esta tarea no se encuentra dispo #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4071,10 +4145,10 @@ msgstr "La información de estado del host para esta tarea no se encuentra dispo #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "Servidores" @@ -4096,15 +4170,15 @@ msgstr "Hosts importados" msgid "Hosts remaining" msgstr "Hosts restantes" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "Hora" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "Híbrido" @@ -4183,7 +4257,8 @@ msgid "" "If checked, all variables for child groups\n" "and hosts will be removed and replaced by those found\n" "on the external source." -msgstr "Si las opciones están marcadas, se eliminarán\n" +msgstr "" +"Si las opciones están marcadas, se eliminarán\n" "todas las variables de los grupos secundarios y se reemplazarán\n" "con aquellas que se hallen en la fuente externa." @@ -4196,7 +4271,8 @@ msgid "" "to the next manually created group or if there is no manually\n" "created group to promote them into, they will be left in the \"all\"\n" "default group for the inventory." -msgstr "Si las opciones están marcadas, cualquier grupo o host que estuvo\n" +msgstr "" +"Si las opciones están marcadas, cualquier grupo o host que estuvo\n" "presente previamente en la fuente externa pero que ahora se eliminó,\n" "se eliminará del inventario. Los hosts y grupos que no fueron\n" "gestionados por la fuente de inventario serán promovidos al siguiente\n" @@ -4213,13 +4289,15 @@ msgid "" "If enabled, show the changes made\n" "by Ansible tasks, where supported. This is equivalent to Ansible’s\n" "--diff mode." -msgstr "Si se habilita esta opción, muestre los cambios realizados\n" +msgstr "" +"Si se habilita esta opción, muestre los cambios realizados\n" "por las tareas de Ansible, donde sea compatible. Esto es equivalente\n" "al modo --diff de Ansible." #: screens/Template/shared/JobTemplate.helptext.js:19 msgid "If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansible's --diff mode." -msgstr "Si se habilita esta opción, muestre los cambios realizados\n" +msgstr "" +"Si se habilita esta opción, muestre los cambios realizados\n" "por las tareas de Ansible, donde sea compatible. Esto es equivalente\n" "al modo --diff de Ansible." @@ -4235,23 +4313,26 @@ msgstr "Si se habilita esta opción, la ejecución de esta plantilla de trabajo msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "Si se habilita esta opción, se permitirá la ejecución de esta plantilla de flujo de trabajo en paralelo." -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "Si se habilita, el inventario impedirá añadir cualquier grupo de instancias de la organización a la lista de grupos de instancias preferidos para ejecutar las plantillas de trabajo asociadas.\n" +msgstr "" +"Si se habilita, el inventario impedirá añadir cualquier grupo de instancias de la organización a la lista de grupos de instancias preferidos para ejecutar las plantillas de trabajo asociadas.\n" "Nota: Si esta configuración está activada y ha proporcionado una lista vacía, se aplicarán los grupos de instancias globales." #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "Si se habilita, la plantilla de trabajo impedirá que se añada cualquier grupo de instancias del inventario o de la organización a la lista de grupos de instancias preferidos para ejecutar.\n" +msgstr "" +"Si se habilita, la plantilla de trabajo impedirá que se añada cualquier grupo de instancias del inventario o de la organización a la lista de grupos de instancias preferidos para ejecutar.\n" "Nota: Si esta configuración está activada y ha proporcionado una lista vacía, se aplicarán los grupos de instancias globales." #: screens/Template/shared/JobTemplate.helptext.js:35 msgid "If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime." -msgstr "Si se habilita esta opción, se almacenarán los eventos recopilados para que estén visibles en el nivel de host. Los eventos persisten y\n" +msgstr "" +"Si se habilita esta opción, se almacenarán los eventos recopilados para que estén visibles en el nivel de host. Los eventos persisten y\n" "se insertan en la caché de eventos en tiempo de ejecución." #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:275 @@ -4266,7 +4347,8 @@ msgstr "Si está listo para actualizar o renovar, <0>póngase en contacto con no msgid "" "If you do not have a subscription, you can visit\n" "Red Hat to obtain a trial subscription." -msgstr "Si no tiene una suscripción, puede visitar\n" +msgstr "" +"Si no tiene una suscripción, puede visitar\n" "Red Hat para obtener una suscripción de prueba." #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:46 @@ -4278,7 +4360,8 @@ msgstr "Si solo desea eliminar el acceso de este usuario específico, elimínelo msgid "" "If you want the Inventory Source to update on\n" "launch and on project update, click on Update on launch, and also go to" -msgstr "Si desea que la fuente de inventario se actualice al\n" +msgstr "" +"Si desea que la fuente de inventario se actualice al\n" "ejecutar y en la actualización del proyecto, haga clic en Actualizar al ejecutar, y también vaya a" #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:80 @@ -4305,7 +4388,8 @@ msgid "" "Indicates if a host is available and should be included in running\n" "jobs. For hosts that are part of an external inventory, this may be\n" "reset by the inventory sync process." -msgstr "Indica si un host está disponible y debe ser incluido en la ejecución de\n" +msgstr "" +"Indica si un host está disponible y debe ser incluido en la ejecución de\n" "tareas. Para los hosts que forman parte de un inventario externo, esto se puede\n" "restablecer mediante el proceso de sincronización del inventario." @@ -4349,7 +4433,8 @@ msgstr "Credencial de Insights" msgid "Insights system ID" msgstr "ID del sistema de Insights" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "Instalar el paquete" @@ -4370,25 +4455,26 @@ msgstr "Filtros de instancias" msgid "Instance Group" msgstr "Grupo de instancias" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "Grupos de instancias" @@ -4418,8 +4504,8 @@ msgstr "Grupo de instancias" msgid "Instance group not found." msgstr "No se encontró el grupo de instancias." -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "Capacidad utilizada del grupo de instancias" @@ -4442,9 +4528,9 @@ msgstr "tipo de instancia" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4477,7 +4563,7 @@ msgstr "Nombre de usuario o contraseña no válidos. Intente de nuevo." #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4501,18 +4587,18 @@ msgstr "No se pueden copiar los inventarios con fuentes" #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4521,8 +4607,8 @@ msgstr "No se pueden copiar los inventarios con fuentes" #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4549,7 +4635,7 @@ msgstr "Fuente de inventario" msgid "Inventory Source Sync" msgstr "Sincronización de fuentes de inventario" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "Error en la sincronización de fuentes de inventario" @@ -4581,8 +4667,8 @@ msgstr "Actualización del inventario" msgid "Inventory copied successfully" msgstr "El inventario se copió correctamente" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "Archivo de inventario" @@ -4594,7 +4680,7 @@ msgstr "No se encontró el inventario." msgid "Inventory sync" msgstr "Sincronización de inventario" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "Errores de sincronización de inventario" @@ -4628,18 +4714,18 @@ msgid "Items per page" msgstr "Elementos por página" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "ID DE TAREA:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "Pestaña JSON" @@ -4654,16 +4740,16 @@ msgstr "Enero" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "Error en la cancelación de tarea" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "Error en la eliminación de tareas" @@ -4686,10 +4772,10 @@ msgid "Job Slice Parent" msgstr "Fraccionamiento de los trabajos principales" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "Fraccionamiento de trabajos" @@ -4700,11 +4786,11 @@ msgstr "Estado de la tarea" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4725,7 +4811,7 @@ msgstr "Plantilla de trabajo" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "Las credenciales predeterminadas de la plantilla de trabajo se deben reemplazar por una del mismo tipo. Seleccione una credencial de los siguientes tipos para continuar: {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4748,26 +4834,26 @@ msgstr "Las plantillas de trabajo con credenciales que solicitan contraseñas no #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "Tipo de trabajo" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "Estado de la tarea" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "Pestaña del gráfico de estado de la tarea" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "Plantillas de trabajo" @@ -4881,7 +4967,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "Etiqueta" @@ -4892,15 +4978,15 @@ msgstr "Nombre de la etiqueta" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4912,18 +4998,19 @@ msgstr "Etiquetas" msgid "Last" msgstr "Último" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "Última comprobación de estado" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "Último estado de la tarea" @@ -4932,8 +5019,8 @@ msgstr "Último estado de la tarea" msgid "Last Login" msgstr "Último inicio de sesión" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4942,17 +5029,17 @@ msgstr "Último inicio de sesión" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4975,7 +5062,7 @@ msgstr "Apellido" msgid "Last Ran" msgstr "Último ejecutado" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "Última ejecución" @@ -4983,8 +5070,8 @@ msgstr "Última ejecución" msgid "Last job" msgstr "Última tarea" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -5008,8 +5095,8 @@ msgstr "Última utilización" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5076,12 +5163,12 @@ msgstr "Menor o igual que la comparación." #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5109,7 +5196,7 @@ msgstr "Cargando" msgid "Local" msgstr "Local" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "Huso horario local" @@ -5152,7 +5239,7 @@ msgstr "Tipo de búsqueda" msgid "Lookup typeahead" msgstr "Escritura anticipada de la búsqueda" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5207,14 +5294,15 @@ msgstr "No se encontró la tarea de gestión." msgid "Management jobs" msgstr "Tareas de gestión" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5234,11 +5322,25 @@ msgstr "Marzo" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "Número máximo de hosts" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "Máximo" @@ -5247,6 +5349,24 @@ msgstr "Máximo" msgid "Maximum length" msgstr "Longitud máxima" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5293,10 +5413,11 @@ msgstr "Cantidad mínima de instancias que se asignará automáticamente a este msgid "" "Minimum percentage of all instances that will be automatically\n" "assigned to this group when new instances come online." -msgstr "Porcentaje mínimo de todas las instancias que se asignará automáticamente\n" +msgstr "" +"Porcentaje mínimo de todas las instancias que se asignará automáticamente\n" "a este grupo cuando aparezcan nuevas instancias en línea." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5338,16 +5459,16 @@ msgstr "Modificado" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5385,7 +5506,7 @@ msgid "Modified by (username)" msgstr "Modificado por (nombre de usuario)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "Módulo" @@ -5408,7 +5529,7 @@ msgstr "Lun" msgid "Monday" msgstr "Lunes" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5457,8 +5578,8 @@ msgstr "Opciones de selección múltiple" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5481,8 +5602,8 @@ msgstr "Opciones de selección múltiple" #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5492,11 +5613,11 @@ msgstr "Opciones de selección múltiple" #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5552,27 +5673,27 @@ msgstr "Opciones de selección múltiple" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5584,7 +5705,7 @@ msgstr "Opciones de selección múltiple" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5594,7 +5715,7 @@ msgstr "Opciones de selección múltiple" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5604,7 +5725,7 @@ msgstr "Opciones de selección múltiple" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5614,7 +5735,7 @@ msgstr "Opciones de selección múltiple" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5636,7 +5757,7 @@ msgstr "Opciones de selección múltiple" #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5667,8 +5788,8 @@ msgstr "Opciones de selección múltiple" #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "Nombre" @@ -5711,7 +5832,7 @@ msgstr "Nuevo" msgid "Next" msgstr "Siguiente" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5731,7 +5852,7 @@ msgstr "Ningún servidor corresponde" msgid "No Hosts Remaining" msgstr "No más servidores" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "No hay ningún JSON disponible" @@ -5755,7 +5876,7 @@ msgstr "No hay datos de tareas disponibles." msgid "No output found for this job." msgstr "No se encontró una salida para este trabajo." -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "No se encontraron resultados" @@ -5774,10 +5895,10 @@ msgstr "No se encontraron resultados" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "No se encontraron resultados" @@ -5805,15 +5926,16 @@ msgstr "No se ha encontrado {pluralizedItemName}" msgid "Node Alias" msgstr "Alias del nodo" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5838,8 +5960,8 @@ msgstr "Tipos de nodo" msgid "None" msgstr "Ninguno" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "Ninguno (se ejecuta una vez)" @@ -5872,7 +5994,8 @@ msgid "" "Note that only hosts directly in this group can\n" "be disassociated. Hosts in sub-groups must be disassociated\n" "directly from the sub-group level that they belong." -msgstr "Tenga en cuenta que solo se pueden disociar los hosts asociados\n" +msgstr "" +"Tenga en cuenta que solo se pueden disociar los hosts asociados\n" "directamente a este grupo. Los hosts en subgrupos deben ser disociados\n" "del nivel de subgrupo al que pertenecen." @@ -5883,7 +6006,8 @@ msgid "" "disassociating if the host is also a member of that group’s\n" "children. This list shows all groups the host is associated\n" "with directly and indirectly." -msgstr "Tenga en cuenta que puede seguir viendo el grupo en la lista después de la disociación si el host también es un miembro de los elementos secundarios de ese grupo. Esta lista muestra todos los grupos a los que está asociado el host\n" +msgstr "" +"Tenga en cuenta que puede seguir viendo el grupo en la lista después de la disociación si el host también es un miembro de los elementos secundarios de ese grupo. Esta lista muestra todos los grupos a los que está asociado el host\n" "directa e indirectamente." #: components/Lookup/InstanceGroupsLookup.js:90 @@ -5906,7 +6030,8 @@ msgid "" "not support password authentication when using SSH. GIT\n" "read only protocol (git://) does not use username or\n" "password information." -msgstr "Note: Si utiliza el protocolo SSH para GitHub o Bitbucket,\n" +msgstr "" +"Note: Si utiliza el protocolo SSH para GitHub o Bitbucket,\n" "ingrese solo la clave de SSH; no ingrese un nombre de usuario\n" "(distinto de git). Además, GitHub y Bitbucket no admiten\n" "la autenticación de contraseña cuando se utiliza SSH. El protocolo\n" @@ -5998,14 +6123,14 @@ msgstr "Octubre" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "Off" @@ -6014,14 +6139,14 @@ msgstr "Off" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "On" @@ -6072,7 +6197,8 @@ msgid "" "Optional labels that describe this inventory,\n" "such as 'dev' or 'test'. Labels can be used to group and filter\n" "inventories and completed jobs." -msgstr "Etiquetas opcionales que describen este inventario,\n" +msgstr "" +"Etiquetas opcionales que describen este inventario,\n" "como 'dev' o 'test'. Las etiquetas se pueden usar para agrupar\n" "y filtrar inventarios y tareas completadas." @@ -6086,7 +6212,8 @@ msgid "" "Optional labels that describe this workflow job template,\n" "such as 'dev' or 'test'. Labels can be used to group and filter\n" "workflow job templates and completed jobs." -msgstr "Etiquetas opcionales que describen esta plantilla de trabajo,\n" +msgstr "" +"Etiquetas opcionales que describen esta plantilla de trabajo,\n" "como 'dev' o 'test'. Las etiquetas se pueden usar para agrupar\n" "y filtrar plantillas de trabajo y tareas completadas." @@ -6098,7 +6225,7 @@ msgstr "Opcionalmente, seleccione la credencial que se usará para devolver las #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6134,11 +6261,11 @@ msgstr "Pedir" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6148,8 +6275,8 @@ msgstr "Pedir" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6193,12 +6320,12 @@ msgid "Out of compliance" msgstr "No cumple con los requisitos" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "Salida" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "Salida" @@ -6207,12 +6334,12 @@ msgid "Overwrite" msgstr "Anular" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "Sobrescribir grupos locales y servidores desde una fuente remota del inventario." #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "Sobrescribir las variables locales desde una fuente remota del inventario." @@ -6272,7 +6399,8 @@ msgstr "Traslade variables de línea de comando adicionales al cuaderno de estra #: screens/Job/Job.helptext.js:13 #: screens/Template/shared/JobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the documentation for example syntax." -msgstr "Traslade variables de línea de comando adicionales al playbook. Este es el\n" +msgstr "" +"Traslade variables de línea de comando adicionales al playbook. Este es el\n" "parámetro de línea de comando -e o --extra-vars para el playbook de Ansible.\n" "Proporcione pares de claves/valores utilizando YAML o JSON. Consulte la\n" "documentación para ver ejemplos de sintaxis." @@ -6334,11 +6462,11 @@ msgstr "Token de acceso personal" msgid "Personal access token" msgstr "Token de acceso personal" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "Jugada" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "Recuento de jugadas" @@ -6348,7 +6476,7 @@ msgstr "Jugada iniciada" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6380,7 +6508,7 @@ msgstr "Ejecución de playbook" msgid "Playbook Started" msgstr "Playbook iniciado" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6392,7 +6520,7 @@ msgstr "Nombre del playbook" msgid "Playbook run" msgstr "Ejecución de playbook" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "Jugadas" @@ -6416,7 +6544,7 @@ msgstr "Añada {pluralizedItemName} para poblar esta lista" msgid "Please click the Start button to begin." msgstr "Haga clic en el botón de inicio para comenzar." -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "Por favor, introduzca un número de ocurrencias." @@ -6436,7 +6564,7 @@ msgstr "Inicie sesión" msgid "Please run a job to populate this list." msgstr "Ejecute un trabajo para rellenar esta lista." -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "Seleccione un número de día entre 1 y 31." @@ -6444,7 +6572,7 @@ msgstr "Seleccione un número de día entre 1 y 31." msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "Seleccione un inventario o marque la opción Preguntar al ejecutar." -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "Seleccione una fecha/hora de finalización que sea posterior a la fecha/hora de inicio." @@ -6460,14 +6588,15 @@ msgstr "Intente otra búsqueda con el filtro de arriba" msgid "Please wait until the topology view is populated..." msgstr "Espere hasta que se complete la vista de topología..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Anulación de las especificaciones del pod" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "Tipo de política" @@ -6494,7 +6623,8 @@ msgid "" "Refer to the documentation for further syntax and\n" "examples. Refer to the Ansible Controller documentation for further syntax and\n" "examples." -msgstr "Complete los hosts para este inventario utilizando un filtro de búsqueda\n" +msgstr "" +"Complete los hosts para este inventario utilizando un filtro de búsqueda\n" "de búsqueda. Ejemplo: ansible_facts.ansible_distribution: \"RedHat\".\n" "Consulte la documentación para obtener más sintaxis y ejemplos. Consulte la documentación de Ansible Tower para obtener más sintaxis y\n" "ejemplos." @@ -6524,20 +6654,21 @@ msgid "" "and use the arrow keys to navigate up or down.\n" "Press enter to confirm the drag, or any other key to\n" "cancel the drag operation." -msgstr "Pulse la barra espaciadora o Intro para empezar a arrastrar,\n" +msgstr "" +"Pulse la barra espaciadora o Intro para empezar a arrastrar,\n" "y utilice las teclas de flecha para desplazarse hacia arriba o hacia abajo.\n" "Pulse Intro para confirmar el arrastre, o cualquier otra tecla para cancelar la operación de arrastre." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "Evitar el retroceso del grupo de instancias" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "Impedir la retroalimentación del grupo de instancias: Si se habilita, el inventario impedirá añadir cualquier grupo de instancias de la organización a la lista de grupos de instancias preferidos para ejecutar las plantillas de trabajo asociadas." @@ -6555,7 +6686,7 @@ msgid "Private key passphrase" msgstr "Frase de paso para llave privada" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "Elevación de privilegios" @@ -6566,7 +6697,8 @@ msgstr "Contraseña para la elevación de privilegios" #: screens/Template/shared/JobTemplate.helptext.js:40 msgid "Privilege escalation: If enabled, run this playbook as an administrator." -msgstr "Si se habilita esta opción, ejecute este playbook\n" +msgstr "" +"Si se habilita esta opción, ejecute este playbook\n" "como administrador." #: components/JobList/JobListItem.js:239 @@ -6577,11 +6709,11 @@ msgstr "Si se habilita esta opción, ejecute este playbook\n" #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "Proyecto" @@ -6622,14 +6754,14 @@ msgstr "El proyecto se copió correctamente" msgid "Project not found." msgstr "No se encontró el proyecto." -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "Errores de sincronización del proyecto" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6644,12 +6776,12 @@ msgstr "Proyectos" msgid "Promote Child Groups and Hosts" msgstr "Promover grupos secundarios y hosts" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "Aviso" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "Anulaciones de avisos" @@ -6663,8 +6795,8 @@ msgstr "Preguntar al ejecutar" msgid "Prompt | {0}" msgstr "Aviso | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "Valores solicitados" @@ -6674,7 +6806,8 @@ msgid "" "the list of hosts that will be managed or affected by the\n" "playbook. Multiple patterns are allowed. Refer to Ansible\n" "documentation for more information and examples on patterns." -msgstr "Proporcione un patrón de host para limitar aún más la lista\n" +msgstr "" +"Proporcione un patrón de host para limitar aún más la lista\n" "de hosts que serán gestionados o que se verán afectados por el playbook.\n" "Se permiten distintos patrones. Consulte la documentación de Ansible\n" "para obtener más información y ejemplos relacionados con los patrones." @@ -6692,7 +6825,8 @@ msgstr "Proporcione un valor para este campo o seleccione la opción Preguntar a msgid "" "Provide key/value pairs using either\n" "YAML or JSON." -msgstr "Proporcione pares de clave/valor utilizando\n" +msgstr "" +"Proporcione pares de clave/valor utilizando\n" "YAML o JSON." #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:191 @@ -6701,7 +6835,8 @@ msgid "" "below and you can choose from a list of your available subscriptions.\n" "The credentials you use will be stored for future use in\n" "retrieving renewal or expanded subscriptions." -msgstr "A continuación, proporcione sus credenciales de Red Hat o de Red Hat Satellite\n" +msgstr "" +"A continuación, proporcione sus credenciales de Red Hat o de Red Hat Satellite\n" "para poder elegir de una lista de sus suscripciones disponibles.\n" "Las credenciales que utilice se almacenarán para su uso futuro\n" "en la recuperación de las suscripciones de renovación o ampliadas." @@ -6716,7 +6851,7 @@ msgid "Provisioning" msgstr "Aprovisionamiento" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "Dirección URL para las llamadas callback" @@ -6726,7 +6861,7 @@ msgid "Provisioning Callback details" msgstr "Detalles de callback de aprovisionamiento" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6734,7 +6869,8 @@ msgstr "Callbacks de aprovisionamiento" #: screens/Template/shared/JobTemplate.helptext.js:41 msgid "Provisioning callbacks: Enables creation of a provisioning callback URL. Using the URL a host can contact Ansible AWX and request a configuration update using this job template." -msgstr "Permite la creación de una URL de\n" +msgstr "" +"Permite la creación de una URL de\n" "de aprovisionamiento. A través de esta URL, un host puede ponerse en contacto con y solicitar una actualización de la configuración utilizando esta plantilla de trabajo." #: components/StatusLabel/StatusLabel.js:62 @@ -6758,10 +6894,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "Configuración de RADIUS" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6775,23 +6912,23 @@ msgstr "Lectura" msgid "Ready" msgstr "Listo" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "Tareas recientes" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "Pestaña de la lista de tareas recientes" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "Plantillas recientes" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "Pestaña de la lista de plantillas recientes" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6882,12 +7019,15 @@ msgstr "Regiones" msgid "Registry credential" msgstr "Credencial de registro" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "Expresión regular en la que solo se importarán los nombres de host que coincidan. El filtro se aplica como un paso posterior al procesamiento después de que se aplique cualquier filtro de complemento de inventario." #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "Grupos relacionados" @@ -6914,12 +7054,12 @@ msgstr "Tipo de búsqueda relacionado typeahead" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "Relanzar" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "Volver a ejecutar la tarea" @@ -6937,7 +7077,7 @@ msgid "Relaunch on" msgstr "Volver a ejecutar el" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "Relanzar utilizando los parámetros de host" @@ -6945,7 +7085,7 @@ msgstr "Relanzar utilizando los parámetros de host" msgid "Reload" msgstr "Recarga" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "Descargar salida" @@ -6958,8 +7098,8 @@ msgstr "Descargar salida" msgid "Remote Archive" msgstr "Archivo remoto" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "Error de eliminación" @@ -7018,7 +7158,7 @@ msgstr "Si quita este enlace, el resto de la rama quedará huérfano y hará que msgid "Reorder" msgstr "Reordenar" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "Frecuencia de repetición" @@ -7082,7 +7222,8 @@ msgstr "Restaurar el valor inicial." msgid "" "Retrieve the enabled state from the given dict of host variables.\n" "The enabled variable may be specified using dot notation, e.g: 'foo.bar'" -msgstr "Recuperar el estado habilitado a partir del dict dado de las variables de host.\n" +msgstr "" +"Recuperar el estado habilitado a partir del dict dado de las variables de host.\n" "La variable habilitada se puede especificar mediante notación de puntos,\n" "por ejemplo: \"foo.bar\"" @@ -7090,8 +7231,8 @@ msgstr "Recuperar el estado habilitado a partir del dict dado de las variables d #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "Volver" @@ -7196,8 +7337,9 @@ msgstr "Ejecutar" msgid "Run Command" msgstr "Ejecutar comando" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "Ejecutar una comprobación de la salud de la instancia" @@ -7214,10 +7356,11 @@ msgstr "Ejecutar comando" msgid "Run every" msgstr "Ejecutar cada" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "Comprobación de estado" @@ -7244,17 +7387,26 @@ msgstr "Ejecutándose" msgid "Running Handlers" msgstr "Handlers ejecutándose" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "Tareas en ejecución" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "Última comprobación de estado" @@ -7293,7 +7445,7 @@ msgid "START" msgstr "INICIAR" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7316,8 +7468,8 @@ msgstr "Sábado" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7371,7 +7523,7 @@ msgstr "La programación está activa" msgid "Schedule is inactive" msgstr "La programación está inactiva" -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "Falta una regla de programación" @@ -7493,7 +7645,7 @@ msgstr "Seleccionar hosts" msgid "Select Input" msgstr "Seleccionar entrada" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "Seleccionar instancias" @@ -7563,11 +7715,19 @@ msgstr "Seleccione un proyecto antes de modificar el entorno de ejecución." msgid "Select a question to delete" msgstr "Seleccione una pregunta para eliminar" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "Seleccionar una fila para eliminar" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "Seleccionar una fila para disociar" @@ -7595,8 +7755,8 @@ msgstr "Seleccionar una suscripción" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7638,7 +7798,7 @@ msgstr "Seleccione una instancia" msgid "Select an instance and a metric to show chart" msgstr "Seleccionar una instancia y una métrica para mostrar el gráfico" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "Seleccione una instancia para ejecutar una comprobación de estado." @@ -7657,7 +7817,8 @@ msgstr "Seleccione una organización antes de modificar el entorno de ejecución #: screens/Job/Job.helptext.js:11 #: screens/Template/shared/JobTemplate.helptext.js:12 msgid "Select credentials for accessing the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking \"Prompt on launch\" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check \"Prompt on launch\", the selected credential(s) become the defaults that can be updated at run time." -msgstr "Seleccione las credenciales para acceder a los nodos en función de\n" +msgstr "" +"Seleccione las credenciales para acceder a los nodos en función de\n" "los cuales se ejecutará este trabajo. Solo puede seleccionar una credencial de cada tipo. Para las\n" "credenciales de máquina (SSH), si marca \"Preguntar al ejecutar\" sin seleccionar las credenciales,\n" "se le pedirá que seleccione una credencial de máquina en el momento de la ejecución. Si selecciona\n" @@ -7674,7 +7835,8 @@ msgid "" "Select from the list of directories found in\n" "the Project Base Path. Together the base path and the playbook\n" "directory provide the full path used to locate playbooks." -msgstr "Seleccione de la lista de directorios que se encuentran en\n" +msgstr "" +"Seleccione de la lista de directorios que se encuentran en\n" "la ruta base del proyecto. La ruta base y el directorio del playbook\n" "proporcionan la ruta completa utilizada para encontrar los playbooks." @@ -7701,9 +7863,9 @@ msgstr "Seleccionar periodo" msgid "Select roles to apply" msgstr "Seleccionar los roles para aplicar" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "Seleccionar la ruta de origen" @@ -7741,7 +7903,8 @@ msgstr "Seleccione la credencial que desea utilizar cuando acceda a los hosts re msgid "" "Select the inventory containing the hosts\n" "you want this job to manage." -msgstr "Seleccione el inventario que contenga los hosts que desea\n" +msgstr "" +"Seleccione el inventario que contenga los hosts que desea\n" "que gestione esta tarea." #: screens/Job/Job.helptext.js:6 @@ -7794,8 +7957,8 @@ msgstr "Seleccionar {0}" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7818,8 +7981,8 @@ msgstr "Seleccionado" msgid "Selected Category" msgstr "Categoría seleccionada" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "El intervalo de fechas seleccionado debe tener al menos 1 ocurrencia de horario." @@ -7853,7 +8016,7 @@ msgstr "Establecer cuántos días de datos debería ser retenidos." msgid "Set preferences for data collection, logos, and logins" msgstr "Establezca preferencias para la recopilación de datos, los logotipos y los inicios de sesión" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "Establecer la ruta de origen en" @@ -7919,10 +8082,10 @@ msgid "Show" msgstr "Mostrar" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "Mostrar cambios" @@ -7996,11 +8159,11 @@ msgstr "Selección de clave simple" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -8015,7 +8178,8 @@ msgstr "Saltar cada" #: screens/Template/shared/JobTemplate.helptext.js:22 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:22 msgid "Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." -msgstr "La omisión de etiquetas resulta útil cuando tiene un playbook\n" +msgstr "" +"La omisión de etiquetas resulta útil cuando tiene un playbook\n" "de gran tamaño y desea omitir partes específicas de la tarea\n" "o la jugada. Utilice comas para separar las distintas etiquetas.\n" "Consulte la documentación para obtener información detallada\n" @@ -8078,8 +8242,8 @@ msgstr "Ordenar" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8087,20 +8251,22 @@ msgid "Source" msgstr "Fuente" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "Rama de fuente de control" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "Rama/etiqueta/commit de fuente de control" @@ -8163,7 +8329,7 @@ msgstr "Tarea del flujo de trabajo de origen" msgid "Source control branch" msgstr "Rama de fuente de control" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "Detalles de la fuente" @@ -8171,7 +8337,7 @@ msgstr "Detalles de la fuente" msgid "Source phone number" msgstr "Número de teléfono de la fuente" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "Variables de fuente" @@ -8189,25 +8355,27 @@ msgstr "Fuentes" msgid "" "Specify HTTP Headers in JSON format. Refer to\n" "the Ansible Controller documentation for example syntax." -msgstr "Especifique los encabezados HTTP en formato JSON. Consulte la\n" +msgstr "" +"Especifique los encabezados HTTP en formato JSON. Consulte la\n" "documentación de Ansible Tower para obtener ejemplos de sintaxis." #: screens/NotificationTemplate/shared/Notifications.helptext.js:24 msgid "" "Specify a notification color. Acceptable colors are hex\n" "color code (example: #3af or #789abc)." -msgstr "Especifique un color para la notificación. Los colores aceptables son\n" +msgstr "" +"Especifique un color para la notificación. Los colores aceptables son\n" "el código de color hexadecimal (ejemplo: #3af o #789abc)." #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:26 msgid "Specify the conditions under which this node should be executed" msgstr "Especificar las condiciones en las que debe ejecutarse este nodo" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "Error estándar" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "Pestaña de error estándar" @@ -8254,27 +8422,28 @@ msgid "Start time" msgstr "Hora de inicio" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "Iniciado" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8282,7 +8451,7 @@ msgstr "Iniciado" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "Estado" @@ -8305,7 +8474,8 @@ msgid "" "the revision specified by the main project.\n" "This is equivalent to specifying the --remote\n" "flag to git submodule update." -msgstr "Los submódulos realizarán el seguimiento del último commit en\n" +msgstr "" +"Los submódulos realizarán el seguimiento del último commit en\n" "su rama maestra (u otra rama especificada en\n" ".gitmodules). De lo contrario, el proyecto principal mantendrá los submódulos en\n" "la revisión especificada.\n" @@ -8374,7 +8544,7 @@ msgstr "Cuerpo del mensaje de éxito" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "Correctamente" @@ -8510,8 +8680,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "Configuración de TACACS+" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "Pestañas" @@ -8519,7 +8689,8 @@ msgstr "Pestañas" #: screens/Template/shared/JobTemplate.helptext.js:21 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:21 msgid "Tags are useful when you have a large playbook, and you want to run a specific part of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." -msgstr "Las etiquetas resultan útiles cuando tiene un playbook\n" +msgstr "" +"Las etiquetas resultan útiles cuando tiene un playbook\n" "de gran tamaño y desea ejecutar una parte específica\n" "de la tarea o la jugada. Utilice comas para separar varias\n" "etiquetas. Consulte la documentación para obtener\n" @@ -8542,11 +8713,11 @@ msgstr "Etiquetas para anotación (opcional)" msgid "Target URL" msgstr "URL destino" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "Tarea" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "Recuento de tareas" @@ -8554,7 +8725,7 @@ msgstr "Recuento de tareas" msgid "Task Started" msgstr "Tarea iniciada" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "Tareas" @@ -8596,7 +8767,7 @@ msgstr "Equipos" msgid "Template" msgstr "Plantilla" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "La plantilla se copió correctamente" @@ -8666,12 +8837,14 @@ msgstr "El" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "El tipo de subvención que el usuario debe utilizar para adquirir tokens para esta aplicación" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." -msgstr "Seleccione los grupos de instancias en los que se ejecutará\n" +msgstr "" +"Seleccione los grupos de instancias en los que se ejecutará\n" "esta organización." -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "Los grupos de instancias a los que pertenece esta instancia." @@ -8680,14 +8853,16 @@ msgid "" "The amount of time (in seconds) before the email\n" "notification stops trying to reach the host and times out. Ranges\n" "from 1 to 120 seconds." -msgstr "La cantidad de tiempo (en segundos) antes de que la notificación\n" +msgstr "" +"La cantidad de tiempo (en segundos) antes de que la notificación\n" "de correo electrónico deje de intentar conectarse con el host\n" "y caduque el tiempo de espera. Rangos de 1 a 120 segundos." #: screens/Job/Job.helptext.js:17 #: screens/Template/shared/JobTemplate.helptext.js:18 msgid "The amount of time (in seconds) to run before the job is canceled. Defaults to 0 for no job timeout." -msgstr "La cantidad de tiempo (en segundos) para ejecutar\n" +msgstr "" +"La cantidad de tiempo (en segundos) para ejecutar\n" "antes de que se cancele la tarea. Valores predeterminados\n" "en 0 para el tiempo de espera de la tarea." @@ -8700,7 +8875,8 @@ msgid "" "The base URL of the Grafana server - the\n" "/api/annotations endpoint will be added automatically to the base\n" "Grafana URL." -msgstr "La URL base del servidor de Grafana:\n" +msgstr "" +"La URL base del servidor de Grafana:\n" "el punto de acceso /api/annotations se agregará automáticamente\n" "a la URL base de Grafana." @@ -8708,7 +8884,7 @@ msgstr "La URL base del servidor de Grafana:\n" msgid "The container image to be used for execution." msgstr "La imagen del contenedor que se utilizará para la ejecución." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8727,7 +8903,8 @@ msgstr "El entorno de ejecución que se utilizará para las tareas que utilizan #: screens/Job/Job.helptext.js:9 #: screens/Template/shared/JobTemplate.helptext.js:10 msgid "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." -msgstr "El entorno de ejecución que se utilizará al lanzar\n" +msgstr "" +"El entorno de ejecución que se utilizará al lanzar\n" "esta plantilla de trabajo. El entorno de ejecución resuelto puede anularse asignando asignando explícitamente uno diferente a esta plantilla de trabajo." #: screens/Project/shared/Project.helptext.js:93 @@ -8735,7 +8912,8 @@ msgid "" "The first fetches all references. The second\n" "fetches the Github pull request number 62, in this example\n" "the branch needs to be \"pull/62/head\"." -msgstr "El primero extrae todas las referencias. El segundo\n" +msgstr "" +"El primero extrae todas las referencias. El segundo\n" "extrae el número de solicitud de extracción 62 de Github; en este ejemplo,\n" "la rama debe ser \"pull/62/head\"." @@ -8743,12 +8921,13 @@ msgstr "El primero extrae todas las referencias. El segundo\n" msgid "The full image location, including the container registry, image name, and version tag." msgstr "La ubicación completa de la imagen, que incluye el registro de contenedores, el nombre de la imagen y la etiqueta de la versión." -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" "the dropdown or enter a file within the input." -msgstr "Seleccione el archivo del inventario que sincronizará\n" +msgstr "" +"Seleccione el archivo del inventario que sincronizará\n" "esta fuente. Puede seleccionar del menú desplegable\n" "o ingresar un archivo en la entrada." @@ -8764,12 +8943,13 @@ msgstr "El último {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "El último {weekday} de {month}" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" "Refer to the Ansible documentation for more details." -msgstr "La cantidad máxima de hosts que puede administrar esta organización.\n" +msgstr "" +"La cantidad máxima de hosts que puede administrar esta organización.\n" "El valor predeterminado es 0, que significa sin límite. Consulte\n" "la documentación de Ansible para obtener más información detallada." @@ -8778,7 +8958,8 @@ msgid "" "The maximum number of hosts allowed to be managed by this organization.\n" "Value defaults to 0 which means no limit. Refer to the Ansible\n" "documentation for more details." -msgstr "La cantidad máxima de hosts que puede administrar esta organización.\n" +msgstr "" +"La cantidad máxima de hosts que puede administrar esta organización.\n" "El valor predeterminado es 0, que significa sin límite. Consulte\n" "la documentación de Ansible para obtener más información detallada." @@ -8786,7 +8967,8 @@ msgstr "La cantidad máxima de hosts que puede administrar esta organización.\n msgid "" "The number associated with the \"Messaging\n" "Service\" in Twilio with the format +18005550199." -msgstr "Ingrese el número asociado con el \"Servicio de mensajería\"\n" +msgstr "" +"Ingrese el número asociado con el \"Servicio de mensajería\"\n" "en Twilio con el formato +18005550199." #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:69 @@ -8813,7 +8995,8 @@ msgstr "El patrón utilizado para dirigir los hosts en el inventario. Si se deja #: screens/Job/Job.helptext.js:7 msgid "The project containing the playbook this job will execute." -msgstr "Seleccione el proyecto que contiene el playbook\n" +msgstr "" +"Seleccione el proyecto que contiene el playbook\n" "que desea que ejecute esta tarea." #: screens/Job/Job.helptext.js:8 @@ -8847,7 +9030,8 @@ msgid "" "The suggested format for variable names is lowercase and\n" "underscore-separated (for example, foo_bar, user_id, host_name,\n" "etc.). Variable names with spaces are not allowed." -msgstr "El formato sugerido para los nombres de variables es minúsculas y\n" +msgstr "" +"El formato sugerido para los nombres de variables es minúsculas y\n" "separados por guiones bajos (por ejemplo, foo_bar, user_id, host_name,\n" "etc.). No se permiten los nombres de variables con espacios." @@ -8859,7 +9043,8 @@ msgid "" "sure the playbook files can be read by the \"awx\" system user,\n" "or have {brandName} directly retrieve your playbooks from\n" "source control using the Source Control Type option above." -msgstr "No hay directorios de playbook disponibles en {project_base_dir}.\n" +msgstr "" +"No hay directorios de playbook disponibles en {project_base_dir}.\n" "O bien ese directorio está vacío, o todo el contenido ya está\n" "asignado a otros proyectos. Cree un nuevo directorio allí y asegúrese de que los archivos de playbook puedan ser leídos por el usuario del sistema \"awx\", o haga que {brandName} recupere directamente sus playbooks desde\n" "control de fuentes utilizando la opción de tipo de control de fuentes anterior." @@ -8935,7 +9120,7 @@ msgstr "Esta acción disociará lo siguiente:" msgid "This action will remove the following instances:" msgstr "Esta acción eliminará las siguientes instancias:" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 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?" @@ -8952,7 +9137,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Software and to provide\n" "Automation Analytics." -msgstr "Estos datos se utilizan para mejorar\n" +msgstr "" +"Estos datos se utilizan para mejorar\n" "futuras versiones del software y para proporcionar Automation Analytics." #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:62 @@ -8960,7 +9146,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Tower Software and help\n" "streamline customer experience and success." -msgstr "Estos datos se utilizan para mejorar futuras versiones\n" +msgstr "" +"Estos datos se utilizan para mejorar futuras versiones\n" "del software Tower y para ayudar a optimizar el éxito\n" "y la experiencia del cliente." @@ -8973,7 +9160,7 @@ msgstr "Este entorno de ejecución está siendo utilizado por otros recursos. ¿ msgid "This feature is deprecated and will be removed in a future release." msgstr "Esta función está obsoleta y se eliminará en una futura versión." -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "Este campo se ignora a menos que se establezca una variable habilitada. Si la variable habilitada coincide con este valor, el host se habilitará en la importación." @@ -9059,7 +9246,7 @@ msgstr "Este campo se recuperará de un sistema externo de gestión de claves se msgid "This has already been acted on" msgstr "Ya se ha actuado al respecto" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "Este grupo de instancias está siendo utilizado por otros recursos. ¿Está seguro de que desea eliminarlo?" @@ -9067,11 +9254,11 @@ msgstr "Este grupo de instancias está siendo utilizado por otros recursos. ¿Es msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "Este inventario se aplica a todos los nodos de este flujo de trabajo ({0}) que solicitan un inventario." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "Este inventario está siendo utilizado por otros recursos. ¿Está seguro de que desea eliminarlo?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "Esta fuente de inventario está siendo utilizada por otros recursos que dependen de ella. ¿Está seguro de que desea eliminarla?" @@ -9087,11 +9274,11 @@ msgstr "Esta es la única vez que se mostrará el valor del token y el valor del msgid "This job failed and has no output." msgstr "Este trabajo ha fallado y no tiene salida." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "Esta plantilla de trabajo está siendo utilizada por otros recursos. ¿Está seguro de que desea eliminarla?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "Esta organización está siendo utilizada por otros recursos. ¿Está seguro de que desea eliminarla?" @@ -9103,7 +9290,7 @@ msgstr "Este proyecto está siendo utilizado por otros recursos. ¿Está seguro msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "Este proyecto se está sincronizando y no se puede hacer clic en él hasta que el proceso de sincronización se haya completado" -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "Este horario no tiene ocurrencias debido a las excepciones seleccionadas." @@ -9119,7 +9306,8 @@ msgstr "Faltan los valores de la encuesta requeridos en esta programación" msgid "" "This schedule uses complex rules that are not supported in the\n" "UI. Please use the API to manage this schedule." -msgstr "Esta programación utiliza reglas complejas que no son compatibles con la\n" +msgstr "" +"Esta programación utiliza reglas complejas que no son compatibles con la\n" "UI. Por favor, utilice la API para gestionar este horario." #: components/LaunchPrompt/steps/StepName.js:26 @@ -9142,7 +9330,8 @@ msgstr "Esto cancelará todos los nodos posteriores de este flujo de trabajo." msgid "" "This will revert all configuration values on this page to\n" "their factory defaults. Are you sure you want to proceed?" -msgstr "Esta operación revertirá todos los valores de configuración\n" +msgstr "" +"Esta operación revertirá todos los valores de configuración\n" "a los valores predeterminados de fábrica. ¿Está seguro de desea continuar?" #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerStartScreen.js:40 @@ -9184,7 +9373,8 @@ msgid "" "update. If it is older than Cache Timeout, it is not\n" "considered current, and a new project update will be\n" "performed." -msgstr "Tiempo en segundos para considerar que\n" +msgstr "" +"Tiempo en segundos para considerar que\n" "un proyecto es actual. Durante la ejecución de trabajos y callbacks,\n" "la tarea del sistema evaluará la marca de tiempo de la última\n" "actualización del proyecto. Si es anterior al tiempo de espera\n" @@ -9198,7 +9388,8 @@ msgid "" "evaluate the timestamp of the latest sync. If it is older than\n" "Cache Timeout, it is not considered current, and a new\n" "inventory sync will be performed." -msgstr "Tiempo en segundos para considerar que un proyecto es actual.\n" +msgstr "" +"Tiempo en segundos para considerar que un proyecto es actual.\n" "Durante la ejecución de trabajos y callbacks, el sistema de tareas\n" "evaluará la marca de tiempo de la última sincronización. Si es anterior\n" "al tiempo de espera de la caché, no se considera actual\n" @@ -9209,13 +9400,13 @@ msgid "Timed out" msgstr "Tiempo de espera agotado" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9318,15 +9509,16 @@ msgid "Tools" msgstr "Herramientas" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "Vista de topología" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "Tareas totales" @@ -9336,7 +9528,7 @@ msgstr "Tareas totales" msgid "Total Nodes" msgstr "Nodos totales" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "Total de anfitriones" @@ -9392,8 +9584,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9406,11 +9598,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9458,13 +9650,14 @@ msgstr "Imposible modificar el inventario en un servidor." msgid "Unable to load last job update" msgstr "No se puede cargar la última actualización del trabajo" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "No disponible" @@ -9484,15 +9677,15 @@ msgstr "Ilimitado" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "Servidor inaccesible" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "Recuento de hosts inaccesibles" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "Hosts inaccesibles" @@ -9509,7 +9702,7 @@ msgid "Update Revision on Launch" msgstr "Revisión de actualización durante el lanzamiento" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "Actualizar al ejecutar" @@ -9558,7 +9751,8 @@ msgid "" "Use custom messages to change the content of\n" "notifications sent when a job starts, succeeds, or fails. Use\n" "curly braces to access information about the job:" -msgstr "Utilice los mensajes personalizados para cambiar el contenido de las notificaciones enviadas cuando una tarea se inicie, se realice correctamente o falle. Utilice llaves\n" +msgstr "" +"Utilice los mensajes personalizados para cambiar el contenido de las notificaciones enviadas cuando una tarea se inicie, se realice correctamente o falle. Utilice llaves\n" "para acceder a la información sobre la tarea:" #: screens/NotificationTemplate/shared/Notifications.helptext.js:12 @@ -9570,13 +9764,15 @@ msgid "" "Use one IRC channel or username per line. The pound\n" "symbol (#) for channels, and the at (@) symbol for users, are not\n" "required." -msgstr "Ingrese un canal de IRC o nombre de usuario por línea. El símbolo numeral (#)\n" +msgstr "" +"Ingrese un canal de IRC o nombre de usuario por línea. El símbolo numeral (#)\n" "para canales y el símbolo arroba (@) para usuarios no son\n" "necesarios." #: screens/NotificationTemplate/shared/Notifications.helptext.js:5 msgid "Use one email address per line to create a recipient list for this type of notification." -msgstr "Ingrese una dirección de correo electrónico por línea\n" +msgstr "" +"Ingrese una dirección de correo electrónico por línea\n" "para crear una lista de destinatarios para este tipo de notificación." #: screens/NotificationTemplate/shared/Notifications.helptext.js:28 @@ -9585,22 +9781,25 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "Introduzca un número de teléfono por línea para especificar a dónde enviar los mensajes SMS. Los números de teléfono deben tener el formato +11231231234. Para más información, consulte la documentación de Twilio." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "Capacidad usada" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "Capacidad usada" @@ -9700,22 +9899,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9731,7 +9930,7 @@ msgstr "Variables solicitadas" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "Ingrese variables con sintaxis JSON o YAML. Use el botón de selección para alternar entre los dos." -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "Introduzca las variables para configurar el origen del inventario. Para una descripción detallada de cómo configurar este plugin, consulte los <0>plugins de inventario en la documentación y la guía de configuración del plugin <1> de ovirt{sourceType}." @@ -9748,16 +9947,16 @@ msgid "Verbose" msgstr "Nivel de detalle" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "Nivel de detalle" @@ -9765,8 +9964,8 @@ msgstr "Nivel de detalle" msgid "View Azure AD settings" msgstr "Ver la configuración de Azure AD" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "Ver detalles de la credencial" @@ -9790,7 +9989,7 @@ msgstr "Ver detalles del host" msgid "View Instance Details" msgstr "Ver detalles de la instancia" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9904,7 +10103,7 @@ msgstr "Ver ejemplos de YAML en <0>docs.ansible.com" msgid "View activity stream" msgstr "Ver el flujo de actividad" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "Ver todas las credenciales." @@ -10067,7 +10266,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Credencial de Webhook" @@ -10078,7 +10277,7 @@ msgstr "Credenciales de Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -10086,7 +10285,7 @@ msgstr "Clave de Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -10094,7 +10293,7 @@ msgstr "Servicio de Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -10118,7 +10317,7 @@ msgstr "Los servicios de Webhook pueden usar esto como un secreto compartido." #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhooks" @@ -10142,7 +10341,7 @@ msgstr "Mié" msgid "Wednesday" msgstr "Miércoles" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10161,7 +10360,8 @@ msgstr "Día del fin de semana" msgid "" "Welcome to Red Hat Ansible Automation Platform!\n" "Please complete the steps below to activate your subscription." -msgstr "¡Bienvenido a Red Hat Ansible Automation Platform!\n" +msgstr "" +"¡Bienvenido a Red Hat Ansible Automation Platform!\n" "Complete los pasos a continuación para activar su suscripción." #: screens/Login/Login.js:190 @@ -10173,7 +10373,8 @@ msgid "" "When not checked, a merge will be performed,\n" "combining local variables with those found on the\n" "external source." -msgstr "Cuando esta opción no esté marcada, se llevará a cabo una fusión,\n" +msgstr "" +"Cuando esta opción no esté marcada, se llevará a cabo una fusión,\n" "que combinará las variables locales con aquellas halladas\n" "en la fuente externa." @@ -10182,7 +10383,8 @@ msgid "" "When not checked, local child\n" "hosts and groups not found on the external source will remain\n" "untouched by the inventory update process." -msgstr "Cuando esta opción no esté marcada, los hosts y grupos secundarios\n" +msgstr "" +"Cuando esta opción no esté marcada, los hosts y grupos secundarios\n" "locales que no se encuentren en la fuente externa no se modificarán\n" "mediante el proceso de actualización del inventario." @@ -10200,8 +10402,8 @@ msgstr "No se encontró la aprobación del flujo de trabajo." #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10212,11 +10414,11 @@ msgstr "Aprobaciones del flujo de trabajo" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "Tarea en flujo de trabajo" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "Tarea en flujo de trabajo 1/{0}" @@ -10244,11 +10446,11 @@ msgstr "Plantillas de trabajos de flujo de trabajo" msgid "Workflow Link" msgstr "Enlace del flujo de trabajo" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "Nodos de flujo de trabajo" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "Estados del flujo de trabajo" @@ -10326,7 +10528,7 @@ msgstr "Escribir" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10337,6 +10539,14 @@ msgstr "Año" msgid "Yes" msgstr "SÍ" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "No se pueden seleccionar varias credenciales con el mismo ID de Vault, ya que anulará automáticamente la selección de la otra con el mismo ID de Vault." @@ -10365,7 +10575,8 @@ msgstr "Has automatizado contra más hosts de los que permite tu suscripción." msgid "" "You may apply a number of possible variables in the\n" "message. For more information, refer to the" -msgstr "Puede aplicar una serie de posibles variables en el\n" +msgstr "" +"Puede aplicar una serie de posibles variables en el\n" "mensaje. Para obtener más información, consulte" #: screens/Login/Login.js:198 @@ -10477,7 +10688,12 @@ msgstr "Detalles" msgid "disassociate" msgstr "disociar" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10489,11 +10705,11 @@ msgstr "documentación" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10505,7 +10721,12 @@ msgstr "modificar" msgid "encrypted" msgstr "cifrado" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "para obtener más información." @@ -10589,7 +10810,7 @@ msgstr "volver a ejecutar las tareas" msgid "sec" msgstr "seg" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "segundos" @@ -10658,7 +10879,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10698,7 +10919,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10743,10 +10964,11 @@ msgstr "{brandName} Logotipo" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} por <0>{username}" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10799,7 +11021,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} min. {seconds} seg" @@ -10823,7 +11045,7 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} ocurrencia} other { msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} Lista" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" diff --git a/awx/ui/src/locales/fr/messages.po b/awx/ui/src/locales/fr/messages.po index 6219912224..4da07c6dda 100644 --- a/awx/ui/src/locales/fr/messages.po +++ b/awx/ui/src/locales/fr/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(10 premiers seulement)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(Me le demander au lancement)" @@ -25,7 +26,7 @@ msgstr "(Me le demander au lancement)" 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é." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (project root)" @@ -65,6 +66,10 @@ msgstr "4 (Débogage de la connexion)" msgid "5 (WinRM Debug)" msgstr "5 (Débogage WinRM)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -99,7 +104,7 @@ msgstr "À propos de " #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -135,7 +140,7 @@ msgstr "Action" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -157,18 +162,19 @@ msgstr "Action" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -192,7 +198,7 @@ msgstr "Action" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "Actions" @@ -360,7 +366,7 @@ msgid "Alert modal" msgstr "Modal d'alerte" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -425,7 +431,7 @@ msgstr "Type de réponse" msgid "Answer variable name" msgstr "Nom de variable de réponse" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "Quelconque" @@ -475,6 +481,10 @@ msgstr "Applications & Jetons" msgid "Approval" msgstr "Approbation" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -542,7 +552,7 @@ msgstr "Êtes-vous sûr de vouloir supprimer {0} l’accès à {1}? Cela risque msgid "Are you sure you want to remove {0} access from {username}?" msgstr "Êtes-vous sûr de vouloir supprimer {0} l’accès de {username} ?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "Voulez-vous vraiment demander l'annulation de ce job ?" @@ -555,7 +565,7 @@ msgstr "Arguments" msgid "Artifacts" msgstr "Artefacts" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "Associé" @@ -591,10 +601,11 @@ msgstr "Expiration du code d'autorisation" msgid "Authorization grant type" msgstr "Type d'autorisation" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -631,7 +642,7 @@ msgstr "Paramètres AD Azure" msgid "Back" msgstr "Retour" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "Retour à Références" @@ -654,7 +665,8 @@ msgstr "Retour aux hôtes" msgid "Back to Instance Groups" msgstr "Retour aux groupes d'instances" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "Retour aux instances" @@ -691,7 +703,7 @@ msgstr "Retour aux horaires" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -770,6 +782,10 @@ msgstr "Branche à extraire. En plus des branches, vous pouvez saisir des balis msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "Branche à utiliser dans l’exécution de la tâche. Projet par défaut utilisé si vide. Uniquement autorisé si le champ allow_override de projet est défini à true." +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "Brand Image" @@ -787,10 +803,11 @@ msgstr "Navigation...." msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "Par défaut, nous collectons et transmettons à Red Hat des données analytiques sur l'utilisation du service. Il existe deux catégories de données collectées par le service. Pour plus d'informations, consultez <0>Tower documentation à la page. Décochez les cases suivantes pour désactiver cette fonctionnalité." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -802,7 +819,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "Expiration Délai d’attente du cache" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "Expiration du délai d’attente du cache" @@ -825,8 +842,8 @@ msgstr "Expiration du délai d’attente du cache (secondes)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -863,14 +880,14 @@ msgstr "Expiration du délai d’attente du cache (secondes)" msgid "Cancel" msgstr "Annuler" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "Annuler Sync Source d’inventaire" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "Annuler Job" @@ -879,7 +896,7 @@ msgstr "Annuler Job" msgid "Cancel Project Sync" msgstr "Annuler Sync Projet" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "Annuler Sync" @@ -891,8 +908,8 @@ msgstr "Annuler Sync" msgid "Cancel Workflow" msgstr "Annuler le flux de travail" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "Annuler le job" @@ -931,7 +948,7 @@ msgstr "Annuler l'édition de l'abonnement" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "Annuler {0}" @@ -949,7 +966,6 @@ msgid "" "logging aggregator host and logging aggregator type." msgstr "Impossible d'activer l'agrégateur de logs sans fournir l'hôte de l'agrégateur de logs et le type d'agrégateur de logs." -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "Impossible d’effectuer des bilans de fonctionnement sur les nœuds Hop." @@ -960,12 +976,13 @@ msgstr "Impossible d’effectuer des bilans de fonctionnement sur les nœuds Hop msgid "Capacity" msgstr "Capacité" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "Ajustement des capacités" @@ -1051,7 +1068,7 @@ msgstr "Choisir un type de job" msgid "Choose a module" msgstr "Choisissez un module" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "Choisissez une source" @@ -1120,7 +1137,8 @@ msgstr "Cliquez sur ce bouton pour vérifier la connexion au système de gestion msgid "Click to create a new link to this node." msgstr "Cliquez pour créer un nouveau lien vers ce nœud." -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "Cliquez pour télécharger l’ensemble (Bundle)" @@ -1195,7 +1213,7 @@ msgstr "Conforme" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1272,7 +1290,7 @@ msgstr "Confirmer la sélection" msgid "Container Group" msgstr "Groupe de conteneurs" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1297,8 +1315,8 @@ msgstr "Certificat de validation de la signature du contenu" msgid "Continue" msgstr "Continuer" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "Contrôle" @@ -1321,7 +1339,7 @@ msgstr "Contrôlez le niveau de sortie qu’Ansible génère lors de l’exécut msgid "Controller Node" msgstr "Noeud du contrôleur" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "Convergence" @@ -1494,28 +1512,28 @@ msgid "Create user token" msgstr "Créer un jeton d'utilisateur" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1528,16 +1546,16 @@ msgstr "Créé" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1578,16 +1596,16 @@ msgstr "Créé par (nom d'utilisateur)" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1624,7 +1642,7 @@ msgstr "Types d'informations d'identification" msgid "Credential copied successfully" msgstr "Informations d’identification copiées." -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "Informations d'identification introuvables." @@ -1633,7 +1651,7 @@ msgstr "Informations d'identification introuvables." msgid "Credential passwords" msgstr "Mots de passes d’identification" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Identifiant pour l'authentification avec Kubernetes ou OpenShift" @@ -1650,13 +1668,13 @@ msgid "Credential type not found." msgstr "Type d'informations d’identification non trouvé." #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1665,7 +1683,7 @@ msgstr "Type d'informations d’identification non trouvé." #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1680,11 +1698,11 @@ msgstr "Les informations d'identification qui nécessitent un mot de passe au la msgid "Current page" msgstr "Page actuelle" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "Spécification pod Kubernetes ou OpenShift personnalisée." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "Spécifications des pods personnalisés" @@ -1706,8 +1724,8 @@ msgstr "L'environnement virtuel personnalisé {virtualEnvironment} doit être re msgid "Customize messages…" msgstr "Personnaliser les messages..." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Personnaliser les spécifications du pod" @@ -1717,7 +1735,7 @@ msgid "DELETED" msgstr "SUPPRIMÉ" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "Tableau de bord" @@ -1733,7 +1751,7 @@ msgstr "Durée de conservation des données" msgid "Date" msgstr "Date" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1746,7 +1764,7 @@ msgstr "Jour" msgid "Day {0}" msgstr "Jour {0}" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "Nombre de jours pendant lesquels on peut conserver les données" @@ -1810,17 +1828,17 @@ msgstr "Définir les fonctions et fonctionnalités niveau système" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1828,11 +1846,11 @@ msgstr "Définir les fonctions et fonctionnalités niveau système" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1859,17 +1877,17 @@ msgstr "Supprimer l'environnement d'exécution" msgid "Delete Host" msgstr "Supprimer l'hôte" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "Supprimer l’inventaire" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "Supprimer Job" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "Modèle de découpage de Job" @@ -1877,7 +1895,7 @@ msgstr "Modèle de découpage de Job" msgid "Delete Notification" msgstr "Supprimer la notification" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "Supprimer l'organisation" @@ -1889,7 +1907,7 @@ msgstr "Suppression du projet" msgid "Delete Questions" msgstr "Supprimer les questions" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "Supprimer la programmation" @@ -1934,16 +1952,16 @@ msgstr "Supprimer le type d'informations d’identification" msgid "Delete error" msgstr "Supprimer l'erreur" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "Supprimer un groupe d'instances" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "Supprimer la source de l'inventaire" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "Supprimer l'inventaire smart" @@ -2010,6 +2028,10 @@ msgstr "Refusé - {0}. Voir le flux d'activité pour plus d'informations." msgid "Denied by {0} - {1}" msgstr "Refusé par {0} - {1}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2035,8 +2057,8 @@ msgstr "Échec du déprovisionnement" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2058,28 +2080,28 @@ msgstr "Échec du déprovisionnement" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2089,7 +2111,7 @@ msgstr "Échec du déprovisionnement" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2106,7 +2128,7 @@ msgstr "Échec du déprovisionnement" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "Description" @@ -2136,10 +2158,11 @@ msgstr "Canaux ou utilisateurs de destination" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2148,7 +2171,7 @@ msgstr "Canaux ou utilisateurs de destination" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2163,7 +2186,7 @@ msgstr "Canaux ou utilisateurs de destination" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2177,7 +2200,7 @@ msgstr "Canaux ou utilisateurs de destination" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2225,7 +2248,7 @@ msgstr "Canaux ou utilisateurs de destination" msgid "Details" msgstr "Détails" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "Onglet Détails" @@ -2273,8 +2296,8 @@ msgstr "Dissocier le groupe de l'hôte ?" msgid "Disassociate host from group?" msgstr "Dissocier Hôte du Groupe" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "Dissocier l'instance du groupe d'instances ?" @@ -2325,8 +2348,8 @@ msgstr "Terminé" msgid "Download Bundle" msgstr "Téléchargement du Bundle" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "Télécharger la sortie" @@ -2372,28 +2395,28 @@ msgid "" "revision of the project prior to starting the job." msgstr "Chaque fois qu’un job s’exécute avec ce projet, réalisez une mise à jour du projet avant de démarrer le job." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2409,8 +2432,8 @@ msgstr "Chaque fois qu’un job s’exécute avec ce projet, réalisez une mise #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2424,8 +2447,8 @@ msgstr "Chaque fois qu’un job s’exécute avec ce projet, réalisez une mise #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2599,7 +2622,8 @@ msgstr "Modifier les détails" msgid "Edit group" msgstr "Modifier le groupe" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "Modifier l’hôte" @@ -2626,16 +2650,16 @@ msgid "Edit workflow" msgstr "Modifier le flux de travail" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "Écoulé" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "Temps écoulé" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "Temps écoulé (en secondes) pendant lequel la tâche s'est exécutée." @@ -2685,7 +2709,8 @@ msgid "" "has remained secure when a project is synced. \n" "If the content has been tampered with, the \n" "job will not run." -msgstr "Activez la signature du contenu pour vérifier que le contenu \n" +msgstr "" +"Activez la signature du contenu pour vérifier que le contenu \n" "est resté sécurisé lorsqu'un projet est synchronisé. \n" "Si le contenu a été altéré, le travail ne sera pas exécuté." @@ -2722,20 +2747,20 @@ msgstr "Activé" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "Options activées" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "Valeur activée" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "Variable activée" @@ -2799,11 +2824,15 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "Entrez les variables avec la syntaxe JSON ou YAML. Consultez la documentation sur le contrôleur Ansible pour avoir un exemple de syntaxe." #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "Entrez les variables d’inventaire avec la syntaxe JSON ou YAML. Utilisez le bouton radio pour basculer entre les deux. Consultez la documentation sur le contrôleur Ansible pour avoir un exemple de syntaxe." +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "Entrez les variables d’inventaire avec la syntaxe JSON ou YAML. Utilisez le bouton radio pour basculer entre les deux. Consultez la documentation sur le contrôleur Ansible pour avoir un exemple de syntaxe." + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2816,8 +2845,8 @@ msgstr "Variables d'environnement ou variables supplémentaires qui spécifient #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2850,14 +2879,14 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2872,29 +2901,30 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2902,7 +2932,7 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2912,14 +2942,14 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2929,7 +2959,8 @@ msgstr "Erreur lors de la sauvegarde du flux de travail !" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2939,8 +2970,8 @@ msgstr "Erreur !" msgid "Error:" msgstr "Erreur :" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "Erreurs" @@ -2970,7 +3001,7 @@ msgstr "Récapitulatif de l’événement non disponible" msgid "Events" msgstr "Événements" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "Traitement des événements terminé." @@ -2978,10 +3009,14 @@ msgstr "Traitement des événements terminé." msgid "Exact match (default lookup if not specified)." msgstr "Correspondance exacte (recherche par défaut si non spécifiée)." -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "Recherche exacte sur le champ d'identification." +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "Voici des exemples d'URL pour le contrôle des sources de GIT :" @@ -3002,7 +3037,7 @@ msgstr "Voici quelques exemples :" msgid "Examples:" msgstr "Exemples :" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "Fréquence des exceptions" @@ -3022,8 +3057,8 @@ msgstr "Exécuter lorsque le nœud parent se trouve dans un état de défaillanc msgid "Execute when the parent node results in a successful state." msgstr "Exécuter lorsque le nœud parent se trouve dans un état de réussite." -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "Exécution" @@ -3037,8 +3072,8 @@ msgstr "Exécution" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "Environnement d'exécution" @@ -3153,7 +3188,7 @@ msgid "Extra variables" msgstr "Variables supplémentaires" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3161,7 +3196,7 @@ msgid "FINISHED:" msgstr "TERMINÉ :" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "Stockage des facts" @@ -3181,23 +3216,23 @@ msgstr "Facts" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "Échec" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "Échec du comptage des hôtes" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "Échec Hôtes" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "Échec des hôtes" @@ -3205,6 +3240,10 @@ msgstr "Échec des hôtes" msgid "Failed jobs" msgstr "Jobs ayant échoué" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "N'a pas approuvé {0}." @@ -3219,7 +3258,7 @@ msgid "Failed to associate role" msgstr "N'a pas réussi à associer le rôle" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3227,7 +3266,7 @@ msgstr "N'a pas réussi à associer le rôle" msgid "Failed to associate." msgstr "N'a pas réussi à associer." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "N'a pas réussi à annuler la synchronisation des sources d'inventaire." @@ -3243,7 +3282,7 @@ msgstr "N'a pas réussi à supprimer un ou plusieurs Jobs" #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "Échec de l'annulation {0}" @@ -3286,15 +3325,15 @@ msgstr "Echec de la suppression du groupe {0}." msgid "Failed to delete host." msgstr "N'a pas réussi à supprimer l'hôte." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "Impossible de supprimer la source d'inventaire {name}." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "N'a pas réussi à supprimer l'inventaire." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "N'a pas réussi à supprimer le modèle de Job." @@ -3323,7 +3362,7 @@ msgid "Failed to delete one or more groups." msgstr "N'a pas réussi à supprimer un ou plusieurs groupes." #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "N'a pas réussi à supprimer un ou plusieurs hôtes." @@ -3339,7 +3378,7 @@ msgstr "N'a pas réussi à supprimer un ou plusieurs inventaires." msgid "Failed to delete one or more inventory sources." msgstr "N'a pas réussi à supprimer une ou plusieurs sources d'inventaire." -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "N'a pas réussi à supprimer un ou plusieurs modèles de Jobs." @@ -3383,11 +3422,11 @@ msgstr "N'a pas réussi à supprimer un ou plusieurs jetons d'utilisateur." msgid "Failed to delete one or more users." msgstr "N'a pas réussi à supprimer un ou plusieurs utilisateurs." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "N'a pas réussi à supprimer une ou plusieurs approbations de flux de travail." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "N'a pas réussi à supprimer l'organisation." @@ -3404,11 +3443,11 @@ msgstr "N'a pas réussi à supprimer le rôle" msgid "Failed to delete role." msgstr "N'a pas réussi à supprimer le rôle." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "N'a pas réussi à supprimer la programmation." -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "N'a pas réussi à supprimer l'inventaire smart." @@ -3433,6 +3472,10 @@ msgstr "N'a pas réussi à supprimer le modèle de flux de travail." msgid "Failed to delete {name}." msgstr "N'a pas réussi à supprimer {name}." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "N'a pas réussi à refuser {0}." @@ -3447,9 +3490,9 @@ msgstr "N'a pas réussi à dissocier un ou plusieurs groupes." msgid "Failed to disassociate one or more hosts." msgstr "N'a pas réussi à dissocier un ou plusieurs hôtes." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "N'a pas réussi à dissocier une ou plusieurs instances." @@ -3465,18 +3508,22 @@ msgstr "Impossible de récupérer les paramètres de configuration de connexion msgid "Failed to fetch the updated project data." msgstr "Échec de la récupération des données de projet mises à jour." -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "Impossible d’obtenir une instance." #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "Echec du lancement du Job." -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "N'a pas réussi à supprimer une ou plusieurs instances." @@ -3488,8 +3535,8 @@ msgstr "Impossible de récupérer la configuration." msgid "Failed to retrieve full node resource object." msgstr "Echec de la récupération de l'objet ressource de noeud complet." -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "Échec de l'exécution d'un contrôle de fonctionnement sur une ou plusieurs instances." @@ -3525,10 +3572,10 @@ msgstr "N'a pas réussi à basculer la notification." msgid "Failed to toggle schedule." msgstr "Impossible de basculer le calendrier." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "Échec de la mise à jour de l'ajustement des capacités." @@ -3576,7 +3623,7 @@ msgstr "Le champ contient une valeur." msgid "Field ends with value." msgstr "Le champ se termine par une valeur." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "Champ permettant de passer une spécification de pod Kubernetes ou OpenShift personnalisée." @@ -3609,11 +3656,11 @@ msgstr "Fichier, répertoire ou script" msgid "Filter By {name}" msgstr "Filtrer par {name}" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "Filtrer par travaux échoués" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "Filtrer par tâches ayant réussi" @@ -3642,7 +3689,7 @@ msgstr "Première" msgid "First Name" msgstr "Prénom" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "Première exécution" @@ -3685,11 +3732,11 @@ msgstr "Pour plus d'informations, reportez-vous à" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3699,12 +3746,12 @@ msgstr "Forks" msgid "Fourth" msgstr "Quatrième" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "Informations sur la fréquence" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "Fréquence Détails de l'exception" @@ -3726,7 +3773,7 @@ msgstr "Ven." msgid "Friday" msgstr "Vendredi" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "Recherche floue sur les champs id, nom ou description." @@ -3738,7 +3785,7 @@ msgstr "Recherche floue sur le champ du nom." msgid "GPG Public Key" msgstr "Clé publique GPG" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Informations d’identification Galaxy" @@ -3776,7 +3823,7 @@ msgstr "Obtenir des abonnements" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3815,7 +3862,7 @@ msgstr "GitHub Team" msgid "GitHub settings" msgstr "Paramètres de GitHub" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3919,6 +3966,19 @@ msgstr "Méthode HTTP" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "Demande(s) de bilan de santé soumise(s). Veuillez patienter et recharger la page." +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "Fonctionne correctement" @@ -3941,7 +4001,7 @@ msgstr "Masquer la description" msgid "Hipchat" msgstr "HipChat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "Hop" @@ -3949,8 +4009,9 @@ msgstr "Hop" msgid "Hop node" msgstr "Noeud Hop" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3965,16 +4026,16 @@ msgid "Host Async OK" msgstr "Désynchronisation des hôtes OK" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "Clé de configuration de l’hôte" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "Nombre d'hôtes" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "Détails sur l'hôte" @@ -3986,13 +4047,14 @@ msgstr "Échec de l'hôte" msgid "Host Failure" msgstr "Échec de l'hôte" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "Filtre d'hôte" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "Nom d'hôte" @@ -4025,7 +4087,7 @@ msgstr "Hôte inaccessible" msgid "Host details" msgstr "Informations sur l'hôte" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "Détails sur l'hôte modal" @@ -4040,7 +4102,7 @@ msgstr "Les informations relatives au statut d'hôte pour ce Job ne sont pas dis #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4052,10 +4114,10 @@ msgstr "Les informations relatives au statut d'hôte pour ce Job ne sont pas dis #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "Hôtes" @@ -4077,15 +4139,15 @@ msgstr "Hôtes importés" msgid "Hosts remaining" msgstr "Hôtes restants" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "Heure" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "Hybride" @@ -4204,18 +4266,20 @@ msgstr "Si activé, il sera possible d’avoir des exécutions de ce modèle de msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "Si activé, il sera possible d’avoir des exécutions de ce modèle de job de flux de travail en simultané." -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "Si cette option est activée, l'inventaire empêchera l'ajout de tout groupe d'instances d'organisation à la liste des groupes d'instances préférés pour l'exécution des modèles de tâches associés.\n" +msgstr "" +"Si cette option est activée, l'inventaire empêchera l'ajout de tout groupe d'instances d'organisation à la liste des groupes d'instances préférés pour l'exécution des modèles de tâches associés.\n" "Remarque : Si ce paramètre est activé et que vous avez fourni une liste vide, les groupes d'instances globaux seront appliqués." #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "S'il est activé, le modèle de tâche empêchera l'ajout de tout groupe d'instance d'inventaire ou d'organisation à la liste des groupes d'instances préférés pour l'exécution.\n" +msgstr "" +"S'il est activé, le modèle de tâche empêchera l'ajout de tout groupe d'instance d'inventaire ou d'organisation à la liste des groupes d'instances préférés pour l'exécution.\n" "Remarque : Si ce paramètre est activé et que vous avez fourni une liste vide, les groupes d'instances globaux seront appliqués." #: screens/Template/shared/JobTemplate.helptext.js:35 @@ -4313,7 +4377,8 @@ msgstr "Insights - Information d’identification" msgid "Insights system ID" msgstr "ID du système Insights" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "Installer Bundle" @@ -4334,25 +4399,26 @@ msgstr "Filtres de l'instance" msgid "Instance Group" msgstr "Groupe d'instance" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "Groupes d'instances" @@ -4382,8 +4448,8 @@ msgstr "Groupe d'instance" msgid "Instance group not found." msgstr "Groupe d'instance non trouvé." -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "La capacité utilisée par le groupe d'instances" @@ -4406,9 +4472,9 @@ msgstr "Type d'instance" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4441,7 +4507,7 @@ msgstr "Nom d’utilisateur et/ou mot de passe non valide. Veuillez réessayer." #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4465,18 +4531,18 @@ msgstr "Les inventaires et les sources ne peuvent pas être copiés" #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4485,8 +4551,8 @@ msgstr "Les inventaires et les sources ne peuvent pas être copiés" #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4513,7 +4579,7 @@ msgstr "Sources d'inventaire" msgid "Inventory Source Sync" msgstr "Sync Source d’inventaire" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "Erreur de synchronisation de la source de l'inventaire" @@ -4545,8 +4611,8 @@ msgstr "Mise à jour de l'inventaire" msgid "Inventory copied successfully" msgstr "Inventaire copié" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "Fichier d'inventaire" @@ -4558,7 +4624,7 @@ msgstr "Inventaire non trouvé." msgid "Inventory sync" msgstr "Synchronisation des inventaires" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "Erreurs de synchronisation des inventaires" @@ -4592,18 +4658,18 @@ msgid "Items per page" msgstr "Éléments par page" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "ID JOB :" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "Onglet JSON" @@ -4618,16 +4684,16 @@ msgstr "Janvier" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "Erreur d'annulation d'un Job" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "Erreur de suppression d’un Job" @@ -4650,10 +4716,10 @@ msgid "Job Slice Parent" msgstr "Parent de tranche de job" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "Tranche de job" @@ -4664,11 +4730,11 @@ msgstr "Statut Job" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4689,7 +4755,7 @@ msgstr "Modèle de Job" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "Les informations d'identification par défaut du modèle de Job doivent être remplacées par une information du même type. Veuillez sélectionner un justificatif d'identité pour les types suivants afin de procéder : {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4712,26 +4778,26 @@ msgstr "Les modèles de Job dont les informations d'identification demandent un #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "Type de Job" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "Statut Job" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "Onglet Graphique de l'état des Jobs" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "Modèles de Jobs" @@ -4845,7 +4911,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "Libellé" @@ -4856,15 +4922,15 @@ msgstr "Nom du label" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4876,18 +4942,19 @@ msgstr "Libellés" msgid "Last" msgstr "Dernier" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "Dernier bilan de fonctionnement" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "Statut du dernier Job" @@ -4896,8 +4963,8 @@ msgstr "Statut du dernier Job" msgid "Last Login" msgstr "Dernière connexion" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4906,17 +4973,17 @@ msgstr "Dernière connexion" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4939,7 +5006,7 @@ msgstr "Nom" msgid "Last Ran" msgstr "Dernière exécution" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "Dernière exécution" @@ -4947,8 +5014,8 @@ msgstr "Dernière exécution" msgid "Last job" msgstr "Dernier Job" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -4972,8 +5039,8 @@ msgstr "Dernière utilisation" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5040,12 +5107,12 @@ msgstr "Moins ou égal à la comparaison." #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5073,7 +5140,7 @@ msgstr "Chargement en cours..." msgid "Local" msgstr "Local" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "Fuseau horaire local" @@ -5116,7 +5183,7 @@ msgstr "Type de recherche" msgid "Lookup typeahead" msgstr "Recherche Typeahead" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5171,14 +5238,15 @@ msgstr "Job de gestion non trouvé." msgid "Management jobs" msgstr "Jobs de gestion" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5198,11 +5266,25 @@ msgstr "Mars" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "Hôtes max." +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "Maximum" @@ -5211,6 +5293,24 @@ msgstr "Maximum" msgid "Maximum length" msgstr "Longueur maximale" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5259,7 +5359,7 @@ msgid "" "assigned to this group when new instances come online." msgstr "Le pourcentage minimum de toutes les instances qui seront automatiquement assignées à ce groupe lorsque de nouvelles instances seront mises en ligne." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5301,16 +5401,16 @@ msgstr "Modifié" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5348,7 +5448,7 @@ msgid "Modified by (username)" msgstr "Modifié par (nom d'utilisateur)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "Module" @@ -5371,7 +5471,7 @@ msgstr "Lun." msgid "Monday" msgstr "Lundi" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5420,8 +5520,8 @@ msgstr "Options à choix multiples." #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5444,8 +5544,8 @@ msgstr "Options à choix multiples." #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5455,11 +5555,11 @@ msgstr "Options à choix multiples." #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5515,27 +5615,27 @@ msgstr "Options à choix multiples." #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5547,7 +5647,7 @@ msgstr "Options à choix multiples." #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5557,7 +5657,7 @@ msgstr "Options à choix multiples." #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5567,7 +5667,7 @@ msgstr "Options à choix multiples." #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5577,7 +5677,7 @@ msgstr "Options à choix multiples." #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5599,7 +5699,7 @@ msgstr "Options à choix multiples." #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5630,8 +5730,8 @@ msgstr "Options à choix multiples." #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "Nom" @@ -5674,7 +5774,7 @@ msgstr "Nouveau" msgid "Next" msgstr "Suivant" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5694,7 +5794,7 @@ msgstr "Aucun hôte correspondant" msgid "No Hosts Remaining" msgstr "Aucun hôte restant" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "Pas de JSON disponible" @@ -5718,7 +5818,7 @@ msgstr "Aucune donnée de tâche disponible." msgid "No output found for this job." msgstr "Aucune sortie de données pour ce job." -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "Aucun résultat trouvé" @@ -5737,10 +5837,10 @@ msgstr "Aucun résultat trouvé" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "Aucun résultat trouvé" @@ -5768,15 +5868,16 @@ msgstr "Aucun(e) {pluralizedItemName} trouvé(e)" msgid "Node Alias" msgstr "Alias de nœud" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5801,8 +5902,8 @@ msgstr "Types de nœud" msgid "None" msgstr "Aucun" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "Aucun (exécution unique)" @@ -5953,14 +6054,14 @@ msgstr "Octobre" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "Désactivé" @@ -5969,14 +6070,14 @@ msgstr "Désactivé" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "Le" @@ -6008,7 +6109,8 @@ msgstr "Tels jours" msgid "" "One Slack channel per line. The pound symbol (#)\n" "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" -msgstr "Saisissez un canal Slack par ligne. Le symbole dièse (#)\n" +msgstr "" +"Saisissez un canal Slack par ligne. Le symbole dièse (#)\n" "est obligatoire pour les canaux. Pour répondre ou démarrer un fil de discussion sur un message spécifique, ajoutez l'Id du message parent au canal où l'Id du message parent est composé de 16 chiffres. Un point (.) doit être inséré manuellement après le 10ème chiffre. ex : #destination-channel, 1231257890.006423. Voir Slack" #: components/PromptDetail/PromptInventorySourceDetail.js:154 @@ -6050,7 +6152,7 @@ msgstr "En option, sélectionnez les informations d'identification à utiliser p #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6086,11 +6188,11 @@ msgstr "Commande" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6100,8 +6202,8 @@ msgstr "Commande" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6145,12 +6247,12 @@ msgid "Out of compliance" msgstr "Non-conformité" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "Sortie" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "Onglet de sortie" @@ -6159,12 +6261,12 @@ msgid "Overwrite" msgstr "Remplacer" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "Remplacer les groupes locaux et les hôtes de la source d'inventaire distante." #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "Remplacer les variables locales de la source d'inventaire distante." @@ -6283,11 +6385,11 @@ msgstr "Jeton d'accès personnel" msgid "Personal access token" msgstr "Jeton d'accès personnel" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "Play" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "Play - Nombre" @@ -6297,7 +6399,7 @@ msgstr "Play - Démarrage" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6329,7 +6431,7 @@ msgstr "Exécution Playbook" msgid "Playbook Started" msgstr "Playbook démarré" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6341,7 +6443,7 @@ msgstr "Nom du playbook" msgid "Playbook run" msgstr "Exécution du playbook" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "Plays" @@ -6365,7 +6467,7 @@ msgstr "Veuillez ajouter {pluralizedItemName} pour remplir cette liste" msgid "Please click the Start button to begin." msgstr "Veuillez cliquer sur le bouton de démarrage pour commencer." -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "Veuillez saisir un nombre d'occurrences." @@ -6385,7 +6487,7 @@ msgstr "Veuillez vous connecter" msgid "Please run a job to populate this list." msgstr "Veuillez ajouter un job pour remplir cette liste" -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "Veuillez choisir un numéro de jour entre 1 et 31." @@ -6393,7 +6495,7 @@ msgstr "Veuillez choisir un numéro de jour entre 1 et 31." msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "Sélectionnez un inventaire ou cochez l’option Me le demander au lancement." -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "Veuillez choisir une date/heure de fin qui vient après la date/heure de début." @@ -6409,14 +6511,15 @@ msgstr "Veuillez sélectionner une autre recherche par le filtre ci-dessus" msgid "Please wait until the topology view is populated..." msgstr "Veuillez patienter jusqu’à ce que la topologie soit remplie..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Remplacement des spécifications du pod" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "Type de politique" @@ -6470,20 +6573,21 @@ msgid "" "and use the arrow keys to navigate up or down.\n" "Press enter to confirm the drag, or any other key to\n" "cancel the drag operation." -msgstr "Appuyez sur la touche Espace ou Entrée pour commencer à faire glisser,\n" +msgstr "" +"Appuyez sur la touche Espace ou Entrée pour commencer à faire glisser,\n" "et utilisez les touches fléchées pour vous déplacer vers le haut ou le bas.\n" "Appuyez sur la touche Entrée pour confirmer le déplacement, ou sur une autre touche pour annuler l'opération de déplacement." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "Empêcher le repli du groupe d'instances" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "Empêcher le repli des groupes d'instances : s'il est activé, l'inventaire empêchera l'ajout de tout groupe d'instances d'organisation à la liste des groupes d'instances préférés pour exécuter les modèles de tâches associés." @@ -6501,7 +6605,7 @@ msgid "Private key passphrase" msgstr "Phrase de passe pour la clé privée" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "Élévation des privilèges" @@ -6522,11 +6626,11 @@ msgstr "Élévation des privilèges: si activé, exécuter ce playbook en tant q #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "Projet" @@ -6567,14 +6671,14 @@ msgstr "Projet copié" msgid "Project not found." msgstr "Projet non trouvé." -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "Erreurs de synchronisation du projet" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6589,12 +6693,12 @@ msgstr "Projets" msgid "Promote Child Groups and Hosts" msgstr "Promouvoir les groupes de dépendants et les hôtes" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "Invite" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "Invite Remplacements" @@ -6608,8 +6712,8 @@ msgstr "Me le demander au lancement" msgid "Prompt | {0}" msgstr "Invite | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "Valeurs incitatrices" @@ -6654,7 +6758,7 @@ msgid "Provisioning" msgstr "Approvisionnement" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "URL de rappel d’exécution " @@ -6664,7 +6768,7 @@ msgid "Provisioning Callback details" msgstr "Détails de rappel d’exécution" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6695,10 +6799,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "Paramètres RADIUS" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6712,23 +6817,23 @@ msgstr "Lecture" msgid "Ready" msgstr "Prêt" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "Jobs récents" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "Onglet Liste des Jobs récents" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "Modèles récents" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "Onglet Liste des modèles récents" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6819,12 +6924,15 @@ msgstr "Régions" msgid "Registry credential" msgstr "Information d’identification au registre" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "Expression régulière où seuls les noms d'hôtes correspondants seront importés. Le filtre est appliqué comme une étape de post-traitement après l'application de tout filtre de plugin d'inventaire." #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "Groupes liés" @@ -6851,12 +6959,12 @@ msgstr "Recherche connexe : type typeahead" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "Relancer" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "Relancer le Job" @@ -6874,7 +6982,7 @@ msgid "Relaunch on" msgstr "Relancer sur" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "Relancer en utilisant les paramètres de l'hôte" @@ -6882,7 +6990,7 @@ msgstr "Relancer en utilisant les paramètres de l'hôte" msgid "Reload" msgstr "Rechargez" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "Recharger la sortie" @@ -6895,8 +7003,8 @@ msgstr "Recharger la sortie" msgid "Remote Archive" msgstr "Archive à distance" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "Erreur de suppression" @@ -6955,7 +7063,7 @@ msgstr "La suppression de ce lien rendra le reste de la branche orphelin et entr msgid "Reorder" msgstr "Réorganiser" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "Fréquence de répétition" @@ -7025,8 +7133,8 @@ msgstr "Récupérez l'état activé à partir des variables dict donnée de l'h #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "Renvoi" @@ -7131,8 +7239,9 @@ msgstr "Exécuter" msgid "Run Command" msgstr "Exécuter Commande" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "Exécuter un contrôle de vérification de fonctionnement sur l'instance" @@ -7149,10 +7258,11 @@ msgstr "Exécuter Commande" msgid "Run every" msgstr "Exécutez tous les" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "Bilan de fonctionnement" @@ -7179,17 +7289,26 @@ msgstr "En cours d'exécution" msgid "Running Handlers" msgstr "Descripteurs d'exécution" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "Jobs en cours d'exécution" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "Dernier bilan de fonctionnement" @@ -7228,7 +7347,7 @@ msgid "START" msgstr "DÉMARRER" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7251,8 +7370,8 @@ msgstr "Samedi" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7306,7 +7425,7 @@ msgstr "Le planning est actif." msgid "Schedule is inactive" msgstr "Le planning est inactif." -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "La programmation manque de règles" @@ -7428,7 +7547,7 @@ msgstr "Sélectionner les hôtes" msgid "Select Input" msgstr "Sélectionnez une entrée" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "Sélectionner les instances" @@ -7498,11 +7617,19 @@ msgstr "Sélectionnez un projet avant de modifier l'environnement d'exécution." msgid "Select a question to delete" msgstr "Sélectionnez une question à supprimer" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "Sélectionnez une ligne à supprimer" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "Sélectionnez une ligne à dissocier" @@ -7530,8 +7657,8 @@ msgstr "Sélectionnez un abonnement" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7573,7 +7700,7 @@ msgstr "Sélectionnez une instance" msgid "Select an instance and a metric to show chart" msgstr "Sélectionnez une instance et une métrique pour afficher le graphique" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "Sélectionnez une instance pour effectuer un bilan de fonctionnement." @@ -7629,9 +7756,9 @@ msgstr "Sélectionnez une période" msgid "Select roles to apply" msgstr "Sélectionner les rôles à pourvoir" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "Sélectionner le chemin d'accès de la source" @@ -7669,7 +7796,8 @@ msgstr "Sélectionnez les informations d’identification qu’il vous faut util msgid "" "Select the inventory containing the hosts\n" "you want this job to manage." -msgstr "Sélectionnez l'inventaire contenant les hôtes\n" +msgstr "" +"Sélectionnez l'inventaire contenant les hôtes\n" "que vous voulez que ce Job gère." #: screens/Job/Job.helptext.js:6 @@ -7722,8 +7850,8 @@ msgstr "Sélectionnez {0}" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7746,8 +7874,8 @@ msgstr "Sélectionné" msgid "Selected Category" msgstr "Catégorie sélectionnée" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "La plage de dates sélectionnée doit avoir au moins une occurrence de calendrier." @@ -7781,7 +7909,7 @@ msgstr "Définissez le nombre de jours pendant lesquels les données doivent êt msgid "Set preferences for data collection, logos, and logins" msgstr "Définissez des préférences pour la collection des données, les logos et logins." -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "Définir le chemin source à" @@ -7847,10 +7975,10 @@ msgid "Show" msgstr "Afficher" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "Afficher Modifications" @@ -7924,11 +8052,11 @@ msgstr "Sélection par simple pression d'une touche" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -8002,8 +8130,8 @@ msgstr "Trier" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8011,20 +8139,22 @@ msgid "Source" msgstr "Source" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "Branche Contrôle de la source" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "Branche/ Balise / Commit du Contrôle de la source" @@ -8087,7 +8217,7 @@ msgstr "Flux de travail Source" msgid "Source control branch" msgstr "Branche Contrôle de la source" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "Détails de la source" @@ -8095,7 +8225,7 @@ msgstr "Détails de la source" msgid "Source phone number" msgstr "Numéro de téléphone de la source" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "Variables sources" @@ -8125,11 +8255,11 @@ msgstr "Spécifier une couleur de notification. Les couleurs acceptées sont d'u msgid "Specify the conditions under which this node should be executed" msgstr "Préciser les conditions dans lesquelles ce nœud doit être exécuté" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "Erreur standard" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "Onglet Erreur standard" @@ -8176,27 +8306,28 @@ msgid "Start time" msgstr "Heure de début" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "Démarré" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8204,7 +8335,7 @@ msgstr "Démarré" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "État" @@ -8227,7 +8358,8 @@ msgid "" "the revision specified by the main project.\n" "This is equivalent to specifying the --remote\n" "flag to git submodule update." -msgstr "Les sous-modules suivront le dernier commit sur\n" +msgstr "" +"Les sous-modules suivront le dernier commit sur\n" "leur branche principale (ou toute autre branche spécifiée dans\n" ".gitmodules). Si non, les sous-modules seront maintenus à\n" "la révision spécifiée par le projet principal.\n" @@ -8297,7 +8429,7 @@ msgstr "Corps du message de réussite" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "Réussi" @@ -8433,8 +8565,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "Paramètres de la TACACS" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "Balises" @@ -8461,11 +8593,11 @@ msgstr "Balises pour l'annotation (facultatif)" msgid "Target URL" msgstr "URL cible" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "Tâche" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "Nombre de tâches" @@ -8473,7 +8605,7 @@ msgstr "Nombre de tâches" msgid "Task Started" msgstr "Tâche démarrée" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "Tâches" @@ -8515,7 +8647,7 @@ msgstr "Équipes" msgid "Template" msgstr "Modèle" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "Modèle copié" @@ -8585,11 +8717,12 @@ msgstr "Le" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "Le type d’autorisation que l'utilisateur doit utiliser pour acquérir des jetons pour cette application" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "Sélectionnez les groupes d'instances sur lesquels exécuter cette organisation." -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "Les groupes d'instances auxquels appartient cette instance." @@ -8620,7 +8753,7 @@ msgstr "URL de base du serveur Grafana - le point de terminaison /api/annotation msgid "The container image to be used for execution." msgstr "L'image du conteneur à utiliser pour l'exécution." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8639,7 +8772,8 @@ msgstr "L'environnement d'exécution qui sera utilisé pour les jobs qui utilise #: screens/Job/Job.helptext.js:9 #: screens/Template/shared/JobTemplate.helptext.js:10 msgid "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." -msgstr "L'environnement d'exécution qui sera utilisé lors du lancement\n" +msgstr "" +"L'environnement d'exécution qui sera utilisé lors du lancement\n" "ce modèle de tâche. L'environnement d'exécution résolu peut être remplacé en\n" "en affectant explicitement un environnement différent à ce modèle de tâche." @@ -8654,7 +8788,7 @@ msgstr "Le premier extrait toutes les références. Le second extrait la requê msgid "The full image location, including the container registry, image name, and version tag." msgstr "L'emplacement complet de l'image, y compris le registre du conteneur, le nom de l'image et la balise de version." -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8673,7 +8807,7 @@ msgstr "Dernier {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "Le dernier {weekday} de {month}" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8833,7 +8967,7 @@ msgstr "Cette action dissociera les éléments suivants :" msgid "This action will remove the following instances:" msgstr "Cette action supprimera les instances suivantes :" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 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 ?" @@ -8850,7 +8984,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Software and to provide\n" "Automation Analytics." -msgstr "Ces données sont utilisées pour améliorer\n" +msgstr "" +"Ces données sont utilisées pour améliorer\n" "les futures versions du logiciel et pour fournir des données d’ Automation Analytics.." #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:62 @@ -8858,7 +8993,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Tower Software and help\n" "streamline customer experience and success." -msgstr "Ces données sont utilisées pour améliorer\n" +msgstr "" +"Ces données sont utilisées pour améliorer\n" "les futures versions du logiciel Tower et contribuer à\n" "à rationaliser l'expérience des clients." @@ -8871,7 +9007,7 @@ msgstr "Cet environnement d'exécution est actuellement utilisé par d'autres re msgid "This feature is deprecated and will be removed in a future release." msgstr "Cette fonctionnalité est obsolète et sera supprimée dans une prochaine version." -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "Ce champ est ignoré à moins qu'une variable activée ne soit définie. Si la variable activée correspond à cette valeur, l'hôte sera activé lors de l'importation." @@ -8957,7 +9093,7 @@ msgstr "Ce champ sera récupéré dans un système externe de gestion des secret msgid "This has already been acted on" msgstr "Ce point a déjà fait l'objet d'une action" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "Ce groupe d'instance est actuellement utilisé par d'autres ressources. Êtes-vous sûr de vouloir le supprimer ?" @@ -8965,11 +9101,11 @@ msgstr "Ce groupe d'instance est actuellement utilisé par d'autres ressources. msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "Cet inventaire est appliqué à tous les nœuds de flux de travail de ce flux de travail ({0}) qui requiert un inventaire." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "Cet inventaire est actuellement utilisé par d'autres ressources. Êtes-vous sûr de vouloir le supprimer ?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "Cette source d'inventaire est actuellement utilisée par d'autres ressources qui en dépendent. Êtes-vous sûr de vouloir la supprimer ?" @@ -8985,11 +9121,11 @@ msgstr "C'est la seule fois où la valeur du jeton et la valeur du jeton de rafr msgid "This job failed and has no output." msgstr "Ce travail a échoué et n'a pas de résultat." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "Ce modèle de poste est actuellement utilisé par d'autres ressources. Êtes-vous sûr de vouloir le supprimer ?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "Cette organisation est actuellement en cours de traitement par d'autres ressources. Êtes-vous sûr de vouloir la supprimer ?" @@ -9001,7 +9137,7 @@ msgstr "Ce projet est actuellement utilisé par d'autres ressources. Êtes-vous msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "Ce projet est actuellement en cours de synchronisation et ne peut être cliqué tant que le processus de synchronisation n'est pas terminé" -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "Cet horaire n'a pas d'occurrences en raison des exceptions sélectionnées." @@ -9039,7 +9175,8 @@ msgstr "Cela annulera tous les nœuds suivants dans ce flux de travail." msgid "" "This will revert all configuration values on this page to\n" "their factory defaults. Are you sure you want to proceed?" -msgstr "Ceci rétablira toutes les valeurs de configuration sur cette page à\n" +msgstr "" +"Ceci rétablira toutes les valeurs de configuration sur cette page à\n" "à leurs valeurs par défaut. Êtes-vous sûr de vouloir continuer ?" #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerStartScreen.js:40 @@ -9097,13 +9234,13 @@ msgid "Timed out" msgstr "Expiré" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9206,15 +9343,16 @@ msgid "Tools" msgstr "Outils" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "Vue topologique" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "Total Jobs" @@ -9224,7 +9362,7 @@ msgstr "Total Jobs" msgid "Total Nodes" msgstr "Total Nœuds" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "Total Hôtes" @@ -9280,8 +9418,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9294,11 +9432,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9346,13 +9484,14 @@ msgstr "Impossible de modifier l'inventaire sur un hôte." msgid "Unable to load last job update" msgstr "Impossible de charger la dernière mise à jour du job" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "Non disponible" @@ -9372,15 +9511,15 @@ msgstr "Illimité" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "Inaccessible" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "Nombre d'hôtes inaccessibles" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "Hôtes inaccessibles" @@ -9397,7 +9536,7 @@ msgid "Update Revision on Launch" msgstr "Mettre à jour Révision au lancement" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "Mettre à jour au lancement" @@ -9469,22 +9608,25 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "Saisissez un numéro de téléphone par ligne pour indiquer où acheminer les messages SMS. Les numéros de téléphone doivent être formatés ainsi +11231231234. Pour plus d'informations, voir la documentation de Twilio" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "Capacité utilisée" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "Capacité utilisée" @@ -9584,22 +9726,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9615,7 +9757,7 @@ msgstr "Variables demandées" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "Variables avec la syntaxe JSON ou YAML. Utilisez le bouton radio pour basculer entre les deux." -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "Variables pour configurer la source de l'inventaire. Pour une description détaillée de la configuration de ce plugin, voir les <0>Plugins d’inventaire dans la documentation et dans le guide de configuration du Plugin <1>{sourceType}." @@ -9632,16 +9774,16 @@ msgid "Verbose" msgstr "Verbeux" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "Verbosité" @@ -9649,8 +9791,8 @@ msgstr "Verbosité" msgid "View Azure AD settings" msgstr "Voir les paramètres Azure AD" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "Afficher les détails des informations d'identification" @@ -9674,7 +9816,7 @@ msgstr "Voir les détails de l'hôte" msgid "View Instance Details" msgstr "Voir les détails de l'instance" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9788,7 +9930,7 @@ msgstr "Voir les exemples YALM sur <0>docs.ansible.com" msgid "View activity stream" msgstr "Afficher le flux d’activité" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "Voir toutes les informations d’identification." @@ -9951,7 +10093,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Informations d'identification du webhook" @@ -9962,7 +10104,7 @@ msgstr "Informations d'identification du webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -9970,7 +10112,7 @@ msgstr "Clé du webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -9978,7 +10120,7 @@ msgstr "Service webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -10002,7 +10144,7 @@ msgstr "Les services webhook peuvent l'utiliser en tant que secret partagé." #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhooks" @@ -10026,7 +10168,7 @@ msgstr "Mer." msgid "Wednesday" msgstr "Mercredi" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10079,8 +10221,8 @@ msgstr "Approbation du flux de travail non trouvée." #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10091,11 +10233,11 @@ msgstr "Approbations des flux de travail" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "Job de flux de travail" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "Job de flux de travail 1/{0}" @@ -10123,11 +10265,11 @@ msgstr "Modèles de Jobs de flux de travail" msgid "Workflow Link" msgstr "Lien vers le flux de travail" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "Nœuds de flux de travail" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "Statuts du flux de travail" @@ -10205,7 +10347,7 @@ msgstr "Écriture" msgid "YAML:" msgstr "YAML :" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10216,6 +10358,14 @@ msgstr "Année" msgid "Yes" msgstr "Oui" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "Vous ne pouvez pas sélectionner plusieurs identifiants d’archivage sécurisé (Vault) avec le même identifiant de d’archivage sécurisé. Cela désélectionnerait automatiquement les autres identifiants d’archivage sécurisé." @@ -10355,7 +10505,12 @@ msgstr "détails" msgid "disassociate" msgstr "dissocier" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10367,11 +10522,11 @@ msgstr "documentation" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10383,7 +10538,12 @@ msgstr "modifier" msgid "encrypted" msgstr "crypté" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "pour plus d'infos." @@ -10467,7 +10627,7 @@ msgstr "relancer les Jobs" msgid "sec" msgstr "sec" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "secondes" @@ -10536,7 +10696,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10576,7 +10736,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10621,10 +10781,11 @@ msgstr "{brandName} logo" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} par <0>{username}" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10677,7 +10838,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} min {seconds} sec" @@ -10701,7 +10862,7 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} occurrence} other { msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} Liste" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" diff --git a/awx/ui/src/locales/ja/messages.po b/awx/ui/src/locales/ja/messages.po index aa9ea8792d..bbbbc96a67 100644 --- a/awx/ui/src/locales/ja/messages.po +++ b/awx/ui/src/locales/ja/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(最初の 10 件に制限)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(起動プロンプト)" @@ -25,7 +26,7 @@ msgstr "(起動プロンプト)" msgid "* This field will be retrieved from an external secret management system using the specified credential." msgstr "*このフィールドは、指定された認証情報を使用して外部のシークレット管理システムから取得されます。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (プロジェクト root)" @@ -65,12 +66,17 @@ msgstr "4 (接続デバッグ)" msgid "5 (WinRM Debug)" msgstr "5 (WinRM デバッグ)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" "module). This parameter allows access to references via\n" "the branch field not otherwise available." -msgstr "取得する refspec (Ansible git モジュールに渡します)。\n" +msgstr "" +"取得する refspec (Ansible git モジュールに渡します)。\n" "このパラメーターを使用すると、(パラメーターなしでは利用できない) \n" "ブランチのフィールド経由で参照にアクセスできるようになります。" @@ -101,7 +107,7 @@ msgstr "情報" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -137,7 +143,7 @@ msgstr "アクション" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -159,18 +165,19 @@ msgstr "アクション" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -194,7 +201,7 @@ msgstr "アクション" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "アクション" @@ -351,7 +358,8 @@ msgid "" "changes, refresh the inventory from the selected source\n" "before executing job tasks. This is intended for static content,\n" "like the Ansible inventory .ini file format." -msgstr "SCM リビジョンを変更するプロジェクトの毎回の更新後に、\n" +msgstr "" +"SCM リビジョンを変更するプロジェクトの毎回の更新後に、\n" "選択されたソースのインベントリーを更新してからジョブのタスクを実行します。\n" "これは、Ansible インベントリーの .ini ファイル形式のような静的コンテンツが対象であることが\n" "意図されています。" @@ -365,7 +373,7 @@ msgid "Alert modal" msgstr "アラートモーダル" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -393,7 +401,8 @@ msgstr "ブランチの上書き許可" msgid "" "Allow changing the Source Control branch or revision in a job\n" "template that uses this project." -msgstr "このプロジェクトを使用するジョブテンプレートで Source Control ブランチまたは\n" +msgstr "" +"このプロジェクトを使用するジョブテンプレートで Source Control ブランチまたは\n" "リビジョンを変更できるようにします。" #: screens/Application/shared/Application.helptext.js:6 @@ -431,7 +440,7 @@ msgstr "回答タイプ" msgid "Answer variable name" msgstr "回答の変数名" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "任意" @@ -481,6 +490,10 @@ msgstr "アプリケーションおよびトークン" msgid "Approval" msgstr "承認" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -548,7 +561,7 @@ msgstr "{1} から {0} のアクセスを削除しますか? これを行うと msgid "Are you sure you want to remove {0} access from {username}?" msgstr "{username} からの {0} のアクセスを削除してもよろしいですか?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "このジョブを取り消す要求を送信してよろしいですか?" @@ -561,7 +574,7 @@ msgstr "引数" msgid "Artifacts" msgstr "アーティファクト" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "関連付け" @@ -597,10 +610,11 @@ msgstr "認証コードの有効期限" msgid "Authorization grant type" msgstr "認証付与タイプ" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "自動" @@ -637,7 +651,7 @@ msgstr "Azure AD の設定" msgid "Back" msgstr "戻る" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "認証情報に戻る" @@ -660,7 +674,8 @@ msgstr "ホストに戻る" msgid "Back to Instance Groups" msgstr "インスタンスグループに戻る" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "インスタンスに戻る" @@ -697,7 +712,7 @@ msgstr "スケジュールに戻る" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -758,7 +773,8 @@ msgid "" "found inside this path will be listed in the playbook directory drop-down.\n" "Together the base path and selected playbook directory provide the full\n" "path used to locate playbooks." -msgstr "Playbook を見つけるために使用されるベースパスです。\n" +msgstr "" +"Playbook を見つけるために使用されるベースパスです。\n" "このパス内にあるディレクトリーは Playbook ディレクトリーのドロップダウンに一覧表示されます。\n" "ベースパスと選択されたPlaybook ディレクトリーは、\n" "Playbook を見つけるために使用される完全なパスを提供します。" @@ -773,7 +789,8 @@ msgid "" "you can input tags, commit hashes, and arbitrary refs. Some\n" "commit hashes and refs may not be available unless you also\n" "provide a custom refspec." -msgstr "チェックアウトするブランチです。\n" +msgstr "" +"チェックアウトするブランチです。\n" "ブランチ以外に、タグ、コミットハッシュ値、任意の参照 (refs) を入力できます。\n" "カスタムの refspec も指定しない限り、コミットハッシュ値や参照で利用できないものもあります。" @@ -781,6 +798,10 @@ msgstr "チェックアウトするブランチです。\n" msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "ジョン実行に使用するブランチ。空白の場合はプロジェクトのデフォルト設定が使用されます。プロジェクトの allow_override フィールドが True の場合のみ許可されます。" +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "ブランドイメージ" @@ -798,10 +819,11 @@ msgstr "参照…" msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "デフォルトでは、サービスの使用状況に関する解析データを収集して、Red Hat に送信します。サービスが収集するデータにはカテゴリーが 2 種類あります。詳細情報は、<0>Tower のドキュメントページ< を参照してください。この機能を無効にするには、以下のボックスのチェックを解除します。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -813,7 +835,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "キャッシュタイムアウト" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "キャッシュタイムアウト" @@ -836,8 +858,8 @@ msgstr "キャッシュのタイムアウト (秒)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -874,14 +896,14 @@ msgstr "キャッシュのタイムアウト (秒)" msgid "Cancel" msgstr "取り消し" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "インベントリーソース同期の取り消し" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "ジョブの取り消し" @@ -890,7 +912,7 @@ msgstr "ジョブの取り消し" msgid "Cancel Project Sync" msgstr "プロジェクトの同期の取り消し" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "同期の取り消し" @@ -902,8 +924,8 @@ msgstr "同期の取り消し" msgid "Cancel Workflow" msgstr "ワークフローの取り消し" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "ジョブの取り消し" @@ -942,7 +964,7 @@ msgstr "サブスクリプションの編集の取り消し" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "{0} の取り消し" @@ -958,10 +980,10 @@ msgstr "取り消し済み" msgid "" "Cannot enable log aggregator without providing\n" "logging aggregator host and logging aggregator type." -msgstr "ログアグリゲーターホストとログアグリゲータータイプを指定せずに、\n" +msgstr "" +"ログアグリゲーターホストとログアグリゲータータイプを指定せずに、\n" "ログアグリゲーターを有効にすることはできません。" -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "ホップノードでは可用性をチェックできません。" @@ -972,12 +994,13 @@ msgstr "ホップノードでは可用性をチェックできません。" msgid "Capacity" msgstr "容量" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "容量調整" @@ -1005,7 +1028,8 @@ msgstr "startswith で大文字小文字の区別なし。" msgid "" "Change PROJECTS_ROOT when deploying\n" "{brandName} to change this location." -msgstr "この場所を変更するには {brandName} のデプロイ時に\n" +msgstr "" +"この場所を変更するには {brandName} のデプロイ時に\n" " PROJECTS_ROOT を変更します。" #: components/StatusLabel/StatusLabel.js:55 @@ -1064,7 +1088,7 @@ msgstr "ジョブタイプの選択" msgid "Choose a module" msgstr "モジュールの選択" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "ソースの選択" @@ -1077,7 +1101,8 @@ msgid "" "Choose an answer type or format you want as the prompt for the user.\n" "Refer to the Ansible Controller Documentation for more additional\n" "information about each option." -msgstr "ユーザーに表示されるプロンプトとして使用する回答タイプまたは形式を選択します。\n" +msgstr "" +"ユーザーに表示されるプロンプトとして使用する回答タイプまたは形式を選択します。\n" "各オプションの詳細については、\n" "Ansible Controller のドキュメントを参照してください。" @@ -1135,7 +1160,8 @@ msgstr "このボタンをクリックして、選択した認証情報と指定 msgid "Click to create a new link to this node." msgstr "クリックして、このノードへの新しいリンクを作成します。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "クリックしてバンドルをダウンロードします。" @@ -1210,7 +1236,7 @@ msgstr "有効" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1287,7 +1313,7 @@ msgstr "選択の確認" msgid "Container Group" msgstr "コンテナーグループ" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1312,8 +1338,8 @@ msgstr "コンテンツ署名検証の認証情報" msgid "Continue" msgstr "続行" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "コントロール" @@ -1325,7 +1351,8 @@ msgstr "コントロールノード" msgid "" "Control the level of output Ansible\n" "will produce for inventory source update jobs." -msgstr "インベントリーソースの更新ジョブ用に\n" +msgstr "" +"インベントリーソースの更新ジョブ用に\n" " Ansible が生成する出力のレベルを制御します。" #: screens/Job/Job.helptext.js:15 @@ -1337,7 +1364,7 @@ msgstr "Playbook の実行時に Ansible が生成する出力のレベルを制 msgid "Controller Node" msgstr "コントローラーノード" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "収束 (コンバージェンス)" @@ -1510,28 +1537,28 @@ msgid "Create user token" msgstr "ユーザートークンの作成" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1544,16 +1571,16 @@ msgstr "作成日時" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1594,16 +1621,16 @@ msgstr "作成者 (ユーザー名)" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1640,7 +1667,7 @@ msgstr "認証情報タイプ" msgid "Credential copied successfully" msgstr "認証情報が正常にコピーされました" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "認証情報が見つかりません。" @@ -1649,7 +1676,7 @@ msgstr "認証情報が見つかりません。" msgid "Credential passwords" msgstr "認証情報のパスワード" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Kubernetes または OpenShift との認証のための認証情報" @@ -1666,13 +1693,13 @@ msgid "Credential type not found." msgstr "認証情報タイプが見つかりません。" #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1681,7 +1708,7 @@ msgstr "認証情報タイプが見つかりません。" #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1696,11 +1723,11 @@ msgstr "起動時にパスワードを必要とする認証情報は許可され msgid "Current page" msgstr "現在のページ" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "カスタムの Kubernetes または OpenShift Pod 仕様" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "カスタム Pod 仕様" @@ -1722,8 +1749,8 @@ msgstr "カスタム仮想環境 {virtualEnvironment} は、実行環境に置 msgid "Customize messages…" msgstr "メッセージのカスタマイズ…" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Pod 仕様のカスタマイズ" @@ -1733,7 +1760,7 @@ msgid "DELETED" msgstr "削除済み" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "ダッシュボード" @@ -1749,7 +1776,7 @@ msgstr "データ保持期間" msgid "Date" msgstr "日付" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1762,7 +1789,7 @@ msgstr "日" msgid "Day {0}" msgstr "日 {0}" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "データの保持日数" @@ -1826,17 +1853,17 @@ msgstr "システムレベルの機能および関数の定義" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1844,11 +1871,11 @@ msgstr "システムレベルの機能および関数の定義" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1875,17 +1902,17 @@ msgstr "実行環境の削除" msgid "Delete Host" msgstr "ホストの削除" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "インベントリーの削除" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "ジョブの削除" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "ジョブテンプレートの削除" @@ -1893,7 +1920,7 @@ msgstr "ジョブテンプレートの削除" msgid "Delete Notification" msgstr "通知の削除" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "組織の削除" @@ -1905,7 +1932,7 @@ msgstr "プロジェクトの削除" msgid "Delete Questions" msgstr "質問の削除" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "スケジュールの削除" @@ -1950,16 +1977,16 @@ msgstr "認証情報タイプの削除" msgid "Delete error" msgstr "エラーの削除" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "インスタンスグループの削除" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "インベントリーソースの削除" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "スマートインベントリーの削除" @@ -1973,7 +2000,8 @@ msgid "" "performing an update. Depending on the size of the\n" "repository this may significantly increase the amount\n" "of time required to complete an update." -msgstr "更新の実行前にローカルリポジトリーを完全に削除します。\n" +msgstr "" +"更新の実行前にローカルリポジトリーを完全に削除します。\n" "リポジトリーのサイズによっては、\n" "更新の完了までにかかる時間が\n" "大幅に増大します。" @@ -2029,6 +2057,10 @@ msgstr "拒否されました - {0}。詳細については、アクティビテ msgid "Denied by {0} - {1}" msgstr "{0} - {1} により拒否済み" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2054,8 +2086,8 @@ msgstr "プロビジョニング解除に失敗" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2077,28 +2109,28 @@ msgstr "プロビジョニング解除に失敗" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2108,7 +2140,7 @@ msgstr "プロビジョニング解除に失敗" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2125,7 +2157,7 @@ msgstr "プロビジョニング解除に失敗" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "説明" @@ -2155,10 +2187,11 @@ msgstr "送信先チャネルまたはユーザー" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2167,7 +2200,7 @@ msgstr "送信先チャネルまたはユーザー" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2182,7 +2215,7 @@ msgstr "送信先チャネルまたはユーザー" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2196,7 +2229,7 @@ msgstr "送信先チャネルまたはユーザー" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2244,7 +2277,7 @@ msgstr "送信先チャネルまたはユーザー" msgid "Details" msgstr "詳細" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "詳細タブ" @@ -2292,8 +2325,8 @@ msgstr "グループのホストとの関連付けを解除しますか?" msgid "Disassociate host from group?" msgstr "ホストのグループとの関連付けを解除しますか?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "インスタンスグループへのインスタンスの関連付けを解除しますか?" @@ -2344,8 +2377,8 @@ msgstr "完了" msgid "Download Bundle" msgstr "バンドルのダウンロード" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "出力のダウンロード" @@ -2383,7 +2416,8 @@ msgid "" "Each time a job runs using this inventory,\n" "refresh the inventory from the selected source before\n" "executing job tasks." -msgstr "このインベントリーでジョブを実行する際は常に、\n" +msgstr "" +"このインベントリーでジョブを実行する際は常に、\n" "選択されたソースのインベントリーを更新してから\n" "ジョブのタスクを実行します。" @@ -2393,28 +2427,28 @@ msgid "" "revision of the project prior to starting the job." msgstr "このプロジェクトでジョブを実行する際は常に、ジョブの開始前にプロジェクトのリビジョンを更新します。" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2430,8 +2464,8 @@ msgstr "このプロジェクトでジョブを実行する際は常に、ジョ #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2445,8 +2479,8 @@ msgstr "このプロジェクトでジョブを実行する際は常に、ジョ #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2620,7 +2654,8 @@ msgstr "詳細の編集" msgid "Edit group" msgstr "グループの編集" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "ホストの編集" @@ -2647,16 +2682,16 @@ msgid "Edit workflow" msgstr "ワークフローの編集" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "経過時間" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "経過時間" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "ジョブ実行の経過時間" @@ -2706,7 +2741,8 @@ msgid "" "has remained secure when a project is synced. \n" "If the content has been tampered with, the \n" "job will not run." -msgstr "コンテンツの署名を有効にして、コンテンツが\n" +msgstr "" +"コンテンツの署名を有効にして、コンテンツが\n" "プロジェクトが同期されても安全です。\n" "内容が改ざんされた場合、\n" "ジョブは実行されません。" @@ -2744,20 +2780,20 @@ msgstr "有効化" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "有効なオプション" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "有効な値" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "有効な変数" @@ -2821,13 +2857,18 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "JSON または YAML 構文のいずれかを使用してインジェクターを入力します。構文のサンプルについては Ansible Controller ドキュメントを参照してください。" #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "JSON または YAML 構文のいずれかを使用してインベントリー変数を入力します。\n" -"ラジオボタンを使用して構文間で切り替えを行います。\n" -"構文のサンプルについては Ansible Controller ドキュメントを参照してください。" +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "" +#~ "JSON または YAML 構文のいずれかを使用してインベントリー変数を入力します。\n" +#~ "ラジオボタンを使用して構文間で切り替えを行います。\n" +#~ "構文のサンプルについては Ansible Controller ドキュメントを参照してください。" + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2840,8 +2881,8 @@ msgstr "認証情報タイプが挿入できる値を指定する環境変数ま #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2874,14 +2915,14 @@ msgstr "ワークフローの保存中にエラー!" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2896,29 +2937,30 @@ msgstr "ワークフローの保存中にエラー!" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2926,7 +2968,7 @@ msgstr "ワークフローの保存中にエラー!" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2936,14 +2978,14 @@ msgstr "ワークフローの保存中にエラー!" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2953,7 +2995,8 @@ msgstr "ワークフローの保存中にエラー!" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2963,8 +3006,8 @@ msgstr "エラー!" msgid "Error:" msgstr "エラー:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "エラー" @@ -2994,7 +3037,7 @@ msgstr "イベントの概要はありません" msgid "Events" msgstr "イベント" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "イベントの処理が完了しました。" @@ -3002,10 +3045,14 @@ msgstr "イベントの処理が完了しました。" msgid "Exact match (default lookup if not specified)." msgstr "完全一致 (指定されない場合のデフォルトのルックアップ)。" -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "id フィールドでの正確な検索。" +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "GIT ソースコントロールの URL の例は次のとおりです。" @@ -3026,7 +3073,7 @@ msgstr "以下に例を示します。" msgid "Examples:" msgstr "例:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "例外頻度" @@ -3046,8 +3093,8 @@ msgstr "親ノードが障害状態になったときに実行します。" msgid "Execute when the parent node results in a successful state." msgstr "親ノードが正常な状態になったときに実行します。" -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "実行" @@ -3061,8 +3108,8 @@ msgstr "実行" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "実行環境" @@ -3177,7 +3224,7 @@ msgid "Extra variables" msgstr "追加変数" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3185,7 +3232,7 @@ msgid "FINISHED:" msgstr "終了日時:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "ファクトストレージ" @@ -3205,23 +3252,23 @@ msgstr "ファクト" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "失敗" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "失敗したホスト数" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "失敗したホスト" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "失敗したホスト" @@ -3229,6 +3276,10 @@ msgstr "失敗したホスト" msgid "Failed jobs" msgstr "失敗したジョブ" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "{0} を承認できませんでした。" @@ -3243,7 +3294,7 @@ msgid "Failed to associate role" msgstr "ロールの関連付けに失敗しました" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3251,7 +3302,7 @@ msgstr "ロールの関連付けに失敗しました" msgid "Failed to associate." msgstr "関連付けに失敗しました。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "インベントリーソースの同期の取り消しに失敗しました。" @@ -3267,7 +3318,7 @@ msgstr "1 つ以上のジョブを取り消すことができませんでした #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "{0} を取り消すことができませんでした。" @@ -3310,15 +3361,15 @@ msgstr "グループ {0} を削除できませんでした。" msgid "Failed to delete host." msgstr "ホストを削除できませんでした。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "インベントリーソース {name} を削除できませんでした。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "インベントリーを削除できませんでした。" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "ジョブテンプレートを削除できませんでした。" @@ -3347,7 +3398,7 @@ msgid "Failed to delete one or more groups." msgstr "1 つ以上のグループを削除できませんでした。" #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "1 つ以上のホストを削除できませんでした。" @@ -3363,7 +3414,7 @@ msgstr "1 つ以上のインベントリーを削除できませんでした。" msgid "Failed to delete one or more inventory sources." msgstr "1 つ以上のインベントリーリソースを削除できませんでした。" -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "1 つ以上のジョブテンプレートを削除できませんでした" @@ -3407,11 +3458,11 @@ msgstr "1 つ以上のユーザートークンを削除できませんでした msgid "Failed to delete one or more users." msgstr "1 人以上のユーザーを削除できませんでした。" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "1 つ以上のワークフロー承認を削除できませんでした。" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "組織を削除できませんでした。" @@ -3428,11 +3479,11 @@ msgstr "ロールを削除できませんでした。" msgid "Failed to delete role." msgstr "ロールを削除できませんでした。" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "スケジュールを削除できませんでした。" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "スマートインベントリーを削除できませんでした。" @@ -3457,6 +3508,10 @@ msgstr "ワークフロージョブテンプレートを削除できませんで msgid "Failed to delete {name}." msgstr "{name} を削除できませんでした。" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "{0} を拒否できませんでした。" @@ -3471,9 +3526,9 @@ msgstr "1 つ以上のグループの関連付けを解除できませんでし msgid "Failed to disassociate one or more hosts." msgstr "1 つ以上のホストの関連付けを解除できませんでした。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "1 つ以上のインスタンスの関連付けを解除できませんでした。" @@ -3489,18 +3544,22 @@ msgstr "カスタムログイン構成設定を取得できません。代わり msgid "Failed to fetch the updated project data." msgstr "更新されたプロジェクトデータの取得に失敗しました。" -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "インスタンスを取得できませんでした。" #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "ジョブを起動できませんでした。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "1 つ以上のインスタンスを削除できませんでした。" @@ -3512,8 +3571,8 @@ msgstr "構成を取得できませんでした。" msgid "Failed to retrieve full node resource object." msgstr "フルノードリソースオブジェクトを取得できませんでした。" -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "1 つ以上のインスタンスで可用性をチェックできませんでした。" @@ -3549,10 +3608,10 @@ msgstr "通知の切り替えに失敗しました。" msgid "Failed to toggle schedule." msgstr "スケジュールの切り替えに失敗しました。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "容量調整の更新に失敗しました。" @@ -3600,7 +3659,7 @@ msgstr "値を含むフィールド。" msgid "Field ends with value." msgstr "値で終了するフィールド。" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "カスタムの Kubernetes または OpenShift Pod 仕様を渡すためのフィールド。" @@ -3633,11 +3692,11 @@ msgstr "ファイル、ディレクトリー、またはスクリプト" msgid "Filter By {name}" msgstr "{name} 別にフィルター" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "失敗したジョブによるフィルター" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "成功ジョブによるフィルター" @@ -3666,7 +3725,7 @@ msgstr "最初" msgid "First Name" msgstr "名" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "初回実行日時" @@ -3709,11 +3768,11 @@ msgstr "詳しい情報は以下の情報を参照してください:" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3723,12 +3782,12 @@ msgstr "フォーク" msgid "Fourth" msgstr "第 4" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "頻度の詳細" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "頻度の例外の詳細" @@ -3750,7 +3809,7 @@ msgstr "金" msgid "Friday" msgstr "金曜" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "ID、名前、または説明フィールドのあいまい検索。" @@ -3762,7 +3821,7 @@ msgstr "名前フィールドのあいまい検索。" msgid "GPG Public Key" msgstr "GPG 公開鍵" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Galaxy 認証情報" @@ -3800,7 +3859,7 @@ msgstr "サブスクリプションの取得" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3839,7 +3898,7 @@ msgstr "GitHub チーム" msgid "GitHub settings" msgstr "GitHub 設定" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3943,6 +4002,19 @@ msgstr "HTTP メソッド" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "送信されたヘルスチェックリクエスト。ページをリロードしてお待ちください。" +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "利用可能" @@ -3965,7 +4037,7 @@ msgstr "説明の非表示" msgid "Hipchat" msgstr "Hipchat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "ホップ" @@ -3973,8 +4045,9 @@ msgstr "ホップ" msgid "Hop node" msgstr "ホップノード" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3989,16 +4062,16 @@ msgid "Host Async OK" msgstr "ホストの非同期 OK" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "ホスト設定キー" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "ホスト数" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "ホストの詳細" @@ -4010,13 +4083,14 @@ msgstr "ホストの失敗" msgid "Host Failure" msgstr "ホストの障害" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "ホストフィルター" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "ホスト名" @@ -4049,7 +4123,7 @@ msgstr "ホストに到達できません" msgid "Host details" msgstr "ホストの詳細" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "ホストの詳細モーダル" @@ -4064,7 +4138,7 @@ msgstr "このジョブのホストのステータス情報は利用できませ #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4076,10 +4150,10 @@ msgstr "このジョブのホストのステータス情報は利用できませ #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "ホスト" @@ -4101,15 +4175,15 @@ msgstr "インポートされたホスト" msgid "Hosts remaining" msgstr "残りのホスト" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "時間" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "ハイブリッド" @@ -4228,18 +4302,20 @@ msgstr "有効な場合は、このジョブテンプレートの同時実行が msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "有効な場合は、このワークフロージョブテンプレートの同時実行が許可されます。" -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "有効にすると、インベントリーは、関連付けられたジョブテンプレートを実行する優先インスタンスグループのリストに組織インスタンスグループを追加することを防ぎます。\n" +msgstr "" +"有効にすると、インベントリーは、関連付けられたジョブテンプレートを実行する優先インスタンスグループのリストに組織インスタンスグループを追加することを防ぎます。\n" "注: この設定が有効で空のリストを指定した場合は、グローバルインスタンスグループが適用されます。" #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "有効にすると、ジョブテンプレートによって、実行する優先インスタンスグループのリストにインベントリーまたは組織インスタンスグループが追加されなくなります。\n" +msgstr "" +"有効にすると、ジョブテンプレートによって、実行する優先インスタンスグループのリストにインベントリーまたは組織インスタンスグループが追加されなくなります。\n" "注: この設定が有効で空のリストを指定した場合は、グローバルインスタンスグループが適用されます。" #: screens/Template/shared/JobTemplate.helptext.js:35 @@ -4337,7 +4413,8 @@ msgstr "Insights 認証情報" msgid "Insights system ID" msgstr "Insights システム ID" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "バンドルのインストール" @@ -4358,25 +4435,26 @@ msgstr "インスタンスフィルター" msgid "Instance Group" msgstr "インスタンスグループ" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "インスタンスグループ" @@ -4406,8 +4484,8 @@ msgstr "インスタンスグループ" msgid "Instance group not found." msgstr "インスタンスグループが見つかりません。" -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "インスタンスグループの使用容量" @@ -4430,9 +4508,9 @@ msgstr "インスタンスタイプ" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4465,7 +4543,7 @@ msgstr "無効なユーザー名またはパスワードです。やり直して #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4489,18 +4567,18 @@ msgstr "ソースを含むインベントリーはコピーできません。" #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4509,8 +4587,8 @@ msgstr "ソースを含むインベントリーはコピーできません。" #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4537,7 +4615,7 @@ msgstr "インベントリーソース" msgid "Inventory Source Sync" msgstr "インベントリーソース同期" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "インベントリーソース同期エラー" @@ -4569,8 +4647,8 @@ msgstr "インベントリー更新" msgid "Inventory copied successfully" msgstr "インベントリーが正常にコピーされました" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "インベントリーファイル" @@ -4582,7 +4660,7 @@ msgstr "インベントリーが見つかりません。" msgid "Inventory sync" msgstr "インベントリーの同期" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "インベントリーの同期の失敗" @@ -4616,18 +4694,18 @@ msgid "Items per page" msgstr "項目/ページ" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "ジョブ ID:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "JSON タブ" @@ -4642,16 +4720,16 @@ msgstr "1 月" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "ジョブキャンセルエラー" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "ジョブ削除エラー" @@ -4674,10 +4752,10 @@ msgid "Job Slice Parent" msgstr "ジョブスライスの親" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "ジョブスライス" @@ -4688,11 +4766,11 @@ msgstr "ジョブステータス" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4713,7 +4791,7 @@ msgstr "ジョブテンプレート" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "ジョブテンプレートのデフォルトの認証情報は、同じタイプの認証情報に置き換える必要があります。続行するには、次のタイプの認証情報を選択してください: {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4736,26 +4814,26 @@ msgstr "ノードの作成時または編集時に、パスワードの入力を #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "ジョブタイプ" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "ジョブステータス" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "ジョブステータスのグラフタブ" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "ジョブテンプレート" @@ -4869,7 +4947,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "ラベル" @@ -4880,15 +4958,15 @@ msgstr "ラベル名" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4900,18 +4978,19 @@ msgstr "ラベル" msgid "Last" msgstr "最終" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "最終可用性チェック" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "最終ジョブステータス" @@ -4920,8 +4999,8 @@ msgstr "最終ジョブステータス" msgid "Last Login" msgstr "前回のログイン" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4930,17 +5009,17 @@ msgstr "前回のログイン" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4963,7 +5042,7 @@ msgstr "姓" msgid "Last Ran" msgstr "最終実行日時" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "最終実行日時" @@ -4971,8 +5050,8 @@ msgstr "最終実行日時" msgid "Last job" msgstr "最後のジョブ" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -4996,8 +5075,8 @@ msgstr "最終使用日時" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5064,12 +5143,12 @@ msgstr "Less than or equal to の比較条件" #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5097,7 +5176,7 @@ msgstr "ロード中" msgid "Local" msgstr "ローカル" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "ローカルタイムゾーン" @@ -5140,7 +5219,7 @@ msgstr "ルックアップタイプ" msgid "Lookup typeahead" msgstr "ルックアップの先行入力" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5195,14 +5274,15 @@ msgstr "管理ジョブが見つかりません。" msgid "Management jobs" msgstr "管理ジョブ" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5222,11 +5302,25 @@ msgstr "3 月" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "最大ホスト数" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "最大" @@ -5235,6 +5329,24 @@ msgstr "最大" msgid "Maximum length" msgstr "最大長" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5283,7 +5395,7 @@ msgid "" "assigned to this group when new instances come online." msgstr "新規インスタンスがオンラインになると、このグループに自動的に最小限割り当てられるインスタンスの割合" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5325,16 +5437,16 @@ msgstr "変更日時" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5372,7 +5484,7 @@ msgid "Modified by (username)" msgstr "変更者 (ユーザー名)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "モジュール" @@ -5395,7 +5507,7 @@ msgstr "月" msgid "Monday" msgstr "月曜" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5444,8 +5556,8 @@ msgstr "多項選択法オプション" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5468,8 +5580,8 @@ msgstr "多項選択法オプション" #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5479,11 +5591,11 @@ msgstr "多項選択法オプション" #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5539,27 +5651,27 @@ msgstr "多項選択法オプション" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5571,7 +5683,7 @@ msgstr "多項選択法オプション" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5581,7 +5693,7 @@ msgstr "多項選択法オプション" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5591,7 +5703,7 @@ msgstr "多項選択法オプション" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5601,7 +5713,7 @@ msgstr "多項選択法オプション" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5623,7 +5735,7 @@ msgstr "多項選択法オプション" #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5654,8 +5766,8 @@ msgstr "多項選択法オプション" #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "名前" @@ -5698,7 +5810,7 @@ msgstr "新規" msgid "Next" msgstr "次へ" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5718,7 +5830,7 @@ msgstr "一致するホストがありません" msgid "No Hosts Remaining" msgstr "残りのホストがありません" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "JSON は利用できません" @@ -5742,7 +5854,7 @@ msgstr "利用可能なジョブデータがありません" msgid "No output found for this job." msgstr "このジョブの出力は見つかりません" -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "結果が見つかりません" @@ -5761,10 +5873,10 @@ msgstr "結果が見つかりません" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "結果が見つかりません" @@ -5792,15 +5904,16 @@ msgstr "{pluralizedItemName} は見つかりません" msgid "Node Alias" msgstr "ノードのエイリアス" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5825,8 +5938,8 @@ msgstr "ノードタイプ" msgid "None" msgstr "なし" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "なし (1回実行)" @@ -5977,14 +6090,14 @@ msgstr "10 月" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "オフ" @@ -5993,14 +6106,14 @@ msgstr "オフ" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "オン" @@ -6051,7 +6164,8 @@ msgid "" "Optional labels that describe this inventory,\n" "such as 'dev' or 'test'. Labels can be used to group and filter\n" "inventories and completed jobs." -msgstr "「dev」、「test」などのこのインベントリーを説明するオプションラベルです。\n" +msgstr "" +"「dev」、「test」などのこのインベントリーを説明するオプションラベルです。\n" "ラベルを使用し、インベントリーおよび完了した\n" "ジョブの分類およびフィルターを実行できます。" @@ -6065,7 +6179,8 @@ msgid "" "Optional labels that describe this workflow job template,\n" "such as 'dev' or 'test'. Labels can be used to group and filter\n" "workflow job templates and completed jobs." -msgstr "「dev」、「test」などのこのワークフロージョブテンプレートを説明するオプションラベルです。\n" +msgstr "" +"「dev」、「test」などのこのワークフロージョブテンプレートを説明するオプションラベルです。\n" "ラベルを使用し、ワークフロージョブテンプレートおよび完了した\n" "ジョブの分類およびフィルターを実行できます。" @@ -6077,7 +6192,7 @@ msgstr "必要に応じて、ステータスの更新を Webhook サービスに #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6113,11 +6228,11 @@ msgstr "順序" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6127,8 +6242,8 @@ msgstr "順序" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6172,12 +6287,12 @@ msgid "Out of compliance" msgstr "コンプライアンス違反" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "出力" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "出力タブ" @@ -6186,12 +6301,12 @@ msgid "Overwrite" msgstr "上書き" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "リモートインベントリーソースからのローカルグループおよびホストを上書きする" #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "リモートインベントリーソースのローカル変数を上書きする" @@ -6310,11 +6425,11 @@ msgstr "パーソナルアクセストークン" msgid "Personal access token" msgstr "パーソナルアクセストークン" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "プレイ" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "再生回数" @@ -6324,7 +6439,7 @@ msgstr "プレイの開始" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6356,7 +6471,7 @@ msgstr "Playbook 実行" msgid "Playbook Started" msgstr "Playbook の開始" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6368,7 +6483,7 @@ msgstr "Playbook 名" msgid "Playbook run" msgstr "Playbook 実行" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "プレイ" @@ -6392,7 +6507,7 @@ msgstr "{pluralizedItemName} を追加してこのリストに入力してくだ msgid "Please click the Start button to begin." msgstr "開始ボタンをクリックして開始してください。" -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "出現回数を入力してください。" @@ -6412,7 +6527,7 @@ msgstr "ログインしてください" msgid "Please run a job to populate this list." msgstr "ジョブを実行してこのリストに入力してください。" -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "1 から 31 までの日付を選択してください。" @@ -6420,7 +6535,7 @@ msgstr "1 から 31 までの日付を選択してください。" msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "インベントリーを選択するか、または起動プロンプトオプションにチェックを付けてください。" -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "開始日時より後の終了日時を選択してください。" @@ -6436,14 +6551,15 @@ msgstr "上記のフィルターを使用して別の検索を試してくださ msgid "Please wait until the topology view is populated..." msgstr "トポロジービューが反映されるまでお待ちください..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Pod 仕様の上書き" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "ポリシータイプ" @@ -6499,16 +6615,16 @@ msgid "" "cancel the drag operation." msgstr "スペースまたは Enter キーを押してドラッグを開始し、矢印キーを使用して上下に移動します。Enter キーを押してドラッグを確認するか、その他のキーを押してドラッグ操作をキャンセルします。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "インスタンスグループのフォールバックを防止する" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "インスタンスグループフォールバックの防止: 有効にすると、インベントリーは、関連付けられたジョブテンプレートを実行する優先インスタンスグループのリストに組織インスタンスグループを追加することを防ぎます。" @@ -6526,7 +6642,7 @@ msgid "Private key passphrase" msgstr "秘密鍵のパスフレーズ" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "権限昇格" @@ -6547,11 +6663,11 @@ msgstr "権限昇格: 有効な場合は、この Playbook を管理者として #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "プロジェクト" @@ -6592,14 +6708,14 @@ msgstr "プロジェクトが正常にコピーされました" msgid "Project not found." msgstr "プロジェクトが見つかりません。" -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "プロジェクトの同期の失敗" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6614,12 +6730,12 @@ msgstr "プロジェクト" msgid "Promote Child Groups and Hosts" msgstr "子グループおよびホストのプロモート" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "プロンプト" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "プロンプトオーバーライド" @@ -6633,8 +6749,8 @@ msgstr "起動プロンプト" msgid "Prompt | {0}" msgstr "プロンプト | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "プロンプト値" @@ -6644,7 +6760,8 @@ msgid "" "the list of hosts that will be managed or affected by the\n" "playbook. Multiple patterns are allowed. Refer to Ansible\n" "documentation for more information and examples on patterns." -msgstr "Playbook によって管理されるか、またはその影響を受けるホストの一覧をさらに制限するためのホストのパターンを指定します。\n" +msgstr "" +"Playbook によって管理されるか、またはその影響を受けるホストの一覧をさらに制限するためのホストのパターンを指定します。\n" "複数のパターンが許可されます。\n" "パターンについての詳細およびサンプルについては、Ansible ドキュメントを参照してください。" @@ -6681,7 +6798,7 @@ msgid "Provisioning" msgstr "プロビジョニング" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "プロビジョニングコールバック URL" @@ -6691,7 +6808,7 @@ msgid "Provisioning Callback details" msgstr "プロビジョニングコールバックの詳細" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6722,10 +6839,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "RADIUS 設定" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "メモリー {0}" @@ -6739,23 +6857,23 @@ msgstr "読み込み" msgid "Ready" msgstr "準備" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "最近のジョブ" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "最近の求人リストタブ" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "最近のテンプレート" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "最近のテンプレートリストタブ" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6846,12 +6964,15 @@ msgstr "リージョン" msgid "Registry credential" msgstr "レジストリーの認証情報" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "一致するホスト名のみがインポートされる正規表現。このフィルターは、インベントリープラグインフィルターが適用された後、後処理ステップとして適用されます。" #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "関連するグループ" @@ -6878,12 +6999,12 @@ msgstr "関連する検索タイプの先行入力" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "再起動" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "ジョブの再起動" @@ -6901,7 +7022,7 @@ msgid "Relaunch on" msgstr "再起動時" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "ホストパラメーターを使用した再起動" @@ -6909,7 +7030,7 @@ msgstr "ホストパラメーターを使用した再起動" msgid "Reload" msgstr "再読み込み" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "出力のリロード" @@ -6922,8 +7043,8 @@ msgstr "出力のリロード" msgid "Remote Archive" msgstr "リモートアーカイブ" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "削除エラー" @@ -6982,7 +7103,7 @@ msgstr "このリンクを削除すると、ブランチの残りの部分が孤 msgid "Reorder" msgstr "並べ替え" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "繰り返しの頻度" @@ -7052,8 +7173,8 @@ msgstr "ホスト変数の指定された辞書から有効な状態を取得し #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "戻る" @@ -7158,8 +7279,9 @@ msgstr "実行" msgid "Run Command" msgstr "コマンドの実行" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "インスタンスでの可用性チェック実行" @@ -7176,10 +7298,11 @@ msgstr "コマンドの実行" msgid "Run every" msgstr "実行する間隔" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "可用性チェックの実行" @@ -7206,17 +7329,26 @@ msgstr "実行中" msgid "Running Handlers" msgstr "実行中のハンドラー" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "実行中のジョブ" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "実行中の可用性チェック" @@ -7255,7 +7387,7 @@ msgid "START" msgstr "開始" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7278,8 +7410,8 @@ msgstr "土曜" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7333,7 +7465,7 @@ msgstr "スケジュールはアクティブです" msgid "Schedule is inactive" msgstr "スケジュールは非アクティブです" -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "スケジュールにルールがありません" @@ -7455,7 +7587,7 @@ msgstr "ホストの選択" msgid "Select Input" msgstr "入力の選択" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "インスタンスの選択" @@ -7525,11 +7657,19 @@ msgstr "実行環境を編集する前にプロジェクトを選択してくだ msgid "Select a question to delete" msgstr "削除する質問の選択" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "削除する行を選択してください" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "関連付けを解除する行を選択してください" @@ -7557,8 +7697,8 @@ msgstr "サブスクリプションの選択" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7600,7 +7740,7 @@ msgstr "インスタンスの選択" msgid "Select an instance and a metric to show chart" msgstr "グラフを表示するインスタンスとメトリクスを選択します" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "可用性チェックを実行するインスタンスを選択してください。" @@ -7631,7 +7771,8 @@ msgid "" "Select from the list of directories found in\n" "the Project Base Path. Together the base path and the playbook\n" "directory provide the full path used to locate playbooks." -msgstr "プロジェクトのベースパスにあるデイレクトリーの一覧から選択します。ベースパスと Playbook ディレクトリーは、Playbook \n" +msgstr "" +"プロジェクトのベースパスにあるデイレクトリーの一覧から選択します。ベースパスと Playbook ディレクトリーは、Playbook \n" "を見つけるために使用される完全なパスを提供します。" #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:98 @@ -7657,9 +7798,9 @@ msgstr "期間の選択" msgid "Select roles to apply" msgstr "適用するロールの選択" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "ソースパスの選択" @@ -7749,8 +7890,8 @@ msgstr "{0} の選択" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7773,8 +7914,8 @@ msgstr "選択済み" msgid "Selected Category" msgstr "選択したカテゴリー" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "選択した日付範囲には、少なくとも 1 つのスケジュールオカレンスが必要です。" @@ -7808,7 +7949,7 @@ msgstr "データの保持日数を設定します。" msgid "Set preferences for data collection, logos, and logins" msgstr "データ収集、ロゴ、およびログイン情報の設定" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "ソースパスの設定:" @@ -7874,10 +8015,10 @@ msgid "Show" msgstr "表示" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "変更の表示" @@ -7951,11 +8092,11 @@ msgstr "簡易キー選択" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -8029,8 +8170,8 @@ msgstr "並び替え" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8038,20 +8179,22 @@ msgid "Source" msgstr "ソース" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "ソースコントロールブランチ" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "ソースコントロールブランチ/タグ/コミット" @@ -8114,7 +8257,7 @@ msgstr "ソースワークフローのジョブ" msgid "Source control branch" msgstr "ソースコントロールのブランチ" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "ソース詳細" @@ -8122,7 +8265,7 @@ msgstr "ソース詳細" msgid "Source phone number" msgstr "発信元の電話番号" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "ソース変数" @@ -8146,18 +8289,19 @@ msgstr "JSON 形式で HTTP ヘッダーを指定します。構文のサンプ msgid "" "Specify a notification color. Acceptable colors are hex\n" "color code (example: #3af or #789abc)." -msgstr "通知の色を指定します。使用できる色は、\n" +msgstr "" +"通知の色を指定します。使用できる色は、\n" "16 進数の色コード (例: #3af または #789abc) です。" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:26 msgid "Specify the conditions under which this node should be executed" msgstr "このノードを実行する条件を指定" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "標準エラー" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "標準エラータブ" @@ -8204,27 +8348,28 @@ msgid "Start time" msgstr "開始時刻" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "開始" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8232,7 +8377,7 @@ msgstr "開始" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "Status" @@ -8320,7 +8465,7 @@ msgstr "成功メッセージボディー" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "成功" @@ -8456,8 +8601,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "TACACS+ 設定" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "タブ" @@ -8484,11 +8629,11 @@ msgstr "アノテーションのタグ (オプション)" msgid "Target URL" msgstr "ターゲット URL" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "タスク" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "タスク数" @@ -8496,7 +8641,7 @@ msgstr "タスク数" msgid "Task Started" msgstr "タスクの開始" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "タスク" @@ -8538,7 +8683,7 @@ msgstr "チーム" msgid "Template" msgstr "テンプレート" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "テンプレートが正常にコピーされました" @@ -8608,11 +8753,12 @@ msgstr "その" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "ユーザーがこのアプリケーションのトークンを取得するために使用する必要のある付与タイプです。" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "この組織を実行するインスタンスグループ。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "このインスタンスが属するインスタンスグループ。" @@ -8621,7 +8767,8 @@ msgid "" "The amount of time (in seconds) before the email\n" "notification stops trying to reach the host and times out. Ranges\n" "from 1 to 120 seconds." -msgstr "メール通知が、ホストへの到達を試行するのをやめてタイムアウトするまでの時間 (秒単位)。\n" +msgstr "" +"メール通知が、ホストへの到達を試行するのをやめてタイムアウトするまでの時間 (秒単位)。\n" "範囲は 1 から 120 秒です。" #: screens/Job/Job.helptext.js:17 @@ -8638,20 +8785,22 @@ msgid "" "The base URL of the Grafana server - the\n" "/api/annotations endpoint will be added automatically to the base\n" "Grafana URL." -msgstr "Grafana サーバーのベース URL。/api/annotations エンドポイントは、ベース Grafana URL に自動的に\n" +msgstr "" +"Grafana サーバーのベース URL。/api/annotations エンドポイントは、ベース Grafana URL に自動的に\n" "追加されます。" #: screens/Template/shared/JobTemplate.helptext.js:9 msgid "The container image to be used for execution." msgstr "実行に使用するコンテナーイメージ。" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" "an execution environment has not been explicitly assigned at the\n" "project, job template or workflow level." -msgstr "この組織内のジョブに使用される実行環境。これは、実行環境がプロジェクト、\n" +msgstr "" +"この組織内のジョブに使用される実行環境。これは、実行環境がプロジェクト、\n" "ジョブテンプレート、またはワークフローレベルで\n" "明示的に割り当てられていない場合に\n" "フォールバックとして使用されます。" @@ -8674,14 +8823,15 @@ msgid "" "The first fetches all references. The second\n" "fetches the Github pull request number 62, in this example\n" "the branch needs to be \"pull/62/head\"." -msgstr "1 番目はすべての参照を取得します。2 番目は Github のプル要求の 62 番を取得します。\n" +msgstr "" +"1 番目はすべての参照を取得します。2 番目は Github のプル要求の 62 番を取得します。\n" "この例では、ブランチは \"pull/62/head\" でなければなりません。" #: screens/ExecutionEnvironment/shared/ExecutionEnvironment.helptext.js:7 msgid "The full image location, including the container registry, image name, and version tag." msgstr "コンテナーレジストリー、イメージ名、およびバージョンタグを含む完全なイメージの場所。" -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8700,12 +8850,13 @@ msgstr "最後の {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "{month} の 最後の {weekday}" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" "Refer to the Ansible documentation for more details." -msgstr "この組織で管理可能な最大ホスト数。\n" +msgstr "" +"この組織で管理可能な最大ホスト数。\n" "デフォルト値は 0 で、管理可能な数に制限がありません。\n" "詳細は、Ansible のドキュメントを参照してください。" @@ -8862,7 +9013,7 @@ msgstr "このアクションにより、以下の関連付けが解除されま msgid "This action will remove the following instances:" msgstr "この操作により、次のインスタンスが削除されます。" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 msgid "This container group is currently being by other resources. Are you sure you want to delete it?" msgstr "このコンテナーグループは、現在他のリソースで使用されています。削除してもよろしいですか?" @@ -8897,7 +9048,7 @@ msgstr "この実行環境は、現在他のリソースで使用されていま msgid "This feature is deprecated and will be removed in a future release." msgstr "この機能は非推奨となり、今後のリリースで削除されます。" -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "有効な変数が設定されていない限り、このフィールドは無視されます。有効な変数がこの値と一致すると、インポート時にこのホストが有効になります。" @@ -8983,7 +9134,7 @@ msgstr "このフィールドは、指定された認証情報を使用して外 msgid "This has already been acted on" msgstr "これはすでに処理されています" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "このインスタンスグループは、現在他のリソースで使用されています。削除してもよろしいですか?" @@ -8991,11 +9142,11 @@ msgstr "このインスタンスグループは、現在他のリソースで使 msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "このインベントリーが、このワークフロー ({0}) 内の、インベントリーをプロンプトするすべてのワークフローノードに適用されます。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "このインベントリーは、現在他のリソースで使用されています。削除してもよろしいですか?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "このインベントリーソースは、現在それに依存している他のリソースで使用されています。削除してもよろしいですか?" @@ -9011,11 +9162,11 @@ msgstr "この時だけ唯一、トークンの値と、関連する更新トー msgid "This job failed and has no output." msgstr "このジョブは失敗し、出力がありません。" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "このジョブテンプレートは、現在他のリソースで使用されています。削除してもよろしいですか?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "この組織は、現在他のリソースで使用されています。削除してもよろしいですか?" @@ -9027,7 +9178,7 @@ msgstr "このプロジェクトは、現在他のリソースで使用されて msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "このプロジェクトは現在同期中で、同期プロセスが完了するまでクリックできません" -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "選択した例外により、このスケジュールには発生がありません。" @@ -9043,7 +9194,8 @@ msgstr "このスケジュールには、必要な Survey 値がありません" msgid "" "This schedule uses complex rules that are not supported in the\n" "UI. Please use the API to manage this schedule." -msgstr "このスケジュールは、でサポートされていない複雑なルールを使用しています\n" +msgstr "" +"このスケジュールは、でサポートされていない複雑なルールを使用しています\n" "UI。このスケジュールを管理するには API を使用してください。" #: components/LaunchPrompt/steps/StepName.js:26 @@ -9066,7 +9218,8 @@ msgstr "これにより、このワークフローの後続のノードがすべ msgid "" "This will revert all configuration values on this page to\n" "their factory defaults. Are you sure you want to proceed?" -msgstr "これにより、このページのすべての設定値が出荷時の設定に戻ります。\n" +msgstr "" +"これにより、このページのすべての設定値が出荷時の設定に戻ります。\n" "続行してもよろしいですか?" #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerStartScreen.js:40 @@ -9124,13 +9277,13 @@ msgid "Timed out" msgstr "タイムアウト" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9233,15 +9386,16 @@ msgid "Tools" msgstr "ツール" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "トポロジービュー" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "ジョブの合計" @@ -9251,7 +9405,7 @@ msgstr "ジョブの合計" msgid "Total Nodes" msgstr "ノードの合計" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "ホストの合計" @@ -9307,8 +9461,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9321,11 +9475,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9373,13 +9527,14 @@ msgstr "ホストのインベントリーを変更できません。" msgid "Unable to load last job update" msgstr "最後のジョブ更新を読み込めません" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "利用不可" @@ -9399,15 +9554,15 @@ msgstr "制限なし" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "到達不能" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "到達不能なホスト数" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "到達不能なホスト" @@ -9424,7 +9579,7 @@ msgid "Update Revision on Launch" msgstr "起動時のリビジョン更新" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "起動時の更新" @@ -9496,22 +9651,25 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "1 行ごとに 1 つの電話番号を指定して、SMS メッセージのルーティング先を指定します。電話番号は +11231231234 の形式にする必要があります。詳細は、Twilio のドキュメントを参照してください" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "使用済み容量" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "使用済み容量" @@ -9611,22 +9769,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9642,7 +9800,7 @@ msgstr "提示される変数" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "変数は JSON または YAML 構文にする必要があります。ラジオボタンを使用してこの構文を切り替えます。" -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "インベントリーソースの設定に使用する変数。このプラグインの設定方法の詳細については、ドキュメントの <0>インベントリープラグイン および <1>{sourceType} プラグイン設定ガイドを参照してください。" @@ -9659,16 +9817,16 @@ msgid "Verbose" msgstr "詳細" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "詳細" @@ -9676,8 +9834,8 @@ msgstr "詳細" msgid "View Azure AD settings" msgstr "Azure AD 設定の表示" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "認証情報の詳細の表示" @@ -9701,7 +9859,7 @@ msgstr "ホストの詳細の表示" msgid "View Instance Details" msgstr "インスタンスの詳細の表示" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9815,7 +9973,7 @@ msgstr "<0>docs.ansible.com での YAML サンプルの表示" msgid "View activity stream" msgstr "アクティビティーストリームの表示" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "すべての認証情報を表示します。" @@ -9978,7 +10136,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Webhook の認証情報" @@ -9989,7 +10147,7 @@ msgstr "Webhook の認証情報" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -9997,7 +10155,7 @@ msgstr "Webhook キー" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -10005,7 +10163,7 @@ msgstr "Webhook サービス" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -10029,7 +10187,7 @@ msgstr "Webhook サービスは、これを共有シークレットとして使 #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhook" @@ -10053,7 +10211,7 @@ msgstr "水" msgid "Wednesday" msgstr "水曜" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10106,8 +10264,8 @@ msgstr "ワークフローの承認が見つかりません。" #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10118,11 +10276,11 @@ msgstr "ワークフローの承認" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "ワークフロージョブ" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "ワークフロージョブ 1/{0}" @@ -10150,11 +10308,11 @@ msgstr "ワークフロージョブテンプレート" msgid "Workflow Link" msgstr "ワークフローのリンク" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "ワークフローノード" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "ワークフローのステータス" @@ -10232,7 +10390,7 @@ msgstr "書き込み" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10243,6 +10401,14 @@ msgstr "年" msgid "Yes" msgstr "はい" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "同じ Vault ID を持つ複数の Vault 認証情報を選択することはできません。これを行うと、同じ Vault ID を持つもう一方の選択が自動的に解除されます。" @@ -10271,7 +10437,8 @@ msgstr "サブスクリプションで許可されているよりも多くのホ msgid "" "You may apply a number of possible variables in the\n" "message. For more information, refer to the" -msgstr "メッセージにはいくつかの可能な変数を適用できます。\n" +msgstr "" +"メッセージにはいくつかの可能な変数を適用できます。\n" "詳細の参照:" #: screens/Login/Login.js:198 @@ -10383,7 +10550,12 @@ msgstr "詳細。" msgid "disassociate" msgstr "関連付けの解除" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10395,11 +10567,11 @@ msgstr "ドキュメント" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10411,7 +10583,12 @@ msgstr "編集" msgid "encrypted" msgstr "暗号化" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "(詳細情報)" @@ -10495,7 +10672,7 @@ msgstr "ジョブの再起動" msgid "sec" msgstr "秒" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "秒" @@ -10564,7 +10741,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10604,7 +10781,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10649,10 +10826,11 @@ msgstr "{brandName} ロゴ" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} (<0>{username} による)" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10705,7 +10883,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} 分 {seconds} 秒" @@ -10729,11 +10907,10 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} occurrence} other { msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} 一覧" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" #: components/AppContainer/AppContainer.js:154 msgid "{sessionCountdown, plural, one {You will be logged out in # second due to inactivity} other {You will be logged out in # seconds due to inactivity}}" msgstr "{sessionCountdown, plural, one {You will be logged out in # second due to inactivity} other {You will be logged out in # seconds due to inactivity}}" - diff --git a/awx/ui/src/locales/ko/messages.po b/awx/ui/src/locales/ko/messages.po index 00ee18f22b..f77b71e012 100644 --- a/awx/ui/src/locales/ko/messages.po +++ b/awx/ui/src/locales/ko/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(상위 10개로 제한)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(실행 시 프롬프트)" @@ -25,7 +26,7 @@ msgstr "(실행 시 프롬프트)" msgid "* This field will be retrieved from an external secret management system using the specified credential." msgstr "*이 필드는 지정된 인증 정보를 사용하여 외부 보안 관리 시스템에서 검색됩니다." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (프로젝트 root)" @@ -65,6 +66,10 @@ msgstr "4 (연결 디버그)" msgid "5 (WinRM Debug)" msgstr "5 (WinRM 디버그)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -99,7 +104,7 @@ msgstr "정보" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -135,7 +140,7 @@ msgstr "동작" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -157,18 +162,19 @@ msgstr "동작" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -192,7 +198,7 @@ msgstr "동작" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "동작" @@ -360,7 +366,7 @@ msgid "Alert modal" msgstr "경고 모달" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -425,7 +431,7 @@ msgstr "응답 유형" msgid "Answer variable name" msgstr "응답 변수 이름" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "모든" @@ -475,6 +481,10 @@ msgstr "애플리케이션 및 토큰" msgid "Approval" msgstr "승인" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -542,7 +552,7 @@ msgstr "{1}에서 {0} 액세스 권한을 삭제하시겠습니까? 이렇게 msgid "Are you sure you want to remove {0} access from {username}?" msgstr "{username} 에서 {0} 액세스 권한을 삭제하시겠습니까?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "이 작업을 취소하기 위한 요청을 제출하시겠습니까?" @@ -555,7 +565,7 @@ msgstr "인수" msgid "Artifacts" msgstr "아티팩트" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "연결" @@ -591,10 +601,11 @@ msgstr "인증 코드 만료" msgid "Authorization grant type" msgstr "인증 권한 부여 유형" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -631,7 +642,7 @@ msgstr "Azure AD 설정" msgid "Back" msgstr "뒤로" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "인증 정보로 돌아가기" @@ -654,7 +665,8 @@ msgstr "호스트로 돌아가기" msgid "Back to Instance Groups" msgstr "인스턴스 그룹으로 돌아가기" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "인스턴스로 돌아가기" @@ -691,7 +703,7 @@ msgstr "일정으로 돌아가기" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -770,6 +782,10 @@ msgstr "체크아웃할 분기입니다. 분기 외에도 태그, 커밋 해시 msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "작업 실행에 사용할 분기입니다. 비어 있는 경우 프로젝트 기본값이 사용됩니다. 프로젝트 allow_override 필드가 true로 설정된 경우에만 허용됩니다." +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "브랜드 이미지" @@ -787,10 +803,11 @@ msgstr "검색 중..." msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "기본적으로 Red Hat은 서비스 사용에 대한 분석 데이터를 수집하여 전송합니다. 서비스에서 수집하는 데이터에는 두 가지 카테고리가 있습니다. 자세한 내용은 <0>Tower 설명서 페이지를 참조하십시오. 이 기능을 비활성화하려면 다음 확인란을 선택 해제하십시오." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -802,7 +819,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "캐시 제한 시간" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "캐시 제한 시간" @@ -825,8 +842,8 @@ msgstr "캐시 제한 시간 (초)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -863,14 +880,14 @@ msgstr "캐시 제한 시간 (초)" msgid "Cancel" msgstr "취소" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "인벤토리 소스 동기화 취소" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "작업 취소" @@ -879,7 +896,7 @@ msgstr "작업 취소" msgid "Cancel Project Sync" msgstr "프로젝트 동기화 취소" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "동기화 취소" @@ -891,8 +908,8 @@ msgstr "동기화 취소" msgid "Cancel Workflow" msgstr "워크플로우 취소" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "작업 취소" @@ -931,7 +948,7 @@ msgstr "서브스크립션 편집 취소" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "취소 {0}" @@ -949,7 +966,6 @@ msgid "" "logging aggregator host and logging aggregator type." msgstr "로깅 수집기 호스트 및 로깅 수집기 유형을 제공하지 않고 로그 수집기를 활성화할 수 없습니다." -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "홉 노드에서 상태 점검을 실행할 수 없습니다." @@ -960,12 +976,13 @@ msgstr "홉 노드에서 상태 점검을 실행할 수 없습니다." msgid "Capacity" msgstr "용량" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "용량 조정" @@ -1051,7 +1068,7 @@ msgstr "작업 유형 선택" msgid "Choose a module" msgstr "모듈 선택" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "소스 선택" @@ -1120,7 +1137,8 @@ msgstr "이 버튼을 클릭하여 선택한 인증 정보 및 지정된 입력 msgid "Click to create a new link to this node." msgstr "이 노드에 대한 새 링크를 생성하려면 클릭합니다." -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "클릭하여 번들을 다운로드합니다" @@ -1195,7 +1213,7 @@ msgstr "준수" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1272,7 +1290,7 @@ msgstr "선택 확인" msgid "Container Group" msgstr "컨테이너 그룹" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1297,8 +1315,8 @@ msgstr "콘텐츠 서명 확인 인증 정보" msgid "Continue" msgstr "계속" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "컨트롤" @@ -1321,7 +1339,7 @@ msgstr "플레이북이 실행되면 ansible이 생성되는 출력 수준을 msgid "Controller Node" msgstr "컨트롤러 노드" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "통합" @@ -1494,28 +1512,28 @@ msgid "Create user token" msgstr "사용자 토큰 만들기" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1528,16 +1546,16 @@ msgstr "생성됨" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1578,16 +1596,16 @@ msgstr "(사용자 이름)에 의해 생성됨" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1624,7 +1642,7 @@ msgstr "인증 정보 유형" msgid "Credential copied successfully" msgstr "인증 정보가 성공적으로 복사됨" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "인증 정보를 찾을 수 없습니다." @@ -1633,7 +1651,7 @@ msgstr "인증 정보를 찾을 수 없습니다." msgid "Credential passwords" msgstr "인증 정보 암호" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Kubernetes 또는 OpenShift로 인증하는 인증 정보" @@ -1650,13 +1668,13 @@ msgid "Credential type not found." msgstr "인증 정보 유형을 찾을 수 없습니다." #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1665,7 +1683,7 @@ msgstr "인증 정보 유형을 찾을 수 없습니다." #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1680,11 +1698,11 @@ msgstr "시작 시 암호가 필요한 인증 정보는 허용되지 않습니 msgid "Current page" msgstr "현재 페이지" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "사용자 정의 Kubernetes 또는 OpenShift Pod 사양" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "사용자 정의 Pod 사양" @@ -1706,8 +1724,8 @@ msgstr "사용자 지정 가상 환경 {virtualEnvironment} 은 실행 환경으 msgid "Customize messages…" msgstr "메시지 사용자 정의..." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Pod 사양 사용자 정의" @@ -1717,7 +1735,7 @@ msgid "DELETED" msgstr "삭제됨" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "대시보드" @@ -1733,7 +1751,7 @@ msgstr "데이터 보존 기간" msgid "Date" msgstr "날짜" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1746,7 +1764,7 @@ msgstr "일" msgid "Day {0}" msgstr "{0} 일" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "데이터 보관 일수" @@ -1810,17 +1828,17 @@ msgstr "시스템 수준 기능 및 함수 정의" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1828,11 +1846,11 @@ msgstr "시스템 수준 기능 및 함수 정의" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1859,17 +1877,17 @@ msgstr "실행 환경 삭제" msgid "Delete Host" msgstr "호스트 삭제" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "인벤토리 삭제" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "작업 삭제" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "작업 템플릿 삭제" @@ -1877,7 +1895,7 @@ msgstr "작업 템플릿 삭제" msgid "Delete Notification" msgstr "알림 삭제" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "조직 삭제" @@ -1889,7 +1907,7 @@ msgstr "프로젝트 삭제" msgid "Delete Questions" msgstr "질문 삭제" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "일정 삭제" @@ -1934,16 +1952,16 @@ msgstr "인증 정보 유형 삭제" msgid "Delete error" msgstr "오류 삭제" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "인스턴스 그룹 삭제" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "인벤토리 소스 삭제" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "스마트 인벤토리 삭제" @@ -2010,6 +2028,10 @@ msgstr "거부됨 - {0} 자세한 내용은 활동 스트림을 참조하십시 msgid "Denied by {0} - {1}" msgstr "{0} - {1} 거부됨" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2035,8 +2057,8 @@ msgstr "프로비저닝 해제 실패" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2058,28 +2080,28 @@ msgstr "프로비저닝 해제 실패" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2089,7 +2111,7 @@ msgstr "프로비저닝 해제 실패" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2106,7 +2128,7 @@ msgstr "프로비저닝 해제 실패" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "설명" @@ -2136,10 +2158,11 @@ msgstr "대상 채널 또는 사용자" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2148,7 +2171,7 @@ msgstr "대상 채널 또는 사용자" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2163,7 +2186,7 @@ msgstr "대상 채널 또는 사용자" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2177,7 +2200,7 @@ msgstr "대상 채널 또는 사용자" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2225,7 +2248,7 @@ msgstr "대상 채널 또는 사용자" msgid "Details" msgstr "세부 정보" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "세부 정보 탭" @@ -2273,8 +2296,8 @@ msgstr "호스트에서 그룹을 분리하시겠습니까?" msgid "Disassociate host from group?" msgstr "그룹에서 호스트를 분리하시겠습니까?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "인스턴스를 인스턴스 그룹에서 분리하시겠습니까?" @@ -2325,8 +2348,8 @@ msgstr "완료" msgid "Download Bundle" msgstr "번들 다운로드" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "출력 다운로드" @@ -2372,28 +2395,28 @@ msgid "" "revision of the project prior to starting the job." msgstr "이 프로젝트를 사용하여 작업을 실행할 때마다 작업을 시작하기 전에 프로젝트의 버전을 업데이트합니다." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2409,8 +2432,8 @@ msgstr "이 프로젝트를 사용하여 작업을 실행할 때마다 작업을 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2424,8 +2447,8 @@ msgstr "이 프로젝트를 사용하여 작업을 실행할 때마다 작업을 #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2599,7 +2622,8 @@ msgstr "세부 정보 편집" msgid "Edit group" msgstr "그룹 편집" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "호스트 편집" @@ -2626,16 +2650,16 @@ msgid "Edit workflow" msgstr "워크플로우 편집" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "경과됨" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "경과된 시간" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "작업이 실행되는 데 경과된 시간" @@ -2685,7 +2709,8 @@ msgid "" "has remained secure when a project is synced. \n" "If the content has been tampered with, the \n" "job will not run." -msgstr "콘텐츠 서명을 활성화하여 프로젝트가 동기화될 때 \n" +msgstr "" +"콘텐츠 서명을 활성화하여 프로젝트가 동기화될 때 \n" " 콘텐츠가 안전하게 유지되는지 확인합니다. \n" " 컨텐츠가 변조된 경우, \n" " 작업이 실행되지 않습니다." @@ -2723,20 +2748,20 @@ msgstr "활성화됨" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "활성화된 옵션" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "활성화된 값" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "활성화된 변수" @@ -2800,11 +2825,15 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "JSON 또는 YAML 구문을 사용하여 입력합니다. 구문 예제는 Ansible Controller 설명서를 참조하십시오." #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "JSON 또는 YAML 구문을 사용하여 인벤토리 변수를 입력합니다. 라디오 버튼을 사용하여 두 항목 사이를 전환합니다. 구문 예제는 Ansible Controller 설명서를 참조하십시오." +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "JSON 또는 YAML 구문을 사용하여 인벤토리 변수를 입력합니다. 라디오 버튼을 사용하여 두 항목 사이를 전환합니다. 구문 예제는 Ansible Controller 설명서를 참조하십시오." + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2817,8 +2846,8 @@ msgstr "인증 정보 유형에서 삽입할 수 있는 값을 지정하는 환 #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2851,14 +2880,14 @@ msgstr "워크플로우를 저장하는 동안 오류가 발생했습니다!" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2873,29 +2902,30 @@ msgstr "워크플로우를 저장하는 동안 오류가 발생했습니다!" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2903,7 +2933,7 @@ msgstr "워크플로우를 저장하는 동안 오류가 발생했습니다!" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2913,14 +2943,14 @@ msgstr "워크플로우를 저장하는 동안 오류가 발생했습니다!" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2930,7 +2960,8 @@ msgstr "워크플로우를 저장하는 동안 오류가 발생했습니다!" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2940,8 +2971,8 @@ msgstr "오류!" msgid "Error:" msgstr "오류:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "오류" @@ -2971,7 +3002,7 @@ msgstr "이벤트 요약을 사용할 수 없음" msgid "Events" msgstr "이벤트" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "이벤트 처리가 완료되었습니다." @@ -2979,10 +3010,14 @@ msgstr "이벤트 처리가 완료되었습니다." msgid "Exact match (default lookup if not specified)." msgstr "정확한 일치(지정되지 않은 경우 기본 조회)." -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "id 필드에서 정확한 검색" +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "GIT 소스 제어용 URL의 예는 다음과 같습니다." @@ -3003,7 +3038,7 @@ msgstr "예를 들면 다음과 같습니다." msgid "Examples:" msgstr "예:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "예외 빈도" @@ -3023,8 +3058,8 @@ msgstr "부모 노드가 실패 상태가 되면 실행합니다." msgid "Execute when the parent node results in a successful state." msgstr "부모 노드가 성공하면 실행됩니다." -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "실행" @@ -3038,8 +3073,8 @@ msgstr "실행" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "실행 환경" @@ -3154,7 +3189,7 @@ msgid "Extra variables" msgstr "추가 변수" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3162,7 +3197,7 @@ msgid "FINISHED:" msgstr "완료:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "실제 스토리지" @@ -3182,23 +3217,23 @@ msgstr "팩트" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "실패" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "실패한 호스트 수" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "실패한 호스트" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "실패한 호스트" @@ -3206,6 +3241,10 @@ msgstr "실패한 호스트" msgid "Failed jobs" msgstr "실패한 작업" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "승인하지 못했습니다 {0}." @@ -3220,7 +3259,7 @@ msgid "Failed to associate role" msgstr "역할을 연결하지 못했습니다." #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3228,7 +3267,7 @@ msgstr "역할을 연결하지 못했습니다." msgid "Failed to associate." msgstr "연결에 실패했습니다." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "인벤토리 소스 동기화를 취소하지 못했습니다." @@ -3244,7 +3283,7 @@ msgstr "하나 이상의 작업을 취소하지 못했습니다." #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "{0} 취소 실패" @@ -3287,15 +3326,15 @@ msgstr "그룹 {0} 을/를 삭제하지 못했습니다." msgid "Failed to delete host." msgstr "호스트를 삭제하지 못했습니다." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "인벤토리 소스 {name} 삭제에 실패했습니다." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "인벤토리를 삭제하지 못했습니다." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "작업 템플릿을 삭제하지 못했습니다." @@ -3324,7 +3363,7 @@ msgid "Failed to delete one or more groups." msgstr "하나 이상의 그룹을 삭제하지 못했습니다." #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "하나 이상의 호스트를 삭제하지 못했습니다." @@ -3340,7 +3379,7 @@ msgstr "하나 이상의 인벤토리를 삭제하지 못했습니다." msgid "Failed to delete one or more inventory sources." msgstr "하나 이상의 인벤토리 소스를 삭제하지 못했습니다." -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "하나 이상의 작업 템플릿을 삭제하지 못했습니다." @@ -3384,11 +3423,11 @@ msgstr "하나 이상의 사용자 토큰을 삭제하지 못했습니다." msgid "Failed to delete one or more users." msgstr "하나 이상의 사용자를 삭제하지 못했습니다." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "하나 이상의 워크플로우 승인을 삭제하지 못했습니다." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "조직을 삭제하지 못했습니다." @@ -3405,11 +3444,11 @@ msgstr "역할을 삭제하지 못했습니다" msgid "Failed to delete role." msgstr "역할을 삭제하지 못했습니다." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "일정을 삭제하지 못했습니다." -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "스마트 인벤토리를 삭제하지 못했습니다." @@ -3434,6 +3473,10 @@ msgstr "워크플로 작업 템플릿을 삭제하지 못했습니다." msgid "Failed to delete {name}." msgstr "{name} 을/를 삭제하지 못했습니다." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "{0} 을/를 거부하지 못했습니다." @@ -3448,9 +3491,9 @@ msgstr "하나 이상의 그룹을 연결 해제하지 못했습니다." msgid "Failed to disassociate one or more hosts." msgstr "하나 이상의 호스트를 연결 해제하지 못했습니다." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "하나 이상의 인스턴스를 연결 해제하지 못했습니다." @@ -3466,18 +3509,22 @@ msgstr "사용자 정의 로그인 구성 설정을 가져오지 못했습니다 msgid "Failed to fetch the updated project data." msgstr "업데이트된 프로젝트 데이터를 가져오지 못했습니다." -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "인스턴스를 가져오지 못했습니다." #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "작업을 시작하지 못했습니다." -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "하나 이상의 인스턴스를 제거하지 못했습니다." @@ -3489,8 +3536,8 @@ msgstr "구성을 검색하지 못했습니다." msgid "Failed to retrieve full node resource object." msgstr "전체 노드 리소스 오브젝트를 검색하지 못했습니다." -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "하나 이상의 인스턴스에서 상태 확인을 실행하지 못했습니다." @@ -3526,10 +3573,10 @@ msgstr "알림을 전환하지 못했습니다." msgid "Failed to toggle schedule." msgstr "일정을 전환하지 못했습니다." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "크기 조정을 업데이트하지 못했습니다." @@ -3577,7 +3624,7 @@ msgstr "필드에 값이 있습니다." msgid "Field ends with value." msgstr "필드는 값으로 끝납니다." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "사용자 정의 Kubernetes 또는 OpenShift Pod 사양을 전달하는 필드입니다." @@ -3610,11 +3657,11 @@ msgstr "파일, 디렉터리 또는 스크립트" msgid "Filter By {name}" msgstr "{name}으로 필터링" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "실패한 작업으로 필터링" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "성공한 작업으로 필터링" @@ -3643,7 +3690,7 @@ msgstr "첫 번째" msgid "First Name" msgstr "이름" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "첫 번째 실행" @@ -3686,11 +3733,11 @@ msgstr "자세한 내용은 다음을 참조하십시오." #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3700,12 +3747,12 @@ msgstr "포크" msgid "Fourth" msgstr "네 번째" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "빈도 세부 정보" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "빈도 예외 세부 정보" @@ -3727,7 +3774,7 @@ msgstr "금요일" msgid "Friday" msgstr "금요일" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "id, 이름 또는 설명 필드에서 퍼지 검색" @@ -3739,7 +3786,7 @@ msgstr "이름 필드에서 퍼지 검색" msgid "GPG Public Key" msgstr "GPG 공개 키" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Galaxy 인증 정보" @@ -3777,7 +3824,7 @@ msgstr "서브스크립션 가져오기" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3816,7 +3863,7 @@ msgstr "GitHub 팀" msgid "GitHub settings" msgstr "GitHub 설정" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3920,6 +3967,19 @@ msgstr "HTTP 방법" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "상태 점검 요청이 제출되었습니다. 잠시 기다렸다가 페이지를 다시 로드하십시오." +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "상태 양호" @@ -3942,7 +4002,7 @@ msgstr "설명 숨기기" msgid "Hipchat" msgstr "Hipchat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "홉" @@ -3950,8 +4010,9 @@ msgstr "홉" msgid "Hop node" msgstr "홉 노드" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3966,16 +4027,16 @@ msgid "Host Async OK" msgstr "호스트 동기화 확인" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "호스트 구성 키" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "호스트 수" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "호스트 세부 정보" @@ -3987,13 +4048,14 @@ msgstr "호스트 실패" msgid "Host Failure" msgstr "호스트 실패" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "호스트 필터" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "호스트 이름" @@ -4026,7 +4088,7 @@ msgstr "호스트에 연결할 수 없음" msgid "Host details" msgstr "호스트 세부 정보" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "호스트 세부 정보 모달" @@ -4041,7 +4103,7 @@ msgstr "이 작업의 호스트 상태 정보를 사용할 수 없습니다." #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4053,10 +4115,10 @@ msgstr "이 작업의 호스트 상태 정보를 사용할 수 없습니다." #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "호스트" @@ -4078,15 +4140,15 @@ msgstr "가져온 호스트" msgid "Hosts remaining" msgstr "남아 있는 호스트" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "시간" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "하이브리드" @@ -4205,18 +4267,20 @@ msgstr "활성화하면 이 작업 템플릿을 동시에 실행할 수 있습 msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "활성화하면 이 워크플로 작업 템플릿을 동시에 실행할 수 있습니다." -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "활성화된 경우 인벤토리에서 연결된 작업 템플릿을 실행할 기본 인스턴스 그룹 목록에 조직 인스턴스 그룹을 추가할 수 없습니다. \n" +msgstr "" +"활성화된 경우 인벤토리에서 연결된 작업 템플릿을 실행할 기본 인스턴스 그룹 목록에 조직 인스턴스 그룹을 추가할 수 없습니다. \n" " 참고: 이 설정이 활성화되어 있고 빈 목록을 제공한 경우 글로벌 인스턴스 그룹이 적용됩니다." #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "활성화된 경우 작업 템플릿에서 실행할 기본 인스턴스 그룹 목록에 인벤토리 또는 조직 인스턴스 그룹을 추가하지 않습니다. \n" +msgstr "" +"활성화된 경우 작업 템플릿에서 실행할 기본 인스턴스 그룹 목록에 인벤토리 또는 조직 인스턴스 그룹을 추가하지 않습니다. \n" " 참고: 이 설정이 활성화되어 있고 빈 목록을 제공한 경우 글로벌 인스턴스 그룹이 적용됩니다." #: screens/Template/shared/JobTemplate.helptext.js:35 @@ -4314,7 +4378,8 @@ msgstr "Insights 인증 정보" msgid "Insights system ID" msgstr "Insights 시스템 ID" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "번들 설치" @@ -4335,25 +4400,26 @@ msgstr "인스턴스 필터" msgid "Instance Group" msgstr "인스턴스 그룹" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "인스턴스 그룹" @@ -4383,8 +4449,8 @@ msgstr "인스턴스 그룹" msgid "Instance group not found." msgstr "인스턴스 그룹을 찾을 수 없습니다." -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "인스턴스 그룹이 사용하는 용량" @@ -4407,9 +4473,9 @@ msgstr "인스턴스 유형" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4442,7 +4508,7 @@ msgstr "사용자 이름 또는 암호가 잘못되었습니다. 다시 시도 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4466,18 +4532,18 @@ msgstr "소스와 함께 인벤토리를 복사할 수 없습니다." #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4486,8 +4552,8 @@ msgstr "소스와 함께 인벤토리를 복사할 수 없습니다." #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4514,7 +4580,7 @@ msgstr "인벤토리 소스" msgid "Inventory Source Sync" msgstr "인벤토리 소스 동기화" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "인벤토리 소스 동기화 오류" @@ -4546,8 +4612,8 @@ msgstr "인벤토리 업데이트" msgid "Inventory copied successfully" msgstr "인벤토리가 성공적으로 복사됨" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "인벤토리 파일" @@ -4559,7 +4625,7 @@ msgstr "인벤토리를 찾을 수 없음" msgid "Inventory sync" msgstr "인벤토리 동기화" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "인벤토리 동기화 실패" @@ -4593,18 +4659,18 @@ msgid "Items per page" msgstr "페이지당 항목" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "작업 ID:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "JSON 탭" @@ -4619,16 +4685,16 @@ msgstr "1월" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "작업 취소 오류" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "작업 삭제 오류" @@ -4651,10 +4717,10 @@ msgid "Job Slice Parent" msgstr "작업 분할 부모" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "작업 분할" @@ -4665,11 +4731,11 @@ msgstr "작업 상태" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4690,7 +4756,7 @@ msgstr "작업 템플릿" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "작업 템플릿 기본 인증 정보는 동일한 유형 중 하나로 교체해야 합니다. 계속하려면 다음 유형의 인증 정보를 선택하십시오. {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4713,26 +4779,26 @@ msgstr "노드를 생성하거나 편집할 때 암호를 입력하라는 인증 #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "작업 유형" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "작업 상태" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "작업 상태 그래프 탭" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "작업 템플릿" @@ -4846,7 +4912,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "레이블" @@ -4857,15 +4923,15 @@ msgstr "레이블 이름" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4877,18 +4943,19 @@ msgstr "레이블" msgid "Last" msgstr "마지막" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "마지막 상태 점검" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "마지막 작업 상태" @@ -4897,8 +4964,8 @@ msgstr "마지막 작업 상태" msgid "Last Login" msgstr "마지막 로그인" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4907,17 +4974,17 @@ msgstr "마지막 로그인" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4940,7 +5007,7 @@ msgstr "성" msgid "Last Ran" msgstr "마지막 실행" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "마지막 실행" @@ -4948,8 +5015,8 @@ msgstr "마지막 실행" msgid "Last job" msgstr "마지막 작업" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -4973,8 +5040,8 @@ msgstr "마지막으로 사용됨" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5041,12 +5108,12 @@ msgstr "비교 값보다 적거나 같습니다." #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5074,7 +5141,7 @@ msgstr "로딩 중" msgid "Local" msgstr "지역" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "현지 시간대" @@ -5117,7 +5184,7 @@ msgstr "검색 유형" msgid "Lookup typeahead" msgstr "자동 완성 검색" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5172,14 +5239,15 @@ msgstr "관리 작업을 찾을 수 없습니다." msgid "Management jobs" msgstr "관리 작업" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5199,11 +5267,25 @@ msgstr "3월" msgid "Mattermost" msgstr "가장 중요" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "최대 호스트" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "최대" @@ -5212,6 +5294,24 @@ msgstr "최대" msgid "Maximum length" msgstr "최대 길이" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5260,7 +5360,7 @@ msgid "" "assigned to this group when new instances come online." msgstr "새 인스턴스가 온라인 상태가 되면 이 그룹에 자동으로 할당되는 모든 인스턴스의 최소 백분율입니다." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5302,16 +5402,16 @@ msgstr "수정됨" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5349,7 +5449,7 @@ msgid "Modified by (username)" msgstr "(사용자 이름)에 의해 수정됨" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "모듈" @@ -5372,7 +5472,7 @@ msgstr "월요일" msgid "Monday" msgstr "월요일" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5421,8 +5521,8 @@ msgstr "다중 선택 옵션" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5445,8 +5545,8 @@ msgstr "다중 선택 옵션" #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5456,11 +5556,11 @@ msgstr "다중 선택 옵션" #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5516,27 +5616,27 @@ msgstr "다중 선택 옵션" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5548,7 +5648,7 @@ msgstr "다중 선택 옵션" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5558,7 +5658,7 @@ msgstr "다중 선택 옵션" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5568,7 +5668,7 @@ msgstr "다중 선택 옵션" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5578,7 +5678,7 @@ msgstr "다중 선택 옵션" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5600,7 +5700,7 @@ msgstr "다중 선택 옵션" #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5631,8 +5731,8 @@ msgstr "다중 선택 옵션" #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "이름" @@ -5675,7 +5775,7 @@ msgstr "새로운" msgid "Next" msgstr "다음" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5695,7 +5795,7 @@ msgstr "일치하는 호스트가 없음" msgid "No Hosts Remaining" msgstr "남아 있는 호스트가 없음" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "사용할 수 있는 JSON 없음" @@ -5719,7 +5819,7 @@ msgstr "사용 가능한 작업 데이터가 없습니다." msgid "No output found for this job." msgstr "이 작업에 대한 출력을 찾을 수 없습니다." -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "결과를 찾을 수 없음" @@ -5738,10 +5838,10 @@ msgstr "결과를 찾을 수 없음" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "결과를 찾을 수 없음" @@ -5769,15 +5869,16 @@ msgstr "{pluralizedItemName} 을/를 찾을 수 없음" msgid "Node Alias" msgstr "노드 별칭" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5802,8 +5903,8 @@ msgstr "노드 유형" msgid "None" msgstr "없음" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "없음 (한 번 실행)" @@ -5954,14 +6055,14 @@ msgstr "10월" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "Off" @@ -5970,14 +6071,14 @@ msgstr "Off" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "On" @@ -6050,7 +6151,7 @@ msgstr "선택적으로 상태 업데이트를 웹 후크 서비스로 다시 #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6086,11 +6187,11 @@ msgstr "순서" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6100,8 +6201,8 @@ msgstr "순서" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6145,12 +6246,12 @@ msgid "Out of compliance" msgstr "규정 준수 외" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "출력" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "출력 탭" @@ -6159,12 +6260,12 @@ msgid "Overwrite" msgstr "덮어쓰기" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "원격 인벤토리 소스에서 로컬 그룹 및 호스트 덮어쓰기" #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "원격 인벤토리 소스에서 로컬 변수 덮어쓰기" @@ -6283,11 +6384,11 @@ msgstr "개인 액세스 토큰" msgid "Personal access token" msgstr "개인 액세스 토큰" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "플레이" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "플레이 수" @@ -6297,7 +6398,7 @@ msgstr "플레이 시작됨" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6329,7 +6430,7 @@ msgstr "플레이북 실행" msgid "Playbook Started" msgstr "플레이북 시작됨" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6341,7 +6442,7 @@ msgstr "플레이북 이름" msgid "Playbook run" msgstr "플레이북 실행" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "플레이" @@ -6365,7 +6466,7 @@ msgstr "이 목록을 채우려면 {pluralizedItemName} 을 추가하십시오." msgid "Please click the Start button to begin." msgstr "시작하려면 시작 버튼을 클릭하십시오." -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "이벤트 발생 횟수를 입력해 주십시오." @@ -6385,7 +6486,7 @@ msgstr "로그인하십시오" msgid "Please run a job to populate this list." msgstr "이 목록을 채우려면 작업을 실행하십시오." -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "1에서 31 사이의 날짜 번호를 선택하십시오." @@ -6393,7 +6494,7 @@ msgstr "1에서 31 사이의 날짜 번호를 선택하십시오." msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "인벤토리를 선택하거나 시작 시 프롬프트 옵션을 선택하십시오." -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "시작 날짜/시간 이후의 종료 날짜/시간을 선택하십시오." @@ -6409,14 +6510,15 @@ msgstr "위의 필터를 사용하여 다른 검색을 시도하십시오." msgid "Please wait until the topology view is populated..." msgstr "토폴로지 보기가 채워질 때까지 기다리십시오..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Pod 사양 덮어쓰기" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "정책 유형" @@ -6472,16 +6574,16 @@ msgid "" "cancel the drag operation." msgstr "스페이스바 또는 Enter 키를 눌러 드래그를 시작하고 화살표 키를 사용하여 위로 또는 아래로 이동합니다. Enter 키를 눌러 끌어오기하거나 다른 키를 눌러 끌어오기 작업을 취소합니다." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "인스턴스 그룹 폴백 방지" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "인스턴스 그룹 폴백 방지: 활성화된 경우, 인벤토리에서 연결된 작업 템플릿을 실행하도록 기본 인스턴스 그룹 목록에 조직 인스턴스 그룹을 추가할 수 없습니다." @@ -6499,7 +6601,7 @@ msgid "Private key passphrase" msgstr "개인 키 암호" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "권한 에스컬레이션" @@ -6520,11 +6622,11 @@ msgstr "권한 에스컬레이션: 활성화하면 이 플레이북을 관리자 #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "프로젝트" @@ -6565,14 +6667,14 @@ msgstr "프로젝트가 성공적으로 복사됨" msgid "Project not found." msgstr "프로젝트를 찾을 수 없음" -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "프로젝트 동기화 실패" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6587,12 +6689,12 @@ msgstr "프로젝트" msgid "Promote Child Groups and Hosts" msgstr "하위 그룹 및 호스트 승격" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "프롬프트" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "프롬프트 덮어쓰기" @@ -6606,8 +6708,8 @@ msgstr "시작 시 프롬프트" msgid "Prompt | {0}" msgstr "프롬프트 | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "프롬프트 값" @@ -6652,7 +6754,7 @@ msgid "Provisioning" msgstr "프로비저닝" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "콜백 URL 프로비저닝" @@ -6662,7 +6764,7 @@ msgid "Provisioning Callback details" msgstr "프로비저닝 호출 세부 정보" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6693,10 +6795,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "RADIUS 설정" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6710,23 +6813,23 @@ msgstr "읽기" msgid "Ready" msgstr "준비됨" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "최근 작업" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "최근 작업 목록 탭" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "최근 템플릿" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "최근 템플릿 목록 탭" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6817,12 +6920,15 @@ msgstr "리전" msgid "Registry credential" msgstr "레지스트리 인증 정보" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "호스트 이름과 일치하는 정규 표현식을 가져옵니다. 필터는 인벤토리 플러그인 필터를 적용한 후 사후 처리 단계로 적용됩니다." #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "관련 그룹" @@ -6849,12 +6955,12 @@ msgstr "관련 검색 자동 완성" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "다시 시작" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "작업 다시 시작" @@ -6872,7 +6978,7 @@ msgid "Relaunch on" msgstr "다시 시작" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "호스트 매개변수를 사용하여 다시 시작" @@ -6880,7 +6986,7 @@ msgstr "호스트 매개변수를 사용하여 다시 시작" msgid "Reload" msgstr "다시 로드" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "출력 다시 로드" @@ -6893,8 +6999,8 @@ msgstr "출력 다시 로드" msgid "Remote Archive" msgstr "원격 아카이브" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "제거 오류" @@ -6953,7 +7059,7 @@ msgstr "이 링크를 제거하면 나머지 분기가 분리되고 시작 시 msgid "Reorder" msgstr "재정렬" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "반복 빈도" @@ -7023,8 +7129,8 @@ msgstr "호스트 변수의 지정된 dict에서 활성화된 상태를 검색 #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "돌아가기" @@ -7129,8 +7235,9 @@ msgstr "실행" msgid "Run Command" msgstr "명령 실행" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "인스턴스에서 상태 점검을 실행합니다." @@ -7147,10 +7254,11 @@ msgstr "명령 실행" msgid "Run every" msgstr "모두 실행" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "실행 상태 점검" @@ -7177,17 +7285,26 @@ msgstr "실행 중" msgid "Running Handlers" msgstr "실행 중인 Handlers" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "실행 중인 작업" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "실행 중인 상태 점검" @@ -7226,7 +7343,7 @@ msgid "START" msgstr "시작" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7249,8 +7366,8 @@ msgstr "토요일" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7304,7 +7421,7 @@ msgstr "일정이 활성화됨" msgid "Schedule is inactive" msgstr "일정이 비활성 상태입니다" -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "일정에 규칙이 누락되어 있습니다" @@ -7426,7 +7543,7 @@ msgstr "호스트 선택" msgid "Select Input" msgstr "입력 선택" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "인스턴스 선택" @@ -7496,11 +7613,19 @@ msgstr "실행 환경을 편집하기 전에 프로젝트를 선택합니다." msgid "Select a question to delete" msgstr "삭제할 질문을 선택" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "삭제할 행 선택" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "연결할 행을 선택" @@ -7528,8 +7653,8 @@ msgstr "서브스크립션 선택" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7571,7 +7696,7 @@ msgstr "인스턴스 선택" msgid "Select an instance and a metric to show chart" msgstr "차트를 표시할 인스턴스 및 메트릭을 선택합니다." -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "상태 점검을 실행할 인스턴스를 선택합니다." @@ -7627,9 +7752,9 @@ msgstr "기간 선택" msgid "Select roles to apply" msgstr "적용할 역할 선택" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "소스 경로 선택" @@ -7719,8 +7844,8 @@ msgstr "{0} 선택" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7743,8 +7868,8 @@ msgstr "선택됨" msgid "Selected Category" msgstr "선택한 카테고리" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "선택한 날짜 범위는 하나 이상의 일정이 포함되어 있어야 합니다." @@ -7778,7 +7903,7 @@ msgstr "유지해야 하는 데이터 일 수를 설정합니다." msgid "Set preferences for data collection, logos, and logins" msgstr "데이터 수집, 로고 및 로그인에 대한 기본 설정" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "소스 경로 설정" @@ -7844,10 +7969,10 @@ msgid "Show" msgstr "표시" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "변경 사항 표시" @@ -7921,11 +8046,11 @@ msgstr "간단한 키 선택" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -7999,8 +8124,8 @@ msgstr "분류" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8008,20 +8133,22 @@ msgid "Source" msgstr "소스" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "소스 제어 분기" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "소스 제어 분기/태그/커밋" @@ -8084,7 +8211,7 @@ msgstr "소스 워크플로 작업" msgid "Source control branch" msgstr "소스 제어 분기" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "소스 세부 정보" @@ -8092,7 +8219,7 @@ msgstr "소스 세부 정보" msgid "Source phone number" msgstr "소스 전화 번호" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "소스 변수" @@ -8122,11 +8249,11 @@ msgstr "알림 색상을 지정합니다. 허용되는 색상은 16진수 색상 msgid "Specify the conditions under which this node should be executed" msgstr "이 노드를 실행해야 하는 조건을 지정합니다." -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "표준 오류" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "표준 오류 탭" @@ -8173,27 +8300,28 @@ msgid "Start time" msgstr "시작 시간" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "시작됨" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8201,7 +8329,7 @@ msgstr "시작됨" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "상태" @@ -8289,7 +8417,7 @@ msgstr "성공 메시지 본문" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "성공" @@ -8425,8 +8553,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "TACACS + 설정" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "탭" @@ -8453,11 +8581,11 @@ msgstr "주석 태그(선택 사항)" msgid "Target URL" msgstr "대상 URL" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "작업" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "작업 수" @@ -8465,7 +8593,7 @@ msgstr "작업 수" msgid "Task Started" msgstr "호스트 시작됨" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "작업" @@ -8507,7 +8635,7 @@ msgstr "팀" msgid "Template" msgstr "템플릿" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "템플릿이 성공적으로 복사됨" @@ -8577,11 +8705,12 @@ msgstr "The" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "사용자가 이 애플리케이션의 토큰을 얻는 데 사용해야 하는 Grant 유형" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "이 조직에서 실행할 인스턴스 그룹입니다." -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "이 인스턴스가 속하는 인스턴스 그룹입니다." @@ -8612,7 +8741,7 @@ msgstr "Grafana 서버의 기본 URL - /api/annotations 엔드포인트가 기 msgid "The container image to be used for execution." msgstr "실행에 사용할 컨테이너 이미지입니다." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8644,7 +8773,7 @@ msgstr "모든 참조에 대한 첫 번째 참조를 가져옵니다. Github pul msgid "The full image location, including the container registry, image name, and version tag." msgstr "컨테이너 레지스트리, 이미지 이름, 버전 태그를 포함한 전체 이미지 위치입니다." -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8663,7 +8792,7 @@ msgstr "마지막 {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "마지막 {weekday} / {month}" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8823,7 +8952,7 @@ msgstr "이 작업은 다음과 같이 연결을 해제합니다." msgid "This action will remove the following instances:" msgstr "이 작업은 다음 인스턴스를 제거합니다." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 msgid "This container group is currently being by other resources. Are you sure you want to delete it?" msgstr "현재 이 컨테이너 그룹에 다른 리소스가 있습니다. 삭제하시겠습니까?" @@ -8840,7 +8969,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Software and to provide\n" "Automation Analytics." -msgstr "이 데이터는\n" +msgstr "" +"이 데이터는\n" "향후 소프트웨어 릴리스를 개선하고\n" "Automation Analytics를 제공하는 데 사용됩니다." @@ -8860,7 +8990,7 @@ msgstr "현재 다른 리소스에서 이 실행 환경이 사용되고 있습 msgid "This feature is deprecated and will be removed in a future release." msgstr "이 기능은 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정입니다." -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "활성화된 변수가 설정되지 않은 경우 이 필드는 무시됩니다. 사용 가능한 변수가 이 값과 일치하면 호스트는 가져오기에서 활성화됩니다." @@ -8946,7 +9076,7 @@ msgstr "이 필드는 지정된 인증 정보를 사용하여 외부 시크릿 msgid "This has already been acted on" msgstr "이 작업은 이미 수행되었습니다." -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "이 인스턴스 그룹은 현재 다른 리소스에 의해 있습니다. 삭제하시겠습니까?" @@ -8954,11 +9084,11 @@ msgstr "이 인스턴스 그룹은 현재 다른 리소스에 의해 있습니 msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "이 인벤토리는 이 워크플로우({0}) 내의 모든 워크플로 노드에 적용되며, 인벤토리를 요청하는 메시지를 표시합니다." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "이 인벤토리는 현재 다른 리소스에서 사용하고 있습니다. 삭제하시겠습니까?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "이 인벤토리 소스는 현재 이를 사용하는 다른 리소스에서 사용되고 있습니다. 삭제하시겠습니까?" @@ -8974,11 +9104,11 @@ msgstr "토큰 값과 연결된 새로 고침 토큰 값이 표시되는 유일 msgid "This job failed and has no output." msgstr "이 작업은 실패하여 출력이 없습니다." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "이 작업 템플릿은 현재 다른 리소스에서 사용하고 있습니다. 삭제하시겠습니까?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "이 조직은 현재 다른 리소스에서 사용 중입니다. 삭제하시겠습니까?" @@ -8990,7 +9120,7 @@ msgstr "이 프로젝트는 현재 다른 리소스에서 사용하고 있습니 msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "이 프로젝트는 현재 동기화 상태에 있으며 동기화 프로세스가 완료될 때까지 클릭할 수 없습니다." -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "이 일정에는 선택한 예외로 인해 발생하지 않습니다." @@ -9006,7 +9136,8 @@ msgstr "이 일정에는 필수 설문 조사 값이 없습니다." msgid "" "This schedule uses complex rules that are not supported in the\n" "UI. Please use the API to manage this schedule." -msgstr "이 일정은 UI에서 지원되지 않는 복잡한 규칙을 사용합니다. \n" +msgstr "" +"이 일정은 UI에서 지원되지 않는 복잡한 규칙을 사용합니다. \n" " API를 사용하여 이 일정을 관리하십시오." #: components/LaunchPrompt/steps/StepName.js:26 @@ -9086,13 +9217,13 @@ msgid "Timed out" msgstr "시간 초과" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9195,15 +9326,16 @@ msgid "Tools" msgstr "툴" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "토폴로지 보기" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "총 작업" @@ -9213,7 +9345,7 @@ msgstr "총 작업" msgid "Total Nodes" msgstr "총 노드" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "총 호스트" @@ -9269,8 +9401,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9283,11 +9415,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9335,13 +9467,14 @@ msgstr "호스트에서 인벤토리를 변경할 수 없음" msgid "Unable to load last job update" msgstr "마지막 작업 업데이트를 로드할 수 없음" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "사용할 수 없음" @@ -9361,15 +9494,15 @@ msgstr "무제한" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "연결할 수 없음" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "연결할 수 없는 호스트 수" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "연결할 수 없는 호스트" @@ -9386,7 +9519,7 @@ msgid "Update Revision on Launch" msgstr "시작 시 버전 업데이트" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "시작 시 업데이트" @@ -9458,22 +9591,25 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "SMS 메시지를 라우팅할 위치를 지정하려면 한 줄에 하나의 전화 번호를 사용합니다. 전화 번호는 +11231231234 형식이어야 합니다. 자세한 내용은 Twilio 문서를 참조하십시오." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "사용된 용량" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "사용된 용량" @@ -9573,22 +9709,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9604,7 +9740,7 @@ msgstr "프롬프트 변수" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "변수는 JSON 또는 YAML 구문이어야 합니다. 라디오 버튼을 사용하여 둘 사이를 전환합니다." -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "인벤토리 소스를 구성하는데 사용되는 변수입니다. 이 플러그인을 구성하는 방법에 대한 자세한 내용은 설명서의 <0>인벤토리 플러그인 섹션과 <1>{sourceType} 플러그인 구성 가이드를 참조하십시오." @@ -9621,16 +9757,16 @@ msgid "Verbose" msgstr "상세 정보" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "상세 정보" @@ -9638,8 +9774,8 @@ msgstr "상세 정보" msgid "View Azure AD settings" msgstr "Azure AD 설정 보기" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "인증 정보 세부 정보보기" @@ -9663,7 +9799,7 @@ msgstr "호스트 세부 정보 보기" msgid "View Instance Details" msgstr "인스턴스 세부 정보 보기" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9777,7 +9913,7 @@ msgstr "<0>docs.ansible.com에서 YAML 예제 보기" msgid "View activity stream" msgstr "활동 스트림 보기" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "모든 인증 정보 보기" @@ -9940,7 +10076,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Webhook 인증 정보" @@ -9951,7 +10087,7 @@ msgstr "Webhook 인증 정보" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -9959,7 +10095,7 @@ msgstr "Webhook 키" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -9967,7 +10103,7 @@ msgstr "Webhook 서비스" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -9991,7 +10127,7 @@ msgstr "Webhook 서비스는 이를 공유 시크릿으로 사용할 수 있습 #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhook" @@ -10015,7 +10151,7 @@ msgstr "수요일" msgid "Wednesday" msgstr "수요일" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10068,8 +10204,8 @@ msgstr "워크플로우 승인을 찾을 수 없습니다." #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10080,11 +10216,11 @@ msgstr "워크플로우 승인" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "워크플로우 작업" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "워크플로 작업 1/{0}" @@ -10112,11 +10248,11 @@ msgstr "워크플로우 작업 템플릿" msgid "Workflow Link" msgstr "워크플로우 링크" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "워크플로 노드" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "워크플로우 상태" @@ -10194,7 +10330,7 @@ msgstr "쓰기" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10205,6 +10341,14 @@ msgstr "년" msgid "Yes" msgstr "제공됨" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "동일한 vault ID로 여러 인증 정보를 선택할 수 없습니다. 이렇게 하면 동일한 vault ID를 가진 다른 인증 정보가 자동으로 선택 취소됩니다." @@ -10344,7 +10488,12 @@ msgstr "세부 정보" msgid "disassociate" msgstr "연결 해제" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10356,11 +10505,11 @@ msgstr "문서" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10372,7 +10521,12 @@ msgstr "편집" msgid "encrypted" msgstr "암호화" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "자세한 내용" @@ -10456,7 +10610,7 @@ msgstr "작업 다시 시작" msgid "sec" msgstr "초" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "초" @@ -10525,7 +10679,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10565,7 +10719,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10610,10 +10764,11 @@ msgstr "{brandName} 로고" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} (<0>{username} 기준)" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10666,7 +10821,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} 분 {seconds} 초" @@ -10690,7 +10845,7 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} occurrence} other { msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} 목록" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" diff --git a/awx/ui/src/locales/nl/messages.po b/awx/ui/src/locales/nl/messages.po index 807ac819da..81b4705a41 100644 --- a/awx/ui/src/locales/nl/messages.po +++ b/awx/ui/src/locales/nl/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(Beperkt tot de eerste 10)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(Melding bij opstarten)" @@ -25,7 +26,7 @@ msgstr "(Melding bij opstarten)" 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." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (projectroot)" @@ -65,6 +66,10 @@ msgstr "4 (Foutopsporing verbinding)" msgid "5 (WinRM Debug)" msgstr "5 (WinRM-foutopsporing)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -99,7 +104,7 @@ msgstr "Over" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -135,7 +140,7 @@ msgstr "Actie" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -157,18 +162,19 @@ msgstr "Actie" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -192,7 +198,7 @@ msgstr "Actie" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "Acties" @@ -360,7 +366,7 @@ msgid "Alert modal" msgstr "Waarschuwingsmodus" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -425,7 +431,7 @@ msgstr "Antwoordtype" msgid "Answer variable name" msgstr "Antwoord naam variabele" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "Iedere" @@ -475,6 +481,10 @@ msgstr "Toepassingen en tokens" msgid "Approval" msgstr "Goedkeuring" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -542,7 +552,7 @@ msgstr "Weet u zeker dat u de {0} toegang vanuit {1} wilt verwijderen? Als u da msgid "Are you sure you want to remove {0} access from {username}?" msgstr "Weet u zeker dat u de {0} toegang vanuit {username} wilt verwijderen?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "Weet u zeker dat u het verzoek om deze taak te annuleren in wilt dienen?" @@ -555,7 +565,7 @@ msgstr "Argumenten" msgid "Artifacts" msgstr "Artefacten" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "Associate" @@ -591,10 +601,11 @@ msgstr "Machtigingscode vervallen" msgid "Authorization grant type" msgstr "Type authenticatieverlening" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -631,7 +642,7 @@ msgstr "Azure AD-instellingen" msgid "Back" msgstr "Terug" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "Terug naar toegangsgegevens" @@ -654,7 +665,8 @@ msgstr "Terug naar hosts" msgid "Back to Instance Groups" msgstr "Terug naar instantiegroepen" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "Terug naar instanties" @@ -691,7 +703,7 @@ msgstr "Terug naar schema's" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -770,6 +782,10 @@ msgstr "Vertakking naar de kassa. Naast vertakkingen kunt u ook tags, commit has msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "Vertakking om bij het uitvoeren van een klus te gebruiken. Projectstandaard wordt gebruikt indien leeg. Alleen toegestaan als project allow_override field is ingesteld op true." +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "Merkimago" @@ -787,10 +803,11 @@ msgstr "Bladeren..." msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "Standaard verzamelen wij analytische gegevens over het gebruik van de service en sturen deze door naar Red Hat. Er zijn twee categorieën gegevens die door de service worden verzameld. Zie voor meer informatie <0>deze Tower-documentatiepagina. Schakel de volgende vakjes uit om deze functie uit te schakelen." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -802,7 +819,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "Cache time-out" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "Cache time-out" @@ -825,8 +842,8 @@ msgstr "Cache time-out (seconden)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -863,14 +880,14 @@ msgstr "Cache time-out (seconden)" msgid "Cancel" msgstr "Annuleren" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "Synchronisatie van inventarisbron annuleren" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "Taak annuleren" @@ -879,7 +896,7 @@ msgstr "Taak annuleren" msgid "Cancel Project Sync" msgstr "Projectsynchronisatie annuleren" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "Synchronisatie annuleren" @@ -891,8 +908,8 @@ msgstr "Synchronisatie annuleren" msgid "Cancel Workflow" msgstr "Workflow annuleren" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "Taak annuleren" @@ -931,7 +948,7 @@ msgstr "Abonnement bewerken annuleren" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "Annuleren {0}" @@ -949,7 +966,6 @@ msgid "" "logging aggregator host and logging aggregator type." msgstr "Kan aggregator logboekregistraties niet inschakelen zonder de host en het type ervan te verstrekken." -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "Kan geen gezondheidscontrole uitvoeren voor hop-knooppunten." @@ -960,12 +976,13 @@ msgstr "Kan geen gezondheidscontrole uitvoeren voor hop-knooppunten." msgid "Capacity" msgstr "Capaciteit" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "Capaciteitsaanpassing" @@ -993,7 +1010,8 @@ msgstr "Hoofdletterongevoelige versie van startswith." msgid "" "Change PROJECTS_ROOT when deploying\n" "{brandName} to change this location." -msgstr "Wijzig PROJECTS_ROOT bij het uitrollen van\n" +msgstr "" +"Wijzig PROJECTS_ROOT bij het uitrollen van\n" "{brandName} om deze locatie te wijzigen." #: components/StatusLabel/StatusLabel.js:55 @@ -1052,7 +1070,7 @@ msgstr "Kies een soort taak" msgid "Choose a module" msgstr "Kies een module" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "Kies een bron" @@ -1121,7 +1139,8 @@ msgstr "Klik op deze knop om de verbinding met het geheimbeheersysteem te verifi msgid "Click to create a new link to this node." msgstr "Klik om een nieuwe link naar dit knooppunt te maken." -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "Klik om de bundel te downloaden" @@ -1196,7 +1215,7 @@ msgstr "Compliant" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1273,7 +1292,7 @@ msgstr "Selectie bevestigen" msgid "Container Group" msgstr "Containergroep" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1298,8 +1317,8 @@ msgstr "Content Signature Validation Credential" msgid "Continue" msgstr "Doorgaan" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "Controle" @@ -1322,7 +1341,7 @@ msgstr "Stel in hoeveel output Ansible produceert bij het uitvoeren van het draa msgid "Controller Node" msgstr "Naam controller" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "Convergentie" @@ -1495,28 +1514,28 @@ msgid "Create user token" msgstr "Gebruikerstoken maken" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1529,16 +1548,16 @@ msgstr "Gemaakt" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1579,16 +1598,16 @@ msgstr "Gemaakt door (gebruikersnaam)" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1625,7 +1644,7 @@ msgstr "Types toegangsgegevens" msgid "Credential copied successfully" msgstr "Toegangsgegeven gekopieerd" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "Toegangsgegevens niet gevonden." @@ -1634,7 +1653,7 @@ msgstr "Toegangsgegevens niet gevonden." msgid "Credential passwords" msgstr "Wachtwoorden toegangsgegevens" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "Credential om te authenticeren met Kubernetes of OpenShift" @@ -1651,13 +1670,13 @@ msgid "Credential type not found." msgstr "Type toegangsgegevens niet gevonden." #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1666,7 +1685,7 @@ msgstr "Type toegangsgegevens niet gevonden." #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1681,11 +1700,11 @@ msgstr "Toegangsgegevens die een wachtwoord vereisen bij het opstarten zijn niet msgid "Current page" msgstr "Huidige pagina" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "Veld voor het opgeven van een aangepaste Kubernetes of OpenShift Pod-specificatie." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "Aangepaste podspecificatie" @@ -1707,8 +1726,8 @@ msgstr "Aangepaste virtuele omgeving {virtualEnvironment} moet worden vervangen msgid "Customize messages…" msgstr "Berichten aanpassen..." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "Podspecificatie aanpassen" @@ -1718,7 +1737,7 @@ msgid "DELETED" msgstr "VERWIJDERD" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "Dashboard" @@ -1734,7 +1753,7 @@ msgstr "Bewaartermijn van gegevens" msgid "Date" msgstr "Datum" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1747,7 +1766,7 @@ msgstr "Dag" msgid "Day {0}" msgstr "Dag {0}" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "Dagen om gegevens te bewaren" @@ -1811,17 +1830,17 @@ msgstr "Kenmerken en functies op systeemniveau definiëren" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1829,11 +1848,11 @@ msgstr "Kenmerken en functies op systeemniveau definiëren" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1860,17 +1879,17 @@ msgstr "Uitvoeringsomgeving verwijderen" msgid "Delete Host" msgstr "Host verwijderen" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "Inventaris verwijderen" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "Taak verwijderen" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "Taaksjabloon verwijderen" @@ -1878,7 +1897,7 @@ msgstr "Taaksjabloon verwijderen" msgid "Delete Notification" msgstr "Bericht verwijderen" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "Organisatie verwijderen" @@ -1890,7 +1909,7 @@ msgstr "Project verwijderen" msgid "Delete Questions" msgstr "Vragen verwijderen" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "Schema verwijderen" @@ -1935,16 +1954,16 @@ msgstr "Soort toegangsgegevens verwijderen" msgid "Delete error" msgstr "Fout verwijderen" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "Instantiegroep verwijderen" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "Inventarisbron maken" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "Smart-inventaris maken" @@ -2011,6 +2030,10 @@ msgstr "Geweigerd - {0}. Zie de activiteitstroom voor meer informatie." msgid "Denied by {0} - {1}" msgstr "Geweigerd door {0} - {1}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2036,8 +2059,8 @@ msgstr "Deprovisionering mislukt" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2059,28 +2082,28 @@ msgstr "Deprovisionering mislukt" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2090,7 +2113,7 @@ msgstr "Deprovisionering mislukt" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2107,7 +2130,7 @@ msgstr "Deprovisionering mislukt" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "Omschrijving" @@ -2137,10 +2160,11 @@ msgstr "Bestemmingskanalen of -gebruikers" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2149,7 +2173,7 @@ msgstr "Bestemmingskanalen of -gebruikers" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2164,7 +2188,7 @@ msgstr "Bestemmingskanalen of -gebruikers" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2178,7 +2202,7 @@ msgstr "Bestemmingskanalen of -gebruikers" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2226,7 +2250,7 @@ msgstr "Bestemmingskanalen of -gebruikers" msgid "Details" msgstr "Meer informatie" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "Tabblad Details" @@ -2274,8 +2298,8 @@ msgstr "Groep van host loskoppelen?" msgid "Disassociate host from group?" msgstr "Host van groep loskoppelen?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "Instantie van instantiegroep loskoppelen?" @@ -2326,8 +2350,8 @@ msgstr "Gereed" msgid "Download Bundle" msgstr "Download Bundel" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "Download output" @@ -2373,28 +2397,28 @@ msgid "" "revision of the project prior to starting the job." msgstr "Voer iedere keer dat een taak uitgevoerd wordt met dit project een update uit voor de herziening van het project voordat u de taak start." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2410,8 +2434,8 @@ msgstr "Voer iedere keer dat een taak uitgevoerd wordt met dit project een updat #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2425,8 +2449,8 @@ msgstr "Voer iedere keer dat een taak uitgevoerd wordt met dit project een updat #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2600,7 +2624,8 @@ msgstr "Details bewerken" msgid "Edit group" msgstr "Groep bewerken" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "Host bewerken" @@ -2627,16 +2652,16 @@ msgid "Edit workflow" msgstr "Workflow bewerken" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "Verlopen" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "Verstreken tijd" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "Verstreken tijd in seconden dat de taak is uitgevoerd" @@ -2686,7 +2711,8 @@ msgid "" "has remained secure when a project is synced. \n" "If the content has been tampered with, the \n" "job will not run." -msgstr "Inhoud ondertekenen inschakelen om te verifiëren dat de inhoud \n" +msgstr "" +"Inhoud ondertekenen inschakelen om te verifiëren dat de inhoud \n" "veilig is gebleven wanneer een project wordt gesynchroniseerd. \n" "Als er met de inhoud is geknoeid, zal de \n" "opdracht niet uitgevoerd." @@ -2724,20 +2750,20 @@ msgstr "Ingeschakeld" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "Ingeschakelde opties" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "Ingeschakelde waarde" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "Ingeschakelde variabele" @@ -2748,12 +2774,14 @@ msgid "" "callback URL. Using the URL a host can contact {brandName}\n" "and request a configuration update using this job\n" "template" -msgstr "Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met {brandName}\n" +msgstr "" +"Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met {brandName}\n" "en een verzoek voor een configuratie-update indienen met behulp van deze taaksjabloon" #: screens/Template/shared/JobTemplate.helptext.js:29 msgid "Enables creation of a provisioning callback URL. Using the URL a host can contact {brandName} and request a configuration update using this job template." -msgstr "Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met {brandName}\n" +msgstr "" +"Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met {brandName}\n" "en een verzoek voor een configuratie-update indienen met behulp van deze taaksjabloon." #: screens/Credential/CredentialDetail/CredentialDetail.js:160 @@ -2803,11 +2831,15 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "Geef inputs op met JSON- of YAML-syntaxis. Raadpleeg de documentatie voor Ansible Tower voor voorbeeldsyntaxis." #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "Voer de variabelen van het inventaris in met JSON- of YAML-syntaxis. Gebruik de radio-knop om tussen de twee te wisselen. Raadpleeg de documentatie van Ansible Tower voor voorbeeldsyntaxis" +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "Voer de variabelen van het inventaris in met JSON- of YAML-syntaxis. Gebruik de radio-knop om tussen de twee te wisselen. Raadpleeg de documentatie van Ansible Tower voor voorbeeldsyntaxis" + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2820,8 +2852,8 @@ msgstr "Omgevingsvariabelen of extra variabelen die aangeven welke waarden een c #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2854,14 +2886,14 @@ msgstr "Fout bij het opslaan van de workflow!" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2876,29 +2908,30 @@ msgstr "Fout bij het opslaan van de workflow!" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2906,7 +2939,7 @@ msgstr "Fout bij het opslaan van de workflow!" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2916,14 +2949,14 @@ msgstr "Fout bij het opslaan van de workflow!" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2933,7 +2966,8 @@ msgstr "Fout bij het opslaan van de workflow!" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2943,8 +2977,8 @@ msgstr "Fout!" msgid "Error:" msgstr "Fout:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "Fouten" @@ -2974,7 +3008,7 @@ msgstr "Samenvatting van de gebeurtenis niet beschikbaar" msgid "Events" msgstr "Gebeurtenissen" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "Verwerking van gebeurtenissen voltooid." @@ -2982,10 +3016,14 @@ msgstr "Verwerking van gebeurtenissen voltooid." msgid "Exact match (default lookup if not specified)." msgstr "Exacte overeenkomst (standaard-opzoeken indien niet opgegeven)." -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "Exact zoeken op id-veld." +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "Voorbeeld-URL's voor GIT-broncontrole zijn:" @@ -3006,7 +3044,7 @@ msgstr "Voorbeelden hiervan zijn:" msgid "Examples:" msgstr "Voorbeelden:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "Uitzonderingsfrequentie" @@ -3026,8 +3064,8 @@ msgstr "Uitvoeren wanneer het bovenliggende knooppunt in een storingstoestand ko msgid "Execute when the parent node results in a successful state." msgstr "Uitvoeren wanneer het bovenliggende knooppunt in een succesvolle status resulteert." -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "Uitvoering" @@ -3041,8 +3079,8 @@ msgstr "Uitvoering" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "Uitvoeringsomgeving" @@ -3157,7 +3195,7 @@ msgid "Extra variables" msgstr "Extra variabelen" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3165,13 +3203,14 @@ msgid "FINISHED:" msgstr "VOLTOOID:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "Feitenopslag" #: screens/Template/shared/JobTemplate.helptext.js:39 msgid "Fact storage: If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime.." -msgstr "Indien ingeschakeld, worden de verzamelde feiten opgeslagen zodat ze kunnen worden weergegeven op hostniveau. Feiten worden bewaard en\n" +msgstr "" +"Indien ingeschakeld, worden de verzamelde feiten opgeslagen zodat ze kunnen worden weergegeven op hostniveau. Feiten worden bewaard en\n" "geïnjecteerd in de feitencache tijdens runtime." #: screens/Host/Host.js:63 @@ -3186,23 +3225,23 @@ msgstr "Feiten" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "Mislukt" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "Aantal mislukte hosts" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "Mislukte hosts" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "Mislukte hosts" @@ -3210,6 +3249,10 @@ msgstr "Mislukte hosts" msgid "Failed jobs" msgstr "Mislukte taken" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "Niet goedgekeurd {0}." @@ -3224,7 +3267,7 @@ msgid "Failed to associate role" msgstr "Kan rol niet koppelen" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3232,7 +3275,7 @@ msgstr "Kan rol niet koppelen" msgid "Failed to associate." msgstr "Kan niet koppelen." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "Kan de synchronisatie van de inventarisbron niet annuleren" @@ -3248,7 +3291,7 @@ msgstr "Kan een of meer taken niet annuleren." #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "Kan {0} niet annuleren" @@ -3291,15 +3334,15 @@ msgstr "Kan groep {0} niet verwijderen." msgid "Failed to delete host." msgstr "Kan host niet verwijderen." -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "Kan inventarisbron {name} niet verwijderen." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "Kan inventaris niet verwijderen." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "Kan taaksjabloon niet verwijderen." @@ -3328,7 +3371,7 @@ msgid "Failed to delete one or more groups." msgstr "Een of meer groepen kunnen niet worden verwijderd." #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "Een of meer hosts kunnen niet worden verwijderd." @@ -3344,7 +3387,7 @@ msgstr "Een of meer inventarissen kunnen niet worden verwijderd." msgid "Failed to delete one or more inventory sources." msgstr "Een of meer inventarisbronnen kunnen niet worden verwijderd." -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "Een of meer taaksjablonen kunnen niet worden verwijderd." @@ -3388,11 +3431,11 @@ msgstr "Een of meer gebruikerstokens kunnen niet worden verwijderd." msgid "Failed to delete one or more users." msgstr "Een of meer gebruikers kunnen niet worden verwijderd." -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "Een of meer workflowgoedkeuringen kunnen niet worden verwijderd." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "Kan organisatie niet verwijderen." @@ -3409,11 +3452,11 @@ msgstr "Kan rol niet verwijderen" msgid "Failed to delete role." msgstr "Kan rol niet verwijderen." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "Kan schema niet verwijderen." -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "Kan Smart-inventaris niet verwijderen." @@ -3438,6 +3481,10 @@ msgstr "Kan workflow-taaksjabloon niet verwijderen." msgid "Failed to delete {name}." msgstr "Kan {name} niet verwijderen." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "Kan {0} niet verwijderen." @@ -3452,9 +3499,9 @@ msgstr "Een of meer groepen kunnen niet worden losgekoppeld." msgid "Failed to disassociate one or more hosts." msgstr "Een of meer hosts kunnen niet worden losgekoppeld." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "Een of meer instanties kunnen niet worden losgekoppeld." @@ -3470,18 +3517,22 @@ msgstr "Kan de aangepaste configuratie-instellingen voor inloggen niet ophalen. msgid "Failed to fetch the updated project data." msgstr "Kan de bijgewerkte projectgegevens niet ophalen." -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "Kon dashboard niet weergeven:" #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "Kan de taak niet starten." -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "Een of meer instanties kunnen niet worden losgekoppeld." @@ -3493,8 +3544,8 @@ msgstr "Kan de configuratie niet ophalen." msgid "Failed to retrieve full node resource object." msgstr "Kan geen volledig bronobject van knooppunt ophalen." -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "Kan geen gezondheidscontrole uitvoeren op een of meer instanties." @@ -3530,10 +3581,10 @@ msgstr "Kan niet van bericht wisselen." msgid "Failed to toggle schedule." msgstr "Kan niet van schema wisselen." -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "Kan de capaciteitsaanpassing niet bijwerken." @@ -3581,7 +3632,7 @@ msgstr "Veld bevat waarde." msgid "Field ends with value." msgstr "Veld eindigt op waarde." -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "Veld voor het opgeven van een aangepaste Kubernetes of OpenShift Pod-specificatie." @@ -3614,11 +3665,11 @@ msgstr "Bestand, map of script" msgid "Filter By {name}" msgstr "Filteren op {name}" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "Filteren op mislukte opdrachten" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "Recente succesvolle taken" @@ -3647,7 +3698,7 @@ msgstr "Eerste" msgid "First Name" msgstr "Voornaam" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "Eerste uitvoering" @@ -3690,11 +3741,11 @@ msgstr "Bekijk voor meer informatie de" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3704,12 +3755,12 @@ msgstr "Vorken" msgid "Fourth" msgstr "Vierde" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "Frequentie-informatie" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "Frequentie Uitzondering Details" @@ -3731,7 +3782,7 @@ msgstr "Vrij" msgid "Friday" msgstr "Vrijdag" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "Fuzzy search op id, naam of beschrijvingsvelden." @@ -3743,7 +3794,7 @@ msgstr "Fuzzy search op naamveld." msgid "GPG Public Key" msgstr "GPG openbare sleutel" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Galaxy-toegangsgegevens" @@ -3781,7 +3832,7 @@ msgstr "Abonnementen ophalen" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3820,7 +3871,7 @@ msgstr "GitHub-team" msgid "GitHub settings" msgstr "GitHub-instellingen" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3924,6 +3975,19 @@ msgstr "HTTP-methode" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "Gezondheidscontrole verzoek(en) ingediend. Wacht even en laad de pagina opnieuw." +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "Gezond" @@ -3946,7 +4010,7 @@ msgstr "Omschrijving verbergen" msgid "Hipchat" msgstr "Hipchat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "Hop" @@ -3954,8 +4018,9 @@ msgstr "Hop" msgid "Hop node" msgstr "Hop-knooppunt" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3970,16 +4035,16 @@ msgid "Host Async OK" msgstr "Host Async OK" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "Configuratiesleutel host" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "Aantal hosts" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "Hostdetails" @@ -3991,13 +4056,14 @@ msgstr "Host is mislukt" msgid "Host Failure" msgstr "Hostmislukking" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "Hostfilter" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "Hostnaam" @@ -4030,7 +4096,7 @@ msgstr "Host onbereikbaar" msgid "Host details" msgstr "Hostdetails" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "Modus hostdetails" @@ -4045,7 +4111,7 @@ msgstr "Statusinformatie van de host is niet beschikbaar voor deze taak." #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4057,10 +4123,10 @@ msgstr "Statusinformatie van de host is niet beschikbaar voor deze taak." #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "Hosts" @@ -4082,15 +4148,15 @@ msgstr "Geïmporteerde hosts" msgid "Hosts remaining" msgstr "Resterende hosts" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "Uur" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "Hybride" @@ -4209,23 +4275,26 @@ msgstr "Indien deze mogelijkheid ingeschakeld is, zijn gelijktijdige uitvoeringe msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "Indien deze mogelijkheid ingeschakeld is, zijn gelijktijdige uitvoeringen van deze workflow-taaksjabloon toegestaan." -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "Indien ingeschakeld, voorkomt de inventaris dat organisatie-instantiegroepen worden toegevoegd aan de lijst van voorkeursinstantiegroepen om geassocieerde taaksjablonen op uit te voeren.\n" +msgstr "" +"Indien ingeschakeld, voorkomt de inventaris dat organisatie-instantiegroepen worden toegevoegd aan de lijst van voorkeursinstantiegroepen om geassocieerde taaksjablonen op uit te voeren.\n" "Opmerking: Als deze instelling is ingeschakeld en u een lege lijst hebt opgegeven, worden de globale instantiegroepen toegepast." #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "Indien ingeschakeld, zal de taaksjabloon voorkomen dat inventaris- of organisatie-instantiegroepen worden toegevoegd aan de lijst met voorkeursinstantiegroepen om op te draaien.\n" +msgstr "" +"Indien ingeschakeld, zal de taaksjabloon voorkomen dat inventaris- of organisatie-instantiegroepen worden toegevoegd aan de lijst met voorkeursinstantiegroepen om op te draaien.\n" "Opmerking: Als deze instelling is ingeschakeld en u een lege lijst hebt opgegeven, worden de globale instantiegroepen toegepast." #: screens/Template/shared/JobTemplate.helptext.js:35 msgid "If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime." -msgstr "Indien ingeschakeld, worden de verzamelde feiten opgeslagen zodat ze kunnen worden weergegeven op hostniveau. Feiten worden bewaard en\n" +msgstr "" +"Indien ingeschakeld, worden de verzamelde feiten opgeslagen zodat ze kunnen worden weergegeven op hostniveau. Feiten worden bewaard en\n" "geïnjecteerd in de feitencache tijdens runtime." #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:275 @@ -4251,7 +4320,8 @@ msgstr "Als u alleen de toegang voor deze specifieke gebruiker wilt verwijderen, msgid "" "If you want the Inventory Source to update on\n" "launch and on project update, click on Update on launch, and also go to" -msgstr "Als u wilt dat de inventarisbron wordt bijgewerkt bij\n" +msgstr "" +"Als u wilt dat de inventarisbron wordt bijgewerkt bij\n" "het opstarten en bij projectupdates, klik op Update bij opstarten, en ga ook naar" #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:80 @@ -4278,7 +4348,8 @@ msgid "" "Indicates if a host is available and should be included in running\n" "jobs. For hosts that are part of an external inventory, this may be\n" "reset by the inventory sync process." -msgstr "Geeft aan of een host beschikbaar is en opgenomen moet worden in lopende taken. Voor hosts die deel uitmaken van een externe inventaris, kan dit worden\n" +msgstr "" +"Geeft aan of een host beschikbaar is en opgenomen moet worden in lopende taken. Voor hosts die deel uitmaken van een externe inventaris, kan dit worden\n" "gereset worden door het inventarissynchronisatieproces." #: components/AppContainer/PageHeaderToolbar.js:103 @@ -4321,7 +4392,8 @@ msgstr "Toegangsgegevens voor Insights" msgid "Insights system ID" msgstr "Systeem-ID Insights" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "Bundel installeren" @@ -4342,25 +4414,26 @@ msgstr "Instantiefilters" msgid "Instance Group" msgstr "Instantiegroep" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "Instantiegroepen" @@ -4390,8 +4463,8 @@ msgstr "Instantiegroep" msgid "Instance group not found." msgstr "Kan instantiegroep niet vinden." -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "Gebruikte capaciteit instantiegroep" @@ -4414,9 +4487,9 @@ msgstr "instantietype" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4449,7 +4522,7 @@ msgstr "Ongeldige gebruikersnaam of wachtwoord. Probeer het opnieuw." #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4473,18 +4546,18 @@ msgstr "Inventarissen met bronnen kunnen niet gekopieerd worden" #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4493,8 +4566,8 @@ msgstr "Inventarissen met bronnen kunnen niet gekopieerd worden" #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4521,7 +4594,7 @@ msgstr "Inventarisbron" msgid "Inventory Source Sync" msgstr "Synchronisatie inventarisbronnen" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "Fout tijdens synchronisatie inventarisbronnen" @@ -4553,8 +4626,8 @@ msgstr "Inventarisupdate" msgid "Inventory copied successfully" msgstr "Inventaris gekopieerd" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "Inventarisbestand" @@ -4566,7 +4639,7 @@ msgstr "Inventaris niet gevonden." msgid "Inventory sync" msgstr "Inventarissynchronisatie" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "Fout tijdens inventarissynchronisatie" @@ -4600,18 +4673,18 @@ msgid "Items per page" msgstr "Items per pagina" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "TAAK-ID:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "JSON-tabblad" @@ -4626,16 +4699,16 @@ msgstr "Januari" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "Fout bij annuleren taak" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "Fout bij verwijderen taak" @@ -4658,10 +4731,10 @@ msgid "Job Slice Parent" msgstr "Ouder taken verdelen" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "Taken verdelen" @@ -4672,11 +4745,11 @@ msgstr "Taakstatus" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4697,7 +4770,7 @@ msgstr "Taaksjabloon" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "De standaardreferenties van de taaksjabloon moeten worden vervangen door een van hetzelfde type. Selecteer een toegangsgegeven voor de volgende typen om verder te gaan: {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4720,26 +4793,26 @@ msgstr "Taaksjablonen met toegangsgegevens die om een wachtwoord vragen, kunnen #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "Soort taak" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "Taakstatus" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "Grafiektabblad Taakstatus" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "Taaksjablonen" @@ -4853,7 +4926,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "Label" @@ -4864,15 +4937,15 @@ msgstr "Labelnaam" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4884,18 +4957,19 @@ msgstr "Labels" msgid "Last" msgstr "Laatste" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "Laatste gezondheidscontrole" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "Laatste taakstatus" @@ -4904,8 +4978,8 @@ msgstr "Laatste taakstatus" msgid "Last Login" msgstr "Laatste login" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4914,17 +4988,17 @@ msgstr "Laatste login" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4947,7 +5021,7 @@ msgstr "Achternaam" msgid "Last Ran" msgstr "Laatst uitgevoerd" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "Laatste uitvoering" @@ -4955,8 +5029,8 @@ msgstr "Laatste uitvoering" msgid "Last job" msgstr "Laatste taak" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -4980,8 +5054,8 @@ msgstr "Laatst gebruikt" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5048,12 +5122,12 @@ msgstr "Minder dan of gelijk aan vergelijking." #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5081,7 +5155,7 @@ msgstr "Laden" msgid "Local" msgstr "Lokaal" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "Lokale tijdzone" @@ -5124,7 +5198,7 @@ msgstr "Type opzoeken" msgid "Lookup typeahead" msgstr "Typeahead opzoeken" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5179,14 +5253,15 @@ msgstr "Beheertaak niet gevonden." msgid "Management jobs" msgstr "Beheertaken" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5206,11 +5281,25 @@ msgstr "Maart" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "Max. hosts" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "Maximum" @@ -5219,6 +5308,24 @@ msgstr "Maximum" msgid "Maximum length" msgstr "Maximumlengte" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5267,7 +5374,7 @@ msgid "" "assigned to this group when new instances come online." msgstr "Minimumpercentage van alle instanties die automatisch toegewezen worden aan deze groep wanneer nieuwe instanties online komen." -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5309,16 +5416,16 @@ msgstr "Gewijzigd" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5356,7 +5463,7 @@ msgid "Modified by (username)" msgstr "Gewijzigd door (gebruikersnaam)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "Module" @@ -5379,7 +5486,7 @@ msgstr "Ma" msgid "Monday" msgstr "Maandag" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5428,8 +5535,8 @@ msgstr "Meerkeuze-opties" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5452,8 +5559,8 @@ msgstr "Meerkeuze-opties" #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5463,11 +5570,11 @@ msgstr "Meerkeuze-opties" #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5523,27 +5630,27 @@ msgstr "Meerkeuze-opties" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5555,7 +5662,7 @@ msgstr "Meerkeuze-opties" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5565,7 +5672,7 @@ msgstr "Meerkeuze-opties" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5575,7 +5682,7 @@ msgstr "Meerkeuze-opties" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5585,7 +5692,7 @@ msgstr "Meerkeuze-opties" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5607,7 +5714,7 @@ msgstr "Meerkeuze-opties" #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5638,8 +5745,8 @@ msgstr "Meerkeuze-opties" #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "Naam" @@ -5682,7 +5789,7 @@ msgstr "Nieuw" msgid "Next" msgstr "Volgende" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5702,7 +5809,7 @@ msgstr "Geen overeenkomende hosts" msgid "No Hosts Remaining" msgstr "Geen resterende hosts" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "Geen JSON beschikbaar" @@ -5726,7 +5833,7 @@ msgstr "Geen taakgegevens beschikbaar" msgid "No output found for this job." msgstr "Geen output gevonden voor deze taak." -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "Geen resultaat gevonden" @@ -5745,10 +5852,10 @@ msgstr "Geen resultaat gevonden" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "Geen resultaten gevonden" @@ -5776,15 +5883,16 @@ msgstr "{pluralizedItemName} niet gevonden" msgid "Node Alias" msgstr "Knooppunt alias" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5809,8 +5917,8 @@ msgstr "Typen knooppunten" msgid "None" msgstr "Geen" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "Geen (eenmaal uitgevoerd)" @@ -5961,14 +6069,14 @@ msgstr "Oktober" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "Uit" @@ -5977,14 +6085,14 @@ msgstr "Uit" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "Aan" @@ -6057,7 +6165,7 @@ msgstr "Optioneel: selecteer de toegangsgegevens die u wilt gebruiken om statusu #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6093,11 +6201,11 @@ msgstr "Bestellen" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6107,8 +6215,8 @@ msgstr "Bestellen" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6152,12 +6260,12 @@ msgid "Out of compliance" msgstr "Niet compliant" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "Output" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "Output" @@ -6166,12 +6274,12 @@ msgid "Overwrite" msgstr "Overschrijven" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "Lokale groepen en hosts overschrijven op grond van externe inventarisbron" #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "Lokale variabelen overschrijven op grond van externe inventarisbron" @@ -6290,11 +6398,11 @@ msgstr "Persoonlijke toegangstoken" msgid "Personal access token" msgstr "Persoonlijke toegangstoken" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "Afspelen" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "Aantal afspelen" @@ -6304,7 +6412,7 @@ msgstr "Afspelen gestart" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6336,7 +6444,7 @@ msgstr "Draaiboek uitvoering" msgid "Playbook Started" msgstr "Draaiboek gestart" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6348,7 +6456,7 @@ msgstr "Naam van draaiboek" msgid "Playbook run" msgstr "Uitvoering van draaiboek" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "Uitvoeringen van het draaiboek" @@ -6372,7 +6480,7 @@ msgstr "Voeg {pluralizedItemName} toe om deze lijst te vullen" msgid "Please click the Start button to begin." msgstr "Klik op de startknop om te beginnen." -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "Voer een aantal voorvallen in." @@ -6392,7 +6500,7 @@ msgstr "Log in" msgid "Please run a job to populate this list." msgstr "Voer een taak uit om deze lijst te vullen." -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "Selecteer een getal tussen 1 en 31." @@ -6400,7 +6508,7 @@ msgstr "Selecteer een getal tussen 1 en 31." msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "Selecteer een inventaris of schakel de optie Melding bij opstarten in" -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "Kies een einddatum/-tijd die na de begindatum/-tijd komt." @@ -6416,14 +6524,15 @@ msgstr "Probeer een andere zoekopdracht met de bovenstaande filter" msgid "Please wait until the topology view is populated..." msgstr "Wacht totdat de topologie-weergave is ingevuld..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Overschrijven Podspec" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "Beleidstype" @@ -6450,7 +6559,8 @@ msgid "" "Refer to the documentation for further syntax and\n" "examples. Refer to the Ansible Controller documentation for further syntax and\n" "examples." -msgstr "Vul de hosts voor deze inventaris door gebruik te maken van een zoekfilter. Voorbeeld: ansible_facts.ansible_distribution: \"RedHat\".\n" +msgstr "" +"Vul de hosts voor deze inventaris door gebruik te maken van een zoekfilter. Voorbeeld: ansible_facts.ansible_distribution: \"RedHat\".\n" "Raadpleeg de documentatie voor verdere syntaxis en\n" "voorbeelden. Raadpleeg de documentatie van Ansible Tower voor verdere syntaxis en\n" "voorbeelden." @@ -6480,21 +6590,22 @@ msgid "" "and use the arrow keys to navigate up or down.\n" "Press enter to confirm the drag, or any other key to\n" "cancel the drag operation." -msgstr "Druk op spatie of enter om te beginnen met slepen,\n" +msgstr "" +"Druk op spatie of enter om te beginnen met slepen,\n" "en gebruik de pijltjestoetsen om omhoog of omlaag te navigeren.\n" "Druk op enter om het slepen te bevestigen, of op een andere toets om\n" "de sleepoperatie te annuleren." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "Instance Group Fallback voorkomen" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "Instance Group Fallback voorkomen: Indien ingeschakeld, zal de inventaris voorkomen dat instantiegroepen van organisaties worden toegevoegd aan de lijst van voorkeursinstantiegroepen om geassocieerde taaksjablonen op uit te voeren." @@ -6512,7 +6623,7 @@ msgid "Private key passphrase" msgstr "Privésleutel wachtwoordzin" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "Verhoging van rechten" @@ -6533,11 +6644,11 @@ msgstr "Als deze optie ingeschakeld is, wordt het draaiboek uitgevoerd als behee #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "Project" @@ -6578,14 +6689,14 @@ msgstr "Project gekopieerd" msgid "Project not found." msgstr "Feit niet gevonden." -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "Mislukte projectsynchronisaties" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6600,12 +6711,12 @@ msgstr "Projecten" msgid "Promote Child Groups and Hosts" msgstr "Onderliggende groepen en hosts promoveren" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "Melding" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "Meldingsoverschrijvingen" @@ -6619,8 +6730,8 @@ msgstr "Melding bij opstarten" msgid "Prompt | {0}" msgstr "Melding | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "Invoerwaarden" @@ -6665,7 +6776,7 @@ msgid "Provisioning" msgstr "Voorziening" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "Provisioning terugkoppelings-URL" @@ -6675,7 +6786,7 @@ msgid "Provisioning Callback details" msgstr "Provisioning terugkoppelingsdetails" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6683,7 +6794,8 @@ msgstr "Provisioning terugkoppelingen" #: screens/Template/shared/JobTemplate.helptext.js:41 msgid "Provisioning callbacks: Enables creation of a provisioning callback URL. Using the URL a host can contact Ansible AWX and request a configuration update using this job template." -msgstr "Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met \n" +msgstr "" +"Maakt het mogelijk een provisioning terugkoppelings-URL aan te maken. Met deze URL kan een host contact opnemen met \n" "en een verzoek voor een configuratie-update indienen met behulp van deze taaksjabloon." #: components/StatusLabel/StatusLabel.js:62 @@ -6707,10 +6819,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "RADIUS-instellingen" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6724,23 +6837,23 @@ msgstr "Lezen" msgid "Ready" msgstr "Klaar" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "Recente taken" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "Tabblad Lijst met recente takenlijst" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "Recente sjablonen" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "Tabblad Lijst met recente sjablonen" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6831,12 +6944,15 @@ msgstr "Regio's" msgid "Registry credential" msgstr "Toegangsgegevens registreren" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "Reguliere expressie waarbij alleen overeenkomende hostnamen worden geïmporteerd. Het filter wordt toegepast als een nabewerkingsstap nadat eventuele filters voor inventarisplugins zijn toegepast." #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "Gerelateerde groepen" @@ -6863,12 +6979,12 @@ msgstr "Verwante zoekopdracht typeahead" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "Opnieuw starten" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "Taak opnieuw starten" @@ -6886,7 +7002,7 @@ msgid "Relaunch on" msgstr "Opnieuw starten bij" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "Opnieuw opstarten met hostparameters" @@ -6894,7 +7010,7 @@ msgstr "Opnieuw opstarten met hostparameters" msgid "Reload" msgstr "Herladen" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "Download output" @@ -6907,8 +7023,8 @@ msgstr "Download output" msgid "Remote Archive" msgstr "Extern archief" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "Verwijderingsfout" @@ -6967,7 +7083,7 @@ msgstr "Als u deze link verwijdert, wordt de rest van de vertakking zwevend en w msgid "Reorder" msgstr "Nabestellen" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "Frequentie herhalen" @@ -7037,8 +7153,8 @@ msgstr "Haal de ingeschakelde status op uit het gegeven dictaat van de hostvaria #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "Teruggeven" @@ -7143,8 +7259,9 @@ msgstr "Uitvoeren" msgid "Run Command" msgstr "Opdracht uitvoeren" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "Een gezondheidscontrole op de instantie uitvoeren" @@ -7161,10 +7278,11 @@ msgstr "Opdracht uitvoeren" msgid "Run every" msgstr "Uitvoeren om de" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "Gezondheidscontrole" @@ -7191,17 +7309,26 @@ msgstr "In uitvoering" msgid "Running Handlers" msgstr "Handlers die worden uitgevoerd" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "Taken in uitvoering" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "Laatste gezondheidscontrole" @@ -7240,7 +7367,7 @@ msgid "START" msgstr "BEGINNEN" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7263,8 +7390,8 @@ msgstr "Zaterdag" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7318,7 +7445,7 @@ msgstr "Schema is actief" msgid "Schedule is inactive" msgstr "Schema is actief" -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "Er ontbreekt een regel in het schema" @@ -7440,7 +7567,7 @@ msgstr "Hosts selecteren" msgid "Select Input" msgstr "Input selecteren" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "Instanties selecteren" @@ -7510,11 +7637,19 @@ msgstr "Selecteer een project voordat u de uitvoeringsomgeving bewerkt." msgid "Select a question to delete" msgstr "Selecteer een vraag om te verwijderen" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "Rij selecteren om deze te verwijderen" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "Rij selecteren om deze te ontkoppelen" @@ -7542,8 +7677,8 @@ msgstr "Abonnement selecteren" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7585,7 +7720,7 @@ msgstr "Selecteer een instantie" msgid "Select an instance and a metric to show chart" msgstr "Instantie en metriek selecteren om grafiek te tonen" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "Selecteer een instantie om een gezondheidscontrole uit te voeren." @@ -7641,9 +7776,9 @@ msgstr "Periode selecteren" msgid "Select roles to apply" msgstr "Rollen selecteren om toe te passen" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "Bronpad selecteren" @@ -7733,8 +7868,8 @@ msgstr "Selecteer {0}" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7757,8 +7892,8 @@ msgstr "Geselecteerd" msgid "Selected Category" msgstr "Geselecteerde categorie" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "Het geselecteerde datumbereik moet ten minste 1 geplande gebeurtenis hebben." @@ -7792,7 +7927,7 @@ msgstr "Stel in hoeveel dagen aan gegevens er moet worden bewaard." msgid "Set preferences for data collection, logos, and logins" msgstr "Stel voorkeuren in voor gegevensverzameling, logo's en aanmeldingen" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "Stel bronpad in op" @@ -7858,10 +7993,10 @@ msgid "Show" msgstr "Tonen" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "Wijzigingen tonen" @@ -7935,11 +8070,11 @@ msgstr "Eenvoudige sleutel selecteren" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -8013,8 +8148,8 @@ msgstr "Sorteren" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8022,20 +8157,22 @@ msgid "Source" msgstr "Bron" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "Vertakking broncontrole" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "Vertakking/tag/binding broncontrole" @@ -8098,7 +8235,7 @@ msgstr "Taak bronworkflow" msgid "Source control branch" msgstr "Vertakking broncontrole" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "Broninformatie" @@ -8106,7 +8243,7 @@ msgstr "Broninformatie" msgid "Source phone number" msgstr "Brontelefoonnummer" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "Bronvariabelen" @@ -8136,11 +8273,11 @@ msgstr "Kies een berichtkleur. Mogelijke kleuren zijn kleuren uit de hexidecimal msgid "Specify the conditions under which this node should be executed" msgstr "Specificeer de voorwaarden waaronder dit knooppunt moet worden uitgevoerd" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "Standaardfout" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "Tabblad Standaardfout" @@ -8187,27 +8324,28 @@ msgid "Start time" msgstr "Starttijd" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "Gestart" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8215,7 +8353,7 @@ msgstr "Gestart" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "Status" @@ -8238,7 +8376,8 @@ msgid "" "the revision specified by the main project.\n" "This is equivalent to specifying the --remote\n" "flag to git submodule update." -msgstr "Submodules volgen de laatste binding op\n" +msgstr "" +"Submodules volgen de laatste binding op\n" "hun hoofdvertakking (of een andere vertakking die is gespecificeerd in\n" ".gitmodules). Als dat niet zo is, dan worden de submodules bewaard tijdens de revisie die door het hoofdproject gespecificeerd is.\n" "Dit is gelijk aan het specificeren van de vlag --remote bij de update van de git-submodule." @@ -8306,7 +8445,7 @@ msgstr "Body succesbericht" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "Geslaagd" @@ -8442,8 +8581,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "TACACS+ instellingen" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "Tabbladen" @@ -8470,11 +8609,11 @@ msgstr "Tags voor de melding (optioneel)" msgid "Target URL" msgstr "Doel-URL" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "Taak" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "Aantal taken" @@ -8482,7 +8621,7 @@ msgstr "Aantal taken" msgid "Task Started" msgstr "Taak gestart" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "Taken" @@ -8524,7 +8663,7 @@ msgstr "Teams" msgid "Template" msgstr "Sjabloon" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "Sjabloon gekopieerd" @@ -8594,11 +8733,12 @@ msgstr "De" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "Het type toekenning dat de gebruiker moet gebruiken om tokens te verkrijgen voor deze toepassing" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "Selecteer de instantiegroepen waar de organisatie op uitgevoerd wordt." -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "De Instance Groups waartoe deze instantie behoort." @@ -8629,7 +8769,7 @@ msgstr "De basis-URL van de Grafana-server - het /api/annotations-eindpunt wordt msgid "The container image to be used for execution." msgstr "De containerimage die gebruikt moet worden voor de uitvoering." -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8648,7 +8788,8 @@ msgstr "De uitvoeringsomgeving die zal worden gebruikt voor taken die dit projec #: screens/Job/Job.helptext.js:9 #: screens/Template/shared/JobTemplate.helptext.js:10 msgid "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." -msgstr "De uitvoeringsomgeving die zal worden gebruikt bij het starten van\n" +msgstr "" +"De uitvoeringsomgeving die zal worden gebruikt bij het starten van\n" "dit taaksjabloon. De geselecteerde uitvoeringsomgeving kan worden opgeheven door\n" "door expliciet een andere omgeving aan dit taaksjabloon toe te wijzen." @@ -8663,7 +8804,7 @@ msgstr "De eerste haalt alle referenties op. De tweede haalt het Github pullverz msgid "The full image location, including the container registry, image name, and version tag." msgstr "De volledige imagelocatie, inclusief het containerregister, de imagenaam en de versietag." -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8682,7 +8823,7 @@ msgstr "De laatste {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "De laatste {weekday} van {month}" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8769,7 +8910,8 @@ msgid "" "sure the playbook files can be read by the \"awx\" system user,\n" "or have {brandName} directly retrieve your playbooks from\n" "source control using the Source Control Type option above." -msgstr "Er zijn geen draaiboekmappen in {project_base_dir} beschikbaar.\n" +msgstr "" +"Er zijn geen draaiboekmappen in {project_base_dir} beschikbaar.\n" "Die map leeg of alle inhoud ervan is al\n" "toegewezen aan andere projecten. Maak daar een nieuwe directory en zorg ervoor dat de draaiboekbestanden kunnen worden gelezen door de 'awx'-systeemgebruiker,\n" "of laat {brandName} uw draaiboeken direct ophalen uit broncontrole met behulp van de optie Type broncontrole hierboven." @@ -8845,7 +8987,7 @@ msgstr "Deze actie ontkoppelt het volgende:" msgid "This action will remove the following instances:" msgstr "Deze actie zal de volgende instanties verwijderen:" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 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?" @@ -8862,7 +9004,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Software and to provide\n" "Automation Analytics." -msgstr "Deze gegevens worden gebruikt om\n" +msgstr "" +"Deze gegevens worden gebruikt om\n" "toekomstige versies van de Software te verbeteren en om\n" "Automatiseringsanalyse te bieden." @@ -8882,7 +9025,7 @@ msgstr "Deze uitvoeringsomgeving wordt momenteel gebruikt door andere bronnen. W msgid "This feature is deprecated and will be removed in a future release." msgstr "Deze functie is afgeschaft en zal worden verwijderd in een toekomstige versie." -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "Dit veld wordt genegeerd, tenzij er een Ingeschakelde variabele is ingesteld. Als de ingeschakelde variabele overeenkomt met deze waarde, wordt de host bij het importeren ingeschakeld." @@ -8968,7 +9111,7 @@ msgstr "Dit veld wordt met behulp van de opgegeven referentie opgehaald uit een msgid "This has already been acted on" msgstr "Hieraan is reeds gevolg gegeven" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "Deze instantiegroep wordt momenteel door andere bronnen gebruikt. Weet u zeker dat u hem wilt verwijderen?" @@ -8976,11 +9119,11 @@ msgstr "Deze instantiegroep wordt momenteel door andere bronnen gebruikt. Weet u msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "Deze inventaris wordt toegepast op alle workflowknooppunten binnen deze workflow ({0}) die vragen naar een inventaris." -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "Deze inventaris wordt momenteel door andere bronnen gebruikt. Weet u zeker dat u hem wilt verwijderen?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "Deze inventarisbron wordt momenteel door andere bronnen gebruikt die erop vertrouwen. Weet u zeker dat u hem wilt verwijderen?" @@ -8996,11 +9139,11 @@ msgstr "Dit is de enige keer dat de tokenwaarde en de bijbehorende ververste tok msgid "This job failed and has no output." msgstr "Deze opdracht is mislukt en heeft geen uitvoer." -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "Deze taaksjabloon wordt momenteel door andere bronnen gebruikt. Weet u zeker dat u hem wilt verwijderen?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "Deze organisatie wordt momenteel door andere bronnen gebruikt. Weet u zeker dat u haar wilt verwijderen?" @@ -9012,7 +9155,7 @@ msgstr "Dit project wordt momenteel gebruikt door andere bronnen. Weet u zeker d msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "Dit project wordt momenteel gesynchroniseerd en er kan pas op worden geklikt nadat het synchronisatieproces is voltooid" -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "Dit schema heeft geen voorvallen vanwege de geselecteerde uitzonderingen." @@ -9028,7 +9171,8 @@ msgstr "In dit schema ontbreken de vereiste vragenlijstwaarden" msgid "" "This schedule uses complex rules that are not supported in the\n" "UI. Please use the API to manage this schedule." -msgstr "Dit schema gebruikt complexe regels die niet worden ondersteund in de\n" +msgstr "" +"Dit schema gebruikt complexe regels die niet worden ondersteund in de\n" "UI. Gebruik de API om deze agenda te beheren." #: components/LaunchPrompt/steps/StepName.js:26 @@ -9108,13 +9252,13 @@ msgid "Timed out" msgstr "Er is een time-out opgetreden" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9217,15 +9361,16 @@ msgid "Tools" msgstr "Gereedschap" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "Topologie-weergave" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "Totale taken" @@ -9235,7 +9380,7 @@ msgstr "Totale taken" msgid "Total Nodes" msgstr "Totaalaantal knooppunten" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "Totaal gastheren" @@ -9291,8 +9436,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9305,11 +9450,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9357,13 +9502,14 @@ msgstr "Kan inventaris op een host niet wijzigen" msgid "Unable to load last job update" msgstr "Kan laatste taakupdate niet laden" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "Niet beschikbaar" @@ -9383,15 +9529,15 @@ msgstr "Onbeperkt" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "Onbereikbaar" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "Aantal onbereikbare hosts" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "Hosts onbereikbaar" @@ -9408,7 +9554,7 @@ msgid "Update Revision on Launch" msgstr "Herziening updaten bij opstarten" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "Update bij opstarten" @@ -9478,25 +9624,29 @@ msgstr "Voer één e-mailadres per regel in om een lijst met ontvangers te maken msgid "" "Use one phone number per line to specify where to\n" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" -msgstr "Voer één telefoonnummer per regel in om aan te geven waar\n" +msgstr "" +"Voer één telefoonnummer per regel in om aan te geven waar\n" "sms-berichten te routeren. Telefoonnummers moeten worden ingedeeld als +11231231234. Voor meer informatie zie Twilio-documentatie" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "Gebruikte capaciteit" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "Gebruikte capaciteit" @@ -9596,22 +9746,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9627,7 +9777,7 @@ msgstr "Variabelen gevraagd" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "Voer variabelen in met JSON- of YAML-syntaxis. Gebruik de radioknop om tussen de twee te wisselen." -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} 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 in de documentatie en de plug-inconfiguratiegids voor <1>{sourceType}." @@ -9644,16 +9794,16 @@ msgid "Verbose" msgstr "Uitgebreid" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "Verbositeit" @@ -9661,8 +9811,8 @@ msgstr "Verbositeit" msgid "View Azure AD settings" msgstr "Azure AD-instellingen weergeven" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "Details toegangsgegevens weergeven" @@ -9686,7 +9836,7 @@ msgstr "Hostdetails weergeven" msgid "View Instance Details" msgstr "Instantiedetails weergeven" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9800,7 +9950,7 @@ msgstr "YAML-voorbeelden weergeven op <0>docs.ansible.com" msgid "View activity stream" msgstr "Activiteitenlogboek weergeven" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "Geef alle toegangsgegevens weer." @@ -9963,7 +10113,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Webhook toegangsgegevens" @@ -9974,7 +10124,7 @@ msgstr "Toegangsgegevens Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -9982,7 +10132,7 @@ msgstr "Webhooksleutel" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -9990,7 +10140,7 @@ msgstr "Webhookservice" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -10014,7 +10164,7 @@ msgstr "Webhookservices kunnen dit gebruiken als een gedeeld geheim." #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhooks" @@ -10038,7 +10188,7 @@ msgstr "Wo" msgid "Wednesday" msgstr "Woensdag" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10057,7 +10207,8 @@ msgstr "Weekenddag" msgid "" "Welcome to Red Hat Ansible Automation Platform!\n" "Please complete the steps below to activate your subscription." -msgstr "Welkom bij Red Hat Ansible Automation Platform! \n" +msgstr "" +"Welkom bij Red Hat Ansible Automation Platform! \n" "Volg de onderstaande stappen om uw abonnement te activeren." #: screens/Login/Login.js:190 @@ -10092,8 +10243,8 @@ msgstr "Workflowgoedkeuring niet gevonden." #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10104,11 +10255,11 @@ msgstr "Workflowgoedkeuringen" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "Workflowtaak" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "Workflowtaak 1/{0}" @@ -10136,11 +10287,11 @@ msgstr "Workflowtaaksjablonen" msgid "Workflow Link" msgstr "Workflowlink" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "Werkstroomknooppunten" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "Werkstroomstatussen" @@ -10218,7 +10369,7 @@ msgstr "Schrijven" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10229,6 +10380,14 @@ msgstr "Jaar" msgid "Yes" msgstr "Ja" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "U kunt niet meerdere kluisreferenties met delfde kluis-ID selecteren. Als u dat wel doet, worden de andere met delfde kluis-ID automatisch gedeselecteerd." @@ -10257,7 +10416,8 @@ msgstr "Je hebt tegen meer hosts geautomatiseerd dan je abonnement toelaat." msgid "" "You may apply a number of possible variables in the\n" "message. For more information, refer to the" -msgstr "U kunt een aantal mogelijke variabelen in het\n" +msgstr "" +"U kunt een aantal mogelijke variabelen in het\n" "bericht toepassen. Voor meer informatie, raadpleeg de" #: screens/Login/Login.js:198 @@ -10369,7 +10529,12 @@ msgstr "Meer informatie" msgid "disassociate" msgstr "loskoppelen" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10381,11 +10546,11 @@ msgstr "documentatie" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10397,7 +10562,12 @@ msgstr "bewerken" msgid "encrypted" msgstr "versleuteld" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "voor meer info." @@ -10481,7 +10651,7 @@ msgstr "taken opnieuw starten" msgid "sec" msgstr "sec" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "seconden" @@ -10550,7 +10720,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10590,7 +10760,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10635,10 +10805,11 @@ msgstr "{brandName} logo" msgid "{dateStr} by <0>{username}" msgstr "{dateStr} door<0>{username}" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10691,7 +10862,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} min {seconds} sec" @@ -10715,7 +10886,7 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} occurrence} other { msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} Lijst" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" diff --git a/awx/ui/src/locales/zh/messages.po b/awx/ui/src/locales/zh/messages.po index c368c70286..3d2bfda0f6 100644 --- a/awx/ui/src/locales/zh/messages.po +++ b/awx/ui/src/locales/zh/messages.po @@ -10,13 +10,14 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Plural-Forms: \n" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:43 msgid "(Limited to first 10)" msgstr "(限制为前 10)" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:161 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "(启动时提示)" @@ -25,7 +26,7 @@ msgstr "(启动时提示)" msgid "* This field will be retrieved from an external secret management system using the specified credential." msgstr "* 此字段将使用指定的凭证从外部 secret 管理系统检索。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:228 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "/ (project root)" @@ -65,6 +66,10 @@ msgstr "4(连接调试)" msgid "5 (WinRM Debug)" msgstr "5(WinRM 调试)" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -99,7 +104,7 @@ msgstr "关于" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -135,7 +140,7 @@ msgstr "操作" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 #: components/Schedule/ScheduleList/ScheduleList.js:172 #: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 @@ -157,18 +162,19 @@ msgstr "操作" #: screens/Host/HostList/HostListItem.js:70 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:271 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:206 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -192,7 +198,7 @@ msgstr "操作" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:167 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "操作" @@ -360,7 +366,7 @@ msgid "Alert modal" msgstr "警报模式" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -425,7 +431,7 @@ msgstr "回答类型" msgid "Answer variable name" msgstr "回答变量名称" -#: components/PromptDetail/PromptDetail.js:132 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "任何" @@ -475,6 +481,10 @@ msgstr "应用程序和令牌" msgid "Approval" msgstr "批准" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 @@ -542,7 +552,7 @@ msgstr "您确定要从 {1} 中删除访问 {0} 吗?这样做会影响团队 msgid "Are you sure you want to remove {0} access from {username}?" msgstr "您确定要从 {username} 中删除 {0} 吗?" -#: screens/Job/JobOutput/JobOutput.js:826 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "您确定要提交取消此任务的请求吗?" @@ -555,7 +565,7 @@ msgstr "参数" msgid "Artifacts" msgstr "工件" -#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "关联" @@ -591,10 +601,11 @@ msgstr "授权代码过期" msgid "Authorization grant type" msgstr "授权授予类型" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "Auto" @@ -631,7 +642,7 @@ msgstr "Azure AD 设置" msgid "Back" msgstr "返回" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "返回到凭证" @@ -654,7 +665,8 @@ msgstr "返回到主机" msgid "Back to Instance Groups" msgstr "返回到实例组" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:173 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 #: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "返回到实例" @@ -691,7 +703,7 @@ msgstr "返回到调度" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 @@ -770,6 +782,10 @@ msgstr "要签出的分支。除了分支外,您可以输入标签、提交散 msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." msgstr "要在任务运行中使用的分支。如果为空,则使用项目默认值。只有项目 allow_override 字段设置为 true 时才允许使用。" +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "品牌图像" @@ -787,10 +803,11 @@ msgstr "浏览..." msgid "By default, we collect and transmit analytics data on the service usage to Red Hat. There are two categories of data collected by the service. For more information, see <0>this Tower documentation page. Uncheck the following boxes to disable this feature." msgstr "默认情况下,我们会收集关于服务使用情况的分析数据并将其传送到红帽。服务收集的数据分为两类。如需更多信息,请参阅<0>此 Tower 文档页。取消选择以下复选框以禁用此功能。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:228 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:271 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 #: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "CPU {0}" @@ -802,7 +819,7 @@ msgstr "CPU {0}" msgid "Cache Timeout" msgstr "缓存超时" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:237 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "缓存超时" @@ -825,8 +842,8 @@ msgstr "缓存超时(秒)" #: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:548 -#: components/Schedule/shared/ScheduleForm.js:553 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 #: components/Schedule/shared/SchedulePromptableFields.js:126 #: components/Schedule/shared/UnsupportedScheduleForm.js:22 #: components/Schedule/shared/UnsupportedScheduleForm.js:27 @@ -863,14 +880,14 @@ msgstr "缓存超时(秒)" msgid "Cancel" msgstr "取消" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "取消清单源同步" #: components/JobCancelButton/JobCancelButton.js:69 -#: screens/Job/JobOutput/JobOutput.js:802 -#: screens/Job/JobOutput/JobOutput.js:803 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "取消作业" @@ -879,7 +896,7 @@ msgstr "取消作业" msgid "Cancel Project Sync" msgstr "取消项目同步" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:302 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 #: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "取消同步" @@ -891,8 +908,8 @@ msgstr "取消同步" msgid "Cancel Workflow" msgstr "取消工作流" -#: screens/Job/JobOutput/JobOutput.js:810 -#: screens/Job/JobOutput/JobOutput.js:813 +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "取消作业" @@ -931,7 +948,7 @@ msgstr "取消订阅编辑" #: components/JobList/JobListItem.js:113 #: screens/Job/JobDetail/JobDetail.js:600 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "取消 {0}" @@ -949,7 +966,6 @@ msgid "" "logging aggregator host and logging aggregator type." msgstr "在不提供日志记录聚合器主机和日志记录聚合器类型的情况下,无法启用日志聚合器。" -#: screens/Instances/InstanceList/InstanceList.js:199 #: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "无法在跃点节点上运行健康检查。" @@ -960,12 +976,13 @@ msgstr "无法在跃点节点上运行健康检查。" msgid "Capacity" msgstr "容量" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:225 -#: screens/InstanceGroup/Instances/InstanceList.js:269 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:267 -#: screens/Instances/InstanceList/InstanceList.js:204 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "容量调整" @@ -1051,7 +1068,7 @@ msgstr "选择作业类型" msgid "Choose a module" msgstr "选择模块" -#: screens/Inventory/shared/InventorySourceForm.js:139 +#: screens/Inventory/shared/InventorySourceForm.js:140 msgid "Choose a source" msgstr "选择一个源" @@ -1120,7 +1137,8 @@ msgstr "点击这个按钮使用所选凭证和指定的输入验证到 secret msgid "Click to create a new link to this node." msgstr "点击以创建到此节点的新链接。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 msgid "Click to download bundle" msgstr "点下载捆绑包" @@ -1195,7 +1213,7 @@ msgstr "合规" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:132 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 #: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" @@ -1272,7 +1290,7 @@ msgstr "确认选择" msgid "Container Group" msgstr "容器组" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1297,8 +1315,8 @@ msgstr "内容签名验证凭证" msgid "Continue" msgstr "继续" -#: screens/InstanceGroup/Instances/InstanceList.js:207 -#: screens/Instances/InstanceList/InstanceList.js:151 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "控制" @@ -1321,7 +1339,7 @@ msgstr "控制 ansible 在 playbook 执行时生成的输出级别。" msgid "Controller Node" msgstr "控制器节点" -#: components/PromptDetail/PromptDetail.js:130 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "趋同" @@ -1494,28 +1512,28 @@ msgid "Create user token" msgstr "创建用户令牌" #: components/Lookup/ApplicationLookup.js:115 -#: components/PromptDetail/PromptDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:406 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 #: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 #: screens/Host/HostDetail/HostDetail.js:86 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:173 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:277 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:149 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 #: screens/Job/JobDetail/JobDetail.js:534 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 #: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:353 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 #: screens/User/UserTokenDetail/UserTokenDetail.js:61 @@ -1528,16 +1546,16 @@ msgstr "创建" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 #: components/Lookup/CredentialLookup.js:194 #: components/Lookup/InventoryLookup.js:152 #: components/Lookup/InventoryLookup.js:207 -#: components/Lookup/MultiCredentialsLookup.js:194 +#: components/Lookup/MultiCredentialsLookup.js:198 #: components/Lookup/OrganizationLookup.js:134 #: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 #: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 @@ -1578,16 +1596,16 @@ msgstr "创建者(用户名)" #: components/AdHocCommands/useAdHocCredentialStep.js:24 #: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 #: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:84 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 @@ -1624,7 +1642,7 @@ msgstr "凭证类型" msgid "Credential copied successfully" msgstr "成功复制的凭证" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "未找到凭证。" @@ -1633,7 +1651,7 @@ msgstr "未找到凭证。" msgid "Credential passwords" msgstr "凭证密码" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "使用 Kubernetes 或 OpenShift 进行身份验证的凭证" @@ -1650,13 +1668,13 @@ msgid "Credential type not found." msgstr "未找到凭证类型。" #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:211 -#: components/PromptDetail/PromptDetail.js:192 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 #: components/PromptDetail/PromptJobTemplateDetail.js:191 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 #: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 @@ -1665,7 +1683,7 @@ msgstr "未找到凭证类型。" #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 #: screens/Job/JobDetail/JobDetail.js:429 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:374 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 #: screens/Template/shared/JobTemplateForm.js:372 #: util/getRelatedResourceDeleteDetails.js:91 @@ -1680,11 +1698,11 @@ msgstr "不允许在启动时需要密码的凭证。请删除或替换为同一 msgid "Current page" msgstr "当前页" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "自定义 Kubernetes 或 OpenShift Pod 的规格。" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "自定义 pod 规格" @@ -1706,8 +1724,8 @@ msgstr "自定义虚拟环境 {virtualEnvironment} 必须替换为执行环境 msgid "Customize messages…" msgstr "自定义消息…" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "自定义 Pod 规格" @@ -1717,7 +1735,7 @@ msgid "DELETED" msgstr "已删除" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "仪表盘" @@ -1733,7 +1751,7 @@ msgstr "数据保留的周期" msgid "Date" msgstr "日期" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:184 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 #: components/Schedule/shared/FrequencyDetailSubform.js:177 #: components/Schedule/shared/FrequencyDetailSubform.js:356 #: components/Schedule/shared/FrequencyDetailSubform.js:460 @@ -1746,7 +1764,7 @@ msgstr "天" msgid "Day {0}" msgstr "天 {0}" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:399 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 #: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "保留数据的天数" @@ -1810,17 +1828,17 @@ msgstr "定义系统级的特性和功能" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:646 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 #: screens/Application/ApplicationDetails/ApplicationDetails.js:128 #: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:201 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:174 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 @@ -1828,11 +1846,11 @@ msgstr "定义系统级的特性和功能" #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 #: screens/Job/JobDetail/JobDetail.js:612 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 #: screens/Project/ProjectDetail/ProjectDetail.js:340 #: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:545 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 @@ -1859,17 +1877,17 @@ msgstr "删除执行环境" msgid "Delete Host" msgstr "删除主机" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:196 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "删除清单" #: screens/Job/JobDetail/JobDetail.js:608 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "删除作业" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:539 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "删除作业模板" @@ -1877,7 +1895,7 @@ msgstr "删除作业模板" msgid "Delete Notification" msgstr "删除通知" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "删除机构" @@ -1889,7 +1907,7 @@ msgstr "删除项目" msgid "Delete Questions" msgstr "删除问题" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:642 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "删除调度" @@ -1934,16 +1952,16 @@ msgstr "删除凭证类型" msgid "Delete error" msgstr "删除错误" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "删除实例组" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:310 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "删除清单源" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "删除智能清单" @@ -2010,6 +2028,10 @@ msgstr "拒绝 - {0}。详情请查看活动流。" msgid "Denied by {0} - {1}" msgstr "已拒绝 {0} - {1}" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 @@ -2035,8 +2057,8 @@ msgstr "取消置备失败" #: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:119 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:327 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 #: components/Schedule/ScheduleList/ScheduleList.js:194 #: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 @@ -2058,28 +2080,28 @@ msgstr "取消置备失败" #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 #: screens/Instances/Shared/InstanceForm.js:26 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 #: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 -#: screens/Inventory/shared/InventorySourceForm.js:108 +#: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 #: screens/Project/ProjectDetail/ProjectDetail.js:177 @@ -2089,7 +2111,7 @@ msgstr "取消置备失败" #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:187 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 @@ -2106,7 +2128,7 @@ msgstr "取消置备失败" #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:128 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "描述" @@ -2136,10 +2158,11 @@ msgstr "目标频道或用户" #: components/AdHocCommands/useAdHocDetailsStep.js:35 #: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2148,7 +2171,7 @@ msgstr "目标频道或用户" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:180 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 #: screens/InstanceGroup/InstanceGroups.js:30 #: screens/InstanceGroup/InstanceGroups.js:38 @@ -2163,7 +2186,7 @@ msgstr "目标频道或用户" #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 #: screens/Job/Job.js:130 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2177,7 +2200,7 @@ msgstr "目标频道或用户" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 @@ -2225,7 +2248,7 @@ msgstr "目标频道或用户" msgid "Details" msgstr "详情" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "详情标签页" @@ -2273,8 +2296,8 @@ msgstr "从主机中解除关联组?" msgid "Disassociate host from group?" msgstr "从组中解除关联主机?" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:296 -#: screens/InstanceGroup/Instances/InstanceList.js:245 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "从实例组中解除关联实例?" @@ -2325,8 +2348,8 @@ msgstr "完成" msgid "Download Bundle" msgstr "下载捆绑包" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "下载输出" @@ -2372,28 +2395,28 @@ msgid "" "revision of the project prior to starting the job." msgstr "每次使用此项目运行作业时,请在启动该作业前更新项目的修订。" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:632 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:636 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 #: screens/Application/ApplicationDetails/ApplicationDetails.js:115 #: screens/Application/ApplicationDetails/ApplicationDetails.js:117 #: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 #: screens/Host/HostDetail/HostDetail.js:108 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:190 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:292 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:164 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 #: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 @@ -2409,8 +2432,8 @@ msgstr "每次使用此项目运行作业时,请在启动该作业前更新项 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 #: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 @@ -2424,8 +2447,8 @@ msgstr "每次使用此项目运行作业时,请在启动该作业前更新项 #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:514 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:516 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 @@ -2599,7 +2622,8 @@ msgstr "编辑详情" msgid "Edit group" msgstr "编辑组" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "编辑主机" @@ -2626,16 +2650,16 @@ msgid "Edit workflow" msgstr "编辑工作流" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "已经过" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "过期的时间" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "作业运行所经过的时间" @@ -2720,20 +2744,20 @@ msgstr "启用" #: components/PromptDetail/PromptProjectDetail.js:145 #: components/PromptDetail/PromptWFJobTemplateDetail.js:99 #: screens/Credential/CredentialDetail/CredentialDetail.js:268 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:138 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:265 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 #: screens/Project/ProjectDetail/ProjectDetail.js:302 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:365 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "启用的选项" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "启用的值" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "启用的变量" @@ -2797,11 +2821,15 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "使用 JSON 或 YAML 语法输入。示例语法请参阅 Ansible 控制器文档。" #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "使用 JSON 或 YAML 语法输入清单变量。使用单选按钮在两者之间切换。示例语法请参阅 Ansible 控制器文档。" +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "使用 JSON 或 YAML 语法输入清单变量。使用单选按钮在两者之间切换。示例语法请参阅 Ansible 控制器文档。" + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." +msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:87 msgid "Environment variables or extra variables that specify the values a credential type can inject." @@ -2814,8 +2842,8 @@ msgstr "用于指定凭证类型可注入值的环境变量或额外变量。" #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 #: screens/Job/JobOutput/JobOutputSearch.js:104 #: screens/TopologyView/Legend.js:178 @@ -2848,14 +2876,14 @@ msgstr "保存工作流时出错!" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:185 +#: components/LaunchButton/LaunchButton.js:196 #: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:654 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 #: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 #: components/Schedule/shared/SchedulePromptableFields.js:63 @@ -2870,29 +2898,30 @@ msgstr "保存工作流时出错!" #: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 -#: screens/InstanceGroup/Instances/InstanceList.js:308 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:360 -#: screens/Instances/InstanceDetail/InstanceDetail.js:375 -#: screens/Instances/InstanceList/InstanceList.js:231 -#: screens/Instances/InstanceList/InstanceList.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 #: screens/Instances/Shared/RemoveInstanceButton.js:104 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:210 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:323 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:183 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 #: screens/Login/Login.js:239 @@ -2900,7 +2929,7 @@ msgstr "保存工作流时出错!" #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 #: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 @@ -2910,14 +2939,14 @@ msgstr "保存工作流时出错!" #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:554 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 -#: screens/TopologyView/MeshGraph.js:405 +#: screens/TopologyView/MeshGraph.js:406 #: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 @@ -2927,7 +2956,8 @@ msgstr "保存工作流时出错!" #: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:189 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" @@ -2937,8 +2967,8 @@ msgstr "错误!" msgid "Error:" msgstr "错误:" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:267 -#: screens/Instances/InstanceDetail/InstanceDetail.js:315 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "错误" @@ -2968,7 +2998,7 @@ msgstr "事件摘要不可用" msgid "Events" msgstr "事件" -#: screens/Job/JobOutput/JobOutput.js:713 +#: screens/Job/JobOutput/JobOutput.js:725 msgid "Events processing complete." msgstr "事件处理完成。" @@ -2976,10 +3006,14 @@ msgstr "事件处理完成。" msgid "Exact match (default lookup if not specified)." msgstr "完全匹配(如果没有指定,则默认查找)。" -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "对 id 字段进行精确搜索。" +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "GIT 源控制的 URL 示例包括:" @@ -3000,7 +3034,7 @@ msgstr "示例包括::" msgid "Examples:" msgstr "示例:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:354 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 msgid "Exception Frequency" msgstr "例外频率" @@ -3020,8 +3054,8 @@ msgstr "当父节点出现故障状态时执行。" msgid "Execute when the parent node results in a successful state." msgstr "当父节点具有成功状态时执行。" -#: screens/InstanceGroup/Instances/InstanceList.js:208 -#: screens/Instances/InstanceList/InstanceList.js:152 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "执行" @@ -3035,8 +3069,8 @@ msgstr "执行" #: components/Lookup/ExecutionEnvironmentLookup.js:159 #: components/Lookup/ExecutionEnvironmentLookup.js:191 #: components/Lookup/ExecutionEnvironmentLookup.js:208 -#: components/PromptDetail/PromptDetail.js:220 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:451 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "执行环境" @@ -3151,7 +3185,7 @@ msgid "Extra variables" msgstr "额外变量" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:164 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3159,7 +3193,7 @@ msgid "FINISHED:" msgstr "完成:" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:137 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "事实存储" @@ -3179,23 +3213,23 @@ msgstr "事实" #: components/JobList/JobList.js:232 #: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:90 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "失败" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "失败的主机计数" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "失败的主机" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "失败的主机" @@ -3203,6 +3237,10 @@ msgstr "失败的主机" msgid "Failed jobs" msgstr "失败的作业" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 +msgid "Failed to approve one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 msgid "Failed to approve {0}." msgstr "批准 {0} 失败。" @@ -3217,7 +3255,7 @@ msgid "Failed to associate role" msgstr "关联角色失败" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:311 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3225,7 +3263,7 @@ msgstr "关联角色失败" msgid "Failed to associate." msgstr "关联失败。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:301 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "取消清单源同步失败" @@ -3241,7 +3279,7 @@ msgstr "取消一个或多个作业失败。" #: components/JobList/JobListItem.js:114 #: screens/Job/JobDetail/JobDetail.js:601 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "取消 {0} 失败" @@ -3284,15 +3322,15 @@ msgstr "删除组 {0} 失败。" msgid "Failed to delete host." msgstr "删除主机失败。" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:327 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "删除清单源 {name} 失败。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:213 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "删除清单失败。" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:557 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "删除作业模板失败。" @@ -3321,7 +3359,7 @@ msgid "Failed to delete one or more groups." msgstr "删除一个或多个组失败。" #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "删除一个或多个主机失败。" @@ -3337,7 +3375,7 @@ msgstr "删除一个或多个清单失败。" msgid "Failed to delete one or more inventory sources." msgstr "删除一个或多个清单源失败。" -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "删除一个或多个作业模板失败。" @@ -3381,11 +3419,11 @@ msgstr "删除一个或多个用户令牌失败。" msgid "Failed to delete one or more users." msgstr "删除一个或多个用户失败。" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:192 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "无法删除一个或多个工作流批准。" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "删除机构失败。" @@ -3402,11 +3440,11 @@ msgstr "删除角色失败" msgid "Failed to delete role." msgstr "删除角色失败。" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:657 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "删除调度失败。" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:186 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "删除智能清单失败。" @@ -3431,6 +3469,10 @@ msgstr "删除工作流任务模板失败。" msgid "Failed to delete {name}." msgstr "删除 {name} 失败。" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 +msgid "Failed to deny one or more workflow approval." +msgstr "" + #: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 msgid "Failed to deny {0}." msgstr "拒绝 {0} 失败。" @@ -3445,9 +3487,9 @@ msgstr "解除关联一个或多个组关联。" msgid "Failed to disassociate one or more hosts." msgstr "解除关联一个或多个主机失败。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:315 -#: screens/InstanceGroup/Instances/InstanceList.js:313 -#: screens/Instances/InstanceDetail/InstanceDetail.js:365 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "解除关联一个或多个实例失败。" @@ -3463,18 +3505,22 @@ msgstr "获取自定义登录配置设置失败。系统默认设置会被显示 msgid "Failed to fetch the updated project data." msgstr "获取更新的项目数据失败。" -#: screens/TopologyView/MeshGraph.js:409 +#: screens/TopologyView/MeshGraph.js:410 msgid "Failed to get instance." msgstr "获取实例失败。" #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:188 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "启动作业失败。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:378 -#: screens/Instances/InstanceList/InstanceList.js:246 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 msgid "Failed to remove one or more instances." msgstr "删除一个或多个实例失败。" @@ -3486,8 +3532,8 @@ msgstr "获取配置失败。" msgid "Failed to retrieve full node resource object." msgstr "获取完整节点资源对象失败。" -#: screens/InstanceGroup/Instances/InstanceList.js:315 -#: screens/Instances/InstanceList/InstanceList.js:234 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "在一个或多个实例上运行健康检查失败。" @@ -3523,10 +3569,10 @@ msgstr "切换通知失败。" msgid "Failed to toggle schedule." msgstr "切换调度失败。" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:314 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:364 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "更新容量调整失败。" @@ -3574,7 +3620,7 @@ msgstr "字段包含值。" msgid "Field ends with value." msgstr "字段以值结尾。" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "用于传递自定义 Kubernetes 或 OpenShift Pod 规格的字段。" @@ -3607,11 +3653,11 @@ msgstr "文件、目录或脚本" msgid "Filter By {name}" msgstr "按 {name} 过滤" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 msgid "Filter by failed jobs" msgstr "根据失败的作业过滤" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 msgid "Filter by successful jobs" msgstr "根据成功的作业过滤" @@ -3640,7 +3686,7 @@ msgstr "第一" msgid "First Name" msgstr "名" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:332 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "首次运行" @@ -3683,11 +3729,11 @@ msgstr "有关详情请参阅" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 #: components/LaunchPrompt/steps/OtherPromptsStep.js:55 -#: components/PromptDetail/PromptDetail.js:345 +#: components/PromptDetail/PromptDetail.js:332 #: components/PromptDetail/PromptJobTemplateDetail.js:150 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:475 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 #: screens/Job/JobDetail/JobDetail.js:389 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:259 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 #: screens/Template/shared/JobTemplateForm.js:409 #: screens/TopologyView/Tooltip.js:282 msgid "Forks" @@ -3697,12 +3743,12 @@ msgstr "Forks" msgid "Fourth" msgstr "第四" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:363 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 #: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "频率详情" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:381 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 msgid "Frequency Exception Details" msgstr "频率例外详情" @@ -3724,7 +3770,7 @@ msgstr "周五" msgid "Friday" msgstr "周五" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "模糊搜索 id、name 或 description 字段。" @@ -3736,7 +3782,7 @@ msgstr "模糊搜索名称字段。" msgid "GPG Public Key" msgstr "GPG 公钥" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "Galaxy 凭证" @@ -3774,7 +3820,7 @@ msgstr "获取订阅" msgid "Git" msgstr "Git" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "GitHub" @@ -3813,7 +3859,7 @@ msgstr "GitHub Team" msgid "GitHub settings" msgstr "GitHub 设置" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 #: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "GitLab" @@ -3917,6 +3963,19 @@ msgstr "HTTP 方法" msgid "Health check request(s) submitted. Please wait and reload the page." msgstr "提交健康检查请求。请等待并重新载入页面。" +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + #: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "健康" @@ -3939,7 +3998,7 @@ msgstr "隐藏描述" msgid "Hipchat" msgstr "HipChat" -#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "Hop(跃点)" @@ -3947,8 +4006,9 @@ msgstr "Hop(跃点)" msgid "Hop node" msgstr "Hop(跃点)节点" -#: screens/Instances/InstanceDetail/InstanceDetail.js:211 -#: screens/Job/JobOutput/HostEventModal.js:109 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" @@ -3963,16 +4023,16 @@ msgid "Host Async OK" msgstr "主机异步正常" #: components/PromptDetail/PromptJobTemplateDetail.js:159 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:297 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 #: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "主机配置键" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "主机计数" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "类型详情" @@ -3984,13 +4044,14 @@ msgstr "主机故障" msgid "Host Failure" msgstr "主机故障" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:242 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "主机过滤器" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/Instances/InstanceDetail/InstanceDetail.js:191 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 #: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "主机名" @@ -4023,7 +4084,7 @@ msgstr "主机无法访问" msgid "Host details" msgstr "主机详情" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "主机详情模式" @@ -4038,7 +4099,7 @@ msgstr "此作业的主机状态信息不可用。" #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4050,10 +4111,10 @@ msgstr "此作业的主机状态信息不可用。" #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 #: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "主机" @@ -4075,15 +4136,15 @@ msgstr "导入的主机" msgid "Hosts remaining" msgstr "剩余主机" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 #: components/Schedule/shared/FrequencyDetailSubform.js:175 #: components/Schedule/shared/ScheduleFormFields.js:126 #: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "小时" -#: screens/InstanceGroup/Instances/InstanceList.js:209 -#: screens/Instances/InstanceList/InstanceList.js:153 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "混合" @@ -4202,18 +4263,20 @@ msgstr "如果启用,将允许同时运行此任务模板。" msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "如果启用,将允许同时运行此工作流任务模板。" -#: screens/Inventory/shared/Inventory.helptext.js:194 +#: screens/Inventory/shared/Inventory.helptext.js:195 msgid "" "If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "如果启用,清单将阻止将任何机构实例组添加到运行关联作业模板的首选实例组列表中。 \n" +msgstr "" +"如果启用,清单将阻止将任何机构实例组添加到运行关联作业模板的首选实例组列表中。 \n" " 注: 如果启用此设置,并且提供了空列表,则会应用全局实例组。" #: screens/Template/shared/JobTemplate.helptext.js:33 msgid "" "If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" "Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." -msgstr "如果启用,作业模板将阻止将任何清单或机构实例组添加到要运行的首选实例组列表中。 \n" +msgstr "" +"如果启用,作业模板将阻止将任何清单或机构实例组添加到要运行的首选实例组列表中。 \n" " 注: 如果启用此设置,并且提供了空列表,则会应用全局实例组。" #: screens/Template/shared/JobTemplate.helptext.js:35 @@ -4311,7 +4374,8 @@ msgstr "Insights 凭证" msgid "Insights system ID" msgstr "Insights 系统 ID" -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 msgid "Install Bundle" msgstr "安装捆绑包" @@ -4332,25 +4396,26 @@ msgstr "实例过滤器" msgid "Instance Group" msgstr "实例组" +#: components/InstanceDetails.js/InstanceDetails.js:263 #: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 #: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 #: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 #: components/Lookup/InstanceGroupsLookup.js:141 #: components/Lookup/InstanceGroupsLookup.js:151 -#: components/PromptDetail/PromptDetail.js:227 +#: components/PromptDetail/PromptDetail.js:228 #: components/PromptDetail/PromptJobTemplateDetail.js:228 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:499 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 #: screens/InstanceGroup/InstanceGroups.js:16 #: screens/InstanceGroup/InstanceGroups.js:26 -#: screens/Instances/InstanceDetail/InstanceDetail.js:217 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:107 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:422 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 #: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "实例组" @@ -4380,8 +4445,8 @@ msgstr "实例组" msgid "Instance group not found." msgstr "没有找到实例组。" -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "实例组使用的容量" @@ -4404,9 +4469,9 @@ msgstr "实例类型" #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 #: screens/InstanceGroup/InstanceGroups.js:31 -#: screens/InstanceGroup/Instances/InstanceList.js:192 -#: screens/InstanceGroup/Instances/InstanceList.js:290 -#: screens/Instances/InstanceList/InstanceList.js:136 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 #: screens/Instances/Instances.js:13 #: screens/Instances/Instances.js:22 msgid "Instances" @@ -4439,7 +4504,7 @@ msgstr "无效的用户名或密码。请重试。" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 @@ -4463,18 +4528,18 @@ msgstr "无法复制含有源的清单" #: components/Lookup/InventoryLookup.js:169 #: components/Lookup/InventoryLookup.js:184 #: components/Lookup/InventoryLookup.js:224 -#: components/PromptDetail/PromptDetail.js:214 +#: components/PromptDetail/PromptDetail.js:215 #: components/PromptDetail/PromptInventorySourceDetail.js:76 #: components/PromptDetail/PromptJobTemplateDetail.js:119 #: components/PromptDetail/PromptJobTemplateDetail.js:129 #: components/PromptDetail/PromptWFJobTemplateDetail.js:79 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 #: components/TemplateList/TemplateListItem.js:285 #: components/TemplateList/TemplateListItem.js:295 #: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 @@ -4483,8 +4548,8 @@ msgstr "无法复制含有源的清单" #: screens/Job/JobDetail/JobDetail.js:107 #: screens/Job/JobDetail/JobDetail.js:122 #: screens/Job/JobDetail/JobDetail.js:129 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:214 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:224 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 @@ -4511,7 +4576,7 @@ msgstr "清单源" msgid "Inventory Source Sync" msgstr "清单源同步" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:299 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "清单源同步错误" @@ -4543,8 +4608,8 @@ msgstr "清单更新" msgid "Inventory copied successfully" msgstr "成功复制清单" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:226 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:109 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "清单文件" @@ -4556,7 +4621,7 @@ msgstr "未找到清单。" msgid "Inventory sync" msgstr "清单同步" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "清单同步失败" @@ -4590,18 +4655,18 @@ msgid "Items per page" msgstr "每页的项" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:157 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "作业 ID:" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "JSON" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "JSON 标签页" @@ -4616,16 +4681,16 @@ msgstr "1 月" #: components/JobList/JobListItem.js:112 #: screens/Job/JobDetail/JobDetail.js:599 -#: screens/Job/JobOutput/JobOutput.js:845 -#: screens/Job/JobOutput/JobOutput.js:846 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "作业取消错误" #: screens/Job/JobDetail/JobDetail.js:621 -#: screens/Job/JobOutput/JobOutput.js:834 -#: screens/Job/JobOutput/JobOutput.js:835 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "作业删除错误" @@ -4648,10 +4713,10 @@ msgid "Job Slice Parent" msgstr "任务分片父级" #: components/LaunchPrompt/steps/OtherPromptsStep.js:76 -#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptDetail.js:336 #: components/PromptDetail/PromptJobTemplateDetail.js:158 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:494 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:289 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 #: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "作业分片" @@ -4662,11 +4727,11 @@ msgstr "作业状态" #: components/LaunchPrompt/steps/OtherPromptsStep.js:97 #: components/LaunchPrompt/steps/OtherPromptsStep.js:98 -#: components/PromptDetail/PromptDetail.js:267 +#: components/PromptDetail/PromptDetail.js:254 #: components/PromptDetail/PromptJobTemplateDetail.js:247 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:571 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 #: screens/Job/JobDetail/JobDetail.js:474 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:449 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 #: screens/Template/shared/JobTemplateForm.js:521 #: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" @@ -4687,7 +4752,7 @@ msgstr "任务模板" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "作业模板默认凭证必须替换为相同类型之一。请为以下类型选择一个凭证才能继续: {0}" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 @@ -4710,26 +4775,26 @@ msgstr "在创建或编辑节点时无法选择具有提示密码凭证的作业 #: components/JobList/JobList.js:208 #: components/LaunchPrompt/steps/OtherPromptsStep.js:146 -#: components/PromptDetail/PromptDetail.js:185 +#: components/PromptDetail/PromptDetail.js:186 #: components/PromptDetail/PromptJobTemplateDetail.js:102 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:423 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 #: screens/Job/JobDetail/JobDetail.js:267 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 #: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "作业类型" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "作业状态" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "作业状态图标签页" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "作业模板" @@ -4843,7 +4908,7 @@ msgstr "LDAP4" msgid "LDAP5" msgstr "LDAP5" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "标志" @@ -4854,15 +4919,15 @@ msgstr "标签名称" #: components/JobList/JobListItem.js:284 #: components/LaunchPrompt/steps/OtherPromptsStep.js:223 -#: components/PromptDetail/PromptDetail.js:323 +#: components/PromptDetail/PromptDetail.js:310 #: components/PromptDetail/PromptJobTemplateDetail.js:209 #: components/PromptDetail/PromptWFJobTemplateDetail.js:116 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:551 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 #: components/TemplateList/TemplateListItem.js:347 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:148 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 #: screens/Inventory/shared/InventoryForm.js:83 #: screens/Job/JobDetail/JobDetail.js:453 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:401 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 #: screens/Template/shared/JobTemplateForm.js:387 #: screens/Template/shared/WorkflowJobTemplateForm.js:195 @@ -4874,18 +4939,19 @@ msgstr "标签" msgid "Last" msgstr "最后" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:220 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:243 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 #: screens/Instances/InstancePeers/InstancePeerListItem.js:47 #: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "最后的健康检查" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:183 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 #: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "最后的作业状态" @@ -4894,8 +4960,8 @@ msgstr "最后的作业状态" msgid "Last Login" msgstr "最近登陆" -#: components/PromptDetail/PromptDetail.js:161 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:411 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 #: components/TemplateList/TemplateListItem.js:316 #: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 @@ -4904,17 +4970,17 @@ msgstr "最近登陆" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 #: screens/Host/HostDetail/HostDetail.js:89 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:178 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 #: screens/Job/JobDetail/JobDetail.js:538 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 #: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:358 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 #: screens/User/UserTokenDetail/UserTokenDetail.js:66 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 @@ -4937,7 +5003,7 @@ msgstr "姓氏" msgid "Last Ran" msgstr "最后运行" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:341 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "最后运行" @@ -4945,8 +5011,8 @@ msgstr "最后运行" msgid "Last job" msgstr "最后作业" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:280 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 #: screens/TopologyView/Tooltip.js:331 @@ -4970,8 +5036,8 @@ msgstr "最后使用" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:520 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:529 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" @@ -5038,12 +5104,12 @@ msgstr "小于或等于比较。" #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 #: components/LaunchPrompt/steps/OtherPromptsStep.js:65 -#: components/PromptDetail/PromptDetail.js:255 +#: components/PromptDetail/PromptDetail.js:242 #: components/PromptDetail/PromptJobTemplateDetail.js:153 #: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:473 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 #: screens/Job/JobDetail/JobDetail.js:325 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:265 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 #: screens/Template/shared/JobTemplateForm.js:429 #: screens/Template/shared/WorkflowJobTemplateForm.js:159 @@ -5071,7 +5137,7 @@ msgstr "正在加载" msgid "Local" msgstr "本地" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:343 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "本地时区" @@ -5114,7 +5180,7 @@ msgstr "查找类型" msgid "Lookup typeahead" msgstr "查找 typeahead" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:155 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5169,14 +5235,15 @@ msgstr "未找到管理作业。" msgid "Management jobs" msgstr "管理作业" +#: components/InstanceDetails.js/InstanceDetails.js:255 #: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:215 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:209 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 #: screens/Instances/InstancePeers/InstancePeerListItem.js:83 #: screens/Job/JobDetail/JobDetail.js:74 #: screens/Project/ProjectDetail/ProjectDetail.js:192 @@ -5196,11 +5263,25 @@ msgstr "3 月" msgid "Mattermost" msgstr "Mattermost" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "最大主机数" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "最大值" @@ -5209,6 +5290,24 @@ msgstr "最大值" msgid "Maximum length" msgstr "最大长度" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + #: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 #: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" @@ -5257,7 +5356,7 @@ msgid "" "assigned to this group when new instances come online." msgstr "新实例上线时将自动分配给此组的所有实例的最小百分比。" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 #: components/Schedule/shared/FrequencyDetailSubform.js:173 #: components/Schedule/shared/ScheduleFormFields.js:125 #: components/Schedule/shared/ScheduleFormFields.js:185 @@ -5299,16 +5398,16 @@ msgstr "修改" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 #: components/Lookup/CredentialLookup.js:198 #: components/Lookup/InventoryLookup.js:156 #: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/MultiCredentialsLookup.js:202 #: components/Lookup/OrganizationLookup.js:138 #: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 #: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 @@ -5346,7 +5445,7 @@ msgid "Modified by (username)" msgstr "修改者(用户名)" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "模块" @@ -5369,7 +5468,7 @@ msgstr "周一" msgid "Monday" msgstr "周一" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:186 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 #: components/Schedule/shared/FrequencyDetailSubform.js:181 #: components/Schedule/shared/ScheduleFormFields.js:129 #: components/Schedule/shared/ScheduleFormFields.js:189 @@ -5418,8 +5517,8 @@ msgstr "多项选择选项" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 #: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 @@ -5442,8 +5541,8 @@ msgstr "多项选择选项" #: components/Lookup/InventoryLookup.js:162 #: components/Lookup/InventoryLookup.js:202 #: components/Lookup/InventoryLookup.js:217 -#: components/Lookup/MultiCredentialsLookup.js:189 -#: components/Lookup/MultiCredentialsLookup.js:204 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 #: components/Lookup/OrganizationLookup.js:129 #: components/Lookup/OrganizationLookup.js:144 #: components/Lookup/ProjectLookup.js:127 @@ -5453,11 +5552,11 @@ msgstr "多项选择选项" #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:114 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:325 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 #: components/Schedule/ScheduleList/ScheduleList.js:189 #: components/Schedule/ScheduleList/ScheduleListItem.js:86 @@ -5513,27 +5612,27 @@ msgstr "多项选择选项" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:199 -#: screens/InstanceGroup/Instances/InstanceList.js:215 -#: screens/InstanceGroup/Instances/InstanceList.js:266 -#: screens/InstanceGroup/Instances/InstanceList.js:299 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 +#: screens/InstanceGroup/Instances/InstanceList.js:288 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:143 -#: screens/Instances/InstanceList/InstanceList.js:160 -#: screens/Instances/InstanceList/InstanceList.js:201 -#: screens/Instances/InstanceList/InstanceListItem.js:128 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 #: screens/Instances/InstancePeers/InstancePeerList.js:80 #: screens/Instances/InstancePeers/InstancePeerList.js:87 #: screens/Instances/InstancePeers/InstancePeerList.js:96 #: screens/Instances/InstancePeers/InstancePeerListItem.js:37 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:89 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5545,7 +5644,7 @@ msgstr "多项选择选项" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5555,7 +5654,7 @@ msgstr "多项选择选项" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:181 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5565,7 +5664,7 @@ msgstr "多项选择选项" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 #: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 -#: screens/Inventory/shared/InventorySourceForm.js:100 +#: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 @@ -5575,7 +5674,7 @@ msgstr "多项选择选项" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5597,7 +5696,7 @@ msgstr "多项选择选项" #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5628,8 +5727,8 @@ msgstr "多项选择选项" #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:123 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:163 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "名称" @@ -5672,7 +5771,7 @@ msgstr "新" msgid "Next" msgstr "下一" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 #: components/Schedule/ScheduleList/ScheduleList.js:171 #: components/Schedule/ScheduleList/ScheduleListItem.js:118 #: components/Schedule/ScheduleList/ScheduleListItem.js:122 @@ -5692,7 +5791,7 @@ msgstr "未匹配主机" msgid "No Hosts Remaining" msgstr "没有剩余主机" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "没有可用的 JSON" @@ -5716,7 +5815,7 @@ msgstr "没有可用作业数据" msgid "No output found for this job." msgstr "没有为该作业找到输出。" -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "未找到结果" @@ -5735,10 +5834,10 @@ msgstr "未找到结果" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "没有找到结果" @@ -5766,15 +5865,16 @@ msgstr "未找到 {pluralizedItemName}" msgid "Node Alias" msgstr "节点别名" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:223 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:268 -#: screens/InstanceGroup/Instances/InstanceList.js:300 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:204 -#: screens/Instances/InstanceList/InstanceList.js:148 -#: screens/Instances/InstanceList/InstanceList.js:203 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 #: screens/Instances/InstancePeers/InstancePeerList.js:98 #: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 @@ -5799,8 +5899,8 @@ msgstr "节点类型" msgid "None" msgstr "无" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:193 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:196 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "无(运行一次)" @@ -5951,14 +6051,14 @@ msgstr "10 月" #: components/HostToggle/HostToggle.js:61 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:195 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "关" @@ -5967,14 +6067,14 @@ msgstr "关" #: components/HostToggle/HostToggle.js:60 #: components/LaunchPrompt/steps/OtherPromptsStep.js:192 #: components/LaunchPrompt/steps/OtherPromptsStep.js:194 -#: components/PromptDetail/PromptDetail.js:362 +#: components/PromptDetail/PromptDetail.js:349 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:489 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:284 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 #: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "开" @@ -6047,7 +6147,7 @@ msgstr "(可选)选择要用来向 Webhook 服务发回状态更新的凭证 #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 #: screens/Instances/Shared/InstanceForm.js:54 #: screens/Inventory/shared/InventoryForm.js:94 #: screens/Project/shared/ProjectSubForms/SharedFields.js:69 @@ -6083,11 +6183,11 @@ msgstr "顺序" #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:96 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:202 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 @@ -6097,8 +6197,8 @@ msgstr "顺序" #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:199 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 @@ -6142,12 +6242,12 @@ msgid "Out of compliance" msgstr "不合规" #: screens/Job/Job.js:131 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "输出" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "输出标签页" @@ -6156,12 +6256,12 @@ msgid "Overwrite" msgstr "覆盖" #: components/PromptDetail/PromptInventorySourceDetail.js:41 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:121 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "从远程清单源覆盖本地组和主机" #: components/PromptDetail/PromptInventorySourceDetail.js:46 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:127 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "从远程清单源覆盖本地变量" @@ -6221,7 +6321,8 @@ msgstr "向 playbook 传递额外的命令行变量。这是 ansible-playbook #: screens/Job/Job.helptext.js:13 #: screens/Template/shared/JobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the documentation for example syntax." -msgstr "向 playbook 传递额外的命令行变量。这是 ansible-playbook 的 -e 或 --extra-vars 命令行参数。使用 YAML \n" +msgstr "" +"向 playbook 传递额外的命令行变量。这是 ansible-playbook 的 -e 或 --extra-vars 命令行参数。使用 YAML \n" "或 JSON 提供键/值对。示例语法请参阅相关文档。" #: screens/Login/Login.js:227 @@ -6281,11 +6382,11 @@ msgstr "个人访问令牌" msgid "Personal access token" msgstr "个人访问令牌" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "Play" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "play 数量" @@ -6295,7 +6396,7 @@ msgstr "Play 已启动" #: components/PromptDetail/PromptJobTemplateDetail.js:148 #: screens/Job/JobDetail/JobDetail.js:319 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:253 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 #: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" @@ -6327,7 +6428,7 @@ msgstr "Playbook 运行" msgid "Playbook Started" msgstr "Playbook 已启动" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 @@ -6339,7 +6440,7 @@ msgstr "Playbook 名称" msgid "Playbook run" msgstr "Playbook 运行" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "Play" @@ -6363,7 +6464,7 @@ msgstr "请添加 {pluralizedItemName} 来填充此列表" msgid "Please click the Start button to begin." msgstr "请点开始按钮开始。" -#: components/Schedule/shared/ScheduleForm.js:421 +#: components/Schedule/shared/ScheduleForm.js:414 msgid "Please enter a number of occurrences." msgstr "请输入事件发生的值。" @@ -6383,7 +6484,7 @@ msgstr "请登录" msgid "Please run a job to populate this list." msgstr "请运行一个作业来填充此列表。" -#: components/Schedule/shared/ScheduleForm.js:417 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "选择的日数字应介于 1 到 31 之间。" @@ -6391,7 +6492,7 @@ msgstr "选择的日数字应介于 1 到 31 之间。" msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "请选择一个清单或者选中“启动时提示”选项" -#: components/Schedule/shared/ScheduleForm.js:429 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "请选择一个比开始日期/时间晚的结束日期/时间。" @@ -6407,14 +6508,15 @@ msgstr "请使用上面的过滤器尝试另一个搜索" msgid "Please wait until the topology view is populated..." msgstr "请等到拓扑视图被填充..." -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "Pod 规格覆写" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:214 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:208 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 #: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "策略类型" @@ -6470,16 +6572,16 @@ msgid "" "cancel the drag operation." msgstr "按空格或输入开始拖动,并使用箭头键导航或关闭。按 Enter 键确认拖动或任何其他键以取消拖动操作。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:130 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 #: screens/Inventory/shared/InventoryForm.js:99 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:147 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:347 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 #: screens/Template/shared/JobTemplateForm.js:603 msgid "Prevent Instance Group Fallback" msgstr "防止实例组 Fallback" -#: screens/Inventory/shared/Inventory.helptext.js:197 +#: screens/Inventory/shared/Inventory.helptext.js:198 msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." msgstr "防止实例组 Fallback:如果启用,则该清单将阻止将任何机构实例组添加到运行相关作业模板的首选实例组列表中。" @@ -6497,7 +6599,7 @@ msgid "Private key passphrase" msgstr "私钥密码" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:122 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 #: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "权限升级" @@ -6518,11 +6620,11 @@ msgstr "权利升级:如果启用,则以管理员身份运行此 playbook。 #: components/PromptDetail/PromptJobTemplateDetail.js:133 #: components/PromptDetail/PromptJobTemplateDetail.js:141 #: components/TemplateList/TemplateListItem.js:300 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:216 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:198 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:239 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "项目" @@ -6563,14 +6665,14 @@ msgstr "成功复制的项目" msgid "Project not found." msgstr "未找到项目。" -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "项目同步失败" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 @@ -6585,12 +6687,12 @@ msgstr "项目" msgid "Promote Child Groups and Hosts" msgstr "提升子组和主机" -#: components/Schedule/shared/ScheduleForm.js:540 -#: components/Schedule/shared/ScheduleForm.js:543 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "提示" -#: components/PromptDetail/PromptDetail.js:182 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "提示覆盖" @@ -6604,8 +6706,8 @@ msgstr "启动时提示" msgid "Prompt | {0}" msgstr "提示 | {0}" -#: components/PromptDetail/PromptDetail.js:180 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:418 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "提示的值" @@ -6630,7 +6732,8 @@ msgstr "为这个字段输入值或者选择「启动时提示」选项。" msgid "" "Provide key/value pairs using either\n" "YAML or JSON." -msgstr "使用 YAML 或 JSON 提供\n" +msgstr "" +"使用 YAML 或 JSON 提供\n" "键/值对。" #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:191 @@ -6651,7 +6754,7 @@ msgid "Provisioning" msgstr "置备" #: components/PromptDetail/PromptJobTemplateDetail.js:162 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 #: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "部署回调 URL" @@ -6661,7 +6764,7 @@ msgid "Provisioning Callback details" msgstr "置备回调详情" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:127 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 #: screens/Template/shared/JobTemplateForm.js:555 #: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" @@ -6692,10 +6795,11 @@ msgstr "RADIUS" msgid "RADIUS settings" msgstr "RADIUS 设置" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:287 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 #: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "RAM {0}" @@ -6709,23 +6813,23 @@ msgstr "读取" msgid "Ready" msgstr "就绪" -#: screens/Dashboard/Dashboard.js:133 +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "最近的作业" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "最近的任务列表标签页" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "最近模板" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "最近模板列表标签页" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" @@ -6816,12 +6920,15 @@ msgstr "区域" msgid "Registry credential" msgstr "注册表凭证" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "仅导入主机名与这个正则表达式匹配的主机。该过滤器在应用任何清单插件过滤器后作为后步骤使用。" #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "相关组" @@ -6848,12 +6955,12 @@ msgstr "相关的搜索类型 typeahead" #: components/LaunchButton/ReLaunchDropDown.js:82 #: screens/Job/JobDetail/JobDetail.js:580 #: screens/Job/JobDetail/JobDetail.js:588 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "重新启动" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "重新启动作业" @@ -6871,7 +6978,7 @@ msgid "Relaunch on" msgstr "重新启动于" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "使用主机参数重新启动" @@ -6879,7 +6986,7 @@ msgstr "使用主机参数重新启动" msgid "Reload" msgstr "重新加载" -#: screens/Job/JobOutput/JobOutput.js:723 +#: screens/Job/JobOutput/JobOutput.js:735 msgid "Reload output" msgstr "重新加载输出" @@ -6892,8 +6999,8 @@ msgstr "重新加载输出" msgid "Remote Archive" msgstr "远程归档" -#: screens/Instances/InstanceDetail/InstanceDetail.js:374 -#: screens/Instances/InstanceList/InstanceList.js:242 +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 msgid "Removal Error" msgstr "删除错误" @@ -6952,7 +7059,7 @@ msgstr "删除此链接将会孤立分支的剩余部分,并导致它在启动 msgid "Reorder" msgstr "重新排序" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:349 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "重复频率" @@ -7022,8 +7129,8 @@ msgstr "从给定的主机变量字典中检索启用的状态。启用的变量 #: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:819 -#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "返回" @@ -7128,8 +7235,9 @@ msgstr "运行" msgid "Run Command" msgstr "运行命令" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:335 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "对实例运行健康检查" @@ -7146,10 +7254,11 @@ msgstr "运行命令" msgid "Run every" msgstr "运行每" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 -#: screens/Instances/InstanceDetail/InstanceDetail.js:344 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "运行健康检查" @@ -7176,17 +7285,26 @@ msgstr "运行中" msgid "Running Handlers" msgstr "正在运行的处理程序" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:217 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:212 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 #: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "运行任务" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:284 -#: screens/Instances/InstanceDetail/InstanceDetail.js:342 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "运行健康检查" @@ -7225,7 +7343,7 @@ msgid "START" msgstr "开始" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 @@ -7248,8 +7366,8 @@ msgstr "周六" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:526 -#: components/Schedule/shared/ScheduleForm.js:532 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 #: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 @@ -7303,7 +7421,7 @@ msgstr "调度处于活跃状态" msgid "Schedule is inactive" msgstr "调度处于非活跃状态" -#: components/Schedule/shared/ScheduleForm.js:394 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "调度缺少规则" @@ -7425,7 +7543,7 @@ msgstr "选择主机" msgid "Select Input" msgstr "选择输入" -#: screens/InstanceGroup/Instances/InstanceList.js:295 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "选择实例" @@ -7495,11 +7613,19 @@ msgstr "在编辑执行环境前选择一个项目。" msgid "Select a question to delete" msgstr "选择要删除的问题" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" + #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "选择要删除的行" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "选择要解除关联的行" @@ -7527,8 +7653,8 @@ msgstr "导入一个订阅" #: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 #: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:97 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 #: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 #: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 #: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 @@ -7570,7 +7696,7 @@ msgstr "选择一个实例" msgid "Select an instance and a metric to show chart" msgstr "选择一个实例和一个指标来显示图表" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "选择一个要运行健康检查的实例。" @@ -7626,9 +7752,9 @@ msgstr "选择周期" msgid "Select roles to apply" msgstr "选择要应用的角色" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "选择源路径" @@ -7718,8 +7844,8 @@ msgstr "选择 {0}" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7742,8 +7868,8 @@ msgstr "已选择" msgid "Selected Category" msgstr "选择的类别" +#: components/Schedule/shared/ScheduleForm.js:445 #: components/Schedule/shared/ScheduleForm.js:446 -#: components/Schedule/shared/ScheduleForm.js:447 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "选定日期范围必须至少有 1 个计划发生。" @@ -7777,7 +7903,7 @@ msgstr "设置数据应保留的天数。" msgid "Set preferences for data collection, logos, and logins" msgstr "为数据收集、日志和登录设置偏好" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:131 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "设置源路径为" @@ -7843,10 +7969,10 @@ msgid "Show" msgstr "显示" #: components/LaunchPrompt/steps/OtherPromptsStep.js:182 -#: components/PromptDetail/PromptDetail.js:361 +#: components/PromptDetail/PromptDetail.js:348 #: components/PromptDetail/PromptJobTemplateDetail.js:156 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:488 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:283 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 #: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "显示更改" @@ -7920,11 +8046,11 @@ msgstr "简单键选择" #: components/LaunchPrompt/steps/OtherPromptsStep.js:106 #: components/LaunchPrompt/steps/OtherPromptsStep.js:107 -#: components/PromptDetail/PromptDetail.js:295 +#: components/PromptDetail/PromptDetail.js:282 #: components/PromptDetail/PromptJobTemplateDetail.js:267 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:595 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 #: screens/Job/JobDetail/JobDetail.js:500 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:475 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 #: screens/Template/shared/JobTemplateForm.js:533 #: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" @@ -7998,8 +8124,8 @@ msgstr "排序" #: components/JobList/JobListItem.js:169 #: components/PromptDetail/PromptInventorySourceDetail.js:84 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 -#: screens/Inventory/shared/InventorySourceForm.js:130 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 +#: screens/Inventory/shared/InventorySourceForm.js:131 #: screens/Job/JobDetail/JobDetail.js:172 #: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 @@ -8007,20 +8133,22 @@ msgid "Source" msgstr "源" #: components/LaunchPrompt/steps/OtherPromptsStep.js:44 -#: components/PromptDetail/PromptDetail.js:250 +#: components/PromptDetail/PromptDetail.js:237 #: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 #: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:467 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 #: screens/Job/JobDetail/JobDetail.js:307 #: screens/Project/ProjectDetail/ProjectDetail.js:230 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:248 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 #: screens/Template/shared/JobTemplateForm.js:335 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "源控制分支" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "源控制分支/标签/提交" @@ -8083,7 +8211,7 @@ msgstr "源工作流作业" msgid "Source control branch" msgstr "源控制分支" -#: screens/Inventory/shared/InventorySourceForm.js:152 +#: screens/Inventory/shared/InventorySourceForm.js:153 msgid "Source details" msgstr "源详情" @@ -8091,7 +8219,7 @@ msgstr "源详情" msgid "Source phone number" msgstr "源电话号码" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:269 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "源变量" @@ -8121,11 +8249,11 @@ msgstr "指定通知颜色。可接受的颜色为十六进制颜色代码(示 msgid "Specify the conditions under which this node should be executed" msgstr "指定应该执行此节点的条件" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "标准错误" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "标准错误标签页" @@ -8172,27 +8300,28 @@ msgid "Start time" msgstr "开始时间" #: screens/Job/JobDetail/JobDetail.js:220 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:165 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "已开始" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:206 -#: screens/InstanceGroup/Instances/InstanceList.js:267 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceList/InstanceList.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:134 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 #: screens/Instances/InstancePeers/InstancePeerList.js:97 #: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 #: screens/Job/JobDetail/JobDetail.js:210 -#: screens/Job/JobOutput/HostEventModal.js:118 +#: screens/Job/JobOutput/HostEventModal.js:119 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 @@ -8200,7 +8329,7 @@ msgstr "已开始" #: screens/Project/ProjectList/ProjectListItem.js:197 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "状态" @@ -8288,7 +8417,7 @@ msgstr "成功消息正文" #: components/JobList/JobList.js:231 #: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:96 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "成功" @@ -8424,8 +8553,8 @@ msgstr "TACACS+" msgid "TACACS+ settings" msgstr "TACACS+ 设置" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "制表符" @@ -8452,11 +8581,11 @@ msgstr "注解的标签(可选)" msgid "Target URL" msgstr "目标 URL" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "任务" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "任务计数" @@ -8464,7 +8593,7 @@ msgstr "任务计数" msgid "Task Started" msgstr "任务已启动" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "任务" @@ -8506,7 +8635,7 @@ msgstr "团队" msgid "Template" msgstr "模板" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "成功复制的模板" @@ -8576,11 +8705,12 @@ msgstr "The" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "用户必须用来获取此应用令牌的授予类型" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "要运行此机构的实例组。" -#: screens/Instances/InstanceDetail/InstanceDetail.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 msgid "The Instance Groups to which this instance belongs." msgstr "此实例所属的实例组。" @@ -8611,7 +8741,7 @@ msgstr "Grafana 服务器的基本 URL - /api/annotations 端点将自动添加 msgid "The container image to be used for execution." msgstr "用于执行的容器镜像。" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8643,7 +8773,7 @@ msgstr "第一次获取所有引用。第二次获取 Github 拉取请求号 62 msgid "The full image location, including the container registry, image name, and version tag." msgstr "完整镜像位置,包括容器注册表、镜像名称和版本标签。" -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" @@ -8662,7 +8792,7 @@ msgstr "最后 {dayOfWeek}" msgid "The last {weekday} of {month}" msgstr "最后 {weekday}({month})" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8822,7 +8952,7 @@ msgstr "此操作将解除以下关联:" msgid "This action will remove the following instances:" msgstr "此操作将删除以下实例:" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 msgid "This container group is currently being by other resources. Are you sure you want to delete it?" msgstr "其他资源目前正在此容器组中。确定要删除它吗?" @@ -8839,7 +8969,8 @@ msgid "" "This data is used to enhance\n" "future releases of the Software and to provide\n" "Automation Analytics." -msgstr "这些用户用于增强\n" +msgstr "" +"这些用户用于增强\n" "以后发行的软件并提供\n" "Automation Analytics。" @@ -8859,7 +8990,7 @@ msgstr "其他资源目前正在使用此执行环境。确定要删除它吗? msgid "This feature is deprecated and will be removed in a future release." msgstr "这个功能已被弃用并将在以后的发行版本中被删除。" -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "除非设置了启用的变量,否则此字段会被忽略。如果启用的变量与这个值匹配,则会在导入时启用主机。" @@ -8945,7 +9076,7 @@ msgstr "此字段将使用指定的凭证从外部 secret 管理系统检索。" msgid "This has already been acted on" msgstr "此已操作" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "其他资源目前正在此实例组中。确定要删除它吗?" @@ -8953,11 +9084,11 @@ msgstr "其他资源目前正在此实例组中。确定要删除它吗?" msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "此清单会应用到在这个工作流 ({0}) 中的所有作业模板,它会提示输入一个清单。" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:199 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "其他资源目前正在使用此清单。确定要删除它吗?" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:313 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "依赖该清单源的其他资源目前正在使用此清单源。确定要删除它吗?" @@ -8973,11 +9104,11 @@ msgstr "这是唯一显示令牌值和关联刷新令牌值的时间。" msgid "This job failed and has no output." msgstr "此作业失败,且没有输出。" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:543 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "其他资源目前正在使用此任务模板。确定要删除它吗?" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "这个机构目前由其他资源使用。您确定要删除它吗?" @@ -8989,7 +9120,7 @@ msgstr "其他资源目前正在使用这个项目。确定要删除它吗?" msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "此项目当前处于同步状态,在同步过程完成前无法点击" -#: components/Schedule/shared/ScheduleForm.js:460 +#: components/Schedule/shared/ScheduleForm.js:459 msgid "This schedule has no occurrences due to the selected exceptions." msgstr "由于所选的例外,此计划没有发生。" @@ -9084,13 +9215,13 @@ msgid "Timed out" msgstr "超时" #: components/LaunchPrompt/steps/OtherPromptsStep.js:86 -#: components/PromptDetail/PromptDetail.js:136 -#: components/PromptDetail/PromptDetail.js:355 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 #: screens/Job/JobDetail/JobDetail.js:397 #: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 #: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" @@ -9193,15 +9324,16 @@ msgid "Tools" msgstr "工具" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "拓扑视图" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:213 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 #: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "作业总数" @@ -9211,7 +9343,7 @@ msgstr "作业总数" msgid "Total Nodes" msgstr "节点总数" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:103 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "主机总数" @@ -9267,8 +9399,8 @@ msgstr "Twilio" #: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:124 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9281,11 +9413,11 @@ msgstr "Twilio" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 @@ -9333,13 +9465,14 @@ msgstr "无法更改主机上的清单" msgid "Unable to load last job update" msgstr "无法加载最后的作业更新" +#: components/InstanceDetails.js/InstanceDetails.js:367 #: components/StatusLabel/StatusLabel.js:61 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:306 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 #: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "不可用" @@ -9359,15 +9492,15 @@ msgstr "无限" #: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "无法访问" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "无法访问的主机数" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "无法访问的主机" @@ -9384,7 +9517,7 @@ msgid "Update Revision on Launch" msgstr "启动时更新修订" #: components/PromptDetail/PromptInventorySourceDetail.js:51 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:133 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "启动时更新" @@ -9456,22 +9589,25 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "每行一个电话号码以指定路由 SMS 消息的位置。电话号的格式化为 +11231231234。如需更多信息,请参阅 Twilio 文档" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:249 -#: screens/InstanceGroup/Instances/InstanceList.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:292 -#: screens/Instances/InstanceList/InstanceList.js:205 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "已使用容量" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:257 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:297 -#: screens/Instances/InstanceDetail/InstanceDetail.js:303 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 #: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "使用的容量" @@ -9571,22 +9707,22 @@ msgstr "VMware vCenter" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 #: components/LaunchPrompt/steps/OtherPromptsStep.js:115 -#: components/PromptDetail/PromptDetail.js:168 -#: components/PromptDetail/PromptDetail.js:369 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 #: components/PromptDetail/PromptJobTemplateDetail.js:286 #: components/PromptDetail/PromptWFJobTemplateDetail.js:135 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:620 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 #: screens/Host/HostDetail/HostDetail.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:165 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:143 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 #: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 #: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 #: screens/Job/JobDetail/JobDetail.js:546 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:501 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 #: screens/Template/shared/JobTemplateForm.js:402 #: screens/Template/shared/WorkflowJobTemplateForm.js:212 @@ -9602,7 +9738,7 @@ msgstr "提示变量" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "变量需要是 JSON 或 YAML 语法格式。使用单选按钮在两者之间切换。" -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "用来配置清单源的变量。有关如何配置此插件的详细描述,请参阅文档中的<0>清单插件部分,以及 <1>{sourceType} 插件配置指南 。" @@ -9619,16 +9755,16 @@ msgid "Verbose" msgstr "详细" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:260 +#: components/PromptDetail/PromptDetail.js:247 #: components/PromptDetail/PromptInventorySourceDetail.js:100 #: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:478 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 #: components/VerbositySelectField/VerbositySelectField.js:34 #: components/VerbositySelectField/VerbositySelectField.js:45 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:232 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 #: screens/Job/JobDetail/JobDetail.js:331 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:271 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "详细程度" @@ -9636,8 +9772,8 @@ msgstr "详细程度" msgid "View Azure AD settings" msgstr "查看 Azure AD 设置" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "查看凭证详情" @@ -9661,7 +9797,7 @@ msgstr "查看主机详情" msgid "View Instance Details" msgstr "查看实例详情" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9775,7 +9911,7 @@ msgstr "在 <0>docs.ansible.com 查看 YAML 示例" msgid "View activity stream" msgstr "查看活动流" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "查看所有凭证。" @@ -9938,7 +10074,7 @@ msgstr "Webhook" #: components/PromptDetail/PromptJobTemplateDetail.js:177 #: components/PromptDetail/PromptWFJobTemplateDetail.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:333 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 #: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "Webhook 凭证" @@ -9949,7 +10085,7 @@ msgstr "Webhook 凭证" #: components/PromptDetail/PromptJobTemplateDetail.js:173 #: components/PromptDetail/PromptWFJobTemplateDetail.js:92 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 #: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" @@ -9957,7 +10093,7 @@ msgstr "Webhook 密钥" #: components/PromptDetail/PromptJobTemplateDetail.js:166 #: components/PromptDetail/PromptWFJobTemplateDetail.js:91 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:311 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 #: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" @@ -9965,7 +10101,7 @@ msgstr "Webhook 服务" #: components/PromptDetail/PromptJobTemplateDetail.js:169 #: components/PromptDetail/PromptWFJobTemplateDetail.js:95 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 #: screens/Template/shared/WebhookSubForm.js:161 #: screens/Template/shared/WebhookSubForm.js:167 @@ -9989,7 +10125,7 @@ msgstr "Webhook 服务可以将此用作共享机密。" #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:142 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "Webhook" @@ -10013,7 +10149,7 @@ msgstr "周三" msgid "Wednesday" msgstr "周三" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:185 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 #: components/Schedule/shared/FrequencyDetailSubform.js:179 #: components/Schedule/shared/ScheduleFormFields.js:128 #: components/Schedule/shared/ScheduleFormFields.js:188 @@ -10066,8 +10202,8 @@ msgstr "未找到工作流批准。" #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:118 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10078,11 +10214,11 @@ msgstr "工作流批准" #: components/Schedule/ScheduleList/ScheduleListItem.js:40 #: screens/Job/JobDetail/JobDetail.js:70 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:164 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "工作流任务" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:76 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 msgid "Workflow Job 1/{0}" msgstr "工作流作业 1/{0}" @@ -10110,11 +10246,11 @@ msgstr "工作流作业模板" msgid "Workflow Link" msgstr "工作流链接" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:100 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 msgid "Workflow Nodes" msgstr "工作流节点" -#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 msgid "Workflow Statuses" msgstr "工作流状态" @@ -10192,7 +10328,7 @@ msgstr "写入" msgid "YAML:" msgstr "YAML:" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:187 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 #: components/Schedule/shared/FrequencyDetailSubform.js:183 #: components/Schedule/shared/ScheduleFormFields.js:130 #: components/Schedule/shared/ScheduleFormFields.js:190 @@ -10203,6 +10339,14 @@ msgstr "年" msgid "Yes" msgstr "是" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" + +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" + #: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "您不能选择具有相同 vault ID 的多个 vault 凭证。这样做会自动取消选择具有相同的 vault ID 的另一个凭证。" @@ -10342,7 +10486,12 @@ msgstr "详情。" msgid "disassociate" msgstr "解除关联" +#: components/InstanceDetails.js/InstanceDetails.js:301 #: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 #: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 @@ -10354,11 +10503,11 @@ msgstr "文档" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 #: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 #: screens/Host/HostDetail/HostDetail.js:104 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:289 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:161 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 #: screens/Project/ProjectDetail/ProjectDetail.js:309 #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 @@ -10370,7 +10519,12 @@ msgstr "编辑" msgid "encrypted" msgstr "加密" +#: components/InstanceDetails.js/InstanceDetails.js:303 #: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "更多信息。" @@ -10454,7 +10608,7 @@ msgstr "重新启动作业" msgid "sec" msgstr "秒" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "秒" @@ -10523,7 +10677,7 @@ msgstr "{0, plural, one {The inventory will be in a pending status until the fin msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:151 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" @@ -10563,7 +10717,7 @@ msgstr "{0, plural, one {This organization is currently being used by other reso 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?}}" msgstr "{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?}}" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" @@ -10608,10 +10762,11 @@ msgstr "{brandName} 标志" msgid "{dateStr} by <0>{username}" msgstr "{dateStr}(由 <0>{username})" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:231 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:274 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 #: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "{forks, plural, one {# fork} other {# forks}}" @@ -10664,7 +10819,7 @@ msgstr "{intervalValue, plural, one {week} other {weeks}}" msgid "{intervalValue, plural, one {year} other {years}}" msgstr "{intervalValue, plural, one {year} other {years}}" -#: components/PromptDetail/PromptDetail.js:44 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "{minutes} 分 {seconds} 秒" @@ -10688,11 +10843,10 @@ msgstr "{numOccurrences, plural, one {After {numOccurrences} 事件发生} other msgid "{pluralizedItemName} List" msgstr "{pluralizedItemName} 列表" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" #: components/AppContainer/AppContainer.js:154 msgid "{sessionCountdown, plural, one {You will be logged out in # second due to inactivity} other {You will be logged out in # seconds due to inactivity}}" msgstr "{sessionCountdown, plural, one {You will be logged out in # second due to inactivity} other {You will be logged out in # seconds due to inactivity}}" - diff --git a/awx/ui/src/locales/zu/messages.po b/awx/ui/src/locales/zu/messages.po index bddcf1ea5a..3448b23140 100644 --- a/awx/ui/src/locales/zu/messages.po +++ b/awx/ui/src/locales/zu/messages.po @@ -18,61 +18,59 @@ msgid "(Limited to first 10)" msgstr "" #: components/TemplateList/TemplateListItem.js:103 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:154 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:162 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:90 msgid "(Prompt on launch)" msgstr "" -#: screens/Credential/CredentialDetail/CredentialDetail.js:284 +#: screens/Credential/CredentialDetail/CredentialDetail.js:283 msgid "* This field will be retrieved from an external secret management system using the specified credential." msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:229 msgid "/ (project root)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:13 -#: constants.js:19 +#: components/VerbositySelectField/VerbositySelectField.js:10 msgid "0 (Normal)" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:34 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:38 msgid "0 (Warning)" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:35 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:39 msgid "1 (Info)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:14 -#: constants.js:20 +#: components/VerbositySelectField/VerbositySelectField.js:11 msgid "1 (Verbose)" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:36 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:40 msgid "2 (Debug)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:15 -#: constants.js:21 +#: components/VerbositySelectField/VerbositySelectField.js:12 msgid "2 (More Verbose)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:16 -#: constants.js:22 +#: components/VerbositySelectField/VerbositySelectField.js:13 msgid "3 (Debug)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:17 -#: constants.js:23 +#: components/VerbositySelectField/VerbositySelectField.js:14 msgid "4 (Connection Debug)" msgstr "" -#: components/VerbositySelectField/VerbositySelectField.js:18 -#: constants.js:24 +#: components/VerbositySelectField/VerbositySelectField.js:15 msgid "5 (WinRM Debug)" msgstr "" +#: screens/Dashboard/Dashboard.js:81 +msgid "<0><1/> A tech preview of the new {brandName} user interface can be found <2>here." +msgstr "" + #: screens/Project/shared/Project.helptext.js:76 msgid "" "A refspec to fetch (passed to the Ansible git\n" @@ -85,29 +83,29 @@ msgid "A subscription manifest is an export of a Red Hat Subscription. To genera msgstr "" #: screens/Job/WorkflowOutput/WorkflowOutputNode.js:143 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:299 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:326 msgid "ALL" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:279 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:284 msgid "API Service/Integration Key" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:282 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:291 msgid "API Token" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:297 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:306 msgid "API service/integration key" msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:130 +#: components/AppContainer/PageHeaderToolbar.js:125 msgid "About" msgstr "" #: routeConfig.js:92 #: screens/ActivityStream/ActivityStream.js:179 -#: screens/Credential/Credential.js:74 +#: screens/Credential/Credential.js:89 #: screens/Credential/Credentials.js:29 #: screens/Inventory/Inventories.js:59 #: screens/Inventory/Inventory.js:65 @@ -128,12 +126,12 @@ msgstr "" msgid "Access Token Expiration" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:347 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:408 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:352 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:421 msgid "Account SID" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:383 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:396 msgid "Account token" msgstr "" @@ -143,9 +141,9 @@ msgstr "" #: components/JobList/JobList.js:249 #: components/JobList/JobListItem.js:103 -#: components/RelatedTemplateList/RelatedTemplateList.js:189 -#: components/Schedule/ScheduleList/ScheduleList.js:171 -#: components/Schedule/ScheduleList/ScheduleListItem.js:114 +#: components/RelatedTemplateList/RelatedTemplateList.js:202 +#: components/Schedule/ScheduleList/ScheduleList.js:172 +#: components/Schedule/ScheduleList/ScheduleListItem.js:128 #: components/SelectedList/DraggableSelectedList.js:101 #: components/TemplateList/TemplateList.js:246 #: components/TemplateList/TemplateListItem.js:195 @@ -163,20 +161,21 @@ msgstr "" #: screens/Host/HostGroups/HostGroupsList.js:177 #: screens/Host/HostList/HostList.js:172 #: screens/Host/HostList/HostListItem.js:70 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:214 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:200 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:75 -#: screens/InstanceGroup/Instances/InstanceList.js:260 -#: screens/InstanceGroup/Instances/InstanceListItem.js:171 -#: screens/Instances/InstanceList/InstanceList.js:155 -#: screens/Instances/InstanceList/InstanceListItem.js:183 +#: screens/InstanceGroup/Instances/InstanceList.js:293 +#: screens/InstanceGroup/Instances/InstanceListItem.js:185 +#: screens/Instances/InstanceList/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceListItem.js:199 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:218 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:53 #: screens/Inventory/InventoryGroups/InventoryGroupItem.js:39 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:142 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:41 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:187 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:44 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:93 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:94 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:141 #: screens/Inventory/InventoryList/InventoryList.js:222 #: screens/Inventory/InventoryList/InventoryListItem.js:131 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:233 @@ -200,6 +199,8 @@ msgstr "" #: screens/Template/Survey/SurveyListItem.js:90 #: screens/User/UserList/UserList.js:164 #: screens/User/UserList/UserListItem.js:56 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:225 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:78 msgid "Actions" msgstr "" @@ -210,17 +211,17 @@ msgstr "" #: screens/Host/HostList/HostListItem.js:95 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:217 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:50 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:77 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:101 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:33 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:116 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:76 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:100 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:32 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:115 msgid "Activity" msgstr "" #: routeConfig.js:49 #: screens/ActivityStream/ActivityStream.js:43 #: screens/ActivityStream/ActivityStream.js:121 -#: screens/Setting/Settings.js:43 +#: screens/Setting/Settings.js:44 msgid "Activity Stream" msgstr "" @@ -228,7 +229,7 @@ msgstr "" msgid "Activity Stream type selector" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:210 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:169 msgid "Actor" msgstr "" @@ -262,7 +263,7 @@ msgid "Add User Roles" msgstr "" #: components/Workflow/WorkflowStartNode.js:68 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:211 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:238 msgid "Add a new node" msgstr "" @@ -270,10 +271,14 @@ msgstr "" msgid "Add a new node between these two nodes" msgstr "" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:113 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:108 msgid "Add container group" msgstr "" +#: components/Schedule/shared/ScheduleFormFields.js:171 +msgid "Add exceptions" +msgstr "" + #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:140 msgid "Add existing group" msgstr "" @@ -282,7 +287,7 @@ msgstr "" msgid "Add existing host" msgstr "" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:114 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:109 msgid "Add instance group" msgstr "" @@ -322,13 +327,17 @@ msgstr "" msgid "Add workflow template" msgstr "" +#: screens/TopologyView/Legend.js:269 +msgid "Adding" +msgstr "" + #: routeConfig.js:113 #: screens/ActivityStream/ActivityStream.js:190 msgid "Administration" msgstr "" #: components/DataListToolbar/DataListToolbar.js:139 -#: screens/Job/JobOutput/JobOutputSearch.js:137 +#: screens/Job/JobOutput/JobOutputSearch.js:136 msgid "Advanced" msgstr "" @@ -349,7 +358,7 @@ msgid "" "like the Ansible inventory .ini file format." msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:517 +#: components/Schedule/shared/FrequencyDetailSubform.js:524 msgid "After number of occurrences" msgstr "" @@ -358,7 +367,7 @@ msgid "Alert modal" msgstr "" #: components/LaunchButton/ReLaunchDropDown.js:48 -#: components/PromptDetail/PromptDetail.js:123 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Metrics/Metrics.js:82 #: screens/Metrics/Metrics.js:82 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:266 @@ -373,16 +382,16 @@ msgstr "" msgid "All jobs" msgstr "" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:97 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:101 msgid "Allow Branch Override" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:66 -#: screens/Project/ProjectDetail/ProjectDetail.js:120 +#: screens/Project/ProjectDetail/ProjectDetail.js:121 msgid "Allow branch override" msgstr "" -#: screens/Project/shared/Project.helptext.js:122 +#: screens/Project/shared/Project.helptext.js:126 msgid "" "Allow changing the Source Control branch or revision in a job\n" "template that uses this project." @@ -427,13 +436,13 @@ msgstr "" msgid "Answer variable name" msgstr "" -#: components/PromptDetail/PromptDetail.js:123 +#: components/PromptDetail/PromptDetail.js:133 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:263 msgid "Any" msgstr "" #: components/Lookup/ApplicationLookup.js:83 -#: screens/User/UserTokenDetail/UserTokenDetail.js:38 +#: screens/User/UserTokenDetail/UserTokenDetail.js:39 #: screens/User/shared/UserTokenForm.js:48 msgid "Application" msgstr "" @@ -456,13 +465,13 @@ msgstr "" msgid "Application not found." msgstr "" -#: components/Lookup/ApplicationLookup.js:95 +#: components/Lookup/ApplicationLookup.js:96 #: routeConfig.js:142 #: screens/Application/Applications.js:26 #: screens/Application/Applications.js:35 #: screens/Application/ApplicationsList/ApplicationsList.js:113 #: screens/Application/ApplicationsList/ApplicationsList.js:148 -#: util/getRelatedResourceDeleteDetails.js:208 +#: util/getRelatedResourceDeleteDetails.js:209 msgid "Applications" msgstr "" @@ -477,17 +486,21 @@ msgstr "" msgid "Approval" msgstr "" -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:99 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:106 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:130 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:58 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:44 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:47 msgid "Approve" msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:115 -msgid "Approve, cancel or deny" -msgstr "" +#~ msgid "Approve, cancel or deny" +#~ msgstr "" -#: components/StatusLabel/StatusLabel.js:31 +#: components/StatusLabel/StatusLabel.js:39 msgid "Approved" msgstr "" @@ -499,11 +512,12 @@ msgstr "" msgid "Approved by {0} - {1}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:128 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:162 +#: components/Schedule/shared/FrequencyDetailSubform.js:113 msgid "April" msgstr "" -#: components/JobCancelButton/JobCancelButton.js:89 +#: components/JobCancelButton/JobCancelButton.js:104 msgid "Are you sure you want to cancel this job?" msgstr "" @@ -547,7 +561,7 @@ msgstr "" msgid "Are you sure you want to remove {0} access from {username}?" msgstr "" -#: screens/Job/JobOutput/JobOutput.js:771 +#: screens/Job/JobOutput/JobOutput.js:838 msgid "Are you sure you want to submit the request to cancel this job?" msgstr "" @@ -556,11 +570,11 @@ msgstr "" msgid "Arguments" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:541 +#: screens/Job/JobDetail/JobDetail.js:559 msgid "Artifacts" msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:251 #: screens/User/UserTeams/UserTeamList.js:208 msgid "Associate" msgstr "" @@ -574,11 +588,12 @@ msgstr "" msgid "Association modal" msgstr "" -#: components/LaunchPrompt/steps/SurveyStep.js:166 +#: components/LaunchPrompt/steps/SurveyStep.js:168 msgid "At least one value must be selected for this field." msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:148 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:166 +#: components/Schedule/shared/FrequencyDetailSubform.js:133 msgid "August" msgstr "" @@ -590,15 +605,17 @@ msgstr "" msgid "Authorization Code Expiration" msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:80 -#: screens/Application/shared/ApplicationForm.js:84 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:81 +#: screens/Application/shared/ApplicationForm.js:85 msgid "Authorization grant type" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:208 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:159 -#: screens/Instances/InstanceList/InstanceListItem.js:219 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:83 msgid "Auto" msgstr "" @@ -611,7 +628,11 @@ msgstr "" msgid "Automation Analytics dashboard" msgstr "" -#: screens/Setting/Settings.js:46 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:175 +msgid "Automation controller version" +msgstr "" + +#: screens/Setting/Settings.js:47 msgid "Azure AD" msgstr "" @@ -619,18 +640,18 @@ msgstr "" msgid "Azure AD settings" msgstr "" -#: components/AdHocCommands/AdHocCommandsWizard.js:50 +#: components/AdHocCommands/AdHocCommandsWizard.js:49 #: components/AddRole/AddResourceRole.js:267 -#: components/LaunchPrompt/LaunchPrompt.js:128 -#: components/Schedule/shared/SchedulePromptableFields.js:132 +#: components/LaunchPrompt/LaunchPrompt.js:158 +#: components/Schedule/shared/SchedulePromptableFields.js:125 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:90 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:70 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:152 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:155 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:154 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:157 msgid "Back" msgstr "" -#: screens/Credential/Credential.js:65 +#: screens/Credential/Credential.js:80 msgid "Back to Credentials" msgstr "" @@ -653,8 +674,9 @@ msgstr "" msgid "Back to Instance Groups" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:171 -#: screens/Instances/Instance.js:18 +#: components/InstanceDetails.js/InstanceDetails.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:175 +#: screens/Instances/Instance.js:22 msgid "Back to Instances" msgstr "" @@ -663,7 +685,7 @@ msgstr "" msgid "Back to Inventories" msgstr "" -#: screens/Job/Job.js:110 +#: screens/Job/Job.js:123 msgid "Back to Jobs" msgstr "" @@ -690,10 +712,11 @@ msgstr "" #: screens/Setting/LDAP/LDAPDetail/LDAPDetail.js:95 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:69 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:43 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:90 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:91 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:44 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:49 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:45 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:25 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:34 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:49 #: screens/Setting/UI/UIDetail/UIDetail.js:59 msgid "Back to Settings" @@ -752,7 +775,7 @@ msgid "" "path used to locate playbooks." msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:433 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:448 msgid "Basic auth password" msgstr "" @@ -764,6 +787,14 @@ msgid "" "provide a custom refspec." msgstr "" +#: screens/Template/shared/JobTemplate.helptext.js:27 +msgid "Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + +#: screens/Inventory/shared/Inventory.helptext.js:155 +msgid "Branch to use on inventory sync. Project default used if blank. Only allowed if project allow_override field is set to true." +msgstr "" + #: components/About/About.js:45 msgid "Brand Image" msgstr "" @@ -786,32 +817,34 @@ msgid "By default, we collect and transmit analytics data on the service usage t msgstr "" #: screens/TopologyView/Legend.js:74 -msgid "C" -msgstr "" +#~ msgid "C" +#~ msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 -#: screens/InstanceGroup/Instances/InstanceListItem.js:145 -#: screens/Instances/InstanceDetail/InstanceDetail.js:171 -#: screens/Instances/InstanceList/InstanceListItem.js:155 +#: components/InstanceDetails.js/InstanceDetails.js:332 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:247 +#: screens/InstanceGroup/Instances/InstanceListItem.js:159 +#: screens/Instances/InstanceDetail/InstanceDetail.js:273 +#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: screens/TopologyView/Tooltip.js:285 msgid "CPU {0}" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:113 -#: components/PromptDetail/PromptProjectDetail.js:136 -#: screens/Project/ProjectDetail/ProjectDetail.js:250 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:114 +#: components/PromptDetail/PromptInventorySourceDetail.js:102 +#: components/PromptDetail/PromptProjectDetail.js:151 +#: screens/Project/ProjectDetail/ProjectDetail.js:268 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:118 msgid "Cache Timeout" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:252 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:243 msgid "Cache timeout" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:114 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:106 msgid "Cache timeout (seconds)" msgstr "" -#: components/AdHocCommands/AdHocCommandsWizard.js:51 +#: components/AdHocCommands/AdHocCommandsWizard.js:50 #: components/AddRole/AddResourceRole.js:268 #: components/AssociateModal/AssociateModal.js:114 #: components/AssociateModal/AssociateModal.js:119 @@ -821,20 +854,21 @@ msgstr "" #: components/DisassociateButton/DisassociateButton.js:142 #: components/FormActionGroup/FormActionGroup.js:23 #: components/FormActionGroup/FormActionGroup.js:29 -#: components/LaunchPrompt/LaunchPrompt.js:129 -#: components/Lookup/HostFilterLookup.js:387 -#: components/Lookup/Lookup.js:203 +#: components/LaunchPrompt/LaunchPrompt.js:159 +#: components/Lookup/HostFilterLookup.js:388 +#: components/Lookup/Lookup.js:209 #: components/PaginatedTable/ToolbarDeleteButton.js:282 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:37 -#: components/Schedule/shared/ScheduleForm.js:462 -#: components/Schedule/shared/ScheduleForm.js:467 -#: components/Schedule/shared/ScheduleForm.js:678 -#: components/Schedule/shared/ScheduleForm.js:683 -#: components/Schedule/shared/SchedulePromptableFields.js:133 +#: components/Schedule/shared/ScheduleForm.js:547 +#: components/Schedule/shared/ScheduleForm.js:552 +#: components/Schedule/shared/SchedulePromptableFields.js:126 +#: components/Schedule/shared/UnsupportedScheduleForm.js:22 +#: components/Schedule/shared/UnsupportedScheduleForm.js:27 #: screens/Credential/shared/CredentialForm.js:343 #: screens/Credential/shared/CredentialForm.js:348 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:100 #: screens/Credential/shared/ExternalTestModal.js:98 +#: screens/Instances/Shared/RemoveInstanceButton.js:174 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:111 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:63 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:66 @@ -855,38 +889,44 @@ msgstr "" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:39 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:45 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeDeleteModal.js:50 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:162 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:165 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:164 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:167 #: screens/User/UserRoles/UserRolesList.js:224 #: screens/User/UserRoles/UserRolesList.js:227 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:84 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:92 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:104 msgid "Cancel" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:306 #: screens/Inventory/InventorySources/InventorySourceListItem.js:112 msgid "Cancel Inventory Source Sync" msgstr "" -#: components/JobCancelButton/JobCancelButton.js:55 -#: screens/Job/JobOutput/JobOutput.js:747 -#: screens/Job/JobOutput/JobOutput.js:748 +#: components/JobCancelButton/JobCancelButton.js:69 +#: screens/Job/JobOutput/JobOutput.js:814 +#: screens/Job/JobOutput/JobOutput.js:815 msgid "Cancel Job" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:303 +#: screens/Project/ProjectDetail/ProjectDetail.js:321 #: screens/Project/ProjectList/ProjectListItem.js:230 msgid "Cancel Project Sync" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:318 -#: screens/Project/ProjectDetail/ProjectDetail.js:305 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 +#: screens/Project/ProjectDetail/ProjectDetail.js:323 msgid "Cancel Sync" msgstr "" -#: screens/Job/JobOutput/JobOutput.js:755 -#: screens/Job/JobOutput/JobOutput.js:758 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:322 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:327 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:95 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:101 +msgid "Cancel Workflow" +msgstr "" + +#: screens/Job/JobOutput/JobOutput.js:822 +#: screens/Job/JobOutput/JobOutput.js:825 msgid "Cancel job" msgstr "" @@ -898,7 +938,7 @@ msgstr "" msgid "Cancel link removal" msgstr "" -#: components/Lookup/Lookup.js:201 +#: components/Lookup/Lookup.js:207 msgid "Cancel lookup" msgstr "" @@ -924,22 +964,22 @@ msgid "Cancel subscription edit" msgstr "" #: components/JobList/JobListItem.js:113 -#: screens/Job/JobDetail/JobDetail.js:582 -#: screens/Job/JobOutput/shared/OutputToolbar.js:137 +#: screens/Job/JobDetail/JobDetail.js:600 +#: screens/Job/JobOutput/shared/OutputToolbar.js:158 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:89 msgid "Cancel {0}" msgstr "" #: components/JobList/JobList.js:234 -#: components/StatusLabel/StatusLabel.js:46 +#: components/StatusLabel/StatusLabel.js:54 #: components/Workflow/WorkflowNodeHelp.js:111 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:253 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:212 msgid "Canceled" msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:58 -msgid "Cannot approve, cancel or deny completed workflow approvals" -msgstr "" +#~ msgid "Cannot approve, cancel or deny completed workflow approvals" +#~ msgstr "" #: screens/Setting/Logging/LoggingEdit/LoggingEdit.js:129 msgid "" @@ -947,21 +987,23 @@ msgid "" "logging aggregator host and logging aggregator type." msgstr "" -#: screens/Instances/InstanceList/InstanceList.js:148 +#: screens/Instances/InstancePeers/InstancePeerList.js:94 msgid "Cannot run health check on hop nodes." msgstr "" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:213 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:199 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:74 +#: screens/TopologyView/Tooltip.js:312 msgid "Capacity" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 -#: screens/InstanceGroup/Instances/InstanceList.js:258 -#: screens/InstanceGroup/Instances/InstanceListItem.js:143 -#: screens/Instances/InstanceDetail/InstanceDetail.js:168 -#: screens/Instances/InstanceList/InstanceList.js:153 -#: screens/Instances/InstanceList/InstanceListItem.js:153 +#: components/InstanceDetails.js/InstanceDetails.js:328 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:244 +#: screens/InstanceGroup/Instances/InstanceList.js:291 +#: screens/InstanceGroup/Instances/InstanceListItem.js:157 +#: screens/Instances/InstanceDetail/InstanceDetail.js:269 +#: screens/Instances/InstanceList/InstanceList.js:224 +#: screens/Instances/InstanceList/InstanceListItem.js:169 msgid "Capacity Adjustment" msgstr "" @@ -991,7 +1033,7 @@ msgid "" "{brandName} to change this location." msgstr "" -#: components/StatusLabel/StatusLabel.js:47 +#: components/StatusLabel/StatusLabel.js:55 #: screens/Job/JobOutput/shared/HostStatusBar.js:43 msgid "Changed" msgstr "" @@ -1000,13 +1042,13 @@ msgstr "" msgid "Changes" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:253 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:257 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:258 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:266 msgid "Channel" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:103 -#: screens/Template/shared/JobTemplateForm.js:214 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:138 +#: screens/Template/shared/JobTemplateForm.js:218 msgid "Check" msgstr "" @@ -1026,20 +1068,20 @@ msgstr "" msgid "Choose a Notification Type" msgstr "" -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:24 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:25 msgid "Choose a Playbook Directory" msgstr "" -#: screens/Project/shared/ProjectForm.js:224 +#: screens/Project/shared/ProjectForm.js:268 msgid "Choose a Source Control Type" msgstr "" -#: screens/Template/shared/WebhookSubForm.js:99 +#: screens/Template/shared/WebhookSubForm.js:100 msgid "Choose a Webhook Service" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:96 -#: screens/Template/shared/JobTemplateForm.js:207 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:131 +#: screens/Template/shared/JobTemplateForm.js:211 msgid "Choose a job type" msgstr "" @@ -1051,7 +1093,7 @@ msgstr "" msgid "Choose a source" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:475 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:490 msgid "Choose an HTTP method" msgstr "" @@ -1074,7 +1116,7 @@ msgstr "" msgid "Choose the type of resource that will be receiving new roles. For example, if you'd like to add new roles to a set of users please choose Users and click Next. You'll be able to select the specific resources in the next step." msgstr "" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:70 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:74 msgid "Clean" msgstr "" @@ -1084,7 +1126,7 @@ msgid "Clear" msgstr "" #: components/DataListToolbar/DataListToolbar.js:95 -#: screens/Job/JobOutput/JobOutputSearch.js:145 +#: screens/Job/JobOutput/JobOutputSearch.js:144 msgid "Clear all filters" msgstr "" @@ -1100,7 +1142,7 @@ msgstr "" msgid "Click an available node to create a new link. Click outside the graph to cancel." msgstr "" -#: screens/TopologyView/Tooltip.js:60 +#: screens/TopologyView/Tooltip.js:191 msgid "Click on a node icon to display the details." msgstr "" @@ -1112,10 +1154,15 @@ msgstr "" msgid "Click this button to verify connection to the secret management system using the selected credential and specified inputs." msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:152 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:179 msgid "Click to create a new link to this node." msgstr "" +#: components/InstanceDetails.js/InstanceDetails.js:312 +#: screens/Instances/InstanceDetail/InstanceDetail.js:253 +msgid "Click to download bundle" +msgstr "" + #: screens/Template/Survey/SurveyToolbar.js:64 msgid "Click to rearrange the order of the survey questions" msgstr "" @@ -1128,16 +1175,16 @@ msgstr "" msgid "Click to view job details" msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:88 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:89 #: screens/Application/Applications.js:84 msgid "Client ID" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:284 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:289 msgid "Client Identifier" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:305 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:314 msgid "Client identifier" msgstr "" @@ -1145,8 +1192,8 @@ msgstr "" msgid "Client secret" msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:99 -#: screens/Application/shared/ApplicationForm.js:126 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:100 +#: screens/Application/shared/ApplicationForm.js:127 msgid "Client type" msgstr "" @@ -1182,26 +1229,26 @@ msgid "Command" msgstr "" #: components/Schedule/shared/ScheduleForm.js:453 -msgid "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." -msgstr "" +#~ msgid "Complex schedules are not supported in the UI yet, please use the API to manage this schedule." +#~ msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:49 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:66 msgid "Compliant" msgstr "" #: components/PromptDetail/PromptJobTemplateDetail.js:68 #: components/PromptDetail/PromptWFJobTemplateDetail.js:36 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:130 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:133 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:58 -#: screens/Template/shared/JobTemplateForm.js:539 +#: screens/Template/shared/JobTemplateForm.js:591 msgid "Concurrent Jobs" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:35 +#: screens/Template/shared/JobTemplate.helptext.js:38 msgid "Concurrent jobs: If enabled, simultaneous runs of this job template will be allowed." msgstr "" -#: screens/Template/shared/WorkflowJobTemplate.helptext.js:23 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:25 msgid "Concurrent jobs: If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "" @@ -1224,11 +1271,11 @@ msgstr "" msgid "Confirm Password" msgstr "" -#: components/JobCancelButton/JobCancelButton.js:71 +#: components/JobCancelButton/JobCancelButton.js:86 msgid "Confirm cancel job" msgstr "" -#: components/JobCancelButton/JobCancelButton.js:75 +#: components/JobCancelButton/JobCancelButton.js:90 msgid "Confirm cancellation" msgstr "" @@ -1252,6 +1299,10 @@ msgstr "" msgid "Confirm removal of all nodes" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:160 +msgid "Confirm remove" +msgstr "" + #: screens/Setting/shared/RevertAllAlert.js:20 msgid "Confirm revert all" msgstr "" @@ -1260,11 +1311,11 @@ msgstr "" msgid "Confirm selection" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:361 +#: screens/Job/JobDetail/JobDetail.js:366 msgid "Container Group" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:47 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:57 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:68 msgid "Container group" @@ -1274,17 +1325,23 @@ msgstr "" msgid "Container group not found." msgstr "" -#: components/LaunchPrompt/LaunchPrompt.js:123 -#: components/Schedule/shared/SchedulePromptableFields.js:127 +#: components/LaunchPrompt/LaunchPrompt.js:153 +#: components/Schedule/shared/SchedulePromptableFields.js:120 msgid "Content Loading" msgstr "" +#: components/PromptDetail/PromptProjectDetail.js:130 +#: screens/Project/ProjectDetail/ProjectDetail.js:240 +#: screens/Project/shared/ProjectForm.js:290 +msgid "Content Signature Validation Credential" +msgstr "" + #: components/AppContainer/AppContainer.js:142 msgid "Continue" msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:196 -#: screens/Instances/InstanceList/InstanceList.js:116 +#: screens/InstanceGroup/Instances/InstanceList.js:225 +#: screens/Instances/InstanceList/InstanceList.js:169 msgid "Control" msgstr "" @@ -1299,10 +1356,10 @@ msgid "" msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:139 -msgid "" -"Control the level of output ansible\n" -"will produce as the playbook executes." -msgstr "" +#~ msgid "" +#~ "Control the level of output ansible\n" +#~ "will produce as the playbook executes." +#~ msgstr "" #: screens/Template/shared/JobTemplateForm.js:464 #~ msgid "" @@ -1310,16 +1367,16 @@ msgstr "" #~ "produce as the playbook executes." #~ msgstr "" -#: screens/Job/Job.helptext.js:14 -#: screens/Template/shared/JobTemplate.helptext.js:15 +#: screens/Job/Job.helptext.js:15 +#: screens/Template/shared/JobTemplate.helptext.js:16 msgid "Control the level of output ansible will produce as the playbook executes." msgstr "" -#: screens/Job/JobDetail/JobDetail.js:346 +#: screens/Job/JobDetail/JobDetail.js:351 msgid "Controller Node" msgstr "" -#: components/PromptDetail/PromptDetail.js:121 +#: components/PromptDetail/PromptDetail.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:225 msgid "Convergence" msgstr "" @@ -1361,7 +1418,7 @@ msgstr "" msgid "Copy Template" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:201 +#: screens/Project/ProjectDetail/ProjectDetail.js:202 #: screens/Project/ProjectList/ProjectListItem.js:98 msgid "Copy full revision to clipboard." msgstr "" @@ -1370,11 +1427,12 @@ msgstr "" msgid "Copyright" msgstr "" +#: components/LaunchPrompt/steps/OtherPromptsStep.js:231 #: components/MultiSelect/TagMultiSelect.js:62 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:66 -#: screens/Inventory/shared/InventoryForm.js:83 -#: screens/Template/shared/JobTemplateForm.js:387 -#: screens/Template/shared/WorkflowJobTemplateForm.js:197 +#: screens/Inventory/shared/InventoryForm.js:91 +#: screens/Template/shared/JobTemplateForm.js:396 +#: screens/Template/shared/WorkflowJobTemplateForm.js:204 msgid "Create" msgstr "" @@ -1437,8 +1495,12 @@ msgstr "" msgid "Create a new Smart Inventory with the applied filter" msgstr "" -#: screens/InstanceGroup/InstanceGroups.js:47 -#: screens/InstanceGroup/InstanceGroups.js:57 +#: screens/Instances/Instances.js:14 +msgid "Create new Instance" +msgstr "" + +#: screens/InstanceGroup/InstanceGroups.js:18 +#: screens/InstanceGroup/InstanceGroups.js:28 msgid "Create new container group" msgstr "" @@ -1465,8 +1527,8 @@ msgstr "" msgid "Create new host" msgstr "" -#: screens/InstanceGroup/InstanceGroups.js:46 -#: screens/InstanceGroup/InstanceGroups.js:56 +#: screens/InstanceGroup/InstanceGroups.js:17 +#: screens/InstanceGroup/InstanceGroups.js:27 msgid "Create new instance group" msgstr "" @@ -1486,34 +1548,34 @@ msgstr "" msgid "Create user token" msgstr "" -#: components/Lookup/ApplicationLookup.js:114 -#: components/PromptDetail/PromptDetail.js:145 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:270 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:104 +#: components/Lookup/ApplicationLookup.js:115 +#: components/PromptDetail/PromptDetail.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:402 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:105 #: screens/Credential/CredentialDetail/CredentialDetail.js:257 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:90 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:102 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:103 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:151 -#: screens/Host/HostDetail/HostDetail.js:84 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:67 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:93 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:134 +#: screens/Host/HostDetail/HostDetail.js:86 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:86 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:107 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:158 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:43 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:82 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:293 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:151 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:47 -#: screens/Job/JobDetail/JobDetail.js:516 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:388 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:115 -#: screens/Project/ProjectDetail/ProjectDetail.js:274 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:283 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:133 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Job/JobDetail/JobDetail.js:534 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:111 +#: screens/Project/ProjectDetail/ProjectDetail.js:292 #: screens/Team/TeamDetail/TeamDetail.js:47 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:339 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:188 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:349 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:187 #: screens/User/UserDetail/UserDetail.js:82 -#: screens/User/UserTokenDetail/UserTokenDetail.js:60 +#: screens/User/UserTokenDetail/UserTokenDetail.js:61 #: screens/User/UserTokenList/UserTokenList.js:150 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:240 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:199 msgid "Created" msgstr "" @@ -1521,17 +1583,17 @@ msgstr "" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:112 #: components/AddRole/AddResourceRole.js:57 #: components/AssociateModal/AssociateModal.js:144 -#: components/LaunchPrompt/steps/CredentialsStep.js:173 +#: components/LaunchPrompt/steps/CredentialsStep.js:177 #: components/LaunchPrompt/steps/InventoryStep.js:89 -#: components/Lookup/CredentialLookup.js:193 -#: components/Lookup/InventoryLookup.js:161 -#: components/Lookup/InventoryLookup.js:216 -#: components/Lookup/MultiCredentialsLookup.js:193 -#: components/Lookup/OrganizationLookup.js:133 -#: components/Lookup/ProjectLookup.js:150 +#: components/Lookup/CredentialLookup.js:194 +#: components/Lookup/InventoryLookup.js:152 +#: components/Lookup/InventoryLookup.js:207 +#: components/Lookup/MultiCredentialsLookup.js:198 +#: components/Lookup/OrganizationLookup.js:134 +#: components/Lookup/ProjectLookup.js:151 #: components/NotificationList/NotificationList.js:206 -#: components/RelatedTemplateList/RelatedTemplateList.js:166 -#: components/Schedule/ScheduleList/ScheduleList.js:197 +#: components/RelatedTemplateList/RelatedTemplateList.js:179 +#: components/Schedule/ScheduleList/ScheduleList.js:198 #: components/TemplateList/TemplateList.js:226 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:27 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:58 @@ -1555,7 +1617,7 @@ msgstr "" #: screens/Organization/OrganizationList/OrganizationList.js:131 #: screens/Project/ProjectList/ProjectList.js:213 #: screens/Team/TeamList/TeamList.js:130 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:163 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:161 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:108 msgid "Created By (Username)" @@ -1569,29 +1631,30 @@ msgstr "" #: components/AdHocCommands/AdHocPreviewStep.js:54 #: components/AdHocCommands/useAdHocCredentialStep.js:24 -#: components/PromptDetail/PromptInventorySourceDetail.js:119 +#: components/PromptDetail/PromptInventorySourceDetail.js:107 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:40 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:52 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:71 #: screens/InstanceGroup/shared/ContainerGroupForm.js:50 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:274 -#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:83 -#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:35 -#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:37 -#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:37 -#: util/getRelatedResourceDeleteDetails.js:166 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:264 +#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/EC2SubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:37 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:91 +#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:36 +#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:38 +#: util/getRelatedResourceDeleteDetails.js:167 msgid "Credential" msgstr "" -#: util/getRelatedResourceDeleteDetails.js:73 +#: util/getRelatedResourceDeleteDetails.js:74 msgid "Credential Input Sources" msgstr "" +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:83 #: components/Lookup/InstanceGroupsLookup.js:108 msgid "Credential Name" msgstr "" @@ -1616,7 +1679,7 @@ msgstr "" msgid "Credential copied successfully" msgstr "" -#: screens/Credential/Credential.js:98 +#: screens/Credential/Credential.js:117 msgid "Credential not found." msgstr "" @@ -1625,7 +1688,7 @@ msgstr "" msgid "Credential passwords" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:53 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 msgid "Credential to authenticate with Kubernetes or OpenShift" msgstr "" @@ -1642,25 +1705,25 @@ msgid "Credential type not found." msgstr "" #: components/JobList/JobListItem.js:260 -#: components/LaunchPrompt/steps/CredentialsStep.js:190 +#: components/LaunchPrompt/steps/CredentialsStep.js:194 #: components/LaunchPrompt/steps/useCredentialsStep.js:62 #: components/Lookup/MultiCredentialsLookup.js:138 -#: components/Lookup/MultiCredentialsLookup.js:210 -#: components/PromptDetail/PromptDetail.js:183 -#: components/PromptDetail/PromptJobTemplateDetail.js:186 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:324 -#: components/TemplateList/TemplateListItem.js:322 +#: components/Lookup/MultiCredentialsLookup.js:215 +#: components/PromptDetail/PromptDetail.js:193 +#: components/PromptDetail/PromptJobTemplateDetail.js:191 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:505 +#: components/TemplateList/TemplateListItem.js:323 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:77 #: routeConfig.js:70 #: screens/ActivityStream/ActivityStream.js:167 #: screens/Credential/CredentialList/CredentialList.js:195 #: screens/Credential/Credentials.js:14 #: screens/Credential/Credentials.js:24 -#: screens/Job/JobDetail/JobDetail.js:414 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:360 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:51 -#: screens/Template/shared/JobTemplateForm.js:365 -#: util/getRelatedResourceDeleteDetails.js:90 +#: screens/Job/JobDetail/JobDetail.js:429 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:370 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:49 +#: screens/Template/shared/JobTemplateForm.js:372 +#: util/getRelatedResourceDeleteDetails.js:91 msgid "Credentials" msgstr "" @@ -1672,11 +1735,11 @@ msgstr "" msgid "Current page" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:85 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:104 msgid "Custom Kubernetes or OpenShift Pod specification." msgstr "" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:99 msgid "Custom pod spec" msgstr "" @@ -1698,18 +1761,18 @@ msgstr "" msgid "Customize messages…" msgstr "" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:65 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:66 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:85 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:86 msgid "Customize pod specification" msgstr "" #: screens/Job/WorkflowOutput/WorkflowOutputNode.js:109 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:185 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:212 msgid "DELETED" msgstr "" #: routeConfig.js:34 -#: screens/Dashboard/Dashboard.js:74 +#: screens/Dashboard/Dashboard.js:91 msgid "Dashboard" msgstr "" @@ -1725,14 +1788,21 @@ msgstr "" msgid "Date" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:349 -#: components/Schedule/shared/FrequencyDetailSubform.js:453 -#: components/Schedule/shared/ScheduleForm.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:180 +#: components/Schedule/shared/FrequencyDetailSubform.js:177 +#: components/Schedule/shared/FrequencyDetailSubform.js:356 +#: components/Schedule/shared/FrequencyDetailSubform.js:460 +#: components/Schedule/shared/ScheduleFormFields.js:127 +#: components/Schedule/shared/ScheduleFormFields.js:187 msgid "Day" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:266 -#: components/Schedule/shared/ScheduleForm.js:167 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:130 +msgid "Day {0}" +msgstr "" + +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:395 +#: components/Schedule/shared/ScheduleFormFields.js:136 msgid "Days of Data to Keep" msgstr "" @@ -1740,7 +1810,7 @@ msgstr "" msgid "Days of data to be retained" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:105 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:167 msgid "Days remaining" msgstr "" @@ -1748,11 +1818,12 @@ msgstr "" msgid "Days to keep" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:103 +#: screens/Job/JobOutput/JobOutputSearch.js:102 msgid "Debug" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:168 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:170 +#: components/Schedule/shared/FrequencyDetailSubform.js:153 msgid "December" msgstr "" @@ -1779,7 +1850,7 @@ msgstr "" msgid "Default answer" msgstr "" -#: screens/Setting/SettingList.js:99 +#: screens/Setting/SettingList.js:103 msgid "Define system-level features and functions" msgstr "" @@ -1794,35 +1865,35 @@ msgstr "" #: components/PaginatedTable/ToolbarDeleteButton.js:250 #: components/PaginatedTable/ToolbarDeleteButton.js:273 #: components/ResourceAccessList/DeleteRoleConfirmationModal.js:29 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:127 -#: screens/Credential/CredentialDetail/CredentialDetail.js:307 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:623 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:128 +#: screens/Credential/CredentialDetail/CredentialDetail.js:306 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:124 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:133 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:115 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:162 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:134 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:134 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:141 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:186 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:101 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:332 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:176 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:322 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:158 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:64 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:68 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:73 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:78 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:102 -#: screens/Job/JobDetail/JobDetail.js:594 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:431 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:199 -#: screens/Project/ProjectDetail/ProjectDetail.js:322 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:76 +#: screens/Job/JobDetail/JobDetail.js:612 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:436 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:177 +#: screens/Project/ProjectDetail/ProjectDetail.js:340 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:80 #: screens/Team/TeamDetail/TeamDetail.js:70 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:528 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:523 #: screens/Template/Survey/SurveyList.js:66 #: screens/Template/Survey/SurveyToolbar.js:93 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:271 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 #: screens/User/UserDetail/UserDetail.js:107 -#: screens/User/UserTokenDetail/UserTokenDetail.js:77 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:365 +#: screens/User/UserTokenDetail/UserTokenDetail.js:78 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:340 msgid "Delete" msgstr "" @@ -1830,42 +1901,42 @@ msgstr "" msgid "Delete All Groups and Hosts" msgstr "" -#: screens/Credential/CredentialDetail/CredentialDetail.js:301 +#: screens/Credential/CredentialDetail/CredentialDetail.js:300 msgid "Delete Credential" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:126 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:127 msgid "Delete Execution Environment" msgstr "" -#: screens/Host/HostDetail/HostDetail.js:112 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:110 +#: screens/Host/HostDetail/HostDetail.js:114 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:109 msgid "Delete Host" msgstr "" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:157 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:181 msgid "Delete Inventory" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:590 -#: screens/Job/JobOutput/shared/OutputToolbar.js:195 -#: screens/Job/JobOutput/shared/OutputToolbar.js:199 +#: screens/Job/JobDetail/JobDetail.js:608 +#: screens/Job/JobOutput/shared/OutputToolbar.js:216 +#: screens/Job/JobOutput/shared/OutputToolbar.js:220 msgid "Delete Job" msgstr "" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:522 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:517 msgid "Delete Job Template" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:427 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:432 msgid "Delete Notification" msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:193 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:171 msgid "Delete Organization" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:316 +#: screens/Project/ProjectDetail/ProjectDetail.js:334 msgid "Delete Project" msgstr "" @@ -1873,7 +1944,7 @@ msgstr "" msgid "Delete Questions" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:415 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:619 msgid "Delete Schedule" msgstr "" @@ -1889,15 +1960,15 @@ msgstr "" msgid "Delete User" msgstr "" -#: screens/User/UserTokenDetail/UserTokenDetail.js:73 +#: screens/User/UserTokenDetail/UserTokenDetail.js:74 msgid "Delete User Token" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:361 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:336 msgid "Delete Workflow Approval" msgstr "" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:265 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:263 msgid "Delete Workflow Job Template" msgstr "" @@ -1906,7 +1977,7 @@ msgstr "" msgid "Delete all nodes" msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:123 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:124 msgid "Delete application" msgstr "" @@ -1918,16 +1989,16 @@ msgstr "" msgid "Delete error" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:109 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:121 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:128 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 msgid "Delete instance group" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:326 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:316 msgid "Delete inventory source" msgstr "" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:172 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:154 msgid "Delete smart inventory" msgstr "" @@ -1935,7 +2006,7 @@ msgstr "" msgid "Delete survey question" msgstr "" -#: screens/Project/shared/Project.helptext.js:110 +#: screens/Project/shared/Project.helptext.js:114 msgid "" "Delete the local repository in its entirety prior to\n" "performing an update. Depending on the size of the\n" @@ -1944,7 +2015,7 @@ msgid "" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:51 -#: screens/Project/ProjectDetail/ProjectDetail.js:99 +#: screens/Project/ProjectDetail/ProjectDetail.js:100 msgid "Delete the project before syncing" msgstr "" @@ -1952,7 +2023,7 @@ msgstr "" msgid "Delete this link" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:247 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:274 msgid "Delete this node" msgstr "" @@ -1963,9 +2034,9 @@ msgstr "" #: components/DetailList/DeletedDetail.js:19 #: components/Workflow/WorkflowNodeHelp.js:157 #: components/Workflow/WorkflowNodeHelp.js:193 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:272 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:40 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:51 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:231 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:49 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:60 msgid "Deleted" msgstr "" @@ -1978,11 +2049,11 @@ msgstr "" #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:202 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:227 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:233 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:219 msgid "Deletion error" msgstr "" -#: components/StatusLabel/StatusLabel.js:32 +#: components/StatusLabel/StatusLabel.js:40 msgid "Denied" msgstr "" @@ -1994,125 +2065,141 @@ msgstr "" msgid "Denied by {0} - {1}" msgstr "" -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:72 -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:80 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:30 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:46 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:54 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:58 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:42 msgid "Deny" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:104 +#: screens/Job/JobOutput/JobOutputSearch.js:103 msgid "Deprecated" msgstr "" +#: components/StatusLabel/StatusLabel.js:60 +#: screens/TopologyView/Legend.js:164 +msgid "Deprovisioning" +msgstr "" + +#: components/StatusLabel/StatusLabel.js:63 +msgid "Deprovisioning fail" +msgstr "" + #: components/HostForm/HostForm.js:104 -#: components/Lookup/ApplicationLookup.js:104 -#: components/Lookup/ApplicationLookup.js:122 -#: components/Lookup/HostFilterLookup.js:422 +#: components/Lookup/ApplicationLookup.js:105 +#: components/Lookup/ApplicationLookup.js:123 +#: components/Lookup/HostFilterLookup.js:423 #: components/Lookup/HostListItem.js:9 #: components/NotificationList/NotificationList.js:186 -#: components/PromptDetail/PromptDetail.js:110 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:253 -#: components/Schedule/ScheduleList/ScheduleList.js:193 -#: components/Schedule/shared/ScheduleForm.js:115 +#: components/PromptDetail/PromptDetail.js:120 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:323 +#: components/Schedule/ScheduleList/ScheduleList.js:194 +#: components/Schedule/shared/ScheduleFormFields.js:80 #: components/TemplateList/TemplateList.js:210 #: components/TemplateList/TemplateListItem.js:271 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:64 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:65 #: screens/Application/ApplicationsList/ApplicationsList.js:123 -#: screens/Application/shared/ApplicationForm.js:61 +#: screens/Application/shared/ApplicationForm.js:62 #: screens/Credential/CredentialDetail/CredentialDetail.js:223 #: screens/Credential/CredentialList/CredentialList.js:146 #: screens/Credential/shared/CredentialForm.js:169 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:72 #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:128 #: screens/CredentialType/shared/CredentialTypeForm.js:29 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:59 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:60 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:159 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:126 -#: screens/Host/HostDetail/HostDetail.js:73 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:127 +#: screens/Host/HostDetail/HostDetail.js:75 #: screens/Host/HostList/HostList.js:153 #: screens/Host/HostList/HostList.js:170 #: screens/Host/HostList/HostListItem.js:57 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:71 +#: screens/Instances/Shared/InstanceForm.js:26 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:94 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:35 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:216 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:81 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:40 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:80 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:70 #: screens/Inventory/InventoryHosts/InventoryHostList.js:124 #: screens/Inventory/InventoryHosts/InventoryHostList.js:139 #: screens/Inventory/InventoryList/InventoryList.js:195 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:213 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:37 -#: screens/Inventory/shared/InventoryForm.js:50 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:199 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:104 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:36 +#: screens/Inventory/shared/InventoryForm.js:58 #: screens/Inventory/shared/InventoryGroupForm.js:40 #: screens/Inventory/shared/InventorySourceForm.js:109 #: screens/Inventory/shared/SmartInventoryForm.js:55 -#: screens/Job/JobOutput/HostEventModal.js:112 +#: screens/Job/JobOutput/HostEventModal.js:113 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:101 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:72 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:108 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:109 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:127 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:49 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:95 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 #: screens/Organization/OrganizationList/OrganizationList.js:127 #: screens/Organization/shared/OrganizationForm.js:64 -#: screens/Project/ProjectDetail/ProjectDetail.js:176 +#: screens/Project/ProjectDetail/ProjectDetail.js:177 #: screens/Project/ProjectList/ProjectList.js:190 #: screens/Project/ProjectList/ProjectListItem.js:281 -#: screens/Project/shared/ProjectForm.js:178 +#: screens/Project/shared/ProjectForm.js:222 #: screens/Team/TeamDetail/TeamDetail.js:38 #: screens/Team/TeamList/TeamList.js:122 #: screens/Team/shared/TeamForm.js:37 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:180 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:183 #: screens/Template/Survey/SurveyQuestionForm.js:171 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:112 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:183 -#: screens/Template/shared/JobTemplateForm.js:247 -#: screens/Template/shared/WorkflowJobTemplateForm.js:112 +#: screens/Template/shared/JobTemplateForm.js:251 +#: screens/Template/shared/WorkflowJobTemplateForm.js:117 #: screens/User/UserOrganizations/UserOrganizationList.js:80 #: screens/User/UserOrganizations/UserOrganizationListItem.js:18 #: screens/User/UserTeams/UserTeamList.js:182 #: screens/User/UserTeams/UserTeamListItem.js:32 -#: screens/User/UserTokenDetail/UserTokenDetail.js:44 +#: screens/User/UserTokenDetail/UserTokenDetail.js:45 #: screens/User/UserTokenList/UserTokenList.js:128 #: screens/User/UserTokenList/UserTokenList.js:138 #: screens/User/UserTokenList/UserTokenList.js:188 #: screens/User/UserTokenList/UserTokenListItem.js:29 #: screens/User/shared/UserTokenForm.js:59 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:205 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:145 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:176 msgid "Description" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:320 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:325 msgid "Destination Channels" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:228 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:233 msgid "Destination Channels or Users" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:341 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:346 msgid "Destination SMS Number(s)" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:399 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:412 msgid "Destination SMS number(s)" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:353 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:364 msgid "Destination channels" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:222 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:231 msgid "Destination channels or users" msgstr "" #: components/AdHocCommands/useAdHocDetailsStep.js:35 -#: components/ErrorDetail/ErrorDetail.js:80 +#: components/ErrorDetail/ErrorDetail.js:88 +#: components/InstanceDetails.js/InstanceDetails.js:221 #: components/Schedule/Schedule.js:71 #: screens/Application/Application/Application.js:79 #: screens/Application/Applications.js:39 -#: screens/Credential/Credential.js:72 +#: screens/Credential/Credential.js:87 #: screens/Credential/Credentials.js:28 #: screens/CredentialType/CredentialType.js:63 #: screens/CredentialType/CredentialTypes.js:26 @@ -2121,12 +2208,12 @@ msgstr "" #: screens/Host/Host.js:58 #: screens/Host/Hosts.js:27 #: screens/InstanceGroup/ContainerGroup.js:66 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:178 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:182 #: screens/InstanceGroup/InstanceGroup.js:69 -#: screens/InstanceGroup/InstanceGroups.js:59 -#: screens/InstanceGroup/InstanceGroups.js:67 -#: screens/Instances/Instance.js:25 -#: screens/Instances/Instances.js:22 +#: screens/InstanceGroup/InstanceGroups.js:30 +#: screens/InstanceGroup/InstanceGroups.js:38 +#: screens/Instances/Instance.js:29 +#: screens/Instances/Instances.js:24 #: screens/Inventory/Inventories.js:61 #: screens/Inventory/Inventories.js:87 #: screens/Inventory/Inventory.js:64 @@ -2135,8 +2222,8 @@ msgstr "" #: screens/Inventory/InventorySource/InventorySource.js:83 #: screens/Inventory/SmartInventory.js:66 #: screens/Inventory/SmartInventoryHost/SmartInventoryHost.js:60 -#: screens/Job/Job.js:117 -#: screens/Job/JobOutput/HostEventModal.js:103 +#: screens/Job/Job.js:130 +#: screens/Job/JobOutput/HostEventModal.js:104 #: screens/Job/Jobs.js:35 #: screens/ManagementJob/ManagementJobs.js:26 #: screens/NotificationTemplate/NotificationTemplate.js:84 @@ -2150,33 +2237,35 @@ msgstr "" #: screens/Setting/Jobs/JobsDetail/JobsDetail.js:65 #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:76 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:50 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:97 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:98 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:51 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:56 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:52 -#: screens/Setting/Settings.js:44 -#: screens/Setting/Settings.js:47 -#: screens/Setting/Settings.js:51 -#: screens/Setting/Settings.js:54 -#: screens/Setting/Settings.js:57 -#: screens/Setting/Settings.js:60 -#: screens/Setting/Settings.js:63 -#: screens/Setting/Settings.js:66 -#: screens/Setting/Settings.js:69 -#: screens/Setting/Settings.js:72 -#: screens/Setting/Settings.js:81 -#: screens/Setting/Settings.js:82 -#: screens/Setting/Settings.js:83 -#: screens/Setting/Settings.js:84 +#: screens/Setting/Settings.js:45 +#: screens/Setting/Settings.js:48 +#: screens/Setting/Settings.js:52 +#: screens/Setting/Settings.js:55 +#: screens/Setting/Settings.js:58 +#: screens/Setting/Settings.js:61 +#: screens/Setting/Settings.js:64 +#: screens/Setting/Settings.js:67 +#: screens/Setting/Settings.js:70 +#: screens/Setting/Settings.js:73 +#: screens/Setting/Settings.js:76 #: screens/Setting/Settings.js:85 #: screens/Setting/Settings.js:86 -#: screens/Setting/Settings.js:94 -#: screens/Setting/Settings.js:97 -#: screens/Setting/Settings.js:100 -#: screens/Setting/Settings.js:103 -#: screens/Setting/Settings.js:106 -#: screens/Setting/Settings.js:109 -#: screens/Setting/Settings.js:112 -#: screens/Setting/Settings.js:115 +#: screens/Setting/Settings.js:87 +#: screens/Setting/Settings.js:88 +#: screens/Setting/Settings.js:89 +#: screens/Setting/Settings.js:90 +#: screens/Setting/Settings.js:98 +#: screens/Setting/Settings.js:101 +#: screens/Setting/Settings.js:104 +#: screens/Setting/Settings.js:107 +#: screens/Setting/Settings.js:110 +#: screens/Setting/Settings.js:113 +#: screens/Setting/Settings.js:116 +#: screens/Setting/Settings.js:119 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:56 #: screens/Setting/UI/UIDetail/UIDetail.js:66 #: screens/Team/Team.js:57 @@ -2184,9 +2273,9 @@ msgstr "" #: screens/Template/Template.js:135 #: screens/Template/Templates.js:43 #: screens/Template/WorkflowJobTemplate.js:117 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:140 -#: screens/TopologyView/Tooltip.js:56 -#: screens/TopologyView/Tooltip.js:70 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:138 +#: screens/TopologyView/Tooltip.js:187 +#: screens/TopologyView/Tooltip.js:213 #: screens/User/User.js:64 #: screens/User/UserToken/UserToken.js:54 #: screens/User/Users.js:30 @@ -2196,7 +2285,7 @@ msgstr "" msgid "Details" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:100 +#: screens/Job/JobOutput/HostEventModal.js:101 msgid "Details tab" msgstr "" @@ -2204,24 +2293,24 @@ msgstr "" msgid "Direct Keys" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:204 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:263 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:308 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:366 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:209 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:268 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:313 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:371 msgid "Disable SSL Verification" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:180 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:231 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:270 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:341 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:446 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:187 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:240 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:279 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:350 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:461 msgid "Disable SSL verification" msgstr "" #: components/InstanceToggle/InstanceToggle.js:56 -#: components/StatusLabel/StatusLabel.js:45 -#: screens/TopologyView/Legend.js:133 +#: components/StatusLabel/StatusLabel.js:53 +#: screens/TopologyView/Legend.js:233 msgid "Disabled" msgstr "" @@ -2244,8 +2333,8 @@ msgstr "" msgid "Disassociate host from group?" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:289 -#: screens/InstanceGroup/Instances/InstanceList.js:234 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:321 +#: screens/InstanceGroup/Instances/InstanceList.js:263 msgid "Disassociate instance from instance group?" msgstr "" @@ -2272,7 +2361,7 @@ msgid "Disassociate?" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:46 -#: screens/Project/ProjectDetail/ProjectDetail.js:93 +#: screens/Project/ProjectDetail/ProjectDetail.js:94 msgid "Discard local changes before syncing" msgstr "" @@ -2283,8 +2372,8 @@ msgstr "" #~ "same tasks against a portion of the inventory." #~ msgstr "" -#: screens/Job/Job.helptext.js:15 -#: screens/Template/shared/JobTemplate.helptext.js:16 +#: screens/Job/Job.helptext.js:16 +#: screens/Template/shared/JobTemplate.helptext.js:17 msgid "Divide the work done by this job template into the specified number of job slices, each running the same tasks against a portion of the inventory." msgstr "" @@ -2299,11 +2388,19 @@ msgstr "" msgid "Done" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:179 -#: screens/Job/JobOutput/shared/OutputToolbar.js:184 +#: screens/TopologyView/Tooltip.js:251 +msgid "Download Bundle" +msgstr "" + +#: screens/Job/JobOutput/shared/OutputToolbar.js:200 +#: screens/Job/JobOutput/shared/OutputToolbar.js:205 msgid "Download Output" msgstr "" +#: screens/TopologyView/Tooltip.js:247 +msgid "Download bundle" +msgstr "" + #: screens/Credential/shared/CredentialFormFields/CredentialField.js:93 #: screens/Credential/shared/CredentialFormFields/CredentialField.js:114 msgid "Drag a file here or browse to upload" @@ -2330,8 +2427,8 @@ msgid "E-mail" msgstr "" #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:121 -msgid "E-mail options" -msgstr "" +#~ msgid "E-mail options" +#~ msgstr "" #: screens/Inventory/shared/Inventory.helptext.js:113 msgid "" @@ -2340,35 +2437,35 @@ msgid "" "executing job tasks." msgstr "" -#: screens/Project/shared/Project.helptext.js:120 +#: screens/Project/shared/Project.helptext.js:124 msgid "" "Each time a job runs using this project, update the\n" "revision of the project prior to starting the job." msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:405 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:409 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:114 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:116 -#: screens/Credential/CredentialDetail/CredentialDetail.js:294 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:609 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:613 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:115 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:117 +#: screens/Credential/CredentialDetail/CredentialDetail.js:293 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:109 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:120 -#: screens/Host/HostDetail/HostDetail.js:106 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:101 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:113 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:151 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:121 +#: screens/Host/HostDetail/HostDetail.js:108 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:120 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:127 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:175 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:55 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:62 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:104 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:308 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:103 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:298 #: screens/Inventory/InventorySources/InventorySourceListItem.js:127 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:166 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:413 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:415 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:148 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:418 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:420 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:138 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:182 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 -#: screens/Project/ProjectDetail/ProjectDetail.js:295 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:160 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:164 +#: screens/Project/ProjectDetail/ProjectDetail.js:313 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:85 #: screens/Setting/AzureAD/AzureADDetail/AzureADDetail.js:89 #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:148 @@ -2383,24 +2480,26 @@ msgstr "" #: screens/Setting/Logging/LoggingDetail/LoggingDetail.js:111 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:84 #: screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.js:88 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:152 -#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:156 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:153 +#: screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.js:157 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:85 +#: screens/Setting/OIDC/OIDCDetail/OIDCDetail.js:89 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:99 #: screens/Setting/RADIUS/RADIUSDetail/RADIUSDetail.js:103 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:86 #: screens/Setting/SAML/SAMLDetail/SAMLDetail.js:90 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:169 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:199 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:103 #: screens/Setting/TACACS/TACACSDetail/TACACSDetail.js:108 #: screens/Setting/UI/UIDetail/UIDetail.js:105 #: screens/Setting/UI/UIDetail/UIDetail.js:110 #: screens/Team/TeamDetail/TeamDetail.js:55 #: screens/Team/TeamDetail/TeamDetail.js:59 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:497 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:499 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:492 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:494 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:239 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:241 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:243 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:241 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:260 #: screens/User/UserDetail/UserDetail.js:96 msgid "Edit" msgstr "" @@ -2423,30 +2522,31 @@ msgstr "" #: screens/Organization/Organizations.js:29 #: screens/Project/Projects.js:25 #: screens/Project/Projects.js:35 -#: screens/Setting/Settings.js:45 -#: screens/Setting/Settings.js:48 -#: screens/Setting/Settings.js:52 -#: screens/Setting/Settings.js:55 -#: screens/Setting/Settings.js:58 -#: screens/Setting/Settings.js:61 -#: screens/Setting/Settings.js:64 -#: screens/Setting/Settings.js:67 -#: screens/Setting/Settings.js:70 -#: screens/Setting/Settings.js:73 -#: screens/Setting/Settings.js:87 -#: screens/Setting/Settings.js:88 -#: screens/Setting/Settings.js:89 -#: screens/Setting/Settings.js:90 +#: screens/Setting/Settings.js:46 +#: screens/Setting/Settings.js:49 +#: screens/Setting/Settings.js:53 +#: screens/Setting/Settings.js:56 +#: screens/Setting/Settings.js:59 +#: screens/Setting/Settings.js:62 +#: screens/Setting/Settings.js:65 +#: screens/Setting/Settings.js:68 +#: screens/Setting/Settings.js:71 +#: screens/Setting/Settings.js:74 +#: screens/Setting/Settings.js:77 #: screens/Setting/Settings.js:91 #: screens/Setting/Settings.js:92 +#: screens/Setting/Settings.js:93 +#: screens/Setting/Settings.js:94 #: screens/Setting/Settings.js:95 -#: screens/Setting/Settings.js:98 -#: screens/Setting/Settings.js:101 -#: screens/Setting/Settings.js:104 -#: screens/Setting/Settings.js:107 -#: screens/Setting/Settings.js:110 -#: screens/Setting/Settings.js:113 -#: screens/Setting/Settings.js:116 +#: screens/Setting/Settings.js:96 +#: screens/Setting/Settings.js:99 +#: screens/Setting/Settings.js:102 +#: screens/Setting/Settings.js:105 +#: screens/Setting/Settings.js:108 +#: screens/Setting/Settings.js:111 +#: screens/Setting/Settings.js:114 +#: screens/Setting/Settings.js:117 +#: screens/Setting/Settings.js:120 #: screens/Team/Teams.js:28 #: screens/Template/Templates.js:44 #: screens/User/Users.js:29 @@ -2487,7 +2587,7 @@ msgid "Edit Login redirect override URL" msgstr "" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeEditModal.js:64 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:238 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:257 msgid "Edit Node" msgstr "" @@ -2513,8 +2613,8 @@ msgstr "" msgid "Edit Question" msgstr "" -#: components/Schedule/ScheduleList/ScheduleListItem.js:118 -#: components/Schedule/ScheduleList/ScheduleListItem.js:122 +#: components/Schedule/ScheduleList/ScheduleListItem.js:132 +#: components/Schedule/ScheduleList/ScheduleListItem.js:136 #: screens/Template/Templates.js:55 msgid "Edit Schedule" msgstr "" @@ -2556,8 +2656,8 @@ msgstr "" #: screens/CredentialType/CredentialTypes.js:25 #: screens/ExecutionEnvironment/ExecutionEnvironments.js:25 -#: screens/InstanceGroup/InstanceGroups.js:64 -#: screens/InstanceGroup/InstanceGroups.js:69 +#: screens/InstanceGroup/InstanceGroups.js:35 +#: screens/InstanceGroup/InstanceGroups.js:40 #: screens/Inventory/Inventories.js:63 #: screens/Inventory/Inventories.js:68 #: screens/Inventory/Inventories.js:77 @@ -2570,7 +2670,8 @@ msgstr "" msgid "Edit group" msgstr "" -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:48 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:100 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:103 msgid "Edit host" msgstr "" @@ -2588,7 +2689,7 @@ msgstr "" msgid "Edit this link" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:221 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:248 msgid "Edit this node" msgstr "" @@ -2597,16 +2698,16 @@ msgid "Edit workflow" msgstr "" #: components/Workflow/WorkflowNodeHelp.js:170 -#: screens/Job/JobOutput/shared/OutputToolbar.js:125 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:257 +#: screens/Job/JobOutput/shared/OutputToolbar.js:140 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:216 msgid "Elapsed" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:124 +#: screens/Job/JobOutput/shared/OutputToolbar.js:139 msgid "Elapsed Time" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:126 +#: screens/Job/JobOutput/shared/OutputToolbar.js:141 msgid "Elapsed time that the job ran" msgstr "" @@ -2618,15 +2719,16 @@ msgstr "" msgid "Email" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:175 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:177 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:125 msgid "Email Options" msgstr "" -#: screens/Template/shared/WorkflowJobTemplateForm.js:232 +#: screens/Template/shared/WorkflowJobTemplateForm.js:263 msgid "Enable Concurrent Jobs" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:545 +#: screens/Template/shared/JobTemplateForm.js:597 msgid "Enable Fact Storage" msgstr "" @@ -2634,10 +2736,14 @@ msgstr "" msgid "Enable HTTPS certificate verification" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:521 -#: screens/Template/shared/JobTemplateForm.js:524 -#: screens/Template/shared/WorkflowJobTemplateForm.js:213 -#: screens/Template/shared/WorkflowJobTemplateForm.js:216 +#: screens/Instances/Shared/InstanceForm.js:58 +msgid "Enable Instance" +msgstr "" + +#: screens/Template/shared/JobTemplateForm.js:573 +#: screens/Template/shared/JobTemplateForm.js:576 +#: screens/Template/shared/WorkflowJobTemplateForm.js:244 +#: screens/Template/shared/WorkflowJobTemplateForm.js:247 msgid "Enable Webhook" msgstr "" @@ -2645,6 +2751,14 @@ msgstr "" msgid "Enable Webhook for this workflow job template." msgstr "" +#: screens/Project/shared/Project.helptext.js:108 +msgid "" +"Enable content signing to verify that the content \n" +"has remained secure when a project is synced. \n" +"If the content has been tampered with, the \n" +"job will not run." +msgstr "" + #: screens/Setting/Logging/LoggingEdit/LoggingEdit.js:136 msgid "Enable external logging" msgstr "" @@ -2666,35 +2780,37 @@ msgstr "" msgid "Enable simplified login for your {brandName} applications" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:30 +#: screens/Template/shared/JobTemplate.helptext.js:31 msgid "Enable webhook for this template." msgstr "" #: components/InstanceToggle/InstanceToggle.js:55 #: components/Lookup/HostFilterLookup.js:110 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 +#: screens/TopologyView/Legend.js:205 msgid "Enabled" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:183 -#: components/PromptDetail/PromptJobTemplateDetail.js:182 -#: components/PromptDetail/PromptProjectDetail.js:130 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:97 -#: screens/Credential/CredentialDetail/CredentialDetail.js:269 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:281 -#: screens/Project/ProjectDetail/ProjectDetail.js:284 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:351 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:200 +#: components/PromptDetail/PromptInventorySourceDetail.js:171 +#: components/PromptDetail/PromptJobTemplateDetail.js:187 +#: components/PromptDetail/PromptProjectDetail.js:145 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:99 +#: screens/Credential/CredentialDetail/CredentialDetail.js:268 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:123 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:271 +#: screens/Project/ProjectDetail/ProjectDetail.js:302 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:361 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:199 msgid "Enabled Options" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:267 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:135 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:258 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:132 msgid "Enabled Value" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:262 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:125 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:119 msgid "Enabled Variable" msgstr "" @@ -2722,7 +2838,7 @@ msgstr "" #~ "template." #~ msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:28 +#: screens/Template/shared/JobTemplate.helptext.js:29 msgid "Enables creation of a provisioning callback URL. Using the URL a host can contact {brandName} and request a configuration update using this job template." msgstr "" @@ -2731,7 +2847,8 @@ msgstr "" msgid "Encrypted" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:500 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:109 +#: components/Schedule/shared/FrequencyDetailSubform.js:507 msgid "End" msgstr "" @@ -2743,12 +2860,16 @@ msgstr "" msgid "End date" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:555 +#: components/Schedule/shared/FrequencyDetailSubform.js:561 msgid "End date/time" msgstr "" #: components/Schedule/shared/buildRuleObj.js:97 -msgid "End did not match an expected value" +#~ msgid "End did not match an expected value" +#~ msgstr "" + +#: components/Schedule/shared/buildRuleObj.js:110 +msgid "End did not match an expected value ({0})" msgstr "" #: components/Schedule/shared/DateTimePicker.js:61 @@ -2772,14 +2893,18 @@ msgid "Enter inputs using either JSON or YAML syntax. Refer to the Ansible Contr msgstr "" #: screens/Inventory/shared/SmartInventoryForm.js:94 -msgid "" -"Enter inventory variables using either JSON or YAML syntax.\n" -"Use the radio button to toggle between the two. Refer to the\n" -"Ansible Controller documentation for example syntax." -msgstr "" +#~ msgid "" +#~ "Enter inventory variables using either JSON or YAML syntax.\n" +#~ "Use the radio button to toggle between the two. Refer to the\n" +#~ "Ansible Controller documentation for example syntax." +#~ msgstr "" #: screens/Inventory/shared/InventoryForm.js:65 -msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" +#~ msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax" +#~ msgstr "" + +#: screens/Inventory/shared/SmartInventoryForm.js:94 +msgid "Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Controller documentation for example syntax." msgstr "" #: screens/NotificationTemplate/shared/TypeInputsSubForm.js:181 @@ -2880,17 +3005,17 @@ msgid "Environment variables or extra variables that specify the values a creden msgstr "" #: components/JobList/JobList.js:233 -#: components/StatusLabel/StatusLabel.js:38 +#: components/StatusLabel/StatusLabel.js:46 #: components/Workflow/WorkflowNodeHelp.js:108 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:133 #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:205 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:142 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:143 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:230 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:123 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:135 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:236 -#: screens/Job/JobOutput/JobOutputSearch.js:105 -#: screens/TopologyView/Legend.js:124 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:142 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:149 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:222 +#: screens/Job/JobOutput/JobOutputSearch.js:104 +#: screens/TopologyView/Legend.js:178 msgid "Error" msgstr "" @@ -2898,18 +3023,18 @@ msgstr "" msgid "Error fetching updated project" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:496 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:501 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:141 msgid "Error message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:505 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:510 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:150 msgid "Error message body" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:617 -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:619 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:709 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:711 msgid "Error saving the workflow!" msgstr "" @@ -2920,88 +3045,90 @@ msgstr "" #: components/InstanceToggle/InstanceToggle.js:67 #: components/JobList/JobList.js:315 #: components/JobList/JobList.js:326 -#: components/LaunchButton/LaunchButton.js:162 -#: components/LaunchPrompt/LaunchPrompt.js:66 +#: components/LaunchButton/LaunchButton.js:196 +#: components/LaunchPrompt/LaunchPrompt.js:96 #: components/NotificationList/NotificationList.js:246 #: components/PaginatedTable/ToolbarDeleteButton.js:205 -#: components/RelatedTemplateList/RelatedTemplateList.js:241 +#: components/RelatedTemplateList/RelatedTemplateList.js:254 #: components/ResourceAccessList/ResourceAccessList.js:277 #: components/ResourceAccessList/ResourceAccessList.js:289 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:427 -#: components/Schedule/ScheduleList/ScheduleList.js:238 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:631 +#: components/Schedule/ScheduleList/ScheduleList.js:239 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:73 -#: components/Schedule/shared/SchedulePromptableFields.js:70 +#: components/Schedule/shared/SchedulePromptableFields.js:63 #: components/TemplateList/TemplateList.js:299 #: contexts/Config.js:94 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:135 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:136 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:155 #: screens/Application/ApplicationsList/ApplicationsList.js:185 -#: screens/Credential/CredentialDetail/CredentialDetail.js:315 +#: screens/Credential/CredentialDetail/CredentialDetail.js:314 #: screens/Credential/CredentialList/CredentialList.js:214 #: screens/Host/HostDetail/HostDetail.js:56 -#: screens/Host/HostDetail/HostDetail.js:121 +#: screens/Host/HostDetail/HostDetail.js:123 #: screens/Host/HostGroups/HostGroupsList.js:244 #: screens/Host/HostList/HostList.js:233 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:303 -#: screens/InstanceGroup/Instances/InstanceList.js:297 -#: screens/InstanceGroup/Instances/InstanceListItem.js:218 -#: screens/Instances/InstanceDetail/InstanceDetail.js:249 -#: screens/Instances/InstanceList/InstanceList.js:178 -#: screens/Instances/InstanceList/InstanceListItem.js:234 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:171 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:335 +#: screens/InstanceGroup/Instances/InstanceList.js:330 +#: screens/InstanceGroup/Instances/InstanceListItem.js:247 +#: screens/Instances/InstanceDetail/InstanceDetail.js:370 +#: screens/Instances/InstanceDetail/InstanceDetail.js:385 +#: screens/Instances/InstanceList/InstanceList.js:251 +#: screens/Instances/InstanceList/InstanceList.js:263 +#: screens/Instances/InstanceList/InstanceListItem.js:265 +#: screens/Instances/Shared/RemoveInstanceButton.js:104 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:195 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:78 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:285 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:296 #: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:56 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:119 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:118 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:261 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:201 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:118 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:202 #: screens/Inventory/InventoryList/InventoryList.js:285 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:264 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:339 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 #: screens/Inventory/InventorySources/InventorySourceList.js:239 #: screens/Inventory/InventorySources/InventorySourceList.js:252 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:185 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:167 #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:152 #: screens/Inventory/shared/InventorySourceSyncButton.js:49 -#: screens/Login/Login.js:217 +#: screens/Login/Login.js:239 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:125 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:439 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:233 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:169 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:208 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:186 #: screens/Organization/OrganizationList/OrganizationList.js:195 -#: screens/Project/ProjectDetail/ProjectDetail.js:330 +#: screens/Project/ProjectDetail/ProjectDetail.js:348 #: screens/Project/ProjectList/ProjectList.js:291 #: screens/Project/ProjectList/ProjectList.js:303 -#: screens/Project/shared/ProjectSyncButton.js:59 +#: screens/Project/shared/ProjectSyncButton.js:60 #: screens/Team/TeamDetail/TeamDetail.js:78 #: screens/Team/TeamList/TeamList.js:192 #: screens/Team/TeamRoles/TeamRolesList.js:247 #: screens/Team/TeamRoles/TeamRolesList.js:258 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:537 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:532 #: screens/Template/TemplateSurvey.js:130 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:279 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:178 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:193 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:318 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:346 -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:357 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:277 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:180 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:195 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:337 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:373 +#: screens/TopologyView/MeshGraph.js:406 +#: screens/TopologyView/Tooltip.js:199 #: screens/User/UserDetail/UserDetail.js:115 #: screens/User/UserList/UserList.js:189 #: screens/User/UserRoles/UserRolesList.js:243 #: screens/User/UserRoles/UserRolesList.js:254 #: screens/User/UserTeams/UserTeamList.js:259 -#: screens/User/UserTokenDetail/UserTokenDetail.js:84 +#: screens/User/UserTokenDetail/UserTokenDetail.js:85 #: screens/User/UserTokenList/UserTokenList.js:214 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:373 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:384 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:395 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:406 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:277 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:288 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:299 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:310 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:348 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:247 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:258 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:53 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:48 msgid "Error!" msgstr "" @@ -3009,14 +3136,18 @@ msgstr "" msgid "Error:" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:260 -#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:286 +#: screens/Instances/InstanceDetail/InstanceDetail.js:319 msgid "Errors" msgstr "" +#: screens/TopologyView/Legend.js:253 +msgid "Established" +msgstr "" + #: screens/ActivityStream/ActivityStream.js:265 #: screens/ActivityStream/ActivityStreamListItem.js:46 -#: screens/Job/JobOutput/JobOutputSearch.js:100 +#: screens/Job/JobOutput/JobOutputSearch.js:99 msgid "Event" msgstr "" @@ -3036,22 +3167,30 @@ msgstr "" msgid "Events" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:144 -msgid "Every minute for {0} times" +#: screens/Job/JobOutput/JobOutput.js:725 +msgid "Events processing complete." msgstr "" +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:144 +#~ msgid "Every minute for {0} times" +#~ msgstr "" + #: screens/TopologyView/Legend.js:82 -msgid "Ex" -msgstr "" +#~ msgid "Ex" +#~ msgstr "" #: components/Search/LookupTypeInput.js:39 msgid "Exact match (default lookup if not specified)." msgstr "" -#: components/Search/RelatedLookupTypeInput.js:38 +#: components/Search/RelatedLookupTypeInput.js:44 msgid "Exact search on id field." msgstr "" +#: components/Search/RelatedLookupTypeInput.js:38 +msgid "Exact search on name field." +msgstr "" + #: screens/Project/shared/Project.helptext.js:23 msgid "Example URLs for GIT Source Control include:" msgstr "" @@ -3072,6 +3211,14 @@ msgstr "" msgid "Examples:" msgstr "" +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:350 +msgid "Exception Frequency" +msgstr "" + +#: components/Schedule/shared/ScheduleFormFields.js:160 +msgid "Exceptions" +msgstr "" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:47 msgid "Execute regardless of the parent node's final state." msgstr "" @@ -3084,8 +3231,8 @@ msgstr "" msgid "Execute when the parent node results in a successful state." msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:197 -#: screens/Instances/InstanceList/InstanceList.js:117 +#: screens/InstanceGroup/Instances/InstanceList.js:226 +#: screens/Instances/InstanceList/InstanceList.js:170 msgid "Execution" msgstr "" @@ -3095,9 +3242,12 @@ msgstr "" #: components/AdHocCommands/useAdHocExecutionEnvironmentStep.js:15 #: components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js:41 #: components/ExecutionEnvironmentDetail/ExecutionEnvironmentDetail.js:105 -#: components/Lookup/ExecutionEnvironmentLookup.js:155 -#: components/Lookup/ExecutionEnvironmentLookup.js:186 -#: components/Lookup/ExecutionEnvironmentLookup.js:201 +#: components/LaunchPrompt/steps/useExecutionEnvironmentStep.js:29 +#: components/Lookup/ExecutionEnvironmentLookup.js:159 +#: components/Lookup/ExecutionEnvironmentLookup.js:191 +#: components/Lookup/ExecutionEnvironmentLookup.js:208 +#: components/PromptDetail/PromptDetail.js:221 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:447 msgid "Execution Environment" msgstr "" @@ -3107,6 +3257,7 @@ msgid "Execution Environment Missing" msgstr "" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:103 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:107 #: routeConfig.js:147 #: screens/ActivityStream/ActivityStream.js:217 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:129 @@ -3116,12 +3267,12 @@ msgstr "" #: screens/Organization/Organization.js:127 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:78 #: screens/Organization/Organizations.js:34 -#: util/getRelatedResourceDeleteDetails.js:80 -#: util/getRelatedResourceDeleteDetails.js:187 +#: util/getRelatedResourceDeleteDetails.js:81 +#: util/getRelatedResourceDeleteDetails.js:188 msgid "Execution Environments" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:340 +#: screens/Job/JobDetail/JobDetail.js:345 msgid "Execution Node" msgstr "" @@ -3175,20 +3326,20 @@ msgstr "" #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:34 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:148 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:172 -#: screens/User/UserTokenDetail/UserTokenDetail.js:55 +#: screens/User/UserTokenDetail/UserTokenDetail.js:56 #: screens/User/UserTokenList/UserTokenList.js:146 #: screens/User/UserTokenList/UserTokenList.js:190 #: screens/User/UserTokenList/UserTokenListItem.js:35 #: screens/User/UserTokens/UserTokens.js:89 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:192 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:151 msgid "Expires" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:84 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:146 msgid "Expires on" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:94 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:156 msgid "Expires on UTC" msgstr "" @@ -3196,8 +3347,8 @@ msgstr "" msgid "Expires on {0}" msgstr "" -#: components/JobList/JobListItem.js:306 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:222 +#: components/JobList/JobListItem.js:307 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181 msgid "Explanation" msgstr "" @@ -3211,7 +3362,7 @@ msgid "Extra variables" msgstr "" #: components/Sparkline/Sparkline.js:35 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:179 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:165 #: screens/Inventory/InventorySources/InventorySourceListItem.js:43 #: screens/Project/ProjectDetail/ProjectDetail.js:139 #: screens/Project/ProjectList/ProjectListItem.js:77 @@ -3219,11 +3370,11 @@ msgid "FINISHED:" msgstr "" #: components/PromptDetail/PromptJobTemplateDetail.js:73 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:135 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:138 msgid "Fact Storage" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:36 +#: screens/Template/shared/JobTemplate.helptext.js:39 msgid "Fact storage: If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime.." msgstr "" @@ -3237,24 +3388,25 @@ msgid "Facts" msgstr "" #: components/JobList/JobList.js:232 -#: components/StatusLabel/StatusLabel.js:37 +#: components/StatusLabel/StatusLabel.js:45 #: components/Workflow/WorkflowNodeHelp.js:105 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:88 #: screens/Dashboard/shared/ChartTooltip.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:47 -#: screens/Job/JobOutput/shared/OutputToolbar.js:113 +#: screens/Job/JobOutput/shared/OutputToolbar.js:128 msgid "Failed" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: screens/Job/JobOutput/shared/OutputToolbar.js:127 msgid "Failed Host Count" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:114 +#: screens/Job/JobOutput/shared/OutputToolbar.js:129 msgid "Failed Hosts" msgstr "" #: components/LaunchButton/ReLaunchDropDown.js:61 -#: screens/Dashboard/Dashboard.js:87 +#: screens/Dashboard/Dashboard.js:104 msgid "Failed hosts" msgstr "" @@ -3262,13 +3414,17 @@ msgstr "" msgid "Failed jobs" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:291 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:262 msgid "Failed to approve one or more workflow approval." msgstr "" #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:387 #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:398 -msgid "Failed to approve workflow approval." +#~ msgid "Failed to approve workflow approval." +#~ msgstr "" + +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:56 +msgid "Failed to approve {0}." msgstr "" #: components/ResourceAccessList/ResourceAccessList.js:281 @@ -3281,7 +3437,7 @@ msgid "Failed to associate role" msgstr "" #: screens/Host/HostGroups/HostGroupsList.js:248 -#: screens/InstanceGroup/Instances/InstanceList.js:300 +#: screens/InstanceGroup/Instances/InstanceList.js:333 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:288 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:265 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:268 @@ -3289,12 +3445,12 @@ msgstr "" msgid "Failed to associate." msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:317 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:307 #: screens/Inventory/InventorySources/InventorySourceListItem.js:111 msgid "Failed to cancel Inventory Source Sync" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:304 +#: screens/Project/ProjectDetail/ProjectDetail.js:322 #: screens/Project/ProjectList/ProjectListItem.js:232 msgid "Failed to cancel Project Sync" msgstr "" @@ -3304,12 +3460,12 @@ msgid "Failed to cancel one or more jobs." msgstr "" #: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:302 -msgid "Failed to cancel one or more workflow approval." -msgstr "" +#~ msgid "Failed to cancel one or more workflow approval." +#~ msgstr "" #: components/JobList/JobListItem.js:114 -#: screens/Job/JobDetail/JobDetail.js:583 -#: screens/Job/JobOutput/shared/OutputToolbar.js:138 +#: screens/Job/JobDetail/JobDetail.js:601 +#: screens/Job/JobOutput/shared/OutputToolbar.js:159 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:90 msgid "Failed to cancel {0}" msgstr "" @@ -3335,11 +3491,11 @@ msgstr "" msgid "Failed to copy template." msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:138 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:139 msgid "Failed to delete application." msgstr "" -#: screens/Credential/CredentialDetail/CredentialDetail.js:318 +#: screens/Credential/CredentialDetail/CredentialDetail.js:317 msgid "Failed to delete credential." msgstr "" @@ -3347,24 +3503,24 @@ msgstr "" msgid "Failed to delete group {0}." msgstr "" -#: screens/Host/HostDetail/HostDetail.js:124 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:122 +#: screens/Host/HostDetail/HostDetail.js:126 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:121 msgid "Failed to delete host." msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:343 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:333 msgid "Failed to delete inventory source {name}." msgstr "" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:174 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:198 msgid "Failed to delete inventory." msgstr "" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:540 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:535 msgid "Failed to delete job template." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:443 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:448 msgid "Failed to delete notification." msgstr "" @@ -3389,11 +3545,11 @@ msgid "Failed to delete one or more groups." msgstr "" #: screens/Host/HostList/HostList.js:236 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:204 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:205 msgid "Failed to delete one or more hosts." msgstr "" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:239 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:225 msgid "Failed to delete one or more instance groups." msgstr "" @@ -3405,7 +3561,7 @@ msgstr "" msgid "Failed to delete one or more inventory sources." msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:244 +#: components/RelatedTemplateList/RelatedTemplateList.js:257 msgid "Failed to delete one or more job templates." msgstr "" @@ -3425,7 +3581,7 @@ msgstr "" msgid "Failed to delete one or more projects." msgstr "" -#: components/Schedule/ScheduleList/ScheduleList.js:241 +#: components/Schedule/ScheduleList/ScheduleList.js:242 msgid "Failed to delete one or more schedules." msgstr "" @@ -3449,15 +3605,15 @@ msgstr "" msgid "Failed to delete one or more users." msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:280 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:250 msgid "Failed to delete one or more workflow approval." msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:211 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:189 msgid "Failed to delete organization." msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:333 +#: screens/Project/ProjectDetail/ProjectDetail.js:351 msgid "Failed to delete project." msgstr "" @@ -3470,11 +3626,11 @@ msgstr "" msgid "Failed to delete role." msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:430 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:634 msgid "Failed to delete schedule." msgstr "" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:188 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:170 msgid "Failed to delete smart inventory." msgstr "" @@ -3486,11 +3642,11 @@ msgstr "" msgid "Failed to delete user." msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:376 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:351 msgid "Failed to delete workflow approval." msgstr "" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:282 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:280 msgid "Failed to delete workflow job template." msgstr "" @@ -3499,12 +3655,16 @@ msgstr "" msgid "Failed to delete {name}." msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:313 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:263 msgid "Failed to deny one or more workflow approval." msgstr "" #: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:409 -msgid "Failed to deny workflow approval." +#~ msgid "Failed to deny workflow approval." +#~ msgstr "" + +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:51 +msgid "Failed to deny {0}." msgstr "" #: screens/Host/HostGroups/HostGroupsList.js:249 @@ -3517,9 +3677,9 @@ msgstr "" msgid "Failed to disassociate one or more hosts." msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:308 -#: screens/InstanceGroup/Instances/InstanceList.js:302 -#: screens/Instances/InstanceDetail/InstanceDetail.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:340 +#: screens/InstanceGroup/Instances/InstanceList.js:335 +#: screens/Instances/InstanceDetail/InstanceDetail.js:375 msgid "Failed to disassociate one or more instances." msgstr "" @@ -3527,7 +3687,7 @@ msgstr "" msgid "Failed to disassociate one or more teams." msgstr "" -#: screens/Login/Login.js:221 +#: screens/Login/Login.js:243 msgid "Failed to fetch custom login configuration settings. System defaults will be shown instead." msgstr "" @@ -3535,26 +3695,39 @@ msgstr "" msgid "Failed to fetch the updated project data." msgstr "" +#: screens/TopologyView/MeshGraph.js:410 +msgid "Failed to get instance." +msgstr "" + #: components/AdHocCommands/AdHocCommands.js:112 -#: components/LaunchButton/LaunchButton.js:165 +#: components/LaunchButton/LaunchButton.js:199 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:128 msgid "Failed to launch job." msgstr "" +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:121 +msgid "Failed to load related groups." +msgstr "" + +#: screens/Instances/InstanceDetail/InstanceDetail.js:388 +#: screens/Instances/InstanceList/InstanceList.js:266 +msgid "Failed to remove one or more instances." +msgstr "" + #: contexts/Config.js:98 msgid "Failed to retrieve configuration." msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:349 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:376 msgid "Failed to retrieve full node resource object." msgstr "" #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:360 -msgid "Failed to retrieve node credentials." -msgstr "" +#~ msgid "Failed to retrieve node credentials." +#~ msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:304 -#: screens/Instances/InstanceList/InstanceList.js:181 +#: screens/InstanceGroup/Instances/InstanceList.js:337 +#: screens/Instances/InstanceList/InstanceList.js:254 msgid "Failed to run a health check on one or more instances." msgstr "" @@ -3566,7 +3739,7 @@ msgstr "" msgid "Failed to sync inventory source." msgstr "" -#: screens/Project/shared/ProjectSyncButton.js:62 +#: screens/Project/shared/ProjectSyncButton.js:63 msgid "Failed to sync project." msgstr "" @@ -3590,18 +3763,22 @@ msgstr "" msgid "Failed to toggle schedule." msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:307 -#: screens/InstanceGroup/Instances/InstanceListItem.js:222 -#: screens/Instances/InstanceDetail/InstanceDetail.js:253 -#: screens/Instances/InstanceList/InstanceListItem.js:238 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:339 +#: screens/InstanceGroup/Instances/InstanceListItem.js:251 +#: screens/Instances/InstanceDetail/InstanceDetail.js:374 +#: screens/Instances/InstanceList/InstanceListItem.js:269 msgid "Failed to update capacity adjustment." msgstr "" +#: screens/TopologyView/Tooltip.js:204 +msgid "Failed to update instance." +msgstr "" + #: screens/Template/TemplateSurvey.js:133 msgid "Failed to update survey." msgstr "" -#: screens/User/UserTokenDetail/UserTokenDetail.js:87 +#: screens/User/UserTokenDetail/UserTokenDetail.js:88 msgid "Failed to user token." msgstr "" @@ -3610,17 +3787,22 @@ msgstr "" msgid "Failure" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:205 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:235 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:265 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:310 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:368 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:80 +#: screens/Job/JobOutput/EmptyOutput.js:45 +msgid "Failure Explanation:" +msgstr "" + +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:66 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:210 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:240 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:270 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:315 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:142 msgid "False" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:118 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:160 +#: components/Schedule/shared/FrequencyDetailSubform.js:103 msgid "February" msgstr "" @@ -3632,7 +3814,7 @@ msgstr "" msgid "Field ends with value." msgstr "" -#: screens/InstanceGroup/shared/ContainerGroupForm.js:76 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:96 msgid "Field for passing a custom Kubernetes or OpenShift Pod specification." msgstr "" @@ -3644,11 +3826,11 @@ msgstr "" msgid "Field starts with value." msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:409 +#: components/Schedule/shared/FrequencyDetailSubform.js:416 msgid "Fifth" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:106 +#: screens/Job/JobOutput/JobOutputSearch.js:105 msgid "File Difference" msgstr "" @@ -3665,17 +3847,25 @@ msgstr "" msgid "Filter By {name}" msgstr "" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:86 +msgid "Filter by failed jobs" +msgstr "" + +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:92 +msgid "Filter by successful jobs" +msgstr "" + #: components/JobList/JobList.js:248 #: components/JobList/JobListItem.js:100 msgid "Finish Time" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:206 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:249 +#: screens/Job/JobDetail/JobDetail.js:226 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:208 msgid "Finished" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:397 +#: components/Schedule/shared/FrequencyDetailSubform.js:404 msgid "First" msgstr "" @@ -3690,7 +3880,7 @@ msgstr "" msgid "First Name" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:255 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:328 msgid "First Run" msgstr "" @@ -3717,7 +3907,7 @@ msgstr "" msgid "Float" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:184 +#: screens/Job/JobOutput/JobOutputSearch.js:183 msgid "Follow" msgstr "" @@ -3730,14 +3920,14 @@ msgstr "" #~ msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:114 -msgid "" -"For job templates, select run to execute the playbook.\n" -"Select check to only check playbook syntax, test environment setup,\n" -"and report problems without executing the playbook." -msgstr "" +#~ msgid "" +#~ "For job templates, select run to execute the playbook.\n" +#~ "Select check to only check playbook syntax, test environment setup,\n" +#~ "and report problems without executing the playbook." +#~ msgstr "" #: screens/Job/Job.helptext.js:5 -#: screens/Template/shared/JobTemplate.helptext.js:5 +#: screens/Template/shared/JobTemplate.helptext.js:6 msgid "For job templates, select run to execute the playbook. Select check to only check playbook syntax, test environment setup, and report problems without executing the playbook." msgstr "" @@ -3747,36 +3937,49 @@ msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:160 #: components/AdHocCommands/AdHocDetailsStep.js:161 -#: components/PromptDetail/PromptJobTemplateDetail.js:147 -#: screens/Job/JobDetail/JobDetail.js:384 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:252 -#: screens/Template/shared/JobTemplateForm.js:403 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:55 +#: components/PromptDetail/PromptDetail.js:332 +#: components/PromptDetail/PromptJobTemplateDetail.js:150 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:471 +#: screens/Job/JobDetail/JobDetail.js:389 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:255 +#: screens/Template/shared/JobTemplateForm.js:409 +#: screens/TopologyView/Tooltip.js:282 msgid "Forks" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:407 +#: components/Schedule/shared/FrequencyDetailSubform.js:414 msgid "Fourth" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:177 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:359 +#: components/Schedule/shared/ScheduleFormFields.js:146 msgid "Frequency Details" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:201 -#: components/Schedule/shared/buildRuleObj.js:71 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:377 +msgid "Frequency Exception Details" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:72 +#: components/Schedule/shared/FrequencyDetailSubform.js:185 +#: components/Schedule/shared/FrequencyDetailSubform.js:206 +#: components/Schedule/shared/buildRuleObj.js:91 msgid "Frequency did not match an expected value" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:303 +#: components/Schedule/shared/FrequencyDetailSubform.js:310 msgid "Fri" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:308 -#: components/Schedule/shared/FrequencyDetailSubform.js:446 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:81 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:187 +#: components/Schedule/shared/FrequencyDetailSubform.js:315 +#: components/Schedule/shared/FrequencyDetailSubform.js:453 msgid "Friday" msgstr "" -#: components/Search/RelatedLookupTypeInput.js:45 +#: components/Search/RelatedLookupTypeInput.js:51 msgid "Fuzzy search on id, name or description fields." msgstr "" @@ -3784,7 +3987,11 @@ msgstr "" msgid "Fuzzy search on name field." msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:153 +#: components/CredentialChip/CredentialChip.js:13 +msgid "GPG Public Key" +msgstr "" + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:131 #: screens/Organization/shared/OrganizationForm.js:101 msgid "Galaxy Credentials" msgstr "" @@ -3793,10 +4000,18 @@ msgstr "" msgid "Galaxy credentials must be owned by an Organization." msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:107 +#: screens/Job/JobOutput/JobOutputSearch.js:106 msgid "Gathering Facts" msgstr "" +#: screens/Setting/Settings.js:72 +msgid "Generic OIDC" +msgstr "" + +#: screens/Setting/SettingList.js:85 +msgid "Generic OIDC settings" +msgstr "" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:222 msgid "Get subscription" msgstr "" @@ -3805,47 +4020,47 @@ msgstr "" msgid "Get subscriptions" msgstr "" -#: components/Lookup/ProjectLookup.js:135 +#: components/Lookup/ProjectLookup.js:136 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:89 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:158 -#: screens/Job/JobDetail/JobDetail.js:74 +#: screens/Job/JobDetail/JobDetail.js:75 #: screens/Project/ProjectList/ProjectList.js:198 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:97 msgid "Git" msgstr "" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:305 -#: screens/Template/shared/WebhookSubForm.js:105 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 +#: screens/Template/shared/WebhookSubForm.js:106 msgid "GitHub" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:85 -#: screens/Setting/Settings.js:50 +#: screens/Setting/Settings.js:51 msgid "GitHub Default" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:100 -#: screens/Setting/Settings.js:59 +#: screens/Setting/Settings.js:60 msgid "GitHub Enterprise" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:105 -#: screens/Setting/Settings.js:62 +#: screens/Setting/Settings.js:63 msgid "GitHub Enterprise Organization" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:110 -#: screens/Setting/Settings.js:65 +#: screens/Setting/Settings.js:66 msgid "GitHub Enterprise Team" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:90 -#: screens/Setting/Settings.js:53 +#: screens/Setting/Settings.js:54 msgid "GitHub Organization" msgstr "" #: screens/Setting/GitHub/GitHubDetail/GitHubDetail.js:95 -#: screens/Setting/Settings.js:56 +#: screens/Setting/Settings.js:57 msgid "GitHub Team" msgstr "" @@ -3853,8 +4068,8 @@ msgstr "" msgid "GitHub settings" msgstr "" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:305 -#: screens/Template/shared/WebhookSubForm.js:111 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:308 +#: screens/Template/shared/WebhookSubForm.js:112 msgid "GitLab" msgstr "" @@ -3862,12 +4077,12 @@ msgstr "" #~ msgid "Global Default Execution Environment" #~ msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:78 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:79 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:84 msgid "Globally Available" msgstr "" -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:133 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:134 msgid "Globally available execution environment can not be reassigned to a specific Organization" msgstr "" @@ -3895,7 +4110,7 @@ msgstr "" msgid "Google OAuth 2 settings" msgstr "" -#: screens/Setting/Settings.js:68 +#: screens/Setting/Settings.js:69 msgid "Google OAuth2" msgstr "" @@ -3904,12 +4119,12 @@ msgstr "" msgid "Grafana" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:153 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:160 msgid "Grafana API key" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:182 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:144 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:187 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:151 msgid "Grafana URL" msgstr "" @@ -3943,17 +4158,17 @@ msgstr "" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:248 #: screens/Inventory/InventoryList/InventoryListItem.js:127 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:251 -#: util/getRelatedResourceDeleteDetails.js:118 +#: util/getRelatedResourceDeleteDetails.js:119 msgid "Groups" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:378 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:453 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:383 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:468 msgid "HTTP Headers" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:466 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:378 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:481 msgid "HTTP Method" msgstr "" @@ -3964,12 +4179,28 @@ msgstr "" #~ msgid "Health Check" #~ msgstr "" -#: components/StatusLabel/StatusLabel.js:34 -#: screens/TopologyView/Legend.js:118 +#: components/HealthCheckAlert/HealthCheckAlert.js:22 +msgid "Health check request(s) submitted. Please wait and reload the page." +msgstr "" + +#: components/InstanceDetails.js/InstanceDetails.js:293 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:227 +#: screens/InstanceGroup/Instances/InstanceListItem.js:225 +#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: screens/Instances/InstanceList/InstanceListItem.js:242 +msgid "Health checks are asynchronous tasks. See the" +msgstr "" + +#: screens/InstanceGroup/Instances/InstanceList.js:286 +#: screens/Instances/InstanceList/InstanceList.js:219 +msgid "Health checks can only be run on execution nodes." +msgstr "" + +#: components/StatusLabel/StatusLabel.js:42 msgid "Healthy" msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:121 +#: components/AppContainer/PageHeaderToolbar.js:116 msgid "Help" msgstr "" @@ -3977,8 +4208,8 @@ msgstr "" msgid "Hide" msgstr "" -#: components/LaunchPrompt/LaunchPrompt.js:105 -#: components/Schedule/shared/SchedulePromptableFields.js:109 +#: components/LaunchPrompt/LaunchPrompt.js:135 +#: components/Schedule/shared/SchedulePromptableFields.js:102 msgid "Hide description" msgstr "" @@ -3987,7 +4218,7 @@ msgstr "" msgid "Hipchat" msgstr "" -#: screens/Instances/InstanceList/InstanceList.js:119 +#: screens/Instances/InstanceList/InstanceList.js:172 msgid "Hop" msgstr "" @@ -3995,73 +4226,77 @@ msgstr "" msgid "Hop node" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:109 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:148 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:76 +#: components/InstanceDetails.js/InstanceDetails.js:257 +#: screens/Instances/InstanceDetail/InstanceDetail.js:214 +#: screens/Job/JobOutput/HostEventModal.js:110 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:149 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:78 msgid "Host" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:108 +#: screens/Job/JobOutput/JobOutputSearch.js:107 msgid "Host Async Failure" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:109 +#: screens/Job/JobOutput/JobOutputSearch.js:108 msgid "Host Async OK" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:154 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:290 -#: screens/Template/shared/JobTemplateForm.js:575 +#: components/PromptDetail/PromptJobTemplateDetail.js:159 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:293 +#: screens/Template/shared/JobTemplateForm.js:633 msgid "Host Config Key" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:96 +#: screens/Job/JobOutput/shared/OutputToolbar.js:111 msgid "Host Count" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:88 +#: screens/Job/JobOutput/HostEventModal.js:89 msgid "Host Details" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:110 +#: screens/Job/JobOutput/JobOutputSearch.js:109 msgid "Host Failed" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:111 +#: screens/Job/JobOutput/JobOutputSearch.js:110 msgid "Host Failure" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:257 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:248 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:145 msgid "Host Filter" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:196 -#: screens/Instances/InstanceDetail/InstanceDetail.js:144 +#: components/InstanceDetails.js/InstanceDetails.js:237 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:205 +#: screens/Instances/InstanceDetail/InstanceDetail.js:194 +#: screens/Instances/Shared/InstanceForm.js:18 msgid "Host Name" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:112 +#: screens/Job/JobOutput/JobOutputSearch.js:111 msgid "Host OK" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:113 +#: screens/Job/JobOutput/JobOutputSearch.js:112 msgid "Host Polling" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:114 +#: screens/Job/JobOutput/JobOutputSearch.js:113 msgid "Host Retry" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:115 +#: screens/Job/JobOutput/JobOutputSearch.js:114 msgid "Host Skipped" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:116 +#: screens/Job/JobOutput/JobOutputSearch.js:115 msgid "Host Started" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:117 +#: screens/Job/JobOutput/JobOutputSearch.js:116 msgid "Host Unreachable" msgstr "" @@ -4069,7 +4304,7 @@ msgstr "" msgid "Host details" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:89 +#: screens/Job/JobOutput/HostEventModal.js:90 msgid "Host details modal" msgstr "" @@ -4084,7 +4319,7 @@ msgstr "" #: routeConfig.js:85 #: screens/ActivityStream/ActivityStream.js:176 -#: screens/Dashboard/Dashboard.js:81 +#: screens/Dashboard/Dashboard.js:98 #: screens/Host/HostList/HostList.js:143 #: screens/Host/HostList/HostList.js:191 #: screens/Host/Hosts.js:14 @@ -4096,41 +4331,44 @@ msgstr "" #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:189 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:272 #: screens/Inventory/InventoryHosts/InventoryHostList.js:112 -#: screens/Inventory/InventoryHosts/InventoryHostList.js:172 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:173 #: screens/Inventory/SmartInventory.js:68 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:71 -#: screens/Job/JobOutput/shared/OutputToolbar.js:97 -#: util/getRelatedResourceDeleteDetails.js:122 +#: screens/Job/JobOutput/shared/OutputToolbar.js:112 +#: util/getRelatedResourceDeleteDetails.js:123 msgid "Hosts" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:132 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:92 msgid "Hosts automated" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:114 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:121 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:118 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:125 msgid "Hosts available" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:127 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:107 msgid "Hosts imported" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:145 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:112 msgid "Hosts remaining" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:155 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:179 +#: components/Schedule/shared/FrequencyDetailSubform.js:175 +#: components/Schedule/shared/ScheduleFormFields.js:126 +#: components/Schedule/shared/ScheduleFormFields.js:186 msgid "Hour" msgstr "" #: screens/TopologyView/Legend.js:92 -msgid "Hy" -msgstr "" +#~ msgid "Hy" +#~ msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:198 -#: screens/Instances/InstanceList/InstanceList.js:118 +#: screens/InstanceGroup/Instances/InstanceList.js:227 +#: screens/Instances/InstanceList/InstanceList.js:171 msgid "Hybrid" msgstr "" @@ -4144,59 +4382,63 @@ msgstr "" msgid "ID" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:188 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:193 msgid "ID of the Dashboard" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:193 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:198 msgid "ID of the Panel" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:160 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:167 msgid "ID of the dashboard (optional)" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:166 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:173 msgid "ID of the panel (optional)" msgstr "" +#: screens/TopologyView/Tooltip.js:265 +msgid "IP address" +msgstr "" + #: components/NotificationList/NotificationList.js:196 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:137 msgid "IRC" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:223 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:228 msgid "IRC Nick" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:218 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:223 msgid "IRC Server Address" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:213 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:218 msgid "IRC Server Port" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:214 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:223 msgid "IRC nick" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:206 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:215 msgid "IRC server address" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:192 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:201 msgid "IRC server password" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:197 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:206 msgid "IRC server port" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:258 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:303 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:263 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:334 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:263 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:308 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:272 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:343 msgid "Icon URL" msgstr "" @@ -4224,11 +4466,11 @@ msgstr "" #~ "administrator." #~ msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:29 +#: screens/Template/shared/JobTemplate.helptext.js:30 msgid "If enabled, run this playbook as an administrator." msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:156 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:184 msgid "" "If enabled, show the changes made\n" "by Ansible tasks, where supported. This is equivalent to Ansible’s\n" @@ -4242,7 +4484,7 @@ msgstr "" #~ "to Ansible's --diff mode." #~ msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:18 +#: screens/Template/shared/JobTemplate.helptext.js:19 msgid "If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansible's --diff mode." msgstr "" @@ -4256,7 +4498,7 @@ msgstr "" #~ "template will be allowed." #~ msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:31 +#: screens/Template/shared/JobTemplate.helptext.js:32 msgid "If enabled, simultaneous runs of this job template will be allowed." msgstr "" @@ -4264,6 +4506,18 @@ msgstr "" msgid "If enabled, simultaneous runs of this workflow job template will be allowed." msgstr "" +#: screens/Inventory/shared/Inventory.helptext.js:195 +msgid "" +"If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." +msgstr "" + +#: screens/Template/shared/JobTemplate.helptext.js:33 +msgid "" +"If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on.\n" +"Note: If this setting is enabled and you provided an empty list, the global instance groups will be applied." +msgstr "" + #: screens/Template/shared/JobTemplateForm.js:611 #~ msgid "" #~ "If enabled, this will store gathered facts so they can\n" @@ -4271,7 +4525,7 @@ msgstr "" #~ "injected into the fact cache at runtime." #~ msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:32 +#: screens/Template/shared/JobTemplate.helptext.js:35 msgid "If enabled, this will store gathered facts so they can be viewed at the host level. Facts are persisted and injected into the fact cache at runtime." msgstr "" @@ -4279,7 +4533,7 @@ msgstr "" msgid "If specified, this field will be shown on the node instead of the resource name when viewing the workflow" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:150 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:180 msgid "If you are ready to upgrade or renew, please <0>contact us." msgstr "" @@ -4300,19 +4554,22 @@ msgid "" "launch and on project update, click on Update on launch, and also go to" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:53 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:80 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:91 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:101 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:54 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:141 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:147 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:166 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:75 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:97 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:98 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:89 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:108 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:21 msgid "Image" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:118 +#: screens/Job/JobOutput/JobOutputSearch.js:117 msgid "Including File" msgstr "" @@ -4323,7 +4580,7 @@ msgid "" "reset by the inventory sync process." msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:108 +#: components/AppContainer/PageHeaderToolbar.js:103 msgid "Info" msgstr "" @@ -4372,31 +4629,49 @@ msgstr "" msgid "Insights system ID" msgstr "" +#: components/InstanceDetails.js/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:251 +msgid "Install Bundle" +msgstr "" + +#: components/StatusLabel/StatusLabel.js:58 +#: screens/TopologyView/Legend.js:136 +msgid "Installed" +msgstr "" + #: screens/Metrics/Metrics.js:187 msgid "Instance" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:147 +#: components/PromptDetail/PromptInventorySourceDetail.js:135 msgid "Instance Filters" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:353 +#: screens/Job/JobDetail/JobDetail.js:358 msgid "Instance Group" msgstr "" -#: components/Lookup/InstanceGroupsLookup.js:69 -#: components/Lookup/InstanceGroupsLookup.js:75 +#: components/InstanceDetails.js/InstanceDetails.js:263 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:96 +#: components/LaunchPrompt/steps/useInstanceGroupsStep.js:31 +#: components/Lookup/InstanceGroupsLookup.js:74 #: components/Lookup/InstanceGroupsLookup.js:121 -#: components/PromptDetail/PromptJobTemplateDetail.js:222 +#: components/Lookup/InstanceGroupsLookup.js:141 +#: components/Lookup/InstanceGroupsLookup.js:151 +#: components/PromptDetail/PromptDetail.js:228 +#: components/PromptDetail/PromptJobTemplateDetail.js:228 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:495 #: routeConfig.js:132 #: screens/ActivityStream/ActivityStream.js:205 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:111 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:193 -#: screens/InstanceGroup/InstanceGroups.js:45 -#: screens/InstanceGroup/InstanceGroups.js:55 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:85 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:127 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:407 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:106 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:179 +#: screens/InstanceGroup/InstanceGroups.js:16 +#: screens/InstanceGroup/InstanceGroups.js:26 +#: screens/Instances/InstanceDetail/InstanceDetail.js:220 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:108 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:123 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:418 +#: util/getRelatedResourceDeleteDetails.js:282 msgid "Instance Groups" msgstr "" @@ -4404,7 +4679,15 @@ msgstr "" msgid "Instance ID" msgstr "" -#: screens/InstanceGroup/InstanceGroups.js:62 +#: screens/Instances/Shared/InstanceForm.js:32 +msgid "Instance State" +msgstr "" + +#: screens/Instances/Shared/InstanceForm.js:48 +msgid "Instance Type" +msgstr "" + +#: screens/InstanceGroup/InstanceGroups.js:33 msgid "Instance details" msgstr "" @@ -4417,26 +4700,35 @@ msgstr "" msgid "Instance group not found." msgstr "" -#: screens/InstanceGroup/Instances/InstanceListItem.js:165 -#: screens/Instances/InstanceList/InstanceListItem.js:176 +#: screens/InstanceGroup/Instances/InstanceListItem.js:179 +#: screens/Instances/InstanceList/InstanceListItem.js:192 msgid "Instance group used capacity" msgstr "" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:124 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:122 +#: screens/TopologyView/Tooltip.js:273 msgid "Instance groups" msgstr "" +#: screens/TopologyView/Tooltip.js:234 +msgid "Instance status" +msgstr "" + +#: screens/TopologyView/Tooltip.js:240 +msgid "Instance type" +msgstr "" + #: routeConfig.js:137 #: screens/ActivityStream/ActivityStream.js:203 #: screens/InstanceGroup/InstanceGroup.js:74 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:212 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:198 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:73 -#: screens/InstanceGroup/InstanceGroups.js:60 -#: screens/InstanceGroup/Instances/InstanceList.js:181 -#: screens/InstanceGroup/Instances/InstanceList.js:279 -#: screens/Instances/InstanceList/InstanceList.js:101 -#: screens/Instances/Instances.js:12 -#: screens/Instances/Instances.js:20 +#: screens/InstanceGroup/InstanceGroups.js:31 +#: screens/InstanceGroup/Instances/InstanceList.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:312 +#: screens/Instances/InstanceList/InstanceList.js:154 +#: screens/Instances/Instances.js:13 +#: screens/Instances/Instances.js:22 msgid "Instances" msgstr "" @@ -4456,7 +4748,7 @@ msgstr "" #~ msgid "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." #~ msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:151 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:178 msgid "Invalid link target. Unable to link to children or ancestor nodes. Graph cycles are not supported." msgstr "" @@ -4464,19 +4756,19 @@ msgstr "" msgid "Invalid time format" msgstr "" -#: screens/Login/Login.js:142 +#: screens/Login/Login.js:153 msgid "Invalid username or password. Please try again." msgstr "" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:119 #: routeConfig.js:80 #: screens/ActivityStream/ActivityStream.js:173 -#: screens/Dashboard/Dashboard.js:92 +#: screens/Dashboard/Dashboard.js:109 #: screens/Inventory/Inventories.js:17 #: screens/Inventory/InventoryList/InventoryList.js:174 #: screens/Inventory/InventoryList/InventoryList.js:237 -#: util/getRelatedResourceDeleteDetails.js:201 -#: util/getRelatedResourceDeleteDetails.js:269 +#: util/getRelatedResourceDeleteDetails.js:202 +#: util/getRelatedResourceDeleteDetails.js:270 msgid "Inventories" msgstr "" @@ -4488,38 +4780,38 @@ msgstr "" #: components/JobList/JobListItem.js:223 #: components/LaunchPrompt/steps/InventoryStep.js:105 #: components/LaunchPrompt/steps/useInventoryStep.js:48 -#: components/Lookup/HostFilterLookup.js:423 +#: components/Lookup/HostFilterLookup.js:424 #: components/Lookup/HostListItem.js:10 -#: components/Lookup/InventoryLookup.js:129 -#: components/Lookup/InventoryLookup.js:138 -#: components/Lookup/InventoryLookup.js:178 -#: components/Lookup/InventoryLookup.js:193 -#: components/Lookup/InventoryLookup.js:233 -#: components/PromptDetail/PromptDetail.js:205 -#: components/PromptDetail/PromptInventorySourceDetail.js:87 -#: components/PromptDetail/PromptJobTemplateDetail.js:117 -#: components/PromptDetail/PromptJobTemplateDetail.js:127 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:77 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:290 -#: components/TemplateList/TemplateListItem.js:284 -#: components/TemplateList/TemplateListItem.js:294 -#: screens/Host/HostDetail/HostDetail.js:75 +#: components/Lookup/InventoryLookup.js:119 +#: components/Lookup/InventoryLookup.js:128 +#: components/Lookup/InventoryLookup.js:169 +#: components/Lookup/InventoryLookup.js:184 +#: components/Lookup/InventoryLookup.js:224 +#: components/PromptDetail/PromptDetail.js:215 +#: components/PromptDetail/PromptInventorySourceDetail.js:76 +#: components/PromptDetail/PromptJobTemplateDetail.js:119 +#: components/PromptDetail/PromptJobTemplateDetail.js:129 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:79 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:426 +#: components/TemplateList/TemplateListItem.js:285 +#: components/TemplateList/TemplateListItem.js:295 +#: screens/Host/HostDetail/HostDetail.js:77 #: screens/Host/HostList/HostList.js:171 #: screens/Host/HostList/HostListItem.js:61 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:186 #: screens/Inventory/InventoryList/InventoryListItem.js:117 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:39 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:38 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:113 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:41 -#: screens/Job/JobDetail/JobDetail.js:106 -#: screens/Job/JobDetail/JobDetail.js:121 -#: screens/Job/JobDetail/JobDetail.js:128 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:207 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:217 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:142 +#: screens/Job/JobDetail/JobDetail.js:107 +#: screens/Job/JobDetail/JobDetail.js:122 +#: screens/Job/JobDetail/JobDetail.js:129 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:210 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:220 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:141 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:33 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:293 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:252 msgid "Inventory" msgstr "" @@ -4527,7 +4819,7 @@ msgstr "" msgid "Inventory (Name)" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:110 +#: components/PromptDetail/PromptInventorySourceDetail.js:99 msgid "Inventory File" msgstr "" @@ -4535,27 +4827,27 @@ msgstr "" msgid "Inventory ID" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:262 +#: screens/Job/JobDetail/JobDetail.js:282 msgid "Inventory Source" msgstr "" #: screens/Job/JobDetail/JobDetail.js:285 -msgid "Inventory Source Project" -msgstr "" +#~ msgid "Inventory Source Project" +#~ msgstr "" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:73 msgid "Inventory Source Sync" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:315 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 #: screens/Inventory/InventorySources/InventorySourceListItem.js:110 msgid "Inventory Source Sync Error" msgstr "" #: screens/Inventory/InventorySources/InventorySourceList.js:176 #: screens/Inventory/InventorySources/InventorySourceList.js:193 -#: util/getRelatedResourceDeleteDetails.js:66 -#: util/getRelatedResourceDeleteDetails.js:146 +#: util/getRelatedResourceDeleteDetails.js:67 +#: util/getRelatedResourceDeleteDetails.js:147 msgid "Inventory Sources" msgstr "" @@ -4563,7 +4855,7 @@ msgstr "" #: components/JobList/JobListItem.js:43 #: components/Schedule/ScheduleList/ScheduleListItem.js:36 #: components/Workflow/WorkflowLegend.js:100 -#: screens/Job/JobDetail/JobDetail.js:65 +#: screens/Job/JobDetail/JobDetail.js:66 msgid "Inventory Sync" msgstr "" @@ -4579,8 +4871,8 @@ msgstr "" msgid "Inventory copied successfully" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:241 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:108 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:227 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:116 msgid "Inventory file" msgstr "" @@ -4592,7 +4884,7 @@ msgstr "" msgid "Inventory sync" msgstr "" -#: screens/Dashboard/Dashboard.js:98 +#: screens/Dashboard/Dashboard.js:115 msgid "Inventory sync failures" msgstr "" @@ -4604,15 +4896,15 @@ msgstr "" msgid "Is not expanded" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:119 +#: screens/Job/JobOutput/JobOutputSearch.js:118 msgid "Item Failed" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:120 +#: screens/Job/JobOutput/JobOutputSearch.js:119 msgid "Item OK" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:121 +#: screens/Job/JobOutput/JobOutputSearch.js:120 msgid "Item Skipped" msgstr "" @@ -4626,18 +4918,18 @@ msgid "Items per page" msgstr "" #: components/Sparkline/Sparkline.js:28 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:172 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:158 #: screens/Inventory/InventorySources/InventorySourceListItem.js:36 #: screens/Project/ProjectDetail/ProjectDetail.js:132 #: screens/Project/ProjectList/ProjectListItem.js:70 msgid "JOB ID:" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:136 +#: screens/Job/JobOutput/HostEventModal.js:134 msgid "JSON" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:137 +#: screens/Job/JobOutput/HostEventModal.js:135 msgid "JSON tab" msgstr "" @@ -4645,7 +4937,8 @@ msgstr "" msgid "JSON:" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:113 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:159 +#: components/Schedule/shared/FrequencyDetailSubform.js:98 msgid "January" msgstr "" @@ -4655,21 +4948,21 @@ msgstr "" #~ msgstr "" #: components/JobList/JobListItem.js:112 -#: screens/Job/JobDetail/JobDetail.js:581 -#: screens/Job/JobOutput/JobOutput.js:790 -#: screens/Job/JobOutput/JobOutput.js:791 -#: screens/Job/JobOutput/shared/OutputToolbar.js:136 +#: screens/Job/JobDetail/JobDetail.js:599 +#: screens/Job/JobOutput/JobOutput.js:857 +#: screens/Job/JobOutput/JobOutput.js:858 +#: screens/Job/JobOutput/shared/OutputToolbar.js:157 #: screens/Job/WorkflowOutput/WorkflowOutputToolbar.js:88 msgid "Job Cancel Error" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:603 -#: screens/Job/JobOutput/JobOutput.js:779 -#: screens/Job/JobOutput/JobOutput.js:780 +#: screens/Job/JobDetail/JobDetail.js:621 +#: screens/Job/JobOutput/JobOutput.js:846 +#: screens/Job/JobOutput/JobOutput.js:847 msgid "Job Delete Error" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:184 +#: screens/Job/JobDetail/JobDetail.js:206 msgid "Job ID" msgstr "" @@ -4677,19 +4970,22 @@ msgstr "" msgid "Job Runs" msgstr "" -#: components/JobList/JobListItem.js:313 -#: screens/Job/JobDetail/JobDetail.js:369 +#: components/JobList/JobListItem.js:314 +#: screens/Job/JobDetail/JobDetail.js:374 msgid "Job Slice" msgstr "" -#: components/JobList/JobListItem.js:318 -#: screens/Job/JobDetail/JobDetail.js:377 +#: components/JobList/JobListItem.js:319 +#: screens/Job/JobDetail/JobDetail.js:382 msgid "Job Slice Parent" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:153 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:282 -#: screens/Template/shared/JobTemplateForm.js:435 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:76 +#: components/PromptDetail/PromptDetail.js:336 +#: components/PromptDetail/PromptJobTemplateDetail.js:158 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:490 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:285 +#: screens/Template/shared/JobTemplateForm.js:453 msgid "Job Slicing" msgstr "" @@ -4697,14 +4993,15 @@ msgstr "" msgid "Job Status" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:57 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:58 -#: components/PromptDetail/PromptDetail.js:228 -#: components/PromptDetail/PromptJobTemplateDetail.js:241 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:346 -#: screens/Job/JobDetail/JobDetail.js:458 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:434 -#: screens/Template/shared/JobTemplateForm.js:469 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:97 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:98 +#: components/PromptDetail/PromptDetail.js:254 +#: components/PromptDetail/PromptJobTemplateDetail.js:247 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:548 +#: screens/Job/JobDetail/JobDetail.js:474 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:427 +#: screens/Template/shared/JobTemplateForm.js:521 +#: screens/Template/shared/WorkflowJobTemplateForm.js:218 msgid "Job Tags" msgstr "" @@ -4714,7 +5011,7 @@ msgstr "" #: components/Workflow/WorkflowNodeHelp.js:59 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:97 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:19 -#: screens/Job/JobDetail/JobDetail.js:213 +#: screens/Job/JobDetail/JobDetail.js:233 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:79 msgid "Job Template" msgstr "" @@ -4723,16 +5020,16 @@ msgstr "" msgid "Job Template default credentials must be replaced with one of the same type. Please select a credential for the following types in order to proceed: {0}" msgstr "" -#: screens/Credential/Credential.js:79 +#: screens/Credential/Credential.js:99 #: screens/Credential/Credentials.js:30 #: screens/Inventory/Inventories.js:62 #: screens/Inventory/Inventory.js:74 #: screens/Inventory/SmartInventory.js:74 #: screens/Project/Project.js:107 #: screens/Project/Projects.js:29 -#: util/getRelatedResourceDeleteDetails.js:55 -#: util/getRelatedResourceDeleteDetails.js:100 -#: util/getRelatedResourceDeleteDetails.js:132 +#: util/getRelatedResourceDeleteDetails.js:56 +#: util/getRelatedResourceDeleteDetails.js:101 +#: util/getRelatedResourceDeleteDetails.js:133 msgid "Job Templates" msgstr "" @@ -4740,32 +5037,32 @@ msgstr "" msgid "Job Templates with a missing inventory or project cannot be selected when creating or editing nodes. Select another template or fix the missing fields to proceed." msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js:316 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js:357 msgid "Job Templates with credentials that prompt for passwords cannot be selected when creating or editing nodes" msgstr "" #: components/JobList/JobList.js:208 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:111 -#: components/PromptDetail/PromptDetail.js:176 -#: components/PromptDetail/PromptJobTemplateDetail.js:100 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:286 -#: screens/Job/JobDetail/JobDetail.js:247 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:185 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:139 -#: screens/Template/shared/JobTemplateForm.js:252 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:146 +#: components/PromptDetail/PromptDetail.js:186 +#: components/PromptDetail/PromptJobTemplateDetail.js:102 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:419 +#: screens/Job/JobDetail/JobDetail.js:267 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:188 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:138 +#: screens/Template/shared/JobTemplateForm.js:256 msgid "Job Type" msgstr "" -#: screens/Dashboard/Dashboard.js:125 +#: screens/Dashboard/Dashboard.js:142 msgid "Job status" msgstr "" -#: screens/Dashboard/Dashboard.js:123 +#: screens/Dashboard/Dashboard.js:140 msgid "Job status graph tab" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:156 -#: components/RelatedTemplateList/RelatedTemplateList.js:206 +#: components/RelatedTemplateList/RelatedTemplateList.js:169 +#: components/RelatedTemplateList/RelatedTemplateList.js:219 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:15 msgid "Job templates" msgstr "" @@ -4779,8 +5076,8 @@ msgstr "" #: screens/Host/Hosts.js:30 #: screens/InstanceGroup/ContainerGroup.js:71 #: screens/InstanceGroup/InstanceGroup.js:79 -#: screens/InstanceGroup/InstanceGroups.js:63 -#: screens/InstanceGroup/InstanceGroups.js:68 +#: screens/InstanceGroup/InstanceGroups.js:34 +#: screens/InstanceGroup/InstanceGroups.js:39 #: screens/Inventory/Inventories.js:60 #: screens/Inventory/Inventories.js:70 #: screens/Inventory/Inventory.js:70 @@ -4788,23 +5085,25 @@ msgstr "" #: screens/Inventory/SmartInventory.js:70 #: screens/Job/Jobs.js:22 #: screens/Job/Jobs.js:32 -#: screens/Setting/SettingList.js:87 -#: screens/Setting/Settings.js:71 +#: screens/Setting/SettingList.js:91 +#: screens/Setting/Settings.js:75 #: screens/Template/Template.js:155 #: screens/Template/Templates.js:47 #: screens/Template/WorkflowJobTemplate.js:141 msgid "Jobs" msgstr "" -#: screens/Setting/SettingList.js:92 +#: screens/Setting/SettingList.js:96 msgid "Jobs settings" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:143 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:165 +#: components/Schedule/shared/FrequencyDetailSubform.js:128 msgid "July" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:138 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:164 +#: components/Schedule/shared/FrequencyDetailSubform.js:123 msgid "June" msgstr "" @@ -4829,27 +5128,27 @@ msgstr "" msgid "LDAP" msgstr "" -#: screens/Setting/Settings.js:76 +#: screens/Setting/Settings.js:80 msgid "LDAP 1" msgstr "" -#: screens/Setting/Settings.js:77 +#: screens/Setting/Settings.js:81 msgid "LDAP 2" msgstr "" -#: screens/Setting/Settings.js:78 +#: screens/Setting/Settings.js:82 msgid "LDAP 3" msgstr "" -#: screens/Setting/Settings.js:79 +#: screens/Setting/Settings.js:83 msgid "LDAP 4" msgstr "" -#: screens/Setting/Settings.js:80 +#: screens/Setting/Settings.js:84 msgid "LDAP 5" msgstr "" -#: screens/Setting/Settings.js:75 +#: screens/Setting/Settings.js:79 msgid "LDAP Default" msgstr "" @@ -4877,7 +5176,7 @@ msgstr "" msgid "LDAP5" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:178 +#: components/RelatedTemplateList/RelatedTemplateList.js:191 #: components/TemplateList/TemplateList.js:234 msgid "Label" msgstr "" @@ -4886,36 +5185,42 @@ msgstr "" msgid "Label Name" msgstr "" -#: components/JobList/JobListItem.js:283 -#: components/PromptDetail/PromptJobTemplateDetail.js:203 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:114 -#: components/TemplateList/TemplateListItem.js:345 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:110 -#: screens/Inventory/shared/InventoryForm.js:75 -#: screens/Job/JobDetail/JobDetail.js:437 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:386 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:208 -#: screens/Template/shared/JobTemplateForm.js:379 -#: screens/Template/shared/WorkflowJobTemplateForm.js:189 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:315 +#: components/JobList/JobListItem.js:284 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:223 +#: components/PromptDetail/PromptDetail.js:310 +#: components/PromptDetail/PromptJobTemplateDetail.js:209 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:116 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:528 +#: components/TemplateList/TemplateListItem.js:347 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:133 +#: screens/Inventory/shared/InventoryForm.js:83 +#: screens/Job/JobDetail/JobDetail.js:453 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:397 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:206 +#: screens/Template/shared/JobTemplateForm.js:387 +#: screens/Template/shared/WorkflowJobTemplateForm.js:195 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:273 msgid "Labels" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:410 +#: components/Schedule/shared/FrequencyDetailSubform.js:417 msgid "Last" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:213 -#: screens/InstanceGroup/Instances/InstanceListItem.js:133 -#: screens/InstanceGroup/Instances/InstanceListItem.js:208 -#: screens/Instances/InstanceDetail/InstanceDetail.js:164 -#: screens/Instances/InstanceList/InstanceListItem.js:138 -#: screens/Instances/InstanceList/InstanceListItem.js:223 +#: components/InstanceDetails.js/InstanceDetails.js:289 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 +#: screens/InstanceGroup/Instances/InstanceListItem.js:147 +#: screens/InstanceGroup/Instances/InstanceListItem.js:222 +#: screens/Instances/InstanceDetail/InstanceDetail.js:230 +#: screens/Instances/InstanceList/InstanceListItem.js:154 +#: screens/Instances/InstanceList/InstanceListItem.js:239 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:47 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:87 msgid "Last Health Check" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:198 -#: screens/Project/ProjectDetail/ProjectDetail.js:160 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:184 +#: screens/Project/ProjectDetail/ProjectDetail.js:161 msgid "Last Job Status" msgstr "" @@ -4923,30 +5228,30 @@ msgstr "" msgid "Last Login" msgstr "" -#: components/PromptDetail/PromptDetail.js:152 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:275 -#: components/TemplateList/TemplateListItem.js:315 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:105 +#: components/PromptDetail/PromptDetail.js:162 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:407 +#: components/TemplateList/TemplateListItem.js:316 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:106 #: screens/Application/ApplicationsList/ApplicationListItem.js:45 #: screens/Application/ApplicationsList/ApplicationsList.js:159 #: screens/Credential/CredentialDetail/CredentialDetail.js:263 #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:95 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:107 -#: screens/Host/HostDetail/HostDetail.js:87 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:72 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:98 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:139 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:108 +#: screens/Host/HostDetail/HostDetail.js:89 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:91 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:112 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:163 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:45 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:85 -#: screens/Job/JobDetail/JobDetail.js:520 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:393 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:120 -#: screens/Project/ProjectDetail/ProjectDetail.js:279 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:84 +#: screens/Job/JobDetail/JobDetail.js:538 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:398 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:116 +#: screens/Project/ProjectDetail/ProjectDetail.js:297 #: screens/Team/TeamDetail/TeamDetail.js:48 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:344 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:354 #: screens/User/UserDetail/UserDetail.js:84 -#: screens/User/UserTokenDetail/UserTokenDetail.js:65 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 +#: screens/User/UserTokenDetail/UserTokenDetail.js:66 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:204 msgid "Last Modified" msgstr "" @@ -4966,7 +5271,7 @@ msgstr "" msgid "Last Ran" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:262 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:337 msgid "Last Run" msgstr "" @@ -4974,10 +5279,11 @@ msgstr "" msgid "Last job" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:296 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:153 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:50 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:286 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:135 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:49 #: screens/Project/ProjectList/ProjectListItem.js:308 +#: screens/TopologyView/Tooltip.js:331 msgid "Last modified" msgstr "" @@ -4986,6 +5292,10 @@ msgstr "" msgid "Last name" msgstr "" +#: screens/TopologyView/Tooltip.js:337 +msgid "Last seen" +msgstr "" + #: screens/Project/ProjectList/ProjectListItem.js:313 msgid "Last used" msgstr "" @@ -4994,10 +5304,10 @@ msgstr "" #: components/LaunchPrompt/steps/usePreviewStep.js:35 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:54 #: screens/ManagementJob/ManagementJobList/LaunchManagementPrompt.js:57 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:503 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:512 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:247 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:256 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:498 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:507 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:245 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:254 msgid "Launch" msgstr "" @@ -5027,7 +5337,7 @@ msgstr "" msgid "Launch workflow" msgstr "" -#: components/LaunchPrompt/LaunchPrompt.js:100 +#: components/LaunchPrompt/LaunchPrompt.js:130 msgid "Launch | {0}" msgstr "" @@ -5047,14 +5357,14 @@ msgstr "" #~ msgid "Learn more about Insights for Ansible Automation Platform" #~ msgstr "" -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:68 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:69 msgid "Leave this field blank to make the execution environment globally available." msgstr "" #: components/Workflow/WorkflowLegend.js:86 #: screens/Metrics/LineChart.js:120 #: screens/TopologyView/Header.js:102 -#: screens/TopologyView/Legend.js:65 +#: screens/TopologyView/Legend.js:67 msgid "Legend" msgstr "" @@ -5069,25 +5379,33 @@ msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:140 #: components/AdHocCommands/AdHocDetailsStep.js:141 #: components/JobList/JobList.js:238 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:36 -#: components/PromptDetail/PromptDetail.js:216 -#: components/PromptDetail/PromptJobTemplateDetail.js:148 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:88 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:314 -#: screens/Job/JobDetail/JobDetail.js:320 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:258 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:152 -#: screens/Template/shared/JobTemplateForm.js:408 -#: screens/Template/shared/WorkflowJobTemplateForm.js:153 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:279 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:65 +#: components/PromptDetail/PromptDetail.js:242 +#: components/PromptDetail/PromptJobTemplateDetail.js:153 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:90 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:469 +#: screens/Job/JobDetail/JobDetail.js:325 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:261 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:151 +#: screens/Template/shared/JobTemplateForm.js:429 +#: screens/Template/shared/WorkflowJobTemplateForm.js:159 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:238 msgid "Limit" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:234 +#: screens/TopologyView/Legend.js:237 +msgid "Link state types" +msgstr "" + +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:261 msgid "Link to an available node" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:334 +#: screens/Instances/Shared/InstanceForm.js:40 +msgid "Listener Port" +msgstr "" + +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:353 msgid "Loading" msgstr "" @@ -5095,34 +5413,34 @@ msgstr "" msgid "Local" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:263 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:339 msgid "Local Time Zone" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:132 +#: components/Schedule/shared/ScheduleFormFields.js:95 msgid "Local time zone" msgstr "" -#: screens/Login/Login.js:195 +#: screens/Login/Login.js:217 msgid "Log In" msgstr "" -#: screens/Setting/Settings.js:93 +#: screens/Setting/Settings.js:97 msgid "Logging" msgstr "" -#: screens/Setting/SettingList.js:111 +#: screens/Setting/SettingList.js:115 msgid "Logging settings" msgstr "" #: components/AppContainer/AppContainer.js:81 #: components/AppContainer/AppContainer.js:150 -#: components/AppContainer/PageHeaderToolbar.js:174 +#: components/AppContainer/PageHeaderToolbar.js:169 msgid "Logout" msgstr "" -#: components/Lookup/HostFilterLookup.js:366 -#: components/Lookup/Lookup.js:181 +#: components/Lookup/HostFilterLookup.js:367 +#: components/Lookup/Lookup.js:187 msgid "Lookup modal" msgstr "" @@ -5138,7 +5456,7 @@ msgstr "" msgid "Lookup typeahead" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:170 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:156 #: screens/Inventory/InventorySources/InventorySourceListItem.js:34 #: screens/Project/ProjectDetail/ProjectDetail.js:130 #: screens/Project/ProjectList/ProjectListItem.js:68 @@ -5148,11 +5466,11 @@ msgstr "" #: components/AdHocCommands/AdHocCredentialStep.js:97 #: components/AdHocCommands/AdHocCredentialStep.js:98 #: components/AdHocCommands/AdHocCredentialStep.js:112 -#: screens/Job/JobDetail/JobDetail.js:392 +#: screens/Job/JobDetail/JobDetail.js:407 msgid "Machine Credential" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:64 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 msgid "Managed" msgstr "" @@ -5166,7 +5484,7 @@ msgstr "" #: components/Schedule/ScheduleList/ScheduleListItem.js:39 #: components/Workflow/WorkflowLegend.js:108 #: components/Workflow/WorkflowNodeHelp.js:79 -#: screens/Job/JobDetail/JobDetail.js:68 +#: screens/Job/JobDetail/JobDetail.js:69 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:102 msgid "Management Job" msgstr "" @@ -5193,23 +5511,26 @@ msgstr "" msgid "Management jobs" msgstr "" -#: components/Lookup/ProjectLookup.js:134 +#: components/InstanceDetails.js/InstanceDetails.js:255 +#: components/Lookup/ProjectLookup.js:135 #: components/PromptDetail/PromptProjectDetail.js:98 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:88 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:157 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:208 -#: screens/InstanceGroup/Instances/InstanceListItem.js:204 -#: screens/Instances/InstanceDetail/InstanceDetail.js:159 -#: screens/Instances/InstanceList/InstanceListItem.js:219 -#: screens/Job/JobDetail/JobDetail.js:73 -#: screens/Project/ProjectDetail/ProjectDetail.js:191 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:219 +#: screens/InstanceGroup/Instances/InstanceListItem.js:218 +#: screens/Instances/InstanceDetail/InstanceDetail.js:212 +#: screens/Instances/InstanceList/InstanceListItem.js:235 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:83 +#: screens/Job/JobDetail/JobDetail.js:74 +#: screens/Project/ProjectDetail/ProjectDetail.js:192 #: screens/Project/ProjectList/ProjectList.js:197 #: screens/Project/ProjectList/ProjectListItem.js:219 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:96 msgid "Manual" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:123 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:161 +#: components/Schedule/shared/FrequencyDetailSubform.js:108 msgid "March" msgstr "" @@ -5218,11 +5539,25 @@ msgstr "" msgid "Mattermost" msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:98 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:94 #: screens/Organization/shared/OrganizationForm.js:71 msgid "Max Hosts" msgstr "" +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:56 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:77 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:62 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:47 +msgid "Max concurrent jobs" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:63 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:84 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:72 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:57 +msgid "Max forks" +msgstr "" + #: screens/Template/Survey/SurveyQuestionForm.js:220 msgid "Maximum" msgstr "" @@ -5231,7 +5566,26 @@ msgstr "" msgid "Maximum length" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:133 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:65 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:77 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:62 +msgid "" +"Maximum number of forks to allow across all jobs running concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:58 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:79 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:67 +#: screens/InstanceGroup/shared/InstanceGroupForm.js:52 +msgid "" +"Maximum number of jobs to run concurrently on this group.\n" +"Zero means no limit will be enforced." +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:163 +#: components/Schedule/shared/FrequencyDetailSubform.js:118 msgid "May" msgstr "" @@ -5278,28 +5632,31 @@ msgid "" "assigned to this group when new instances come online." msgstr "" -#: components/Schedule/shared/ScheduleForm.js:154 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:178 +#: components/Schedule/shared/FrequencyDetailSubform.js:173 +#: components/Schedule/shared/ScheduleFormFields.js:125 +#: components/Schedule/shared/ScheduleFormFields.js:185 msgid "Minute" msgstr "" -#: screens/Setting/Settings.js:96 +#: screens/Setting/Settings.js:100 msgid "Miscellaneous Authentication" msgstr "" -#: screens/Setting/SettingList.js:107 +#: screens/Setting/SettingList.js:111 msgid "Miscellaneous Authentication settings" msgstr "" -#: screens/Setting/Settings.js:99 +#: screens/Setting/Settings.js:103 msgid "Miscellaneous System" msgstr "" -#: screens/Setting/SettingList.js:103 +#: screens/Setting/SettingList.js:107 msgid "Miscellaneous System settings" msgstr "" #: components/Workflow/WorkflowNodeHelp.js:120 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:86 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:87 msgid "Missing" msgstr "" @@ -5308,7 +5665,7 @@ msgstr "" msgid "Missing resource" msgstr "" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:193 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:192 #: screens/User/UserTokenList/UserTokenList.js:154 msgid "Modified" msgstr "" @@ -5317,17 +5674,17 @@ msgstr "" #: components/AdHocCommands/AdHocExecutionEnvironmentStep.js:116 #: components/AddRole/AddResourceRole.js:61 #: components/AssociateModal/AssociateModal.js:148 -#: components/LaunchPrompt/steps/CredentialsStep.js:177 +#: components/LaunchPrompt/steps/CredentialsStep.js:181 #: components/LaunchPrompt/steps/InventoryStep.js:93 -#: components/Lookup/CredentialLookup.js:197 -#: components/Lookup/InventoryLookup.js:165 -#: components/Lookup/InventoryLookup.js:220 -#: components/Lookup/MultiCredentialsLookup.js:197 -#: components/Lookup/OrganizationLookup.js:137 -#: components/Lookup/ProjectLookup.js:146 +#: components/Lookup/CredentialLookup.js:198 +#: components/Lookup/InventoryLookup.js:156 +#: components/Lookup/InventoryLookup.js:211 +#: components/Lookup/MultiCredentialsLookup.js:202 +#: components/Lookup/OrganizationLookup.js:138 +#: components/Lookup/ProjectLookup.js:147 #: components/NotificationList/NotificationList.js:210 -#: components/RelatedTemplateList/RelatedTemplateList.js:170 -#: components/Schedule/ScheduleList/ScheduleList.js:201 +#: components/RelatedTemplateList/RelatedTemplateList.js:183 +#: components/Schedule/ScheduleList/ScheduleList.js:202 #: components/TemplateList/TemplateList.js:230 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:31 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:62 @@ -5351,7 +5708,7 @@ msgstr "" #: screens/Organization/OrganizationList/OrganizationList.js:135 #: screens/Project/ProjectList/ProjectList.js:209 #: screens/Team/TeamList/TeamList.js:134 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:167 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:165 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:108 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:112 msgid "Modified By (Username)" @@ -5364,28 +5721,33 @@ msgid "Modified by (username)" msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:59 -#: screens/Job/JobOutput/HostEventModal.js:125 +#: screens/Job/JobOutput/HostEventModal.js:126 msgid "Module" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:512 +#: screens/Job/JobDetail/JobDetail.js:530 msgid "Module Arguments" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:506 +#: screens/Job/JobDetail/JobDetail.js:524 msgid "Module Name" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:259 +#: components/Schedule/shared/FrequencyDetailSubform.js:266 msgid "Mon" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:264 -#: components/Schedule/shared/FrequencyDetailSubform.js:426 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:77 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:183 +#: components/Schedule/shared/FrequencyDetailSubform.js:271 +#: components/Schedule/shared/FrequencyDetailSubform.js:433 msgid "Monday" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:158 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:182 +#: components/Schedule/shared/FrequencyDetailSubform.js:181 +#: components/Schedule/shared/ScheduleFormFields.js:129 +#: components/Schedule/shared/ScheduleFormFields.js:189 msgid "Month" msgstr "" @@ -5431,45 +5793,50 @@ msgstr "" #: components/JobList/JobList.js:195 #: components/JobList/JobList.js:244 #: components/JobList/JobListItem.js:86 -#: components/LaunchPrompt/steps/CredentialsStep.js:168 -#: components/LaunchPrompt/steps/CredentialsStep.js:183 +#: components/LaunchPrompt/steps/CredentialsStep.js:172 +#: components/LaunchPrompt/steps/CredentialsStep.js:187 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:76 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:86 +#: components/LaunchPrompt/steps/ExecutionEnvironmentStep.js:97 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:78 +#: components/LaunchPrompt/steps/InstanceGroupsStep.js:89 #: components/LaunchPrompt/steps/InventoryStep.js:84 #: components/LaunchPrompt/steps/InventoryStep.js:99 -#: components/Lookup/ApplicationLookup.js:99 -#: components/Lookup/ApplicationLookup.js:110 -#: components/Lookup/CredentialLookup.js:188 -#: components/Lookup/CredentialLookup.js:203 -#: components/Lookup/ExecutionEnvironmentLookup.js:172 -#: components/Lookup/ExecutionEnvironmentLookup.js:179 +#: components/Lookup/ApplicationLookup.js:100 +#: components/Lookup/ApplicationLookup.js:111 +#: components/Lookup/CredentialLookup.js:189 +#: components/Lookup/CredentialLookup.js:204 +#: components/Lookup/ExecutionEnvironmentLookup.js:177 +#: components/Lookup/ExecutionEnvironmentLookup.js:184 #: components/Lookup/HostFilterLookup.js:93 -#: components/Lookup/HostFilterLookup.js:421 +#: components/Lookup/HostFilterLookup.js:422 #: components/Lookup/HostListItem.js:8 #: components/Lookup/InstanceGroupsLookup.js:103 #: components/Lookup/InstanceGroupsLookup.js:114 -#: components/Lookup/InventoryLookup.js:156 -#: components/Lookup/InventoryLookup.js:171 -#: components/Lookup/InventoryLookup.js:211 -#: components/Lookup/InventoryLookup.js:226 -#: components/Lookup/MultiCredentialsLookup.js:188 -#: components/Lookup/MultiCredentialsLookup.js:203 -#: components/Lookup/OrganizationLookup.js:128 -#: components/Lookup/OrganizationLookup.js:143 -#: components/Lookup/ProjectLookup.js:126 -#: components/Lookup/ProjectLookup.js:156 +#: components/Lookup/InventoryLookup.js:147 +#: components/Lookup/InventoryLookup.js:162 +#: components/Lookup/InventoryLookup.js:202 +#: components/Lookup/InventoryLookup.js:217 +#: components/Lookup/MultiCredentialsLookup.js:193 +#: components/Lookup/MultiCredentialsLookup.js:208 +#: components/Lookup/OrganizationLookup.js:129 +#: components/Lookup/OrganizationLookup.js:144 +#: components/Lookup/ProjectLookup.js:127 +#: components/Lookup/ProjectLookup.js:157 #: components/NotificationList/NotificationList.js:181 #: components/NotificationList/NotificationList.js:218 #: components/NotificationList/NotificationListItem.js:28 #: components/OptionsList/OptionsList.js:57 #: components/PaginatedTable/PaginatedTable.js:72 -#: components/PromptDetail/PromptDetail.js:105 -#: components/RelatedTemplateList/RelatedTemplateList.js:161 -#: components/RelatedTemplateList/RelatedTemplateList.js:186 +#: components/PromptDetail/PromptDetail.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:199 #: components/ResourceAccessList/ResourceAccessListItem.js:58 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:252 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:321 #: components/Schedule/ScheduleList/ScheduleList.js:168 -#: components/Schedule/ScheduleList/ScheduleList.js:188 -#: components/Schedule/ScheduleList/ScheduleListItem.js:80 -#: components/Schedule/shared/ScheduleForm.js:107 +#: components/Schedule/ScheduleList/ScheduleList.js:189 +#: components/Schedule/ScheduleList/ScheduleListItem.js:86 +#: components/Schedule/shared/ScheduleFormFields.js:72 #: components/TemplateList/TemplateList.js:205 #: components/TemplateList/TemplateList.js:242 #: components/TemplateList/TemplateListItem.js:142 @@ -5485,7 +5852,7 @@ msgstr "" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:179 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:191 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:206 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:59 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:60 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:109 #: screens/Application/ApplicationTokens/ApplicationTokenList.js:135 #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:28 @@ -5493,7 +5860,7 @@ msgstr "" #: screens/Application/ApplicationsList/ApplicationListItem.js:33 #: screens/Application/ApplicationsList/ApplicationsList.js:118 #: screens/Application/ApplicationsList/ApplicationsList.js:155 -#: screens/Application/shared/ApplicationForm.js:53 +#: screens/Application/shared/ApplicationForm.js:54 #: screens/Credential/CredentialDetail/CredentialDetail.js:217 #: screens/Credential/CredentialList/CredentialList.js:141 #: screens/Credential/CredentialList/CredentialList.js:164 @@ -5506,14 +5873,14 @@ msgstr "" #: screens/CredentialType/CredentialTypeList/CredentialTypeList.js:176 #: screens/CredentialType/CredentialTypeList/CredentialTypeListItem.js:33 #: screens/CredentialType/shared/CredentialTypeForm.js:21 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:48 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:49 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:136 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:165 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:69 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:89 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:115 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:12 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:88 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:89 #: screens/Host/HostDetail/HostDetail.js:69 #: screens/Host/HostGroups/HostGroupItem.js:28 #: screens/Host/HostGroups/HostGroupsList.js:159 @@ -5521,23 +5888,27 @@ msgstr "" #: screens/Host/HostList/HostList.js:148 #: screens/Host/HostList/HostList.js:169 #: screens/Host/HostList/HostListItem.js:50 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:41 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:49 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:175 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:208 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:161 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:194 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:61 -#: screens/InstanceGroup/Instances/InstanceList.js:188 -#: screens/InstanceGroup/Instances/InstanceList.js:204 -#: screens/InstanceGroup/Instances/InstanceList.js:255 +#: screens/InstanceGroup/Instances/InstanceList.js:217 +#: screens/InstanceGroup/Instances/InstanceList.js:233 #: screens/InstanceGroup/Instances/InstanceList.js:288 -#: screens/InstanceGroup/Instances/InstanceListItem.js:124 +#: screens/InstanceGroup/Instances/InstanceList.js:321 +#: screens/InstanceGroup/Instances/InstanceListItem.js:138 #: screens/InstanceGroup/shared/ContainerGroupForm.js:44 #: screens/InstanceGroup/shared/InstanceGroupForm.js:19 -#: screens/Instances/InstanceList/InstanceList.js:108 -#: screens/Instances/InstanceList/InstanceList.js:125 -#: screens/Instances/InstanceList/InstanceList.js:150 -#: screens/Instances/InstanceList/InstanceListItem.js:128 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:67 +#: screens/Instances/InstanceList/InstanceList.js:161 +#: screens/Instances/InstanceList/InstanceList.js:178 +#: screens/Instances/InstanceList/InstanceList.js:221 +#: screens/Instances/InstanceList/InstanceListItem.js:144 +#: screens/Instances/InstancePeers/InstancePeerList.js:80 +#: screens/Instances/InstancePeers/InstancePeerList.js:87 +#: screens/Instances/InstancePeers/InstancePeerList.js:96 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:37 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:90 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:31 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:194 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js:209 @@ -5549,7 +5920,7 @@ msgstr "" #: screens/Inventory/InventoryHostGroups/InventoryHostGroupItem.js:36 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:169 #: screens/Inventory/InventoryHostGroups/InventoryHostGroupsList.js:186 -#: screens/Inventory/InventoryHosts/InventoryHostItem.js:33 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:63 #: screens/Inventory/InventoryHosts/InventoryHostList.js:119 #: screens/Inventory/InventoryHosts/InventoryHostList.js:138 #: screens/Inventory/InventoryList/InventoryList.js:178 @@ -5559,7 +5930,7 @@ msgstr "" #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:180 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:195 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:232 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:196 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:182 #: screens/Inventory/InventorySources/InventorySourceList.js:211 #: screens/Inventory/InventorySources/InventorySourceListItem.js:71 #: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:98 @@ -5567,19 +5938,19 @@ msgstr "" #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:76 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:111 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:33 -#: screens/Inventory/shared/InventoryForm.js:42 +#: screens/Inventory/shared/InventoryForm.js:50 #: screens/Inventory/shared/InventoryGroupForm.js:32 #: screens/Inventory/shared/InventorySourceForm.js:101 #: screens/Inventory/shared/SmartInventoryForm.js:47 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:90 #: screens/ManagementJob/ManagementJobList/ManagementJobList.js:100 #: screens/ManagementJob/ManagementJobList/ManagementJobListItem.js:67 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:106 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:107 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:122 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:178 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:112 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:41 -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:91 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:87 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:84 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvList.js:107 #: screens/Organization/OrganizationExecEnvList/OrganizationExecEnvListItem.js:16 @@ -5590,18 +5961,18 @@ msgstr "" #: screens/Organization/OrganizationTeams/OrganizationTeamList.js:85 #: screens/Organization/OrganizationTeams/OrganizationTeamListItem.js:14 #: screens/Organization/shared/OrganizationForm.js:56 -#: screens/Project/ProjectDetail/ProjectDetail.js:175 +#: screens/Project/ProjectDetail/ProjectDetail.js:176 #: screens/Project/ProjectList/ProjectList.js:185 #: screens/Project/ProjectList/ProjectList.js:221 #: screens/Project/ProjectList/ProjectListItem.js:179 -#: screens/Project/shared/ProjectForm.js:170 +#: screens/Project/shared/ProjectForm.js:214 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:146 #: screens/Team/TeamDetail/TeamDetail.js:37 #: screens/Team/TeamList/TeamList.js:117 #: screens/Team/TeamList/TeamList.js:142 #: screens/Team/TeamList/TeamListItem.js:33 #: screens/Team/shared/TeamForm.js:29 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:178 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:181 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyList.js:102 #: screens/Template/Survey/SurveyListItem.js:39 @@ -5611,8 +5982,8 @@ msgstr "" #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:111 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:69 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:88 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:122 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:154 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:120 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:152 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:178 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:68 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:88 @@ -5620,8 +5991,8 @@ msgstr "" #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/SystemJobTemplatesList.js:94 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:75 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.js:95 -#: screens/Template/shared/JobTemplateForm.js:239 -#: screens/Template/shared/WorkflowJobTemplateForm.js:104 +#: screens/Template/shared/JobTemplateForm.js:243 +#: screens/Template/shared/WorkflowJobTemplateForm.js:109 #: screens/User/UserOrganizations/UserOrganizationList.js:75 #: screens/User/UserOrganizations/UserOrganizationList.js:79 #: screens/User/UserOrganizations/UserOrganizationListItem.js:13 @@ -5631,10 +6002,10 @@ msgstr "" #: screens/User/UserTeams/UserTeamList.js:232 #: screens/User/UserTeams/UserTeamListItem.js:18 #: screens/User/UserTokenList/UserTokenListItem.js:22 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:181 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:200 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:251 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:34 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:140 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:171 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:221 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:43 msgid "Name" msgstr "" @@ -5646,7 +6017,8 @@ msgstr "" msgid "Navigation" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:505 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:221 +#: components/Schedule/shared/FrequencyDetailSubform.js:512 #: screens/Dashboard/shared/ChartTooltip.js:106 #: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:57 msgid "Never" @@ -5665,24 +6037,24 @@ msgstr "" msgid "New" msgstr "" -#: components/AdHocCommands/AdHocCommandsWizard.js:52 +#: components/AdHocCommands/AdHocCommandsWizard.js:51 #: components/AdHocCommands/useAdHocCredentialStep.js:29 #: components/AdHocCommands/useAdHocDetailsStep.js:40 #: components/AdHocCommands/useAdHocExecutionEnvironmentStep.js:22 #: components/AddRole/AddResourceRole.js:196 #: components/AddRole/AddResourceRole.js:231 -#: components/LaunchPrompt/LaunchPrompt.js:130 -#: components/Schedule/shared/SchedulePromptableFields.js:134 +#: components/LaunchPrompt/LaunchPrompt.js:160 +#: components/Schedule/shared/SchedulePromptableFields.js:127 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:66 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:59 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:130 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:132 msgid "Next" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:259 -#: components/Schedule/ScheduleList/ScheduleList.js:170 -#: components/Schedule/ScheduleList/ScheduleListItem.js:104 -#: components/Schedule/ScheduleList/ScheduleListItem.js:108 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:333 +#: components/Schedule/ScheduleList/ScheduleList.js:171 +#: components/Schedule/ScheduleList/ScheduleListItem.js:118 +#: components/Schedule/ScheduleList/ScheduleListItem.js:122 msgid "Next Run" msgstr "" @@ -5690,16 +6062,16 @@ msgstr "" msgid "No" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:122 +#: screens/Job/JobOutput/JobOutputSearch.js:121 msgid "No Hosts Matched" msgstr "" +#: screens/Job/JobOutput/JobOutputSearch.js:122 #: screens/Job/JobOutput/JobOutputSearch.js:123 -#: screens/Job/JobOutput/JobOutputSearch.js:124 msgid "No Hosts Remaining" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:150 +#: screens/Job/JobOutput/HostEventModal.js:148 msgid "No JSON Available" msgstr "" @@ -5727,17 +6099,17 @@ msgstr "" msgid "No job data available" msgstr "" -#: screens/Job/JobOutput/EmptyOutput.js:25 +#: screens/Job/JobOutput/EmptyOutput.js:52 msgid "No output found for this job." msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:126 +#: screens/Job/JobOutput/HostEventModal.js:127 msgid "No result found" msgstr "" -#: components/LabelSelect/LabelSelect.js:102 -#: components/LaunchPrompt/steps/SurveyStep.js:134 -#: components/LaunchPrompt/steps/SurveyStep.js:193 +#: components/LabelSelect/LabelSelect.js:130 +#: components/LaunchPrompt/steps/SurveyStep.js:136 +#: components/LaunchPrompt/steps/SurveyStep.js:195 #: components/MultiSelect/TagMultiSelect.js:60 #: components/Search/AdvancedSearch.js:151 #: components/Search/AdvancedSearch.js:266 @@ -5750,10 +6122,10 @@ msgstr "" #: screens/Credential/shared/CredentialForm.js:143 #: screens/Credential/shared/CredentialFormFields/BecomeMethodField.js:65 #: screens/Dashboard/DashboardGraph.js:106 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:144 #: screens/Template/Survey/SurveyReorderModal.js:166 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:260 -#: screens/Template/shared/PlaybookSelect.js:72 +#: screens/Template/shared/PlaybookSelect.js:73 msgid "No results found" msgstr "" @@ -5766,6 +6138,10 @@ msgstr "" msgid "No survey questions found." msgstr "" +#: screens/Job/JobDetail/JobDetail.js:399 +msgid "No timeout specified" +msgstr "" + #: components/PaginatedTable/PaginatedTable.js:80 msgid "No {pluralizedItemName} Found" msgstr "" @@ -5777,36 +6153,47 @@ msgstr "" msgid "Node Alias" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:216 -#: screens/InstanceGroup/Instances/InstanceList.js:193 -#: screens/InstanceGroup/Instances/InstanceList.js:257 -#: screens/InstanceGroup/Instances/InstanceList.js:289 -#: screens/InstanceGroup/Instances/InstanceListItem.js:142 -#: screens/Instances/InstanceDetail/InstanceDetail.js:154 -#: screens/Instances/InstanceList/InstanceList.js:113 -#: screens/Instances/InstanceList/InstanceList.js:152 -#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: components/InstanceDetails.js/InstanceDetails.js:250 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 +#: screens/InstanceGroup/Instances/InstanceList.js:222 +#: screens/InstanceGroup/Instances/InstanceList.js:290 +#: screens/InstanceGroup/Instances/InstanceList.js:322 +#: screens/InstanceGroup/Instances/InstanceListItem.js:156 +#: screens/Instances/InstanceDetail/InstanceDetail.js:207 +#: screens/Instances/InstanceList/InstanceList.js:166 +#: screens/Instances/InstanceList/InstanceList.js:223 +#: screens/Instances/InstanceList/InstanceListItem.js:166 +#: screens/Instances/InstancePeers/InstancePeerList.js:98 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:59 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:118 msgid "Node Type" msgstr "" +#: screens/TopologyView/Legend.js:107 +msgid "Node state types" +msgstr "" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/useNodeTypeStep.js:75 msgid "Node type" msgstr "" -#: screens/TopologyView/Legend.js:68 +#: screens/TopologyView/Legend.js:70 msgid "Node types" msgstr "" +#: components/Schedule/shared/ScheduleFormFields.js:180 +#: components/Schedule/shared/ScheduleFormFields.js:184 #: components/Workflow/WorkflowNodeHelp.js:123 msgid "None" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:136 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:189 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:192 msgid "None (Run Once)" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:153 +#: components/Schedule/shared/ScheduleFormFields.js:120 +#: components/Schedule/shared/ScheduleFormFields.js:124 msgid "None (run once)" msgstr "" @@ -5867,7 +6254,7 @@ msgid "" "password information." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:326 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:331 msgid "Notification Color" msgstr "" @@ -5881,15 +6268,15 @@ msgstr "" #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:171 #: screens/NotificationTemplate/NotificationTemplates.js:14 #: screens/NotificationTemplate/NotificationTemplates.js:21 -#: util/getRelatedResourceDeleteDetails.js:180 +#: util/getRelatedResourceDeleteDetails.js:181 msgid "Notification Templates" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:133 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:134 msgid "Notification Type" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:369 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:380 msgid "Notification color" msgstr "" @@ -5897,7 +6284,7 @@ msgstr "" msgid "Notification sent successfully" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:444 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:449 msgid "Notification test failed." msgstr "" @@ -5926,11 +6313,12 @@ msgstr "" msgid "Notifications" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:163 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:169 +#: components/Schedule/shared/FrequencyDetailSubform.js:148 msgid "November" msgstr "" -#: components/StatusLabel/StatusLabel.js:36 +#: components/StatusLabel/StatusLabel.js:44 #: components/Workflow/WorkflowNodeHelp.js:117 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:66 #: screens/Job/JobOutput/shared/HostStatusBar.js:35 @@ -5938,43 +6326,44 @@ msgid "OK" msgstr "" #: components/Schedule/ScheduleOccurrences/ScheduleOccurrences.js:42 -#: components/Schedule/shared/FrequencyDetailSubform.js:542 +#: components/Schedule/shared/FrequencyDetailSubform.js:549 msgid "Occurrences" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:158 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:168 +#: components/Schedule/shared/FrequencyDetailSubform.js:143 msgid "October" msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:189 #: components/HostToggle/HostToggle.js:61 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:164 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:167 -#: components/PromptDetail/PromptDetail.js:284 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:318 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:192 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:195 +#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:58 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:150 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 -#: screens/Template/shared/JobTemplateForm.js:455 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 +#: screens/Template/shared/JobTemplateForm.js:504 msgid "Off" msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:188 #: components/HostToggle/HostToggle.js:60 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:164 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:166 -#: components/PromptDetail/PromptDetail.js:284 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:318 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:192 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:194 +#: components/PromptDetail/PromptDetail.js:349 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:485 #: components/Schedule/ScheduleToggle/ScheduleToggle.js:57 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:46 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:45 #: screens/Setting/shared/SettingDetail.js:98 #: screens/Setting/shared/SharedFields.js:149 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:277 -#: screens/Template/shared/JobTemplateForm.js:455 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:280 +#: screens/Template/shared/JobTemplateForm.js:504 msgid "On" msgstr "" @@ -5992,11 +6381,12 @@ msgstr "" msgid "On Success" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:529 +#: components/Schedule/shared/FrequencyDetailSubform.js:536 msgid "On date" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:244 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:99 +#: components/Schedule/shared/FrequencyDetailSubform.js:251 msgid "On days" msgstr "" @@ -6006,7 +6396,7 @@ msgid "" "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" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:166 +#: components/PromptDetail/PromptInventorySourceDetail.js:154 msgid "Only Group By" msgstr "" @@ -6014,7 +6404,7 @@ msgstr "" msgid "OpenStack" msgstr "" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:107 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:111 msgid "Option Details" msgstr "" @@ -6026,18 +6416,25 @@ msgid "" msgstr "" #: screens/Template/shared/WorkflowJobTemplate.helptext.js:11 -msgid "" -"Optional labels that describe this job template,\n" -"such as 'dev' or 'test'. Labels can be used to group and filter\n" -"job templates and completed jobs." -msgstr "" +#~ msgid "" +#~ "Optional labels that describe this job template,\n" +#~ "such as 'dev' or 'test'. Labels can be used to group and filter\n" +#~ "job templates and completed jobs." +#~ msgstr "" -#: screens/Job/Job.helptext.js:11 -#: screens/Template/shared/JobTemplate.helptext.js:12 +#: screens/Job/Job.helptext.js:12 +#: screens/Template/shared/JobTemplate.helptext.js:13 msgid "Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs." msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:25 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:11 +msgid "" +"Optional labels that describe this workflow job template,\n" +"such as 'dev' or 'test'. Labels can be used to group and filter\n" +"workflow job templates and completed jobs." +msgstr "" + +#: screens/Template/shared/JobTemplate.helptext.js:26 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:19 msgid "Optionally select the credential to use to send status updates back to the webhook service." msgstr "" @@ -6045,10 +6442,12 @@ msgstr "" #: components/NotificationList/NotificationList.js:220 #: components/NotificationList/NotificationListItem.js:34 #: screens/Credential/shared/TypeInputsSubForm.js:47 -#: screens/InstanceGroup/shared/ContainerGroupForm.js:61 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:65 -#: screens/Template/shared/JobTemplateForm.js:493 -#: screens/Template/shared/WorkflowJobTemplateForm.js:210 +#: screens/InstanceGroup/shared/ContainerGroupForm.js:81 +#: screens/Instances/Shared/InstanceForm.js:54 +#: screens/Inventory/shared/InventoryForm.js:94 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:69 +#: screens/Template/shared/JobTemplateForm.js:545 +#: screens/Template/shared/WorkflowJobTemplateForm.js:241 msgid "Options" msgstr "" @@ -6058,44 +6457,44 @@ msgstr "" msgid "Order" msgstr "" -#: components/Lookup/ApplicationLookup.js:118 +#: components/Lookup/ApplicationLookup.js:119 #: components/Lookup/OrganizationLookup.js:101 #: components/Lookup/OrganizationLookup.js:107 -#: components/Lookup/OrganizationLookup.js:123 -#: components/PromptDetail/PromptInventorySourceDetail.js:73 -#: components/PromptDetail/PromptInventorySourceDetail.js:83 -#: components/PromptDetail/PromptJobTemplateDetail.js:103 -#: components/PromptDetail/PromptJobTemplateDetail.js:113 +#: components/Lookup/OrganizationLookup.js:124 +#: components/PromptDetail/PromptInventorySourceDetail.js:62 +#: components/PromptDetail/PromptInventorySourceDetail.js:72 +#: components/PromptDetail/PromptJobTemplateDetail.js:105 +#: components/PromptDetail/PromptJobTemplateDetail.js:115 #: components/PromptDetail/PromptProjectDetail.js:77 #: components/PromptDetail/PromptProjectDetail.js:88 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:65 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:67 #: components/TemplateList/TemplateList.js:244 #: components/TemplateList/TemplateListItem.js:185 -#: screens/Application/ApplicationDetails/ApplicationDetails.js:69 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:70 #: screens/Application/ApplicationsList/ApplicationListItem.js:38 #: screens/Application/ApplicationsList/ApplicationsList.js:157 #: screens/Credential/CredentialDetail/CredentialDetail.js:230 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:69 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:70 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:155 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentList.js:167 #: screens/ExecutionEnvironment/ExecutionEnvironmentList/ExecutionEnvironmentListItem.js:76 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:74 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:97 #: screens/Inventory/InventoryList/InventoryList.js:191 #: screens/Inventory/InventoryList/InventoryList.js:221 #: screens/Inventory/InventoryList/InventoryListItem.js:119 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:108 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:120 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:130 -#: screens/Project/ProjectDetail/ProjectDetail.js:179 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:203 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:107 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:121 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:131 +#: screens/Project/ProjectDetail/ProjectDetail.js:180 #: screens/Project/ProjectList/ProjectListItem.js:287 #: screens/Project/ProjectList/ProjectListItem.js:298 #: screens/Team/TeamDetail/TeamDetail.js:40 #: screens/Team/TeamList/TeamList.js:143 #: screens/Team/TeamList/TeamListItem.js:38 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:192 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:203 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:121 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:195 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:206 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:120 #: screens/User/UserTeams/UserTeamList.js:181 #: screens/User/UserTeams/UserTeamList.js:237 #: screens/User/UserTeams/UserTeamListItem.js:23 @@ -6124,52 +6523,52 @@ msgstr "" #: screens/User/User.js:66 #: screens/User/UserOrganizations/UserOrganizationList.js:72 #: screens/User/Users.js:33 -#: util/getRelatedResourceDeleteDetails.js:231 -#: util/getRelatedResourceDeleteDetails.js:265 +#: util/getRelatedResourceDeleteDetails.js:232 +#: util/getRelatedResourceDeleteDetails.js:266 msgid "Organizations" msgstr "" -#: components/LaunchPrompt/steps/useOtherPromptsStep.js:85 +#: components/LaunchPrompt/steps/useOtherPromptsStep.js:90 msgid "Other prompts" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:57 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:79 msgid "Out of compliance" msgstr "" -#: screens/Job/Job.js:118 -#: screens/Job/JobOutput/HostEventModal.js:156 +#: screens/Job/Job.js:131 +#: screens/Job/JobOutput/HostEventModal.js:154 #: screens/Job/Jobs.js:34 msgid "Output" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:157 +#: screens/Job/JobOutput/HostEventModal.js:155 msgid "Output tab" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:76 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:80 msgid "Overwrite" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:47 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:126 +#: components/PromptDetail/PromptInventorySourceDetail.js:41 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:122 msgid "Overwrite local groups and hosts from remote inventory source" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:52 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:132 +#: components/PromptDetail/PromptInventorySourceDetail.js:46 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:128 msgid "Overwrite local variables from remote inventory source" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:82 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:86 msgid "Overwrite variables" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:478 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:493 msgid "POST" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:479 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:494 msgid "PUT" msgstr "" @@ -6178,11 +6577,11 @@ msgstr "" msgid "Pagerduty" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:274 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:279 msgid "Pagerduty Subdomain" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:289 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:298 msgid "Pagerduty subdomain" msgstr "" @@ -6218,17 +6617,17 @@ msgstr "" #~ "documentation for example syntax." #~ msgstr "" -#: screens/Template/shared/WorkflowJobTemplateForm.js:215 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the Ansible Controller documentation for example syntax." msgstr "" -#: screens/Job/Job.helptext.js:12 -#: screens/Template/shared/JobTemplate.helptext.js:13 +#: screens/Job/Job.helptext.js:13 +#: screens/Template/shared/JobTemplate.helptext.js:14 msgid "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON. Refer to the documentation for example syntax." msgstr "" -#: screens/Login/Login.js:205 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:71 +#: screens/Login/Login.js:227 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:73 #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:101 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:212 #: screens/Template/Survey/SurveyQuestionForm.js:82 @@ -6252,13 +6651,18 @@ msgstr "" msgid "Past week" msgstr "" +#: screens/Instances/Instance.js:51 +#: screens/Instances/InstancePeers/InstancePeerList.js:74 +msgid "Peers" +msgstr "" + #: components/JobList/JobList.js:228 -#: components/StatusLabel/StatusLabel.js:41 +#: components/StatusLabel/StatusLabel.js:49 #: components/Workflow/WorkflowNodeHelp.js:93 msgid "Pending" msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:83 +#: components/AppContainer/PageHeaderToolbar.js:76 msgid "Pending Workflow Approvals" msgstr "" @@ -6266,11 +6670,11 @@ msgstr "" msgid "Pending delete" msgstr "" -#: components/Lookup/HostFilterLookup.js:369 +#: components/Lookup/HostFilterLookup.js:370 msgid "Perform a search to define a host filter" msgstr "" -#: screens/User/UserTokenDetail/UserTokenDetail.js:72 +#: screens/User/UserTokenDetail/UserTokenDetail.js:73 #: screens/User/UserTokenList/UserTokenList.js:105 msgid "Personal Access Token" msgstr "" @@ -6279,57 +6683,57 @@ msgstr "" msgid "Personal access token" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:122 +#: screens/Job/JobOutput/HostEventModal.js:123 msgid "Play" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:84 +#: screens/Job/JobOutput/shared/OutputToolbar.js:99 msgid "Play Count" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:125 +#: screens/Job/JobOutput/JobOutputSearch.js:124 msgid "Play Started" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:146 -#: screens/Job/JobDetail/JobDetail.js:314 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:246 +#: components/PromptDetail/PromptJobTemplateDetail.js:148 +#: screens/Job/JobDetail/JobDetail.js:319 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:249 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:43 -#: screens/Template/shared/JobTemplateForm.js:350 +#: screens/Template/shared/JobTemplateForm.js:357 msgid "Playbook" msgstr "" #: components/JobList/JobListItem.js:44 -#: screens/Job/JobDetail/JobDetail.js:66 +#: screens/Job/JobDetail/JobDetail.js:67 msgid "Playbook Check" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:126 +#: screens/Job/JobOutput/JobOutputSearch.js:125 msgid "Playbook Complete" msgstr "" -#: components/PromptDetail/PromptProjectDetail.js:150 -#: screens/Project/ProjectDetail/ProjectDetail.js:270 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:71 +#: components/PromptDetail/PromptProjectDetail.js:165 +#: screens/Project/ProjectDetail/ProjectDetail.js:288 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:72 msgid "Playbook Directory" msgstr "" #: components/JobList/JobList.js:213 #: components/JobList/JobListItem.js:44 #: components/Schedule/ScheduleList/ScheduleListItem.js:37 -#: screens/Job/JobDetail/JobDetail.js:66 +#: screens/Job/JobDetail/JobDetail.js:67 msgid "Playbook Run" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:127 +#: screens/Job/JobOutput/JobOutputSearch.js:126 msgid "Playbook Started" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:174 +#: components/RelatedTemplateList/RelatedTemplateList.js:187 #: components/TemplateList/TemplateList.js:222 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:23 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:54 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:159 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:157 msgid "Playbook name" msgstr "" @@ -6337,7 +6741,7 @@ msgstr "" msgid "Playbook run" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:85 +#: screens/Job/JobOutput/shared/OutputToolbar.js:100 msgid "Plays" msgstr "" @@ -6361,6 +6765,10 @@ msgstr "" msgid "Please click the Start button to begin." msgstr "" +#: components/Schedule/shared/ScheduleForm.js:414 +msgid "Please enter a number of occurrences." +msgstr "" + #: util/validators.js:160 msgid "Please enter a valid URL" msgstr "" @@ -6369,7 +6777,7 @@ msgstr "" msgid "Please enter a value." msgstr "" -#: screens/Login/Login.js:169 +#: screens/Login/Login.js:191 msgid "Please log in" msgstr "" @@ -6377,23 +6785,23 @@ msgstr "" msgid "Please run a job to populate this list." msgstr "" -#: components/Schedule/shared/ScheduleForm.js:622 +#: components/Schedule/shared/ScheduleForm.js:410 msgid "Please select a day number between 1 and 31." msgstr "" -#: screens/Template/shared/JobTemplateForm.js:170 +#: screens/Template/shared/JobTemplateForm.js:174 msgid "Please select an Inventory or check the Prompt on Launch option" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:614 +#: components/Schedule/shared/ScheduleForm.js:428 msgid "Please select an end date/time that comes after the start date/time." msgstr "" -#: components/Lookup/HostFilterLookup.js:358 +#: components/Lookup/HostFilterLookup.js:359 msgid "Please select an organization before editing the host filter" msgstr "" -#: screens/Job/JobOutput/EmptyOutput.js:20 +#: screens/Job/JobOutput/EmptyOutput.js:32 msgid "Please try another search using the filter above" msgstr "" @@ -6401,14 +6809,16 @@ msgstr "" msgid "Please wait until the topology view is populated..." msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:78 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 msgid "Pod spec override" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:207 -#: screens/InstanceGroup/Instances/InstanceListItem.js:203 -#: screens/Instances/InstanceDetail/InstanceDetail.js:158 -#: screens/Instances/InstanceList/InstanceListItem.js:218 +#: components/InstanceDetails.js/InstanceDetails.js:254 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:218 +#: screens/InstanceGroup/Instances/InstanceListItem.js:217 +#: screens/Instances/InstanceDetail/InstanceDetail.js:211 +#: screens/Instances/InstanceList/InstanceListItem.js:234 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:82 msgid "Policy Type" msgstr "" @@ -6436,7 +6846,7 @@ msgstr "" #~ "examples." #~ msgstr "" -#: components/Lookup/HostFilterLookup.js:348 +#: components/Lookup/HostFilterLookup.js:349 msgid "" "Populate the hosts for this inventory by using a search\n" "filter. Example: ansible_facts__ansible_distribution:\"RedHat\".\n" @@ -6445,8 +6855,8 @@ msgid "" "examples." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:164 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:102 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:165 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:104 msgid "Port" msgstr "" @@ -6472,6 +6882,23 @@ msgid "" "cancel the drag operation." msgstr "" +#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:115 +#: screens/Inventory/shared/InventoryForm.js:99 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:148 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:343 +#: screens/Template/shared/JobTemplateForm.js:603 +msgid "Prevent Instance Group Fallback" +msgstr "" + +#: screens/Inventory/shared/Inventory.helptext.js:198 +msgid "Prevent Instance Group Fallback: If enabled, the inventory will prevent adding any organization instance groups to the list of preferred instances groups to run associated job templates on." +msgstr "" + +#: screens/Template/shared/JobTemplate.helptext.js:43 +msgid "Prevent Instance Group Fallback: If enabled, the job template will prevent adding any inventory or organization instance groups to the list of preferred instances groups to run on." +msgstr "" + #: components/AdHocCommands/useAdHocPreviewStep.js:17 #: components/LaunchPrompt/steps/usePreviewStep.js:23 msgid "Preview" @@ -6482,8 +6909,8 @@ msgid "Private key passphrase" msgstr "" #: components/PromptDetail/PromptJobTemplateDetail.js:58 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:120 -#: screens/Template/shared/JobTemplateForm.js:499 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:123 +#: screens/Template/shared/JobTemplateForm.js:551 msgid "Privilege Escalation" msgstr "" @@ -6491,30 +6918,30 @@ msgstr "" msgid "Privilege escalation password" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:37 +#: screens/Template/shared/JobTemplate.helptext.js:40 msgid "Privilege escalation: If enabled, run this playbook as an administrator." msgstr "" #: components/JobList/JobListItem.js:239 #: components/Lookup/ProjectLookup.js:104 #: components/Lookup/ProjectLookup.js:109 -#: components/Lookup/ProjectLookup.js:165 -#: components/PromptDetail/PromptInventorySourceDetail.js:98 -#: components/PromptDetail/PromptJobTemplateDetail.js:131 -#: components/PromptDetail/PromptJobTemplateDetail.js:139 -#: components/TemplateList/TemplateListItem.js:299 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:231 -#: screens/Job/JobDetail/JobDetail.js:158 -#: screens/Job/JobDetail/JobDetail.js:176 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:222 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:232 +#: components/Lookup/ProjectLookup.js:166 +#: components/PromptDetail/PromptInventorySourceDetail.js:87 +#: components/PromptDetail/PromptJobTemplateDetail.js:133 +#: components/PromptDetail/PromptJobTemplateDetail.js:141 +#: components/TemplateList/TemplateListItem.js:300 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:217 +#: screens/Job/JobDetail/JobDetail.js:172 +#: screens/Job/JobDetail/JobDetail.js:198 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:225 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:235 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.js:38 msgid "Project" msgstr "" -#: components/PromptDetail/PromptProjectDetail.js:143 -#: screens/Project/ProjectDetail/ProjectDetail.js:263 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:60 +#: components/PromptDetail/PromptProjectDetail.js:158 +#: screens/Project/ProjectDetail/ProjectDetail.js:281 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:61 msgid "Project Base Path" msgstr "" @@ -6527,7 +6954,7 @@ msgstr "" msgid "Project Sync" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:302 +#: screens/Project/ProjectDetail/ProjectDetail.js:320 #: screens/Project/ProjectList/ProjectListItem.js:229 msgid "Project Sync Error" msgstr "" @@ -6536,11 +6963,11 @@ msgstr "" msgid "Project Update" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:164 +#: screens/Job/JobDetail/JobDetail.js:180 msgid "Project Update Status" msgstr "" -#: screens/Job/Job.helptext.js:21 +#: screens/Job/Job.helptext.js:22 msgid "Project checkout results" msgstr "" @@ -6552,21 +6979,21 @@ msgstr "" msgid "Project not found." msgstr "" -#: screens/Dashboard/Dashboard.js:109 +#: screens/Dashboard/Dashboard.js:126 msgid "Project sync failures" msgstr "" #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:146 #: routeConfig.js:75 #: screens/ActivityStream/ActivityStream.js:170 -#: screens/Dashboard/Dashboard.js:103 +#: screens/Dashboard/Dashboard.js:120 #: screens/Project/ProjectList/ProjectList.js:180 #: screens/Project/ProjectList/ProjectList.js:249 #: screens/Project/Projects.js:12 #: screens/Project/Projects.js:22 -#: util/getRelatedResourceDeleteDetails.js:59 -#: util/getRelatedResourceDeleteDetails.js:194 -#: util/getRelatedResourceDeleteDetails.js:224 +#: util/getRelatedResourceDeleteDetails.js:60 +#: util/getRelatedResourceDeleteDetails.js:195 +#: util/getRelatedResourceDeleteDetails.js:225 msgid "Projects" msgstr "" @@ -6574,12 +7001,12 @@ msgstr "" msgid "Promote Child Groups and Hosts" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:670 -#: components/Schedule/shared/ScheduleForm.js:673 +#: components/Schedule/shared/ScheduleForm.js:539 +#: components/Schedule/shared/ScheduleForm.js:542 msgid "Prompt" msgstr "" -#: components/PromptDetail/PromptDetail.js:173 +#: components/PromptDetail/PromptDetail.js:183 msgid "Prompt Overrides" msgstr "" @@ -6589,12 +7016,12 @@ msgstr "" msgid "Prompt on launch" msgstr "" -#: components/Schedule/shared/SchedulePromptableFields.js:104 +#: components/Schedule/shared/SchedulePromptableFields.js:97 msgid "Prompt | {0}" msgstr "" -#: components/PromptDetail/PromptDetail.js:171 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:282 +#: components/PromptDetail/PromptDetail.js:181 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:414 msgid "Prompted Values" msgstr "" @@ -6607,15 +7034,15 @@ msgid "" msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:37 -msgid "" -"Provide a host pattern to further constrain the list\n" -"of hosts that will be managed or affected by the playbook. Multiple\n" -"patterns are allowed. Refer to Ansible documentation for more\n" -"information and examples on patterns." -msgstr "" +#~ msgid "" +#~ "Provide a host pattern to further constrain the list\n" +#~ "of hosts that will be managed or affected by the playbook. Multiple\n" +#~ "patterns are allowed. Refer to Ansible documentation for more\n" +#~ "information and examples on patterns." +#~ msgstr "" -#: screens/Job/Job.helptext.js:13 -#: screens/Template/shared/JobTemplate.helptext.js:14 +#: screens/Job/Job.helptext.js:14 +#: screens/Template/shared/JobTemplate.helptext.js:15 msgid "Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. Multiple patterns are allowed. Refer to Ansible documentation for more information and examples on patterns." msgstr "" @@ -6645,29 +7072,38 @@ msgstr "" #~ msgid "Provide your Red Hat or Red Hat Satellite credentials to enable Insights for Ansible Automation Platform." #~ msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:157 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:295 -#: screens/Template/shared/JobTemplateForm.js:562 +#: components/StatusLabel/StatusLabel.js:59 +#: screens/TopologyView/Legend.js:150 +msgid "Provisioning" +msgstr "" + +#: components/PromptDetail/PromptJobTemplateDetail.js:162 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:298 +#: screens/Template/shared/JobTemplateForm.js:620 msgid "Provisioning Callback URL" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:557 +#: screens/Template/shared/JobTemplateForm.js:615 msgid "Provisioning Callback details" msgstr "" #: components/PromptDetail/PromptJobTemplateDetail.js:63 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:125 -#: screens/Template/shared/JobTemplateForm.js:503 -#: screens/Template/shared/JobTemplateForm.js:506 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:128 +#: screens/Template/shared/JobTemplateForm.js:555 +#: screens/Template/shared/JobTemplateForm.js:558 msgid "Provisioning Callbacks" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:38 +#: screens/Template/shared/JobTemplate.helptext.js:41 msgid "Provisioning callbacks: Enables creation of a provisioning callback URL. Using the URL a host can contact Ansible AWX and request a configuration update using this job template." msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:85 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:113 +#: components/StatusLabel/StatusLabel.js:62 +msgid "Provisioning fail" +msgstr "" + +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:86 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:114 msgid "Pull" msgstr "" @@ -6675,7 +7111,7 @@ msgstr "" msgid "Question" msgstr "" -#: screens/Setting/Settings.js:102 +#: screens/Setting/Settings.js:106 msgid "RADIUS" msgstr "" @@ -6683,10 +7119,12 @@ msgstr "" msgid "RADIUS settings" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 -#: screens/InstanceGroup/Instances/InstanceListItem.js:161 -#: screens/Instances/InstanceDetail/InstanceDetail.js:187 -#: screens/Instances/InstanceList/InstanceListItem.js:171 +#: components/InstanceDetails.js/InstanceDetails.js:348 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:263 +#: screens/InstanceGroup/Instances/InstanceListItem.js:175 +#: screens/Instances/InstanceDetail/InstanceDetail.js:291 +#: screens/Instances/InstanceList/InstanceListItem.js:187 +#: screens/TopologyView/Tooltip.js:307 msgid "RAM {0}" msgstr "" @@ -6694,33 +7132,38 @@ msgstr "" msgid "Read" msgstr "" -#: screens/Dashboard/Dashboard.js:133 +#: components/StatusLabel/StatusLabel.js:57 +#: screens/TopologyView/Legend.js:122 +msgid "Ready" +msgstr "" + +#: screens/Dashboard/Dashboard.js:150 msgid "Recent Jobs" msgstr "" -#: screens/Dashboard/Dashboard.js:131 +#: screens/Dashboard/Dashboard.js:148 msgid "Recent Jobs list tab" msgstr "" -#: screens/Dashboard/Dashboard.js:145 +#: screens/Dashboard/Dashboard.js:162 msgid "Recent Templates" msgstr "" -#: screens/Dashboard/Dashboard.js:143 +#: screens/Dashboard/Dashboard.js:160 msgid "Recent Templates list tab" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:188 +#: components/RelatedTemplateList/RelatedTemplateList.js:201 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js:112 #: screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js:38 msgid "Recent jobs" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:153 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:154 msgid "Recipient List" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:84 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:86 msgid "Recipient list" msgstr "" @@ -6728,10 +7171,10 @@ msgstr "" msgid "Red Hat Ansible Automation Platform" msgstr "" -#: components/Lookup/ProjectLookup.js:138 +#: components/Lookup/ProjectLookup.js:139 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:92 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:161 -#: screens/Job/JobDetail/JobDetail.js:76 +#: screens/Job/JobDetail/JobDetail.js:77 #: screens/Project/ProjectList/ProjectList.js:201 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:100 msgid "Red Hat Insights" @@ -6753,8 +7196,8 @@ msgstr "" msgid "Red Hat, Inc." msgstr "" -#: screens/Application/ApplicationDetails/ApplicationDetails.js:93 -#: screens/Application/shared/ApplicationForm.js:106 +#: screens/Application/ApplicationDetails/ApplicationDetails.js:94 +#: screens/Application/shared/ApplicationForm.js:107 msgid "Redirect URIs" msgstr "" @@ -6771,6 +7214,7 @@ msgid "Redirecting to subscription detail" msgstr "" #: screens/Template/Survey/SurveyQuestionForm.js:261 +#: screens/Template/shared/JobTemplate.helptext.js:55 msgid "Refer to the" msgstr "" @@ -6780,8 +7224,8 @@ msgstr "" #~ "about the configuration file." #~ msgstr "" -#: screens/Job/Job.helptext.js:26 -#: screens/Template/shared/JobTemplate.helptext.js:46 +#: screens/Job/Job.helptext.js:27 +#: screens/Template/shared/JobTemplate.helptext.js:50 msgid "Refer to the Ansible documentation for details about the configuration file." msgstr "" @@ -6801,21 +7245,24 @@ msgstr "" msgid "Refresh project revision" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:128 +#: components/PromptDetail/PromptInventorySourceDetail.js:116 msgid "Regions" msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:91 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:142 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:92 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:143 msgid "Registry credential" msgstr "" -#: screens/Inventory/shared/Inventory.helptext.js:156 +#: screens/Inventory/shared/Inventory.helptext.js:157 msgid "Regular expression where only matching host names will be imported. The filter is applied as a post-processing step after any inventory plugin filters are applied." msgstr "" #: screens/Inventory/Inventories.js:81 #: screens/Inventory/InventoryGroup/InventoryGroup.js:62 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:76 +#: screens/Inventory/InventoryHosts/InventoryHostItem.js:79 +#: screens/Inventory/InventoryHosts/InventoryHostList.js:140 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js:175 msgid "Related Groups" msgstr "" @@ -6824,6 +7271,11 @@ msgstr "" msgid "Related Keys" msgstr "" +#: components/Schedule/ScheduleList/ScheduleList.js:169 +#: components/Schedule/ScheduleList/ScheduleListItem.js:105 +msgid "Related resource" +msgstr "" + #: components/Search/RelatedLookupTypeInput.js:16 #: components/Search/RelatedLookupTypeInput.js:24 msgid "Related search type" @@ -6835,14 +7287,14 @@ msgstr "" #: components/JobList/JobListItem.js:146 #: components/LaunchButton/ReLaunchDropDown.js:82 -#: screens/Job/JobDetail/JobDetail.js:562 -#: screens/Job/JobDetail/JobDetail.js:570 -#: screens/Job/JobOutput/shared/OutputToolbar.js:167 +#: screens/Job/JobDetail/JobDetail.js:580 +#: screens/Job/JobDetail/JobDetail.js:588 +#: screens/Job/JobOutput/shared/OutputToolbar.js:188 msgid "Relaunch" msgstr "" #: components/JobList/JobListItem.js:126 -#: screens/Job/JobOutput/shared/OutputToolbar.js:147 +#: screens/Job/JobOutput/shared/OutputToolbar.js:168 msgid "Relaunch Job" msgstr "" @@ -6860,20 +7312,37 @@ msgid "Relaunch on" msgstr "" #: components/JobList/JobListItem.js:125 -#: screens/Job/JobOutput/shared/OutputToolbar.js:146 +#: screens/Job/JobOutput/shared/OutputToolbar.js:167 msgid "Relaunch using host parameters" msgstr "" -#: components/Lookup/ProjectLookup.js:137 +#: components/HealthCheckAlert/HealthCheckAlert.js:27 +msgid "Reload" +msgstr "" + +#: screens/Job/JobOutput/JobOutput.js:735 +msgid "Reload output" +msgstr "" + +#: components/Lookup/ProjectLookup.js:138 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:91 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:160 -#: screens/Job/JobDetail/JobDetail.js:77 +#: screens/Job/JobDetail/JobDetail.js:78 #: screens/Project/ProjectList/ProjectList.js:200 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:99 msgid "Remote Archive" msgstr "" +#: screens/Instances/InstanceDetail/InstanceDetail.js:384 +#: screens/Instances/InstanceList/InstanceList.js:262 +msgid "Removal Error" +msgstr "" + #: components/SelectedList/DraggableSelectedList.js:105 +#: screens/Instances/Shared/RemoveInstanceButton.js:75 +#: screens/Instances/Shared/RemoveInstanceButton.js:129 +#: screens/Instances/Shared/RemoveInstanceButton.js:143 +#: screens/Instances/Shared/RemoveInstanceButton.js:163 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/DeleteAllNodesModal.js:21 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:29 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeDeleteModal.js:40 @@ -6884,6 +7353,10 @@ msgstr "" msgid "Remove All Nodes" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:152 +msgid "Remove Instances" +msgstr "" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:17 msgid "Remove Link" msgstr "" @@ -6896,7 +7369,7 @@ msgstr "" msgid "Remove Node {nodeName}" msgstr "" -#: screens/Project/shared/Project.helptext.js:109 +#: screens/Project/shared/Project.helptext.js:113 msgid "Remove any local modifications prior to performing an update." msgstr "" @@ -6912,6 +7385,10 @@ msgstr "" msgid "Remove {0} chip" msgstr "" +#: screens/TopologyView/Legend.js:285 +msgid "Removing" +msgstr "" + #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkDeleteModal.js:48 msgid "Removing this link will orphan the rest of the branch and cause it to be executed immediately on launch." msgstr "" @@ -6920,10 +7397,14 @@ msgstr "" msgid "Reorder" msgstr "" -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:264 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:345 msgid "Repeat Frequency" msgstr "" +#: components/Schedule/shared/ScheduleFormFields.js:113 +msgid "Repeat frequency" +msgstr "" + #: screens/Credential/shared/CredentialFormFields/CredentialField.js:52 msgid "Replace" msgstr "" @@ -6954,10 +7435,15 @@ msgstr "" msgid "Resource Name" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:227 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:246 msgid "Resource deleted" msgstr "" +#: components/Schedule/ScheduleList/ScheduleList.js:170 +#: components/Schedule/ScheduleList/ScheduleListItem.js:111 +msgid "Resource type" +msgstr "" + #: routeConfig.js:61 #: screens/ActivityStream/ActivityStream.js:159 msgid "Resources" @@ -6977,15 +7463,19 @@ msgid "" "The enabled variable may be specified using dot notation, e.g: 'foo.bar'" msgstr "" -#: components/JobCancelButton/JobCancelButton.js:81 -#: components/JobCancelButton/JobCancelButton.js:85 +#: components/JobCancelButton/JobCancelButton.js:96 +#: components/JobCancelButton/JobCancelButton.js:100 #: components/JobList/JobListCancelButton.js:160 #: components/JobList/JobListCancelButton.js:163 -#: screens/Job/JobOutput/JobOutput.js:764 -#: screens/Job/JobOutput/JobOutput.js:767 +#: screens/Job/JobOutput/JobOutput.js:831 +#: screens/Job/JobOutput/JobOutput.js:834 msgid "Return" msgstr "" +#: screens/Job/JobOutput/EmptyOutput.js:40 +msgid "Return to" +msgstr "" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:129 msgid "Return to subscription management." msgstr "" @@ -7029,13 +7519,13 @@ msgstr "" msgid "Revert to factory default." msgstr "" -#: screens/Job/JobDetail/JobDetail.js:309 +#: screens/Job/JobDetail/JobDetail.js:314 #: screens/Project/ProjectList/ProjectList.js:224 #: screens/Project/ProjectList/ProjectListItem.js:221 msgid "Revision" msgstr "" -#: screens/Project/shared/ProjectSubForms/SvnSubForm.js:20 +#: screens/Project/shared/ProjectSubForms/SvnSubForm.js:22 msgid "Revision #" msgstr "" @@ -7066,12 +7556,12 @@ msgstr "" msgid "Roles" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:99 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:134 #: components/Workflow/WorkflowLinkHelp.js:39 #: screens/Credential/shared/ExternalTestModal.js:89 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:49 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/RunStep.js:23 -#: screens/Template/shared/JobTemplateForm.js:210 +#: screens/Template/shared/JobTemplateForm.js:214 msgid "Run" msgstr "" @@ -7079,12 +7569,13 @@ msgstr "" #: components/AdHocCommands/AdHocCommands.js:135 #: components/AdHocCommands/AdHocCommands.js:141 #: components/AdHocCommands/AdHocCommands.js:145 -#: screens/Job/JobDetail/JobDetail.js:67 +#: screens/Job/JobDetail/JobDetail.js:68 msgid "Run Command" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:270 -#: screens/Instances/InstanceDetail/InstanceDetail.js:225 +#: components/InstanceDetails.js/InstanceDetails.js:385 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:297 +#: screens/Instances/InstanceDetail/InstanceDetail.js:340 msgid "Run a health check on the instance" msgstr "" @@ -7092,26 +7583,32 @@ msgstr "" msgid "Run ad hoc command" msgstr "" -#: components/AdHocCommands/AdHocCommandsWizard.js:49 +#: components/AdHocCommands/AdHocCommandsWizard.js:48 msgid "Run command" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:216 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:93 +#: components/Schedule/shared/FrequencyDetailSubform.js:223 msgid "Run every" msgstr "" #: components/Schedule/shared/ScheduleForm.js:148 -msgid "Run frequency" -msgstr "" +#~ msgid "Run frequency" +#~ msgstr "" -#: components/HealthCheckButton/HealthCheckButton.js:32 -#: components/HealthCheckButton/HealthCheckButton.js:45 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 -#: screens/Instances/InstanceDetail/InstanceDetail.js:234 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:396 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:310 +#: screens/Instances/InstanceDetail/InstanceDetail.js:353 msgid "Run health check" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:337 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:129 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:138 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:175 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:197 +#: components/Schedule/shared/FrequencyDetailSubform.js:344 msgid "Run on" msgstr "" @@ -7120,26 +7617,36 @@ msgid "Run type" msgstr "" #: components/JobList/JobList.js:230 -#: components/StatusLabel/StatusLabel.js:40 +#: components/StatusLabel/StatusLabel.js:48 #: components/TemplateList/TemplateListItem.js:118 #: components/Workflow/WorkflowNodeHelp.js:99 msgid "Running" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:128 +#: screens/Job/JobOutput/JobOutputSearch.js:127 msgid "Running Handlers" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:210 -#: screens/InstanceGroup/Instances/InstanceListItem.js:194 -#: screens/Instances/InstanceDetail/InstanceDetail.js:161 -#: screens/Instances/InstanceList/InstanceListItem.js:209 +#: components/InstanceDetails.js/InstanceDetails.js:258 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:221 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 +#: screens/InstanceGroup/Instances/InstanceListItem.js:208 +#: screens/Instances/InstanceDetail/InstanceDetail.js:215 +#: screens/Instances/InstanceList/InstanceListItem.js:225 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:73 msgid "Running Jobs" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:277 -#: screens/Instances/InstanceDetail/InstanceDetail.js:232 +#: components/HealthCheckButton/HealthCheckButton.js:37 +#: components/HealthCheckButton/HealthCheckButton.js:39 +#: components/HealthCheckButton/HealthCheckButton.js:53 +#: components/HealthCheckButton/HealthCheckButton.js:55 +#: components/InstanceDetails.js/InstanceDetails.js:392 +#: components/InstanceDetails.js/InstanceDetails.js:395 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:306 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:309 +#: screens/Instances/InstanceDetail/InstanceDetail.js:349 +#: screens/Instances/InstanceDetail/InstanceDetail.js:352 msgid "Running health check" msgstr "" @@ -7147,7 +7654,7 @@ msgstr "" msgid "Running jobs" msgstr "" -#: screens/Setting/Settings.js:105 +#: screens/Setting/Settings.js:109 msgid "SAML" msgstr "" @@ -7168,29 +7675,31 @@ msgstr "" msgid "SSH password" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:234 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:239 msgid "SSL Connection" msgstr "" #: components/Workflow/WorkflowStartNode.js:60 -#: components/Workflow/workflowReducer.js:413 +#: components/Workflow/workflowReducer.js:419 msgid "START" msgstr "" #: components/Sparkline/Sparkline.js:31 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:175 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:161 #: screens/Inventory/InventorySources/InventorySourceListItem.js:39 #: screens/Project/ProjectDetail/ProjectDetail.js:135 #: screens/Project/ProjectList/ProjectListItem.js:73 msgid "STATUS:" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:314 +#: components/Schedule/shared/FrequencyDetailSubform.js:321 msgid "Sat" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:319 -#: components/Schedule/shared/FrequencyDetailSubform.js:451 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:82 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:188 +#: components/Schedule/shared/FrequencyDetailSubform.js:326 +#: components/Schedule/shared/FrequencyDetailSubform.js:458 msgid "Saturday" msgstr "" @@ -7199,9 +7708,9 @@ msgstr "" #: components/AssociateModal/AssociateModal.js:110 #: components/FormActionGroup/FormActionGroup.js:13 #: components/FormActionGroup/FormActionGroup.js:19 -#: components/Schedule/shared/ScheduleForm.js:656 -#: components/Schedule/shared/ScheduleForm.js:662 -#: components/Schedule/shared/useSchedulePromptSteps.js:45 +#: components/Schedule/shared/ScheduleForm.js:525 +#: components/Schedule/shared/ScheduleForm.js:531 +#: components/Schedule/shared/useSchedulePromptSteps.js:49 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:130 #: screens/Credential/shared/CredentialForm.js:318 #: screens/Credential/shared/CredentialForm.js:323 @@ -7209,7 +7718,7 @@ msgstr "" #: screens/Setting/shared/RevertFormActionGroup.js:18 #: screens/Template/Survey/SurveyReorderModal.js:205 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/LinkModals/LinkModal.js:35 -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:129 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.js:131 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.js:158 #: screens/Template/WorkflowJobTemplateVisualizer/VisualizerToolbar.js:162 msgid "Save" @@ -7238,7 +7747,7 @@ msgstr "" msgid "Schedule Details" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:455 +#: components/Schedule/shared/UnsupportedScheduleForm.js:15 msgid "Schedule Rules" msgstr "" @@ -7254,7 +7763,7 @@ msgstr "" msgid "Schedule is inactive" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:566 +#: components/Schedule/shared/ScheduleForm.js:387 msgid "Schedule is missing rrule" msgstr "" @@ -7263,7 +7772,7 @@ msgid "Schedule not found." msgstr "" #: components/Schedule/ScheduleList/ScheduleList.js:163 -#: components/Schedule/ScheduleList/ScheduleList.js:228 +#: components/Schedule/ScheduleList/ScheduleList.js:229 #: routeConfig.js:44 #: screens/ActivityStream/ActivityStream.js:153 #: screens/Inventory/Inventories.js:89 @@ -7281,7 +7790,7 @@ msgstr "" #: screens/Application/ApplicationTokens/ApplicationTokenList.js:136 #: screens/Application/ApplicationTokens/ApplicationTokenListItem.js:33 -#: screens/User/UserTokenDetail/UserTokenDetail.js:49 +#: screens/User/UserTokenDetail/UserTokenDetail.js:50 #: screens/User/UserTokenList/UserTokenList.js:142 #: screens/User/UserTokenList/UserTokenList.js:189 #: screens/User/UserTokenList/UserTokenListItem.js:32 @@ -7309,12 +7818,12 @@ msgstr "" msgid "Scroll previous" msgstr "" -#: components/Lookup/HostFilterLookup.js:289 -#: components/Lookup/Lookup.js:137 +#: components/Lookup/HostFilterLookup.js:290 +#: components/Lookup/Lookup.js:143 msgid "Search" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:152 +#: screens/Job/JobOutput/JobOutputSearch.js:151 msgid "Search is disabled while the job is running" msgstr "" @@ -7327,28 +7836,32 @@ msgstr "" msgid "Search text input" msgstr "" -#: components/Lookup/HostFilterLookup.js:397 +#: components/Lookup/HostFilterLookup.js:398 msgid "Searching by ansible_facts requires special syntax. Refer to the" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:401 +#: components/Schedule/shared/FrequencyDetailSubform.js:408 msgid "Second" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:114 -#: components/PromptDetail/PromptProjectDetail.js:138 -#: screens/Project/ProjectDetail/ProjectDetail.js:251 +#: components/PromptDetail/PromptInventorySourceDetail.js:103 +#: components/PromptDetail/PromptProjectDetail.js:153 +#: screens/Project/ProjectDetail/ProjectDetail.js:269 msgid "Seconds" msgstr "" +#: screens/NotificationTemplate/shared/Notifications.helptext.js:34 +msgid "See Django" +msgstr "" + #: components/AdHocCommands/AdHocPreviewStep.js:35 -#: components/LaunchPrompt/steps/PreviewStep.js:63 +#: components/LaunchPrompt/steps/PreviewStep.js:61 msgid "See errors on the left" msgstr "" #: components/JobList/JobListItem.js:84 -#: components/Lookup/HostFilterLookup.js:379 -#: components/Lookup/Lookup.js:194 +#: components/Lookup/HostFilterLookup.js:380 +#: components/Lookup/Lookup.js:200 #: components/Pagination/Pagination.js:33 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:98 msgid "Select" @@ -7372,7 +7885,7 @@ msgstr "" msgid "Select Input" msgstr "" -#: screens/InstanceGroup/Instances/InstanceList.js:284 +#: screens/InstanceGroup/Instances/InstanceList.js:317 msgid "Select Instances" msgstr "" @@ -7384,7 +7897,7 @@ msgstr "" msgid "Select Items from List" msgstr "" -#: components/LabelSelect/LabelSelect.js:99 +#: components/LabelSelect/LabelSelect.js:127 msgid "Select Labels" msgstr "" @@ -7415,11 +7928,10 @@ msgstr "" #~ msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:48 -msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" -msgstr "" +#~ msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch" +#~ msgstr "" -#: screens/Job/Job.helptext.js:20 -#: screens/Template/shared/JobTemplate.helptext.js:26 +#: screens/Job/Job.helptext.js:21 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:10 msgid "Select a branch for the workflow. This branch is applied to all job template nodes that prompt for a branch." msgstr "" @@ -7449,7 +7961,7 @@ msgstr "" msgid "Select a playbook" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:319 +#: screens/Template/shared/JobTemplateForm.js:323 msgid "Select a project before editing the execution environment." msgstr "" @@ -7457,62 +7969,67 @@ msgstr "" msgid "Select a question to delete" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:19 -#~ msgid "Select a row to approve" -#~ msgstr "" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:18 +msgid "Select a row to approve" +msgstr "" #: components/PaginatedTable/ToolbarDeleteButton.js:160 #: screens/Inventory/InventoryGroups/InventoryGroupsList.js:103 msgid "Select a row to delete" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:19 -#~ msgid "Select a row to deny" -#~ msgstr "" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:18 +msgid "Select a row to deny" +msgstr "" #: components/DisassociateButton/DisassociateButton.js:75 msgid "Select a row to disassociate" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:77 +msgid "Select a row to remove" +msgstr "" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:87 msgid "Select a subscription" msgstr "" #: components/HostForm/HostForm.js:39 -#: components/Schedule/shared/FrequencyDetailSubform.js:59 -#: components/Schedule/shared/FrequencyDetailSubform.js:87 -#: components/Schedule/shared/FrequencyDetailSubform.js:91 -#: components/Schedule/shared/FrequencyDetailSubform.js:99 -#: components/Schedule/shared/ScheduleForm.js:95 -#: components/Schedule/shared/ScheduleForm.js:99 +#: components/Schedule/shared/FrequencyDetailSubform.js:71 +#: components/Schedule/shared/FrequencyDetailSubform.js:78 +#: components/Schedule/shared/FrequencyDetailSubform.js:88 +#: components/Schedule/shared/ScheduleFormFields.js:33 +#: components/Schedule/shared/ScheduleFormFields.js:37 +#: components/Schedule/shared/ScheduleFormFields.js:61 #: screens/Credential/shared/CredentialForm.js:44 -#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:78 -#: screens/Inventory/shared/InventoryForm.js:64 -#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:44 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:36 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:96 -#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:43 -#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:45 -#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:45 +#: screens/ExecutionEnvironment/shared/ExecutionEnvironmentForm.js:79 +#: screens/Inventory/shared/InventoryForm.js:72 +#: screens/Inventory/shared/InventorySourceSubForms/AzureSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/ControllerSubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/GCESubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/InsightsSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/OpenStackSubForm.js:45 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:38 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:104 +#: screens/Inventory/shared/InventorySourceSubForms/SatelliteSubForm.js:44 +#: screens/Inventory/shared/InventorySourceSubForms/VMwareSubForm.js:46 +#: screens/Inventory/shared/InventorySourceSubForms/VirtualizationSubForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:67 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:24 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:61 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:421 -#: screens/Project/shared/ProjectForm.js:190 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:436 +#: screens/Project/shared/ProjectForm.js:234 #: screens/Project/shared/ProjectSubForms/InsightsSubForm.js:39 -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:36 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:37 #: screens/Team/shared/TeamForm.js:49 #: screens/Template/Survey/SurveyQuestionForm.js:30 -#: screens/Template/shared/WorkflowJobTemplateForm.js:125 +#: screens/Template/shared/WorkflowJobTemplateForm.js:130 #: screens/User/shared/UserForm.js:139 +#: util/validators.js:201 msgid "Select a value for this field" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:22 +#: screens/Template/shared/JobTemplate.helptext.js:23 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:20 msgid "Select a webhook service." msgstr "" @@ -7535,7 +8052,7 @@ msgstr "" msgid "Select an instance and a metric to show chart" msgstr "" -#: components/HealthCheckButton/HealthCheckButton.js:19 +#: components/HealthCheckButton/HealthCheckButton.js:24 msgid "Select an instance to run a health check." msgstr "" @@ -7543,11 +8060,11 @@ msgstr "" msgid "Select an inventory for the workflow. This inventory is applied to all workflow nodes that prompt for an inventory." msgstr "" -#: components/LaunchPrompt/steps/SurveyStep.js:129 +#: components/LaunchPrompt/steps/SurveyStep.js:131 msgid "Select an option" msgstr "" -#: screens/Project/shared/ProjectForm.js:201 +#: screens/Project/shared/ProjectForm.js:245 msgid "Select an organization before editing the default execution environment." msgstr "" @@ -7560,11 +8077,16 @@ msgstr "" #~ "credential(s) become the defaults that can be updated at run time." #~ msgstr "" -#: screens/Job/Job.helptext.js:10 -#: screens/Template/shared/JobTemplate.helptext.js:11 +#: screens/Job/Job.helptext.js:11 +#: screens/Template/shared/JobTemplate.helptext.js:12 msgid "Select credentials for accessing the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking \"Prompt on launch\" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check \"Prompt on launch\", the selected credential(s) become the defaults that can be updated at run time." msgstr "" +#: components/Schedule/shared/ScheduleFormFields.js:120 +#: components/Schedule/shared/ScheduleFormFields.js:179 +msgid "Select frequency" +msgstr "" + #: screens/Project/shared/Project.helptext.js:18 msgid "" "Select from the list of directories found in\n" @@ -7577,15 +8099,15 @@ msgid "Select items from list" msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:55 -msgid "Select items to approve, deny, or cancel" -msgstr "" +#~ msgid "Select items to approve, deny, or cancel" +#~ msgstr "" #: screens/Dashboard/DashboardGraph.js:124 #: screens/Dashboard/DashboardGraph.js:125 msgid "Select job type" msgstr "" -#: components/LaunchPrompt/steps/SurveyStep.js:177 +#: components/LaunchPrompt/steps/SurveyStep.js:179 msgid "Select option(s)" msgstr "" @@ -7599,9 +8121,9 @@ msgstr "" msgid "Select roles to apply" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:127 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:128 -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:129 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:135 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:136 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:137 msgid "Select source path" msgstr "" @@ -7628,8 +8150,8 @@ msgstr "" #~ "to run on." #~ msgstr "" -#: screens/Job/Job.helptext.js:17 -#: screens/Template/shared/JobTemplate.helptext.js:19 +#: screens/Job/Job.helptext.js:18 +#: screens/Template/shared/JobTemplate.helptext.js:20 msgid "Select the Instance Groups for this Job Template to run on." msgstr "" @@ -7656,17 +8178,17 @@ msgid "Select the credential you want to use when accessing the remote hosts to msgstr "" #: screens/Template/shared/JobTemplate.helptext.js:8 -msgid "Select the execution environment for this job template." -msgstr "" +#~ msgid "Select the execution environment for this job template." +#~ msgstr "" -#: components/Lookup/InventoryLookup.js:133 +#: components/Lookup/InventoryLookup.js:123 msgid "" "Select the inventory containing the hosts\n" "you want this job to manage." msgstr "" #: screens/Job/Job.helptext.js:6 -#: screens/Template/shared/JobTemplate.helptext.js:6 +#: screens/Template/shared/JobTemplate.helptext.js:7 msgid "Select the inventory containing the hosts you want this job to manage." msgstr "" @@ -7682,19 +8204,22 @@ msgstr "" msgid "Select the inventory that this host will belong to." msgstr "" -#: screens/Job/Job.helptext.js:9 -#: screens/Template/shared/JobTemplate.helptext.js:10 +#: screens/Job/Job.helptext.js:10 +#: screens/Template/shared/JobTemplate.helptext.js:11 msgid "Select the playbook to be executed by this job." msgstr "" +#: screens/Instances/Shared/InstanceForm.js:43 +msgid "Select the port that Receptor will listen on for incoming connections. Default is 27199." +msgstr "" + #: screens/Template/shared/JobTemplateForm.js:300 #~ msgid "" #~ "Select the project containing the playbook\n" #~ "you want this job to execute." #~ msgstr "" -#: screens/Job/Job.helptext.js:7 -#: screens/Template/shared/JobTemplate.helptext.js:7 +#: screens/Template/shared/JobTemplate.helptext.js:8 msgid "Select the project containing the playbook you want this job to execute." msgstr "" @@ -7702,7 +8227,7 @@ msgstr "" msgid "Select your Ansible Automation Platform subscription to use." msgstr "" -#: components/Lookup/Lookup.js:180 +#: components/Lookup/Lookup.js:186 msgid "Select {0}" msgstr "" @@ -7713,7 +8238,7 @@ msgstr "" #: components/CheckboxListItem/CheckboxListItem.js:44 #: components/Lookup/InstanceGroupsLookup.js:87 #: components/OptionsList/OptionsList.js:74 -#: components/Schedule/ScheduleList/ScheduleListItem.js:78 +#: components/Schedule/ScheduleList/ScheduleListItem.js:84 #: components/TemplateList/TemplateListItem.js:140 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:107 #: components/UserAndTeamAccessAdd/UserAndTeamAccessAdd.js:125 @@ -7725,8 +8250,8 @@ msgstr "" #: screens/Host/HostGroups/HostGroupItem.js:26 #: screens/Host/HostList/HostListItem.js:48 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:59 -#: screens/InstanceGroup/Instances/InstanceListItem.js:122 -#: screens/Instances/InstanceList/InstanceListItem.js:126 +#: screens/InstanceGroup/Instances/InstanceListItem.js:136 +#: screens/Instances/InstanceList/InstanceListItem.js:142 #: screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js:42 #: screens/Inventory/InventoryList/InventoryListItem.js:90 #: screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js:37 @@ -7738,31 +8263,32 @@ msgstr "" #: screens/Team/TeamList/TeamListItem.js:31 #: screens/Template/Survey/SurveyListItem.js:34 #: screens/User/UserTokenList/UserTokenListItem.js:19 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:32 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:41 msgid "Selected" msgstr "" #: components/LaunchPrompt/steps/CredentialsStep.js:142 #: components/LaunchPrompt/steps/CredentialsStep.js:147 -#: components/Lookup/MultiCredentialsLookup.js:161 -#: components/Lookup/MultiCredentialsLookup.js:166 +#: components/Lookup/MultiCredentialsLookup.js:162 +#: components/Lookup/MultiCredentialsLookup.js:167 msgid "Selected Category" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:605 -#: components/Schedule/shared/ScheduleForm.js:606 +#: components/Schedule/shared/ScheduleForm.js:445 +#: components/Schedule/shared/ScheduleForm.js:446 msgid "Selected date range must have at least 1 schedule occurrence." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:159 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:160 msgid "Sender Email" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:94 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:96 msgid "Sender e-mail" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:153 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:167 +#: components/Schedule/shared/FrequencyDetailSubform.js:138 msgid "September" msgstr "" @@ -7771,7 +8297,7 @@ msgid "Service account JSON file" msgstr "" #: screens/Inventory/shared/InventorySourceForm.js:46 -#: screens/Project/shared/ProjectForm.js:94 +#: screens/Project/shared/ProjectForm.js:112 msgid "Set a value for this field" msgstr "" @@ -7779,15 +8305,16 @@ msgstr "" msgid "Set how many days of data should be retained." msgstr "" -#: screens/Setting/SettingList.js:118 +#: screens/Setting/SettingList.js:122 msgid "Set preferences for data collection, logos, and logins" msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:130 +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:138 msgid "Set source path to" msgstr "" #: components/InstanceToggle/InstanceToggle.js:48 +#: screens/Instances/Shared/InstanceForm.js:59 msgid "Set the instance enabled or disabled. If disabled, jobs will not be assigned to this instance." msgstr "" @@ -7819,6 +8346,14 @@ msgstr "" msgid "Set zoom to 100% and center graph" msgstr "" +#: screens/Instances/Shared/InstanceForm.js:35 +msgid "Sets the current life cycle stage of this instance. Default is \"installed.\"" +msgstr "" + +#: screens/Instances/Shared/InstanceForm.js:51 +msgid "Sets the role that this instance will play within mesh topology. Default is \"execution.\"" +msgstr "" + #: screens/ActivityStream/ActivityStreamDetailButton.js:46 msgid "Setting category" msgstr "" @@ -7835,7 +8370,7 @@ msgstr "" #: routeConfig.js:163 #: screens/ActivityStream/ActivityStream.js:220 #: screens/ActivityStream/ActivityStream.js:222 -#: screens/Setting/Settings.js:42 +#: screens/Setting/Settings.js:43 msgid "Settings" msgstr "" @@ -7843,12 +8378,12 @@ msgstr "" msgid "Show" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:154 -#: components/PromptDetail/PromptDetail.js:283 -#: components/PromptDetail/PromptJobTemplateDetail.js:151 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:317 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:276 -#: screens/Template/shared/JobTemplateForm.js:448 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:182 +#: components/PromptDetail/PromptDetail.js:348 +#: components/PromptDetail/PromptJobTemplateDetail.js:156 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:484 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:279 +#: screens/Template/shared/JobTemplateForm.js:497 msgid "Show Changes" msgstr "" @@ -7861,8 +8396,8 @@ msgstr "" msgid "Show changes" msgstr "" -#: components/LaunchPrompt/LaunchPrompt.js:105 -#: components/Schedule/shared/SchedulePromptableFields.js:109 +#: components/LaunchPrompt/LaunchPrompt.js:135 +#: components/Schedule/shared/SchedulePromptableFields.js:102 msgid "Show description" msgstr "" @@ -7874,43 +8409,47 @@ msgstr "" msgid "Show only root groups" msgstr "" -#: screens/Login/Login.js:240 +#: screens/Login/Login.js:262 msgid "Sign in with Azure AD" msgstr "" -#: screens/Login/Login.js:254 +#: screens/Login/Login.js:276 msgid "Sign in with GitHub" msgstr "" -#: screens/Login/Login.js:296 +#: screens/Login/Login.js:318 msgid "Sign in with GitHub Enterprise" msgstr "" -#: screens/Login/Login.js:311 +#: screens/Login/Login.js:333 msgid "Sign in with GitHub Enterprise Organizations" msgstr "" -#: screens/Login/Login.js:327 +#: screens/Login/Login.js:349 msgid "Sign in with GitHub Enterprise Teams" msgstr "" -#: screens/Login/Login.js:268 +#: screens/Login/Login.js:290 msgid "Sign in with GitHub Organizations" msgstr "" -#: screens/Login/Login.js:282 +#: screens/Login/Login.js:304 msgid "Sign in with GitHub Teams" msgstr "" -#: screens/Login/Login.js:342 +#: screens/Login/Login.js:364 msgid "Sign in with Google" msgstr "" -#: screens/Login/Login.js:361 +#: screens/Login/Login.js:378 +msgid "Sign in with OIDC" +msgstr "" + +#: screens/Login/Login.js:397 msgid "Sign in with SAML" msgstr "" -#: screens/Login/Login.js:360 +#: screens/Login/Login.js:396 msgid "Sign in with SAML {samlIDP}" msgstr "" @@ -7919,17 +8458,23 @@ msgstr "" msgid "Simple key select" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:69 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:70 -#: components/PromptDetail/PromptDetail.js:256 -#: components/PromptDetail/PromptJobTemplateDetail.js:260 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:369 -#: screens/Job/JobDetail/JobDetail.js:483 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:459 -#: screens/Template/shared/JobTemplateForm.js:481 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:106 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:107 +#: components/PromptDetail/PromptDetail.js:282 +#: components/PromptDetail/PromptJobTemplateDetail.js:267 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:572 +#: screens/Job/JobDetail/JobDetail.js:500 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:453 +#: screens/Template/shared/JobTemplateForm.js:533 +#: screens/Template/shared/WorkflowJobTemplateForm.js:230 msgid "Skip Tags" msgstr "" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:93 +#: components/Schedule/shared/FrequencyDetailSubform.js:223 +msgid "Skip every" +msgstr "" + #: screens/Template/shared/JobTemplateForm.js:538 #~ msgid "" #~ "Skip tags are useful when you have a\n" @@ -7940,15 +8485,16 @@ msgstr "" #~ msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:71 -msgid "" -"Skip tags are useful when you have a large\n" -"playbook, and you want to skip specific parts of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." -msgstr "" +#~ msgid "" +#~ "Skip tags are useful when you have a large\n" +#~ "playbook, and you want to skip specific parts of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." +#~ msgstr "" -#: screens/Job/Job.helptext.js:19 -#: screens/Template/shared/JobTemplate.helptext.js:21 +#: screens/Job/Job.helptext.js:20 +#: screens/Template/shared/JobTemplate.helptext.js:22 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:22 msgid "Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." msgstr "" @@ -7956,7 +8502,7 @@ msgstr "" msgid "Skipped" msgstr "" -#: components/StatusLabel/StatusLabel.js:42 +#: components/StatusLabel/StatusLabel.js:50 msgid "Skipped'" msgstr "" @@ -7977,17 +8523,17 @@ msgstr "" msgid "Smart Inventory not found." msgstr "" -#: components/Lookup/HostFilterLookup.js:344 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:117 +#: components/Lookup/HostFilterLookup.js:345 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:116 msgid "Smart host filter" msgstr "" -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:106 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 msgid "Smart inventory" msgstr "" #: components/AdHocCommands/AdHocPreviewStep.js:32 -#: components/LaunchPrompt/steps/PreviewStep.js:60 +#: components/LaunchPrompt/steps/PreviewStep.js:58 msgid "Some of the previous step(s) have errors" msgstr "" @@ -8012,37 +8558,40 @@ msgstr "" #~ msgid "Sort question order" #~ msgstr "" -#: components/JobList/JobListItem.js:170 -#: components/PromptDetail/PromptInventorySourceDetail.js:95 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:214 +#: components/JobList/JobListItem.js:169 +#: components/PromptDetail/PromptInventorySourceDetail.js:84 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:200 #: screens/Inventory/shared/InventorySourceForm.js:131 -#: screens/Job/JobDetail/JobDetail.js:274 +#: screens/Job/JobDetail/JobDetail.js:172 +#: screens/Job/JobDetail/JobDetail.js:294 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.js:93 msgid "Source" msgstr "" -#: components/LaunchPrompt/steps/OtherPromptsStep.js:47 -#: components/PromptDetail/PromptDetail.js:211 -#: components/PromptDetail/PromptJobTemplateDetail.js:145 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:44 +#: components/PromptDetail/PromptDetail.js:237 +#: components/PromptDetail/PromptJobTemplateDetail.js:147 #: components/PromptDetail/PromptProjectDetail.js:106 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:87 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:312 -#: screens/Job/JobDetail/JobDetail.js:302 -#: screens/Project/ProjectDetail/ProjectDetail.js:229 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:241 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:134 -#: screens/Template/shared/JobTemplateForm.js:328 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:286 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:89 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:463 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:238 +#: screens/Job/JobDetail/JobDetail.js:307 +#: screens/Project/ProjectDetail/ProjectDetail.js:230 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:244 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:133 +#: screens/Template/shared/JobTemplateForm.js:335 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:245 msgid "Source Control Branch" msgstr "" +#: screens/Inventory/shared/InventorySourceSubForms/SCMSubForm.js:85 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:29 msgid "Source Control Branch/Tag/Commit" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:117 -#: screens/Project/ProjectDetail/ProjectDetail.js:239 -#: screens/Project/shared/ProjectSubForms/SharedFields.js:53 +#: screens/Project/ProjectDetail/ProjectDetail.js:256 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:56 msgid "Source Control Credential" msgstr "" @@ -8051,27 +8600,27 @@ msgstr "" #~ msgstr "" #: components/PromptDetail/PromptProjectDetail.js:111 -#: screens/Project/ProjectDetail/ProjectDetail.js:234 +#: screens/Project/ProjectDetail/ProjectDetail.js:235 #: screens/Project/shared/ProjectSubForms/GitSubForm.js:32 msgid "Source Control Refspec" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:194 +#: screens/Project/ProjectDetail/ProjectDetail.js:195 msgid "Source Control Revision" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:96 -#: screens/Job/JobDetail/JobDetail.js:253 -#: screens/Project/ProjectDetail/ProjectDetail.js:190 -#: screens/Project/shared/ProjectForm.js:215 +#: screens/Job/JobDetail/JobDetail.js:273 +#: screens/Project/ProjectDetail/ProjectDetail.js:191 +#: screens/Project/shared/ProjectForm.js:259 msgid "Source Control Type" msgstr "" -#: components/Lookup/ProjectLookup.js:142 +#: components/Lookup/ProjectLookup.js:143 #: components/PromptDetail/PromptProjectDetail.js:101 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:96 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:165 -#: screens/Project/ProjectDetail/ProjectDetail.js:224 +#: screens/Project/ProjectDetail/ProjectDetail.js:225 #: screens/Project/ProjectList/ProjectList.js:205 #: screens/Project/shared/ProjectSubForms/SharedFields.js:16 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:104 @@ -8081,24 +8630,24 @@ msgstr "" #: components/JobList/JobList.js:211 #: components/JobList/JobListItem.js:42 #: components/Schedule/ScheduleList/ScheduleListItem.js:38 -#: screens/Job/JobDetail/JobDetail.js:64 +#: screens/Job/JobDetail/JobDetail.js:65 msgid "Source Control Update" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:335 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:340 msgid "Source Phone Number" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:188 +#: components/PromptDetail/PromptInventorySourceDetail.js:176 msgid "Source Variables" msgstr "" #: components/JobList/JobListItem.js:213 -#: screens/Job/JobDetail/JobDetail.js:237 +#: screens/Job/JobDetail/JobDetail.js:257 msgid "Source Workflow Job" msgstr "" -#: screens/Template/shared/WorkflowJobTemplateForm.js:172 +#: screens/Template/shared/WorkflowJobTemplateForm.js:177 msgid "Source control branch" msgstr "" @@ -8106,12 +8655,12 @@ msgstr "" msgid "Source details" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:390 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:403 msgid "Source phone number" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:285 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:19 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:275 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:21 msgid "Source variables" msgstr "" @@ -8144,7 +8693,7 @@ msgstr "" msgid "Specify the conditions under which this node should be executed" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:173 +#: screens/Job/JobOutput/HostEventModal.js:171 msgid "Standard Error" msgstr "" @@ -8152,7 +8701,7 @@ msgstr "" #~ msgid "Standard Out" #~ msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:174 +#: screens/Job/JobOutput/HostEventModal.js:172 msgid "Standard error tab" msgstr "" @@ -8176,16 +8725,16 @@ msgstr "" msgid "Start date" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:122 +#: components/Schedule/shared/ScheduleFormFields.js:87 msgid "Start date/time" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:460 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:465 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:105 msgid "Start message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:469 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:474 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:114 msgid "Start message body" msgstr "" @@ -8202,45 +8751,46 @@ msgstr "" msgid "Start time" msgstr "" -#: screens/Job/JobDetail/JobDetail.js:200 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:253 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:54 +#: screens/Job/JobDetail/JobDetail.js:220 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:223 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:63 msgid "Started" msgstr "" +#: components/InstanceDetails.js/InstanceDetails.js:242 #: components/JobList/JobList.js:224 #: components/JobList/JobList.js:245 #: components/JobList/JobListItem.js:95 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:201 -#: screens/InstanceGroup/Instances/InstanceList.js:256 -#: screens/InstanceGroup/Instances/InstanceListItem.js:129 -#: screens/Instances/InstanceDetail/InstanceDetail.js:149 -#: screens/Instances/InstanceList/InstanceList.js:151 -#: screens/Instances/InstanceList/InstanceListItem.js:134 -#: screens/Inventory/InventoryList/InventoryList.js:219 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:210 +#: screens/InstanceGroup/Instances/InstanceList.js:289 +#: screens/InstanceGroup/Instances/InstanceListItem.js:143 +#: screens/Instances/InstanceDetail/InstanceDetail.js:199 +#: screens/Instances/InstanceList/InstanceList.js:222 +#: screens/Instances/InstanceList/InstanceListItem.js:150 +#: screens/Instances/InstancePeers/InstancePeerList.js:97 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:43 #: screens/Inventory/InventoryList/InventoryListItem.js:101 #: screens/Inventory/InventorySources/InventorySourceList.js:212 #: screens/Inventory/InventorySources/InventorySourceListItem.js:87 -#: screens/Job/JobDetail/JobDetail.js:188 -#: screens/Job/JobOutput/HostEventModal.js:118 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:114 +#: screens/Job/JobDetail/JobDetail.js:210 +#: screens/Job/JobOutput/HostEventModal.js:119 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:115 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:179 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:117 #: screens/Project/ProjectList/ProjectList.js:222 #: screens/Project/ProjectList/ProjectListItem.js:197 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:45 -#: screens/TopologyView/Tooltip.js:98 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:203 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:254 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:57 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:61 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:162 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:224 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:66 msgid "Status" msgstr "" #: screens/TopologyView/Legend.js:107 -msgid "Status types" -msgstr "" +#~ msgid "Status types" +#~ msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:92 +#: screens/Job/JobOutput/JobOutputSearch.js:91 msgid "Stdout" msgstr "" @@ -8250,7 +8800,7 @@ msgstr "" msgid "Submit" msgstr "" -#: screens/Project/shared/Project.helptext.js:114 +#: screens/Project/shared/Project.helptext.js:118 msgid "" "Submodules will track the latest commit on\n" "their master branch (or other branch specified in\n" @@ -8260,14 +8810,14 @@ msgid "" "flag to git submodule update." msgstr "" -#: screens/Setting/SettingList.js:128 -#: screens/Setting/Settings.js:108 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:74 +#: screens/Setting/SettingList.js:132 +#: screens/Setting/Settings.js:112 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:136 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionEdit.js:195 msgid "Subscription" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:32 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:41 msgid "Subscription Details" msgstr "" @@ -8283,11 +8833,11 @@ msgstr "" msgid "Subscription selection modal" msgstr "" -#: screens/Setting/SettingList.js:133 +#: screens/Setting/SettingList.js:137 msgid "Subscription settings" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:69 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:131 msgid "Subscription type" msgstr "" @@ -8295,10 +8845,10 @@ msgstr "" msgid "Subscriptions table" msgstr "" -#: components/Lookup/ProjectLookup.js:136 +#: components/Lookup/ProjectLookup.js:137 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:90 #: components/UserAndTeamAccessAdd/getResourceAccessConfig.js:159 -#: screens/Job/JobDetail/JobDetail.js:75 +#: screens/Job/JobDetail/JobDetail.js:76 #: screens/Project/ProjectList/ProjectList.js:199 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:98 msgid "Subversion" @@ -8306,23 +8856,24 @@ msgstr "" #: components/NotificationList/NotificationListItem.js:71 #: components/NotificationList/NotificationListItem.js:72 -#: components/StatusLabel/StatusLabel.js:33 +#: components/StatusLabel/StatusLabel.js:41 msgid "Success" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:478 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:483 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:123 msgid "Success message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:487 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:492 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:132 msgid "Success message body" msgstr "" #: components/JobList/JobList.js:231 -#: components/StatusLabel/StatusLabel.js:35 +#: components/StatusLabel/StatusLabel.js:43 #: components/Workflow/WorkflowNodeHelp.js:102 +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:94 #: screens/Dashboard/shared/ChartTooltip.js:59 msgid "Successful" msgstr "" @@ -8331,17 +8882,27 @@ msgstr "" msgid "Successful jobs" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:200 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:28 +msgid "Successfully Approved" +msgstr "" + +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:25 +msgid "Successfully Denied" +msgstr "" + +#: screens/Project/ProjectDetail/ProjectDetail.js:201 #: screens/Project/ProjectList/ProjectListItem.js:97 msgid "Successfully copied to clipboard!" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:248 +#: components/Schedule/shared/FrequencyDetailSubform.js:255 msgid "Sun" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:253 -#: components/Schedule/shared/FrequencyDetailSubform.js:421 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:83 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:182 +#: components/Schedule/shared/FrequencyDetailSubform.js:260 +#: components/Schedule/shared/FrequencyDetailSubform.js:428 msgid "Sunday" msgstr "" @@ -8386,17 +8947,21 @@ msgstr "" #: screens/Inventory/InventorySources/InventorySourceListItem.js:120 #: screens/Inventory/shared/InventorySourceSyncButton.js:41 -#: screens/Project/shared/ProjectSyncButton.js:40 -#: screens/Project/shared/ProjectSyncButton.js:52 +#: screens/Project/shared/ProjectSyncButton.js:41 +#: screens/Project/shared/ProjectSyncButton.js:53 msgid "Sync" msgstr "" #: screens/Project/ProjectList/ProjectListItem.js:238 -#: screens/Project/shared/ProjectSyncButton.js:36 -#: screens/Project/shared/ProjectSyncButton.js:47 +#: screens/Project/shared/ProjectSyncButton.js:37 +#: screens/Project/shared/ProjectSyncButton.js:48 msgid "Sync Project" msgstr "" +#: screens/Inventory/InventoryList/InventoryList.js:219 +msgid "Sync Status" +msgstr "" + #: components/PaginatedTable/ToolbarSyncSourceButton.js:19 #: components/PaginatedTable/ToolbarSyncSourceButton.js:29 #: components/PaginatedTable/ToolbarSyncSourceButton.js:32 @@ -8411,7 +8976,7 @@ msgstr "" msgid "Sync error" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:212 +#: screens/Project/ProjectDetail/ProjectDetail.js:213 #: screens/Project/ProjectList/ProjectListItem.js:109 msgid "Sync for revision" msgstr "" @@ -8420,7 +8985,7 @@ msgstr "" msgid "Syncing" msgstr "" -#: screens/Setting/SettingList.js:98 +#: screens/Setting/SettingList.js:102 #: screens/User/UserRoles/UserRolesListItem.js:18 msgid "System" msgstr "" @@ -8439,7 +9004,7 @@ msgstr "" msgid "System Auditor" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:129 +#: screens/Job/JobOutput/JobOutputSearch.js:128 msgid "System Warning" msgstr "" @@ -8448,7 +9013,7 @@ msgstr "" msgid "System administrators have unrestricted access to all resources." msgstr "" -#: screens/Setting/Settings.js:111 +#: screens/Setting/Settings.js:115 msgid "TACACS+" msgstr "" @@ -8456,8 +9021,8 @@ msgstr "" msgid "TACACS+ settings" msgstr "" -#: screens/Dashboard/Dashboard.js:117 -#: screens/Job/JobOutput/HostEventModal.js:94 +#: screens/Dashboard/Dashboard.js:134 +#: screens/Job/JobOutput/HostEventModal.js:95 msgid "Tabs" msgstr "" @@ -8471,48 +9036,49 @@ msgstr "" #~ msgstr "" #: components/LaunchPrompt/steps/OtherPromptsStep.js:59 -msgid "" -"Tags are useful when you have a large\n" -"playbook, and you want to run a specific part of a play or task.\n" -"Use commas to separate multiple tags. Refer to Ansible Controller\n" -"documentation for details on the usage of tags." -msgstr "" +#~ msgid "" +#~ "Tags are useful when you have a large\n" +#~ "playbook, and you want to run a specific part of a play or task.\n" +#~ "Use commas to separate multiple tags. Refer to Ansible Controller\n" +#~ "documentation for details on the usage of tags." +#~ msgstr "" -#: screens/Job/Job.helptext.js:18 -#: screens/Template/shared/JobTemplate.helptext.js:20 +#: screens/Job/Job.helptext.js:19 +#: screens/Template/shared/JobTemplate.helptext.js:21 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:21 msgid "Tags are useful when you have a large playbook, and you want to run a specific part of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:198 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:203 msgid "Tags for the Annotation" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:172 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:179 msgid "Tags for the annotation (optional)" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:243 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:293 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:361 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:243 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:320 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:438 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:248 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:298 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:366 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:252 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:329 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:453 msgid "Target URL" msgstr "" -#: screens/Job/JobOutput/HostEventModal.js:123 +#: screens/Job/JobOutput/HostEventModal.js:124 msgid "Task" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:90 +#: screens/Job/JobOutput/shared/OutputToolbar.js:105 msgid "Task Count" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:130 +#: screens/Job/JobOutput/JobOutputSearch.js:129 msgid "Task Started" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:91 +#: screens/Job/JobOutput/shared/OutputToolbar.js:106 msgid "Tasks" msgstr "" @@ -8520,7 +9086,7 @@ msgstr "" msgid "Team" msgstr "" -#: components/ResourceAccessList/ResourceAccessListItem.js:87 +#: components/ResourceAccessList/ResourceAccessListItem.js:85 #: screens/Team/TeamRoles/TeamRolesList.js:144 msgid "Team Roles" msgstr "" @@ -8546,7 +9112,7 @@ msgstr "" #: screens/User/UserTeams/UserTeamList.js:175 #: screens/User/UserTeams/UserTeamList.js:246 #: screens/User/Users.js:32 -#: util/getRelatedResourceDeleteDetails.js:173 +#: util/getRelatedResourceDeleteDetails.js:174 msgid "Teams" msgstr "" @@ -8554,7 +9120,7 @@ msgstr "" msgid "Template" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:115 +#: components/RelatedTemplateList/RelatedTemplateList.js:121 #: components/TemplateList/TemplateList.js:133 msgid "Template copied successfully" msgstr "" @@ -8571,15 +9137,15 @@ msgstr "" #: screens/ExecutionEnvironment/ExecutionEnvironment.js:70 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:83 #: screens/Template/Templates.js:17 -#: util/getRelatedResourceDeleteDetails.js:217 -#: util/getRelatedResourceDeleteDetails.js:274 +#: util/getRelatedResourceDeleteDetails.js:218 +#: util/getRelatedResourceDeleteDetails.js:275 msgid "Templates" msgstr "" #: screens/Credential/shared/CredentialForm.js:331 #: screens/Credential/shared/CredentialForm.js:337 #: screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.js:80 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:421 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:426 msgid "Test" msgstr "" @@ -8612,11 +9178,11 @@ msgstr "" msgid "Textarea" msgstr "" -#: components/Lookup/Lookup.js:62 +#: components/Lookup/Lookup.js:63 msgid "That value was not found. Please enter or select a valid value." msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:391 +#: components/Schedule/shared/FrequencyDetailSubform.js:398 msgid "The" msgstr "" @@ -8632,10 +9198,15 @@ msgstr "" msgid "The Grant type the user must use to acquire tokens for this application" msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:128 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:124 msgid "The Instance Groups for this Organization to run on." msgstr "" +#: components/InstanceDetails.js/InstanceDetails.js:265 +#: screens/Instances/InstanceDetail/InstanceDetail.js:222 +msgid "The Instance Groups to which this instance belongs." +msgstr "" + #: screens/NotificationTemplate/shared/Notifications.helptext.js:6 msgid "" "The amount of time (in seconds) before the email\n" @@ -8650,8 +9221,8 @@ msgstr "" #~ "timeout." #~ msgstr "" -#: screens/Job/Job.helptext.js:16 -#: screens/Template/shared/JobTemplate.helptext.js:17 +#: screens/Job/Job.helptext.js:17 +#: screens/Template/shared/JobTemplate.helptext.js:18 msgid "The amount of time (in seconds) to run before the job is canceled. Defaults to 0 for no job timeout." msgstr "" @@ -8666,7 +9237,11 @@ msgid "" "Grafana URL." msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:109 +#: screens/Template/shared/JobTemplate.helptext.js:9 +msgid "The container image to be used for execution." +msgstr "" + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:105 msgid "" "The execution environment that will be used for jobs\n" "inside of this organization. This will be used a fallback when\n" @@ -8689,8 +9264,8 @@ msgstr "" #~ "explicitly assigning a different one to this job template." #~ msgstr "" -#: screens/Job/Job.helptext.js:8 -#: screens/Template/shared/JobTemplate.helptext.js:9 +#: screens/Job/Job.helptext.js:9 +#: screens/Template/shared/JobTemplate.helptext.js:10 msgid "The execution environment that will be used when launching this job template. The resolved execution environment can be overridden by explicitly assigning a different one to this job template." msgstr "" @@ -8702,25 +9277,33 @@ msgid "" msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:66 -msgid "The following selected items are complete and cannot be acted on: {completedItems}" -msgstr "" +#~ msgid "The following selected items are complete and cannot be acted on: {completedItems}" +#~ msgstr "" #: screens/ExecutionEnvironment/shared/ExecutionEnvironment.helptext.js:7 msgid "The full image location, including the container registry, image name, and version tag." msgstr "" -#: screens/Inventory/shared/Inventory.helptext.js:191 +#: screens/Inventory/shared/Inventory.helptext.js:192 msgid "" "The inventory file\n" "to be synced by this source. You can select from\n" "the dropdown or enter a file within the input." msgstr "" -#: screens/Host/HostDetail/HostDetail.js:77 +#: screens/Host/HostDetail/HostDetail.js:79 msgid "The inventory that this host belongs to." msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:100 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:141 +msgid "The last {dayOfWeek}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:200 +msgid "The last {weekday} of {month}" +msgstr "" + +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:96 msgid "" "The maximum number of hosts allowed to be managed by\n" "this organization. Value defaults to 0 which means no limit.\n" @@ -8740,6 +9323,10 @@ msgid "" "Service\" in Twilio with the format +18005550199." msgstr "" +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:69 +msgid "The number of hosts you have automated against is below your subscription count." +msgstr "" + #: screens/Template/shared/JobTemplateForm.js:427 #~ msgid "" #~ "The number of parallel or simultaneous\n" @@ -8749,8 +9336,8 @@ msgstr "" #~ "with a change to" #~ msgstr "" -#: screens/Job/Job.helptext.js:24 -#: screens/Template/shared/JobTemplate.helptext.js:44 +#: screens/Job/Job.helptext.js:25 +#: screens/Template/shared/JobTemplate.helptext.js:48 msgid "The number of parallel or simultaneous processes to use while executing the playbook. An empty value, or a value less than 1 will use the Ansible default which is usually 5. The default number of forks can be overwritten with a change to" msgstr "" @@ -8759,7 +9346,7 @@ msgid "The number of parallel or simultaneous processes to use while executing t msgstr "" #: components/ContentError/ContentError.js:41 -#: screens/Job/Job.js:138 +#: screens/Job/Job.js:161 msgid "The page you requested could not be found." msgstr "" @@ -8767,11 +9354,19 @@ msgstr "" msgid "The pattern used to target hosts in the inventory. Leaving the field blank, all, and * will all target all hosts in the inventory. You can find more information about Ansible's host patterns" msgstr "" +#: screens/Job/Job.helptext.js:7 +msgid "The project containing the playbook this job will execute." +msgstr "" + +#: screens/Job/Job.helptext.js:8 +msgid "The project from which this inventory update is sourced." +msgstr "" + #: screens/Project/ProjectList/ProjectListItem.js:120 msgid "The project is currently syncing and the revision will be available after the sync is complete." msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:210 +#: screens/Project/ProjectDetail/ProjectDetail.js:211 #: screens/Project/ProjectList/ProjectListItem.js:107 msgid "The project must be synced before a revision is available." msgstr "" @@ -8785,7 +9380,7 @@ msgstr "" msgid "The resource associated with this node has been deleted." msgstr "" -#: screens/Job/JobOutput/EmptyOutput.js:19 +#: screens/Job/JobOutput/EmptyOutput.js:31 msgid "The search filter did not produce any results…" msgstr "" @@ -8806,7 +9401,7 @@ msgstr "" #~ "source control using the Source Control Type option above." #~ msgstr "" -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:49 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:50 msgid "" "There are no available playbook directories in {project_base_dir}.\n" "Either that directory is empty, or all of the contents are already\n" @@ -8820,7 +9415,7 @@ msgstr "" msgid "There must be a value in at least one input" msgstr "" -#: screens/Login/Login.js:144 +#: screens/Login/Login.js:155 msgid "There was a problem logging in. Please try again." msgstr "" @@ -8832,7 +9427,7 @@ msgstr "" msgid "There was an error parsing the file. Please check the file formatting and try again." msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:621 +#: screens/Template/WorkflowJobTemplateVisualizer/Visualizer.js:713 msgid "There was an error saving the workflow." msgstr "" @@ -8849,7 +9444,7 @@ msgid "These are the verbosity levels for standard out of the command run that a msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:122 -#: screens/Job/Job.helptext.js:42 +#: screens/Job/Job.helptext.js:43 msgid "These arguments are used with the specified module." msgstr "" @@ -8857,15 +9452,15 @@ msgstr "" msgid "These arguments are used with the specified module. You can find information about {0} by clicking" msgstr "" -#: screens/Job/Job.helptext.js:32 +#: screens/Job/Job.helptext.js:33 msgid "These arguments are used with the specified module. You can find information about {moduleName} by clicking" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:403 +#: components/Schedule/shared/FrequencyDetailSubform.js:410 msgid "Third" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:153 +#: screens/Template/shared/JobTemplateForm.js:157 msgid "This Project needs to be updated" msgstr "" @@ -8887,11 +9482,15 @@ msgstr "" msgid "This action will disassociate the following:" msgstr "" -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:113 +#: screens/Instances/Shared/RemoveInstanceButton.js:178 +msgid "This action will remove the following instances:" +msgstr "" + +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:132 msgid "This container group is currently being by other resources. Are you sure you want to delete it?" msgstr "" -#: screens/Credential/CredentialDetail/CredentialDetail.js:305 +#: screens/Credential/CredentialDetail/CredentialDetail.js:304 msgid "This credential is currently being used by other resources. Are you sure you want to delete it?" msgstr "" @@ -8920,7 +9519,7 @@ msgid "" "streamline customer experience and success." msgstr "" -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:131 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:132 msgid "This execution environment is currently being used by other resources. Are you sure you want to delete it?" msgstr "" @@ -8929,7 +9528,7 @@ msgstr "" msgid "This feature is deprecated and will be removed in a future release." msgstr "" -#: screens/Inventory/shared/Inventory.helptext.js:155 +#: screens/Inventory/shared/Inventory.helptext.js:156 msgid "This field is ignored unless an Enabled Variable is set. If the enabled variable matches this value, the host will be enabled on import." msgstr "" @@ -8970,8 +9569,8 @@ msgstr "" msgid "This field must be a regular expression" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:52 #: util/validators.js:111 +#: util/validators.js:194 msgid "This field must be an integer" msgstr "" @@ -8983,13 +9582,13 @@ msgstr "" msgid "This field must be at least {min} characters" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:55 +#: util/validators.js:197 msgid "This field must be greater than 0" msgstr "" #: components/AdHocCommands/useAdHocDetailsStep.js:52 #: components/LaunchPrompt/steps/useSurveyStep.js:111 -#: screens/Template/shared/JobTemplateForm.js:150 +#: screens/Template/shared/JobTemplateForm.js:154 #: screens/User/shared/UserForm.js:92 #: screens/User/shared/UserForm.js:103 #: util/validators.js:5 @@ -9017,7 +9616,13 @@ msgstr "" msgid "This field will be retrieved from an external secret management system using the specified credential." msgstr "" -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:125 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:82 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:89 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:104 +msgid "This has already been acted on" +msgstr "" + +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:139 msgid "This instance group is currently being by other resources. Are you sure you want to delete it?" msgstr "" @@ -9025,11 +9630,11 @@ msgstr "" msgid "This inventory is applied to all workflow nodes within this workflow ({0}) that prompt for an inventory." msgstr "" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:160 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:184 msgid "This inventory is currently being used by other resources. Are you sure you want to delete it?" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:329 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:319 msgid "This inventory source is currently being used by other resources that rely on it. Are you sure you want to delete it?" msgstr "" @@ -9041,15 +9646,19 @@ msgstr "" msgid "This is the only time the token value and associated refresh token value will be shown." msgstr "" -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:526 +#: screens/Job/JobOutput/EmptyOutput.js:37 +msgid "This job failed and has no output." +msgstr "" + +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:521 msgid "This job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "" -#: screens/Organization/OrganizationDetail/OrganizationDetail.js:197 +#: screens/Organization/OrganizationDetail/OrganizationDetail.js:175 msgid "This organization is currently being by other resources. Are you sure you want to delete it?" msgstr "" -#: screens/Project/ProjectDetail/ProjectDetail.js:320 +#: screens/Project/ProjectDetail/ProjectDetail.js:338 msgid "This project is currently being used by other resources. Are you sure you want to delete it?" msgstr "" @@ -9057,6 +9666,10 @@ msgstr "" msgid "This project is currently on sync and cannot be clicked until sync process completed" msgstr "" +#: components/Schedule/shared/ScheduleForm.js:459 +msgid "This schedule has no occurrences due to the selected exceptions." +msgstr "" + #: components/Schedule/ScheduleList/ScheduleList.js:122 msgid "This schedule is missing an Inventory" msgstr "" @@ -9065,6 +9678,12 @@ msgstr "" msgid "This schedule is missing required survey values" msgstr "" +#: components/Schedule/shared/UnsupportedScheduleForm.js:12 +msgid "" +"This schedule uses complex rules that are not supported in the\n" +"UI. Please use the API to manage this schedule." +msgstr "" + #: components/LaunchPrompt/steps/StepName.js:26 msgid "This step contains errors" msgstr "" @@ -9073,17 +9692,25 @@ msgstr "" msgid "This value does not match the password you entered previously. Please confirm that password." msgstr "" -#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:90 -msgid "This will cancel the workflow and no subsequent nodes will execute." +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListItem.js:106 +msgid "This will cancel all subsequent nodes in this workflow" msgstr "" +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:328 +msgid "This will cancel all subsequent nodes in this workflow." +msgstr "" + +#: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:90 +#~ msgid "This will cancel the workflow and no subsequent nodes will execute." +#~ msgstr "" + #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:105 -msgid "This will continue the workflow" -msgstr "" +#~ msgid "This will continue the workflow" +#~ msgstr "" #: screens/WorkflowApproval/shared/WorkflowApprovalControls.js:78 -msgid "This will continue the workflow along failure and always paths." -msgstr "" +#~ msgid "This will continue the workflow along failure and always paths." +#~ msgstr "" #: screens/Setting/shared/RevertAllAlert.js:36 msgid "" @@ -9095,16 +9722,23 @@ msgstr "" msgid "This workflow does not have any nodes configured." msgstr "" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:269 +#: screens/WorkflowApproval/shared/WorkflowApprovalButton.js:43 +#: screens/WorkflowApproval/shared/WorkflowDenyButton.js:35 +msgid "This workflow has already been acted on" +msgstr "" + +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:267 msgid "This workflow job template is currently being used by other resources. Are you sure you want to delete it?" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:292 +#: components/Schedule/shared/FrequencyDetailSubform.js:299 msgid "Thu" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:297 -#: components/Schedule/shared/FrequencyDetailSubform.js:441 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:80 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:186 +#: components/Schedule/shared/FrequencyDetailSubform.js:304 +#: components/Schedule/shared/FrequencyDetailSubform.js:448 msgid "Thursday" msgstr "" @@ -9115,7 +9749,7 @@ msgstr "" msgid "Time" msgstr "" -#: screens/Project/shared/Project.helptext.js:124 +#: screens/Project/shared/Project.helptext.js:128 msgid "" "Time in seconds to consider a project\n" "to be current. During job runs and callbacks the task\n" @@ -9134,16 +9768,20 @@ msgid "" "inventory sync will be performed." msgstr "" -#: components/StatusLabel/StatusLabel.js:43 +#: components/StatusLabel/StatusLabel.js:51 msgid "Timed out" msgstr "" -#: components/PromptDetail/PromptDetail.js:127 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:169 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:112 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:270 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:86 +#: components/PromptDetail/PromptDetail.js:137 +#: components/PromptDetail/PromptDetail.js:342 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:480 +#: screens/Job/JobDetail/JobDetail.js:397 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:170 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:114 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:273 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:186 -#: screens/Template/shared/JobTemplateForm.js:443 +#: screens/Template/shared/JobTemplateForm.js:475 msgid "Timeout" msgstr "" @@ -9219,7 +9857,7 @@ msgstr "" msgid "Toggle tools" msgstr "" -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:362 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:373 #: screens/User/UserTokens/UserTokens.js:64 msgid "Token" msgstr "" @@ -9252,15 +9890,17 @@ msgstr "" #~ msgstr "" #: routeConfig.js:152 -#: screens/TopologyView/TopologyView.js:40 +#: screens/TopologyView/TopologyView.js:42 msgid "Topology View" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:211 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:211 -#: screens/InstanceGroup/Instances/InstanceListItem.js:199 -#: screens/Instances/InstanceDetail/InstanceDetail.js:162 -#: screens/Instances/InstanceList/InstanceListItem.js:214 +#: components/InstanceDetails.js/InstanceDetails.js:259 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:222 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:197 +#: screens/InstanceGroup/Instances/InstanceListItem.js:213 +#: screens/Instances/InstanceDetail/InstanceDetail.js:216 +#: screens/Instances/InstanceList/InstanceListItem.js:230 +#: screens/Instances/InstancePeers/InstancePeerListItem.js:78 msgid "Total Jobs" msgstr "" @@ -9269,8 +9909,8 @@ msgstr "" msgid "Total Nodes" msgstr "" -#: screens/Inventory/InventoryDetail/InventoryDetail.js:81 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:120 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:104 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:119 msgid "Total hosts" msgstr "" @@ -9278,38 +9918,40 @@ msgstr "" msgid "Total jobs" msgstr "" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:83 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:87 msgid "Track submodules" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:56 -#: screens/Project/ProjectDetail/ProjectDetail.js:108 +#: screens/Project/ProjectDetail/ProjectDetail.js:109 msgid "Track submodules latest commit on branch" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:79 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:141 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:168 msgid "Trial" msgstr "" -#: components/JobList/JobListItem.js:318 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:65 -#: screens/Job/JobDetail/JobDetail.js:378 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:205 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:235 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:265 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:310 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:368 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:80 +#: components/JobList/JobListItem.js:319 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:66 +#: screens/Job/JobDetail/JobDetail.js:383 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:210 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:240 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:270 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:315 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:373 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:142 msgid "True" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:270 +#: components/Schedule/shared/FrequencyDetailSubform.js:277 msgid "Tue" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:275 -#: components/Schedule/shared/FrequencyDetailSubform.js:431 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:78 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:184 +#: components/Schedule/shared/FrequencyDetailSubform.js:282 +#: components/Schedule/shared/FrequencyDetailSubform.js:438 msgid "Tuesday" msgstr "" @@ -9320,13 +9962,11 @@ msgstr "" #: components/JobList/JobList.js:246 #: components/JobList/JobListItem.js:98 -#: components/Lookup/ProjectLookup.js:131 +#: components/Lookup/ProjectLookup.js:132 #: components/NotificationList/NotificationList.js:219 #: components/NotificationList/NotificationListItem.js:33 -#: components/PromptDetail/PromptDetail.js:115 -#: components/RelatedTemplateList/RelatedTemplateList.js:187 -#: components/Schedule/ScheduleList/ScheduleList.js:169 -#: components/Schedule/ScheduleList/ScheduleListItem.js:97 +#: components/PromptDetail/PromptDetail.js:125 +#: components/RelatedTemplateList/RelatedTemplateList.js:200 #: components/TemplateList/TemplateList.js:214 #: components/TemplateList/TemplateList.js:243 #: components/TemplateList/TemplateListItem.js:184 @@ -9339,16 +9979,16 @@ msgstr "" #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:94 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:116 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:17 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:46 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:51 #: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:54 -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:209 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:195 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:66 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:72 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:95 #: screens/Inventory/InventoryList/InventoryList.js:220 #: screens/Inventory/InventoryList/InventoryListItem.js:116 #: screens/Inventory/InventorySources/InventorySourceList.js:213 #: screens/Inventory/InventorySources/InventorySourceListItem.js:100 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:106 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:105 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.js:180 #: screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.js:120 #: screens/NotificationTemplate/shared/NotificationTemplateForm.js:68 @@ -9361,7 +10001,6 @@ msgstr "" #: screens/Template/Survey/SurveyList.js:103 #: screens/Template/Survey/SurveyListItem.js:60 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.js:93 -#: screens/TopologyView/Tooltip.js:92 #: screens/User/UserDetail/UserDetail.js:75 #: screens/User/UserRoles/UserRolesList.js:156 #: screens/User/UserRoles/UserRolesListItem.js:21 @@ -9369,8 +10008,8 @@ msgid "Type" msgstr "" #: screens/Credential/shared/TypeInputsSubForm.js:25 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:46 -#: screens/Project/shared/ProjectForm.js:247 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:47 +#: screens/Project/shared/ProjectForm.js:298 msgid "Type Details" msgstr "" @@ -9392,12 +10031,15 @@ msgstr "" msgid "Unable to load last job update" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:253 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:87 +#: components/InstanceDetails.js/InstanceDetails.js:367 +#: components/StatusLabel/StatusLabel.js:61 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:279 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:101 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:46 -#: screens/InstanceGroup/Instances/InstanceListItem.js:78 -#: screens/Instances/InstanceDetail/InstanceDetail.js:205 -#: screens/Instances/InstanceList/InstanceListItem.js:77 +#: screens/InstanceGroup/Instances/InstanceListItem.js:80 +#: screens/Instances/InstanceDetail/InstanceDetail.js:310 +#: screens/Instances/InstanceList/InstanceListItem.js:79 +#: screens/TopologyView/Tooltip.js:121 msgid "Unavailable" msgstr "" @@ -9410,25 +10052,25 @@ msgstr "" msgid "Undo" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:184 +#: screens/Job/JobOutput/JobOutputSearch.js:183 msgid "Unfollow" msgstr "" -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:122 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:126 msgid "Unlimited" msgstr "" -#: components/StatusLabel/StatusLabel.js:39 +#: components/StatusLabel/StatusLabel.js:47 #: screens/Job/JobOutput/shared/HostStatusBar.js:51 -#: screens/Job/JobOutput/shared/OutputToolbar.js:103 +#: screens/Job/JobOutput/shared/OutputToolbar.js:118 msgid "Unreachable" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:102 +#: screens/Job/JobOutput/shared/OutputToolbar.js:117 msgid "Unreachable Host Count" msgstr "" -#: screens/Job/JobOutput/shared/OutputToolbar.js:104 +#: screens/Job/JobOutput/shared/OutputToolbar.js:119 msgid "Unreachable Hosts" msgstr "" @@ -9440,28 +10082,28 @@ msgstr "" msgid "Unsaved changes modal" msgstr "" -#: screens/Project/shared/ProjectSubForms/SharedFields.js:90 +#: screens/Project/shared/ProjectSubForms/SharedFields.js:94 msgid "Update Revision on Launch" msgstr "" -#: components/PromptDetail/PromptInventorySourceDetail.js:57 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:138 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:89 +#: components/PromptDetail/PromptInventorySourceDetail.js:51 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:134 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:92 msgid "Update on launch" msgstr "" #: components/PromptDetail/PromptInventorySourceDetail.js:62 #: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:148 #: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:97 -msgid "Update on project update" -msgstr "" +#~ msgid "Update on project update" +#~ msgstr "" -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:71 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:75 msgid "Update options" msgstr "" #: components/PromptDetail/PromptProjectDetail.js:61 -#: screens/Project/ProjectDetail/ProjectDetail.js:114 +#: screens/Project/ProjectDetail/ProjectDetail.js:115 msgid "Update revision on job launch" msgstr "" @@ -9469,11 +10111,11 @@ msgstr "" #~ msgid "Update settings pertaining to Jobs within {0}" #~ msgstr "" -#: screens/Setting/SettingList.js:88 +#: screens/Setting/SettingList.js:92 msgid "Update settings pertaining to Jobs within {brandName}" msgstr "" -#: screens/Template/shared/WebhookSubForm.js:187 +#: screens/Template/shared/WebhookSubForm.js:188 msgid "Update webhook key" msgstr "" @@ -9489,13 +10131,13 @@ msgstr "" msgid "Upload a Red Hat Subscription Manifest containing your subscription. To generate your subscription manifest, go to <0>subscription allocations on the Red Hat Customer Portal." msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:52 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:126 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:53 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:132 msgid "Use SSL" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:57 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:131 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:58 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:137 msgid "Use TLS" msgstr "" @@ -9527,22 +10169,26 @@ msgid "" "route SMS messages. Phone numbers should be formatted +11231231234. For more information see Twilio documentation" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:242 -#: screens/InstanceGroup/Instances/InstanceList.js:259 -#: screens/Instances/InstanceDetail/InstanceDetail.js:192 -#: screens/Instances/InstanceList/InstanceList.js:154 +#: components/InstanceDetails.js/InstanceDetails.js:353 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:268 +#: screens/InstanceGroup/Instances/InstanceList.js:292 +#: screens/Instances/InstanceDetail/InstanceDetail.js:296 +#: screens/Instances/InstanceList/InstanceList.js:225 msgid "Used Capacity" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:246 -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:78 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:86 +#: components/InstanceDetails.js/InstanceDetails.js:358 +#: components/InstanceDetails.js/InstanceDetails.js:364 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:272 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:276 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:92 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:100 #: screens/InstanceGroup/InstanceGroupList/InstanceGroupListItem.js:42 -#: screens/InstanceGroup/Instances/InstanceListItem.js:74 -#: screens/Instances/InstanceDetail/InstanceDetail.js:196 -#: screens/Instances/InstanceDetail/InstanceDetail.js:202 -#: screens/Instances/InstanceList/InstanceListItem.js:73 +#: screens/InstanceGroup/Instances/InstanceListItem.js:76 +#: screens/Instances/InstanceDetail/InstanceDetail.js:301 +#: screens/Instances/InstanceDetail/InstanceDetail.js:307 +#: screens/Instances/InstanceList/InstanceListItem.js:75 +#: screens/TopologyView/Tooltip.js:117 msgid "Used capacity" msgstr "" @@ -9550,20 +10196,20 @@ msgstr "" msgid "User" msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:165 +#: components/AppContainer/PageHeaderToolbar.js:160 msgid "User Details" msgstr "" -#: screens/Setting/SettingList.js:117 -#: screens/Setting/Settings.js:114 +#: screens/Setting/SettingList.js:121 +#: screens/Setting/Settings.js:118 msgid "User Interface" msgstr "" -#: screens/Setting/SettingList.js:122 +#: screens/Setting/SettingList.js:126 msgid "User Interface settings" msgstr "" -#: components/ResourceAccessList/ResourceAccessListItem.js:73 +#: components/ResourceAccessList/ResourceAccessListItem.js:72 #: screens/User/UserRoles/UserRolesList.js:142 msgid "User Roles" msgstr "" @@ -9588,7 +10234,7 @@ msgstr "" #~ msgid "User and Insights analytics" #~ msgstr "" -#: components/AppContainer/PageHeaderToolbar.js:159 +#: components/AppContainer/PageHeaderToolbar.js:154 msgid "User details" msgstr "" @@ -9604,15 +10250,15 @@ msgstr "" #: components/AddRole/AddResourceRole.js:38 #: components/ResourceAccessList/ResourceAccessList.js:173 #: components/ResourceAccessList/ResourceAccessList.js:226 -#: screens/Login/Login.js:208 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:143 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:248 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:298 -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:356 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:65 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:251 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:328 -#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:427 +#: screens/Login/Login.js:230 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:144 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:253 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:303 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:361 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:67 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:260 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:337 +#: screens/NotificationTemplate/shared/TypeInputsSubForm.js:442 #: screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js:92 #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionStep.js:204 #: screens/User/UserDetail/UserDetail.js:68 @@ -9645,31 +10291,31 @@ msgstr "" #: components/AdHocCommands/AdHocPreviewStep.js:69 #: components/HostForm/HostForm.js:113 -#: components/LaunchPrompt/steps/OtherPromptsStep.js:81 -#: components/PromptDetail/PromptDetail.js:159 -#: components/PromptDetail/PromptDetail.js:291 -#: components/PromptDetail/PromptJobTemplateDetail.js:278 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:132 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:393 -#: screens/Host/HostDetail/HostDetail.js:91 -#: screens/Inventory/InventoryDetail/InventoryDetail.js:126 +#: components/LaunchPrompt/steps/OtherPromptsStep.js:115 +#: components/PromptDetail/PromptDetail.js:169 +#: components/PromptDetail/PromptDetail.js:356 +#: components/PromptDetail/PromptJobTemplateDetail.js:286 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:135 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:597 +#: screens/Host/HostDetail/HostDetail.js:93 +#: screens/Inventory/InventoryDetail/InventoryDetail.js:150 #: screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js:37 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:89 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 -#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:54 -#: screens/Inventory/shared/InventoryForm.js:90 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:88 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:127 +#: screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js:53 +#: screens/Inventory/shared/InventoryForm.js:108 #: screens/Inventory/shared/InventoryGroupForm.js:46 #: screens/Inventory/shared/SmartInventoryForm.js:93 -#: screens/Job/JobDetail/JobDetail.js:528 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:484 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:228 -#: screens/Template/shared/JobTemplateForm.js:393 -#: screens/Template/shared/WorkflowJobTemplateForm.js:205 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:335 +#: screens/Job/JobDetail/JobDetail.js:546 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:479 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:226 +#: screens/Template/shared/JobTemplateForm.js:402 +#: screens/Template/shared/WorkflowJobTemplateForm.js:212 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:293 msgid "Variables" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:131 +#: screens/Job/JobOutput/JobOutputSearch.js:130 msgid "Variables Prompted" msgstr "" @@ -9677,7 +10323,7 @@ msgstr "" msgid "Variables must be in JSON or YAML syntax. Use the radio button to toggle between the two." msgstr "" -#: screens/Inventory/shared/Inventory.helptext.js:166 +#: screens/Inventory/shared/Inventory.helptext.js:167 msgid "Variables used to configure the inventory source. For a detailed description of how to configure this plugin, see <0>Inventory Plugins in the documentation and the <1>{sourceType} plugin configuration guide." msgstr "" @@ -9689,34 +10335,34 @@ msgstr "" msgid "Vault password | {credId}" msgstr "" -#: screens/Job/JobOutput/JobOutputSearch.js:132 +#: screens/Job/JobOutput/JobOutputSearch.js:131 msgid "Verbose" msgstr "" #: components/AdHocCommands/AdHocPreviewStep.js:63 -#: components/PromptDetail/PromptDetail.js:221 -#: components/PromptDetail/PromptInventorySourceDetail.js:111 -#: components/PromptDetail/PromptJobTemplateDetail.js:149 -#: components/Schedule/ScheduleDetail/ScheduleDetail.js:309 -#: components/VerbositySelectField/VerbositySelectField.js:47 -#: components/VerbositySelectField/VerbositySelectField.js:58 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:247 -#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:43 -#: screens/Job/JobDetail/JobDetail.js:326 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:264 +#: components/PromptDetail/PromptDetail.js:247 +#: components/PromptDetail/PromptInventorySourceDetail.js:100 +#: components/PromptDetail/PromptJobTemplateDetail.js:154 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:474 +#: components/VerbositySelectField/VerbositySelectField.js:34 +#: components/VerbositySelectField/VerbositySelectField.js:45 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:233 +#: screens/Inventory/shared/InventorySourceSubForms/SharedFields.js:47 +#: screens/Job/JobDetail/JobDetail.js:331 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:267 msgid "Verbosity" msgstr "" #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:64 -msgid "Version" -msgstr "" +#~ msgid "Version" +#~ msgstr "" #: screens/Setting/AzureAD/AzureAD.js:25 msgid "View Azure AD settings" msgstr "" -#: screens/Credential/Credential.js:143 -#: screens/Credential/Credential.js:155 +#: screens/Credential/Credential.js:165 +#: screens/Credential/Credential.js:177 msgid "View Credential Details" msgstr "" @@ -9736,11 +10382,11 @@ msgstr "" msgid "View Host Details" msgstr "" -#: screens/Instances/Instance.js:41 +#: screens/Instances/Instance.js:78 msgid "View Instance Details" msgstr "" -#: screens/Inventory/Inventory.js:192 +#: screens/Inventory/Inventory.js:193 #: screens/Inventory/InventoryGroup/InventoryGroup.js:142 #: screens/Inventory/SmartInventory.js:175 msgid "View Inventory Details" @@ -9758,7 +10404,7 @@ msgstr "" msgid "View JSON examples at <0>www.json.org" msgstr "" -#: screens/Job/Job.js:183 +#: screens/Job/Job.js:212 msgid "View Job Details" msgstr "" @@ -9782,6 +10428,10 @@ msgstr "" msgid "View Miscellaneous System settings" msgstr "" +#: screens/Setting/OIDC/OIDC.js:25 +msgid "View OIDC settings" +msgstr "" + #: screens/Organization/Organization.js:225 msgid "View Organization Details" msgstr "" @@ -9837,7 +10487,7 @@ msgstr "" msgid "View User Interface settings" msgstr "" -#: screens/WorkflowApproval/WorkflowApproval.js:102 +#: screens/WorkflowApproval/WorkflowApproval.js:105 msgid "View Workflow Approval Details" msgstr "" @@ -9850,7 +10500,7 @@ msgstr "" msgid "View activity stream" msgstr "" -#: screens/Credential/Credential.js:99 +#: screens/Credential/Credential.js:118 msgid "View all Credentials." msgstr "" @@ -9871,7 +10521,7 @@ msgstr "" msgid "View all Jobs" msgstr "" -#: screens/Job/Job.js:139 +#: screens/Job/Job.js:162 msgid "View all Jobs." msgstr "" @@ -9926,7 +10576,7 @@ msgstr "" msgid "View all management jobs" msgstr "" -#: screens/Setting/Settings.js:197 +#: screens/Setting/Settings.js:204 msgid "View all settings" msgstr "" @@ -9934,7 +10584,7 @@ msgstr "" msgid "View all tokens." msgstr "" -#: screens/Setting/SettingList.js:129 +#: screens/Setting/SettingList.js:133 msgid "View and edit your subscription information" msgstr "" @@ -9951,7 +10601,7 @@ msgstr "" msgid "View job {0}" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:193 +#: screens/Template/WorkflowJobTemplateVisualizer/VisualizerNode.js:220 msgid "View node details" msgstr "" @@ -9970,22 +10620,22 @@ msgstr "" msgid "Visualizer" msgstr "" -#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:43 +#: screens/Project/shared/ProjectSubForms/ManualSubForm.js:44 msgid "WARNING:" msgstr "" #: components/JobList/JobList.js:229 -#: components/StatusLabel/StatusLabel.js:44 +#: components/StatusLabel/StatusLabel.js:52 #: components/Workflow/WorkflowNodeHelp.js:96 msgid "Waiting" msgstr "" -#: screens/Job/JobOutput/EmptyOutput.js:23 +#: screens/Job/JobOutput/EmptyOutput.js:35 msgid "Waiting for job output…" msgstr "" #: components/Workflow/WorkflowLegend.js:118 -#: screens/Job/JobOutput/JobOutputSearch.js:133 +#: screens/Job/JobOutput/JobOutputSearch.js:132 msgid "Warning" msgstr "" @@ -9993,6 +10643,10 @@ msgstr "" msgid "Warning: Unsaved Changes" msgstr "" +#: components/Schedule/shared/ScheduleFormFields.js:43 +msgid "Warning: {selectedValue} is a link to {0} and will be saved as that." +msgstr "" + #: screens/Setting/Subscription/SubscriptionEdit/SubscriptionModal.js:119 msgid "We were unable to locate licenses associated with this account." msgstr "" @@ -10007,90 +10661,95 @@ msgstr "" msgid "Webhook" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:172 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:101 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:326 -#: screens/Template/shared/WebhookSubForm.js:198 +#: components/PromptDetail/PromptJobTemplateDetail.js:177 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:103 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:329 +#: screens/Template/shared/WebhookSubForm.js:199 msgid "Webhook Credential" msgstr "" -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:176 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:175 msgid "Webhook Credentials" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:168 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:90 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:319 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:169 -#: screens/Template/shared/WebhookSubForm.js:172 +#: components/PromptDetail/PromptJobTemplateDetail.js:173 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:92 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:322 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:168 +#: screens/Template/shared/WebhookSubForm.js:173 msgid "Webhook Key" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:161 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:89 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:304 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:157 -#: screens/Template/shared/WebhookSubForm.js:128 +#: components/PromptDetail/PromptJobTemplateDetail.js:166 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:91 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:307 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:156 +#: screens/Template/shared/WebhookSubForm.js:129 msgid "Webhook Service" msgstr "" -#: components/PromptDetail/PromptJobTemplateDetail.js:164 -#: components/PromptDetail/PromptWFJobTemplateDetail.js:93 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:312 -#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:163 -#: screens/Template/shared/WebhookSubForm.js:160 -#: screens/Template/shared/WebhookSubForm.js:166 +#: components/PromptDetail/PromptJobTemplateDetail.js:169 +#: components/PromptDetail/PromptWFJobTemplateDetail.js:95 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:315 +#: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:162 +#: screens/Template/shared/WebhookSubForm.js:161 +#: screens/Template/shared/WebhookSubForm.js:167 msgid "Webhook URL" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:588 -#: screens/Template/shared/WorkflowJobTemplateForm.js:240 +#: screens/Template/shared/JobTemplateForm.js:646 +#: screens/Template/shared/WorkflowJobTemplateForm.js:271 msgid "Webhook details" msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:23 +#: screens/Template/shared/JobTemplate.helptext.js:24 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:17 msgid "Webhook services can launch jobs with this workflow job template by making a POST request to this URL." msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:24 +#: screens/Template/shared/JobTemplate.helptext.js:25 #: screens/Template/shared/WorkflowJobTemplate.helptext.js:18 msgid "Webhook services can use this as a shared secret." msgstr "" #: components/PromptDetail/PromptJobTemplateDetail.js:78 #: components/PromptDetail/PromptWFJobTemplateDetail.js:41 -#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:140 +#: screens/Template/JobTemplateDetail/JobTemplateDetail.js:143 #: screens/Template/WorkflowJobTemplateDetail/WorkflowJobTemplateDetail.js:63 msgid "Webhooks" msgstr "" -#: screens/Template/shared/WorkflowJobTemplate.helptext.js:24 +#: screens/Template/shared/WorkflowJobTemplate.helptext.js:26 msgid "Webhooks: Enable Webhook for this workflow job template." msgstr "" -#: screens/Template/shared/JobTemplate.helptext.js:39 +#: screens/Template/shared/JobTemplate.helptext.js:42 msgid "Webhooks: Enable webhook for this template." msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:281 +#: components/Schedule/shared/FrequencyDetailSubform.js:288 msgid "Wed" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:286 -#: components/Schedule/shared/FrequencyDetailSubform.js:436 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:79 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:185 +#: components/Schedule/shared/FrequencyDetailSubform.js:293 +#: components/Schedule/shared/FrequencyDetailSubform.js:443 msgid "Wednesday" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:157 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:181 +#: components/Schedule/shared/FrequencyDetailSubform.js:179 +#: components/Schedule/shared/ScheduleFormFields.js:128 +#: components/Schedule/shared/ScheduleFormFields.js:188 msgid "Week" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:457 +#: components/Schedule/shared/FrequencyDetailSubform.js:464 msgid "Weekday" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:462 +#: components/Schedule/shared/FrequencyDetailSubform.js:469 msgid "Weekend day" msgstr "" @@ -10100,7 +10759,7 @@ msgid "" "Please complete the steps below to activate your subscription." msgstr "" -#: screens/Login/Login.js:168 +#: screens/Login/Login.js:190 msgid "Welcome to {brandName}!" msgstr "" @@ -10132,8 +10791,8 @@ msgstr "" #: routeConfig.js:54 #: screens/ActivityStream/ActivityStream.js:156 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:195 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:233 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:166 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:203 #: screens/WorkflowApproval/WorkflowApprovals.js:13 #: screens/WorkflowApproval/WorkflowApprovals.js:22 msgid "Workflow Approvals" @@ -10142,29 +10801,33 @@ msgstr "" #: components/JobList/JobList.js:216 #: components/JobList/JobListItem.js:47 #: components/Schedule/ScheduleList/ScheduleListItem.js:40 -#: screens/Job/JobDetail/JobDetail.js:69 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:265 -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:252 +#: screens/Job/JobDetail/JobDetail.js:70 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:224 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:222 msgid "Workflow Job" msgstr "" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:74 +msgid "Workflow Job 1/{0}" +msgstr "" + #: components/JobList/JobListItem.js:201 #: components/Workflow/WorkflowNodeHelp.js:63 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.js:20 -#: screens/Job/JobDetail/JobDetail.js:224 +#: screens/Job/JobDetail/JobDetail.js:244 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:91 -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:227 -#: util/getRelatedResourceDeleteDetails.js:104 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:186 +#: util/getRelatedResourceDeleteDetails.js:105 msgid "Workflow Job Template" msgstr "" -#: util/getRelatedResourceDeleteDetails.js:114 -#: util/getRelatedResourceDeleteDetails.js:156 -#: util/getRelatedResourceDeleteDetails.js:259 +#: util/getRelatedResourceDeleteDetails.js:115 +#: util/getRelatedResourceDeleteDetails.js:157 +#: util/getRelatedResourceDeleteDetails.js:260 msgid "Workflow Job Template Nodes" msgstr "" -#: util/getRelatedResourceDeleteDetails.js:139 +#: util/getRelatedResourceDeleteDetails.js:140 msgid "Workflow Job Templates" msgstr "" @@ -10172,27 +10835,35 @@ msgstr "" msgid "Workflow Link" msgstr "" +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:98 +msgid "Workflow Nodes" +msgstr "" + +#: components/WorkflowOutputNavigation/WorkflowOutputNavigation.js:84 +msgid "Workflow Statuses" +msgstr "" + #: components/TemplateList/TemplateList.js:218 #: screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.js:98 msgid "Workflow Template" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:514 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:519 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:159 msgid "Workflow approved message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:526 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:531 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:168 msgid "Workflow approved message body" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:538 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:543 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:177 msgid "Workflow denied message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:550 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:555 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:186 msgid "Workflow denied message body" msgstr "" @@ -10202,7 +10873,7 @@ msgstr "" msgid "Workflow documentation" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:261 +#: screens/WorkflowApproval/WorkflowApprovalDetail/WorkflowApprovalDetail.js:220 msgid "Workflow job details" msgstr "" @@ -10214,26 +10885,26 @@ msgstr "" msgid "Workflow link modal" msgstr "" -#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:228 +#: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeViewModal.js:247 msgid "Workflow node view modal" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:562 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:567 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:195 msgid "Workflow pending message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:574 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:579 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:204 msgid "Workflow pending message body" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:586 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:591 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:213 msgid "Workflow timed out message" msgstr "" -#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:598 +#: screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.js:603 #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:222 msgid "Workflow timed out message body" msgstr "" @@ -10246,7 +10917,10 @@ msgstr "" msgid "YAML:" msgstr "" -#: components/Schedule/shared/ScheduleForm.js:159 +#: components/Schedule/ScheduleDetail/ScheduleDetail.js:183 +#: components/Schedule/shared/FrequencyDetailSubform.js:183 +#: components/Schedule/shared/ScheduleFormFields.js:130 +#: components/Schedule/shared/ScheduleFormFields.js:190 msgid "Year" msgstr "" @@ -10254,15 +10928,15 @@ msgstr "" msgid "Yes" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:28 -#~ msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" -#~ msgstr "" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListApproveButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToApprove}" +msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:28 -#~ msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" -#~ msgstr "" +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalListDenyButton.js:27 +msgid "You are unable to act on the following workflow approvals: {itemsUnableToDeny}" +msgstr "" -#: components/Lookup/MultiCredentialsLookup.js:154 +#: components/Lookup/MultiCredentialsLookup.js:155 msgid "You cannot select multiple vault credentials with the same vault ID. Doing so will automatically deselect the other with the same vault ID." msgstr "" @@ -10278,13 +10952,21 @@ msgstr "" msgid "You do not have permission to disassociate the following: {itemsUnableToDisassociate}" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:72 +msgid "You do not have permission to remove instances: {itemsUnableToremove}" +msgstr "" + +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:82 +msgid "You have automated against more hosts than your subscription allows." +msgstr "" + #: screens/NotificationTemplate/shared/CustomMessagesSubForm.js:87 msgid "" "You may apply a number of possible variables in the\n" "message. For more information, refer to the" msgstr "" -#: screens/Login/Login.js:176 +#: screens/Login/Login.js:198 msgid "Your session has expired. Please log in to continue where you left off." msgstr "" @@ -10310,13 +10992,13 @@ msgstr "" msgid "Zoom out" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:685 -#: screens/Template/shared/WebhookSubForm.js:149 +#: screens/Template/shared/JobTemplateForm.js:754 +#: screens/Template/shared/WebhookSubForm.js:150 msgid "a new webhook key will be generated on save." msgstr "" -#: screens/Template/shared/JobTemplateForm.js:682 -#: screens/Template/shared/WebhookSubForm.js:139 +#: screens/Template/shared/JobTemplateForm.js:751 +#: screens/Template/shared/WebhookSubForm.js:140 msgid "a new webhook url will be generated on save." msgstr "" @@ -10346,6 +11028,14 @@ msgstr "" msgid "cancel edit login redirect" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:169 +msgid "cancel remove" +msgstr "" + +#: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:34 +msgid "canceled" +msgstr "" + #: components/AdHocCommands/AdHocDetailsStep.js:217 msgid "command" msgstr "" @@ -10368,35 +11058,51 @@ msgstr "" msgid "content-loading-in-progress" msgstr "" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:189 +msgid "day" +msgstr "" + #: screens/Inventory/shared/InventoryGroupsDeleteModal.js:151 msgid "deletion error" msgstr "" #: screens/ActivityStream/ActivityStreamDescription.js:513 +#: screens/WorkflowApproval/shared/WorkflowApprovalUtils.js:37 msgid "denied" msgstr "" +#: screens/Job/JobOutput/EmptyOutput.js:41 +msgid "details." +msgstr "" + #: components/DisassociateButton/DisassociateButton.js:91 msgid "disassociate" msgstr "" -#: components/Lookup/HostFilterLookup.js:405 +#: components/InstanceDetails.js/InstanceDetails.js:301 +#: components/Lookup/HostFilterLookup.js:406 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:235 +#: screens/InstanceGroup/Instances/InstanceListItem.js:233 +#: screens/Instances/InstanceDetail/InstanceDetail.js:242 +#: screens/Instances/InstanceList/InstanceListItem.js:250 #: screens/NotificationTemplate/shared/Notifications.helptext.js:20 +#: screens/NotificationTemplate/shared/Notifications.helptext.js:39 #: screens/Template/Survey/SurveyQuestionForm.js:269 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:239 +#: screens/Template/shared/JobTemplate.helptext.js:61 msgid "documentation" msgstr "" #: screens/CredentialType/CredentialTypeDetails/CredentialTypeDetails.js:105 -#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:116 -#: screens/Host/HostDetail/HostDetail.js:102 -#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:97 -#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:109 -#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:100 -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:305 -#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:163 -#: screens/Project/ProjectDetail/ProjectDetail.js:291 -#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:165 +#: screens/ExecutionEnvironment/ExecutionEnvironmentDetails/ExecutionEnvironmentDetails.js:117 +#: screens/Host/HostDetail/HostDetail.js:104 +#: screens/InstanceGroup/ContainerGroupDetails/ContainerGroupDetails.js:116 +#: screens/InstanceGroup/InstanceGroupDetails/InstanceGroupDetails.js:123 +#: screens/Inventory/InventoryHostDetail/InventoryHostDetail.js:99 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:295 +#: screens/Inventory/SmartInventoryDetail/SmartInventoryDetail.js:145 +#: screens/Project/ProjectDetail/ProjectDetail.js:309 +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:195 #: screens/User/UserDetail/UserDetail.js:92 msgid "edit" msgstr "" @@ -10410,19 +11116,26 @@ msgstr "" msgid "encrypted" msgstr "" -#: components/Lookup/HostFilterLookup.js:407 +#: components/InstanceDetails.js/InstanceDetails.js:303 +#: components/Lookup/HostFilterLookup.js:408 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:237 +#: screens/InstanceGroup/Instances/InstanceListItem.js:235 +#: screens/Instances/InstanceDetail/InstanceDetail.js:244 +#: screens/Instances/InstanceList/InstanceListItem.js:252 #: screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/NodeTypeStep.js:241 msgid "for more info." msgstr "" #: screens/NotificationTemplate/shared/Notifications.helptext.js:21 +#: screens/NotificationTemplate/shared/Notifications.helptext.js:40 #: screens/Template/Survey/SurveyQuestionForm.js:271 +#: screens/Template/shared/JobTemplate.helptext.js:63 msgid "for more information." msgstr "" #: screens/TopologyView/Legend.js:100 -msgid "h" -msgstr "" +#~ msgid "h" +#~ msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:150 msgid "here" @@ -10430,7 +11143,7 @@ msgstr "" #: components/AdHocCommands/AdHocDetailsStep.js:118 #: components/AdHocCommands/AdHocDetailsStep.js:170 -#: screens/Job/Job.helptext.js:38 +#: screens/Job/Job.helptext.js:39 msgid "here." msgstr "" @@ -10442,7 +11155,7 @@ msgstr "" msgid "host-name-{0}" msgstr "" -#: components/Lookup/HostFilterLookup.js:417 +#: components/Lookup/HostFilterLookup.js:418 msgid "hosts" msgstr "" @@ -10475,11 +11188,11 @@ msgid "new choice" msgstr "" #: screens/TopologyView/Tooltip.js:94 -msgid "node" -msgstr "" +#~ msgid "node" +#~ msgstr "" #: components/Pagination/Pagination.js:36 -#: components/Schedule/shared/FrequencyDetailSubform.js:473 +#: components/Schedule/shared/FrequencyDetailSubform.js:480 msgid "of" msgstr "" @@ -10508,7 +11221,7 @@ msgstr "" msgid "sec" msgstr "" -#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:253 +#: screens/Inventory/InventorySourceDetail/InventorySourceDetail.js:244 msgid "seconds" msgstr "" @@ -10521,15 +11234,15 @@ msgstr "" #~ msgstr "" #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:135 -msgid "since" -msgstr "" +#~ msgid "since" +#~ msgstr "" #: screens/User/UserList/UserListItem.js:49 msgid "social login" msgstr "" -#: screens/Template/shared/JobTemplateForm.js:339 -#: screens/Template/shared/WorkflowJobTemplateForm.js:183 +#: screens/Template/shared/JobTemplateForm.js:346 +#: screens/Template/shared/WorkflowJobTemplateForm.js:188 msgid "source control branch" msgstr "" @@ -10549,7 +11262,15 @@ msgstr "" msgid "updated" msgstr "" -#: screens/Template/shared/WebhookSubForm.js:180 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:190 +msgid "weekday" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:191 +msgid "weekend day" +msgstr "" + +#: screens/Template/shared/WebhookSubForm.js:181 msgid "workflow job template webhook key" msgstr "" @@ -10585,7 +11306,7 @@ msgstr "" msgid "{0, plural, one {The selected job cannot be deleted due to insufficient permission or a running job status} other {The selected jobs cannot be deleted due to insufficient permissions or a running job status}}" msgstr "" -#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:239 +#: screens/WorkflowApproval/WorkflowApprovalList/WorkflowApprovalList.js:209 msgid "{0, plural, one {This approval cannot be deleted due to insufficient permissions or a pending job status} other {These approvals cannot be deleted due to insufficient permissions or a pending job status}}" msgstr "" @@ -10601,10 +11322,14 @@ msgstr "" msgid "{0, plural, one {This execution environment is currently being used by other resources. Are you sure you want to delete it?} other {These execution environments could be in use by other resources that rely on them. Are you sure you want to delete them anyway?}}" msgstr "" -#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:196 +#: screens/InstanceGroup/InstanceGroupList/InstanceGroupList.js:182 msgid "{0, plural, one {This instance group is currently being by other resources. Are you sure you want to delete it?} other {Deleting these instance groups could impact other resources that rely on them. Are you sure you want to delete anyway?}}" msgstr "" +#: screens/Instances/Shared/RemoveInstanceButton.js:85 +msgid "{0, plural, one {This intance is currently being used by other resources. Are you sure you want to delete it?} other {Deprovisioning these instances could impact other resources that rely on them. Are you sure you want to delete anyway?}}" +msgstr "" + #: screens/Inventory/InventoryList/InventoryList.js:240 msgid "{0, plural, one {This inventory is currently being used by some templates. Are you sure you want to delete it?} other {Deleting these inventories could impact some templates that rely on them. Are you sure you want to delete anyway?}}" msgstr "" @@ -10625,7 +11350,7 @@ msgstr "" 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?}}" msgstr "" -#: components/RelatedTemplateList/RelatedTemplateList.js:209 +#: components/RelatedTemplateList/RelatedTemplateList.js:222 #: components/TemplateList/TemplateList.js:266 msgid "{0, plural, one {This template is currently being used by some workflow nodes. Are you sure you want to delete it?} other {Deleting these templates could impact some workflow nodes that rely on them. Are you sure you want to delete anyway?}}" msgstr "" @@ -10638,6 +11363,14 @@ msgstr "" msgid "{0, plural, one {You do not have permission to cancel the following job:} other {You do not have permission to cancel the following jobs:}}" msgstr "" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:143 +msgid "{0, selectordinal, one {The first {dayOfWeek}} two {The second {dayOfWeek}} =3 {The third {dayOfWeek}} =4 {The fourth {dayOfWeek}} =5 {The fifth {dayOfWeek}}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:202 +msgid "{0, selectordinal, one {The first {weekday} of {month}} two {The second {weekday} of {month}} =3 {The third {weekday} of {month}} =4 {The fourth {weekday} of {month}} =5 {The fifth {weekday} of {month}}}" +msgstr "" + #: screens/ActivityStream/ActivityStreamListItem.js:28 msgid "{0} (deleted)" msgstr "" @@ -10646,6 +11379,10 @@ msgstr "" msgid "{0} more" msgstr "" +#: screens/Job/JobDetail/JobDetail.js:399 +msgid "{0} seconds" +msgstr "" + #: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:138 #~ msgid "{0} since {1}" #~ msgstr "" @@ -10654,6 +11391,10 @@ msgstr "" #~ msgid "{0} sources with sync failures." #~ msgstr "" +#: screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js:95 +msgid "{automatedInstancesCount} since {automatedInstancesSinceDateTime}" +msgstr "" + #: components/AppContainer/AppContainer.js:55 msgid "{brandName} logo" msgstr "" @@ -10662,10 +11403,12 @@ msgstr "" msgid "{dateStr} by <0>{username}" msgstr "" -#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:224 -#: screens/InstanceGroup/Instances/InstanceListItem.js:148 -#: screens/Instances/InstanceDetail/InstanceDetail.js:174 -#: screens/Instances/InstanceList/InstanceListItem.js:158 +#: components/InstanceDetails.js/InstanceDetails.js:335 +#: screens/InstanceGroup/InstanceDetails/InstanceDetails.js:250 +#: screens/InstanceGroup/Instances/InstanceListItem.js:162 +#: screens/Instances/InstanceDetail/InstanceDetail.js:276 +#: screens/Instances/InstanceList/InstanceListItem.js:174 +#: screens/TopologyView/Tooltip.js:288 msgid "{forks, plural, one {# fork} other {# forks}}" msgstr "" @@ -10673,27 +11416,51 @@ msgstr "" #~ msgid "{hopNodeSelected, plural, one {Cannot run health check on a hop node. Deselect the hop node to run a health check.} other {Cannot run health check on hop nodes. Deselect the hop nodes to run health checks.}}" #~ msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:193 +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:41 +msgid "{interval, plural, one {{interval} day} other {{interval} days}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:33 +msgid "{interval, plural, one {{interval} hour} other {{interval} hours}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:25 +msgid "{interval, plural, one {{interval} minute} other {{interval} minutes}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:57 +msgid "{interval, plural, one {{interval} month} other {{interval} months}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:49 +msgid "{interval, plural, one {{interval} week} other {{interval} weeks}}" +msgstr "" + +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:65 +msgid "{interval, plural, one {{interval} year} other {{interval} years}}" +msgstr "" + +#: components/Schedule/shared/FrequencyDetailSubform.js:198 msgid "{intervalValue, plural, one {day} other {days}}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:191 +#: components/Schedule/shared/FrequencyDetailSubform.js:196 msgid "{intervalValue, plural, one {hour} other {hours}}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:189 +#: components/Schedule/shared/FrequencyDetailSubform.js:194 msgid "{intervalValue, plural, one {minute} other {minutes}}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:197 +#: components/Schedule/shared/FrequencyDetailSubform.js:202 msgid "{intervalValue, plural, one {month} other {months}}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:195 +#: components/Schedule/shared/FrequencyDetailSubform.js:200 msgid "{intervalValue, plural, one {week} other {weeks}}" msgstr "" -#: components/Schedule/shared/FrequencyDetailSubform.js:199 +#: components/Schedule/shared/FrequencyDetailSubform.js:204 msgid "{intervalValue, plural, one {year} other {years}}" msgstr "" @@ -10705,7 +11472,7 @@ msgstr "" #~ msgid "{label} time" #~ msgstr "" -#: components/PromptDetail/PromptDetail.js:41 +#: components/PromptDetail/PromptDetail.js:45 msgid "{minutes} min {seconds} sec" msgstr "" @@ -10721,6 +11488,10 @@ msgstr "" msgid "{numJobsToCancel, plural, one {{0}} other {{1}}}" msgstr "" +#: components/Schedule/ScheduleDetail/FrequencyDetails.js:226 +msgid "{numOccurrences, plural, one {After {numOccurrences} occurrence} other {After {numOccurrences} occurrences}}" +msgstr "" + #: components/DetailList/NumberSinceDetail.js:19 #~ msgid "{number} since {dateStr}" #~ msgstr "" @@ -10729,7 +11500,7 @@ msgstr "" msgid "{pluralizedItemName} List" msgstr "" -#: components/HealthCheckButton/HealthCheckButton.js:13 +#: components/HealthCheckButton/HealthCheckButton.js:18 msgid "{selectedItemsCount, plural, one {Click to run a health check on the selected instance.} other {Click to run a health check on the selected instances.}}" msgstr "" From 8d47644659a8625d00a0f277e591faa6bf3b2ca1 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 12:25:28 -0400 Subject: [PATCH 017/167] Move placeholder index_awx.html out of build dir - move placeholder index_awx.html out of ui_next build dir - copy index_awx.html to build dir during development bootstrap if UI_NEXT has not been build --- awx/ui_next/Makefile | 1 + .../awx/index_awx.html => placeholder_index_awx.html} | 0 tools/docker-compose/bootstrap_development.sh | 7 ++++++- 3 files changed, 7 insertions(+), 1 deletion(-) rename awx/ui_next/{build/awx/index_awx.html => placeholder_index_awx.html} (100%) diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index bcbaf0f623..8506a12204 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -36,6 +36,7 @@ $(UI_NEXT_DIR)/src/build: ui-next/src ui-next/src/webpack .PHONY: ui-next/src ui-next/src: $(UI_NEXT_DIR)/src +# TODO: Rewrite this big bash script in a more readable way. .PHONY: $(UI_NEXT_DIR)/src ## Real target for ui-next/src. $(UI_NEXT_DIR)/src: diff --git a/awx/ui_next/build/awx/index_awx.html b/awx/ui_next/placeholder_index_awx.html similarity index 100% rename from awx/ui_next/build/awx/index_awx.html rename to awx/ui_next/placeholder_index_awx.html diff --git a/tools/docker-compose/bootstrap_development.sh b/tools/docker-compose/bootstrap_development.sh index c049beeb23..87c3f81ee7 100755 --- a/tools/docker-compose/bootstrap_development.sh +++ b/tools/docker-compose/bootstrap_development.sh @@ -25,7 +25,12 @@ fi # Make sure that the UI static file directory exists, Django complains otherwise. mkdir -p /awx_devel/awx/ui/build/static -mkdir -p /awx_devel/awx/ui_next/build/awx + +# Make sure that the UI_NEXT statifc file directory exists, if UI_NEXT is not built yet put a placeholder file in it. +if [ ! -d "/awx_devel/awx/ui_next/build/awx" ]; then + mkdir -p /awx_devel/awx/ui_next/build/awx + cp /awx_devel/awx/ui_next/placeholder_index_awx.html /awx_devel/awx/ui_next/build/awx/index_awx.html +fi if output=$(awx-manage createsuperuser --noinput --username=admin --email=admin@localhost 2> /dev/null); then echo $output From d1895bb92e01952a521b651efa2773d5ff84b62b Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 12:38:21 -0400 Subject: [PATCH 018/167] PHONY all UI_NEXT build target - they were all PHONY to start with and also all target are written to be rerun able --- awx/ui_next/Makefile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index 8506a12204..8cb71b6a12 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -16,8 +16,8 @@ ui-next: ui-next/build .PHONY: ui-next/build ## Build ui-next/build ui-next/build: $(UI_NEXT_DIR)/build - -## Real target for ui-next. +.PHONY: $(UI_NEXT_DIR)/build +## True build target for ui-next. $(UI_NEXT_DIR)/build: ui-next/src/build @echo "=== Copying $(UI_NEXT_DIR)/src/build to $(UI_NEXT_DIR)/build ===" @rm -rf $(UI_NEXT_DIR)/build @@ -28,17 +28,19 @@ $(UI_NEXT_DIR)/build: ui-next/src/build ## Build ui-next/src/build ui-next/src/build: $(UI_NEXT_DIR)/src/build -## Real target for ui-next/src/build. +.PHONY: $(UI_NEXT_DIR)/src/build +## True target for ui-next/src/build. $(UI_NEXT_DIR)/src/build: ui-next/src ui-next/src/webpack @echo "=== Building ui_next ===" @cd $(UI_NEXT_DIR)/src && npm run build:awx .PHONY: ui-next/src +## Clone or link src of UI_NEXT to ui-next/src, will re-clone/link/update if necessary. ui-next/src: $(UI_NEXT_DIR)/src # TODO: Rewrite this big bash script in a more readable way. .PHONY: $(UI_NEXT_DIR)/src -## Real target for ui-next/src. +## True target for ui-next/src. $(UI_NEXT_DIR)/src: @echo "=== Setting up $(UI_NEXT_DIR)/src ===" @if [ ! -z "$(UI_NEXT_LOCAL)" ]; then \ @@ -78,7 +80,8 @@ $(UI_NEXT_DIR)/src: ## Install webpack. ui-next/src/webpack: $(UI_NEXT_DIR)/src/node_modules/webpack -## Real target for ui-next/src/webpack. +.PHONY: $(UI_NEXT_DIR)/src/node_modules/webpack +## True target for ui-next/src/webpack. $(UI_NEXT_DIR)/src/node_modules/webpack: @echo "=== Installing webpack ===" @cd $(UI_NEXT_DIR)/src && npm install webpack From cd6cb3352efa99e423ddc0d2e5141dde55754633 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 12:39:16 -0400 Subject: [PATCH 019/167] fail UI_NEXT make src if variable not set --- awx/ui_next/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index 8cb71b6a12..3e7f77bf9e 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -73,7 +73,8 @@ $(UI_NEXT_DIR)/src: git clone --depth 1 --branch $(UI_NEXT_GIT_BRANCH) $(UI_NEXT_GIT_REPO) $(UI_NEXT_DIR)/src || true; \ fi; \ else \ - echo "SKIP: ui-next/src. UI_NEXT_LOCAL and UI_NEXT_GIT_REPO are not set."; \ + echo "FAILED: ui-next/src. UI_NEXT_LOCAL and UI_NEXT_GIT_REPO are not set."; \ + exit 1; \ fi .PHONY: ui-next/src/webpack From 4302348e8e6bef1fcbc06e25b6e59362c48307ba Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Wed, 15 Mar 2023 09:48:11 -0400 Subject: [PATCH 020/167] Fixes bug where editing a node always defaulted to all convergence --- .../Modals/NodeModals/useWorkflowNodeSteps.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/awx/ui/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js b/awx/ui/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js index 853c23d31a..b512188168 100644 --- a/awx/ui/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js +++ b/awx/ui/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/useWorkflowNodeSteps.js @@ -66,7 +66,13 @@ const getNodeToEditDefaultValues = ( // There is a case where the nodeToEdit convergence value will not align with the // original node object value. This allows the nodeToEdit value to take precedence over the // original node object. - if (nodeToEdit) { + if ( + nodeToEdit && + Object.prototype.hasOwnProperty.call( + nodeToEdit, + 'all_parents_must_converge' + ) + ) { return nodeToEdit.all_parents_must_converge ? 'all' : 'any'; } return nodeToEdit?.originalNodeObject?.all_parents_must_converge From 28b1c622759ddb4deb0ea03f1b8bdc15a37ee87f Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Mon, 20 Mar 2023 15:26:34 -0400 Subject: [PATCH 021/167] Fix bug with awx collection manual type alias (#13671) * Fix bug with manual type alias * Add unit test for creating manual project with path --- awx_collection/plugins/modules/project.py | 9 ++++++--- awx_collection/test/awx/test_project.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/awx_collection/plugins/modules/project.py b/awx_collection/plugins/modules/project.py index 97713a267f..877340a111 100644 --- a/awx_collection/plugins/modules/project.py +++ b/awx_collection/plugins/modules/project.py @@ -284,13 +284,15 @@ def main(): argument_spec=argument_spec, ) + # Alias for manual projects + if module.params.get('scm_type') == "manual": + module.params['scm_type'] = '' + # Extract our parameters name = module.params.get('name') new_name = module.params.get("new_name") copy_from = module.params.get('copy_from') scm_type = module.params.get('scm_type') - if scm_type == "manual": - scm_type = "" local_path = module.params.get('local_path') credential = module.params.get('credential') scm_update_on_launch = module.params.get('scm_update_on_launch') @@ -387,7 +389,8 @@ def main(): # this is resolved earlier, so save an API call and don't do it again in the loop above project_fields['organization'] = org_id - if scm_type == '' and local_path is not None: + # Respect local_path if scm_type is manual type or not specified + if scm_type in ('', None) and local_path is not None: project_fields['local_path'] = local_path if scm_update_cache_timeout not in (0, None) and scm_update_on_launch is not True: diff --git a/awx_collection/test/awx/test_project.py b/awx_collection/test/awx/test_project.py index 2f8724566a..04ec05bbf7 100644 --- a/awx_collection/test/awx/test_project.py +++ b/awx_collection/test/awx/test_project.py @@ -26,6 +26,24 @@ def test_create_project(run_module, admin_user, organization, silence_warning): assert result == {'name': 'foo', 'id': proj.id} +@pytest.mark.django_db +def test_create_manual_project(run_module, admin_user, organization, mocker): + mocker.patch('awx.main.models.projects.Project.get_local_path_choices', return_value=['foo_folder/']) + result = run_module( + 'project', + dict(name='foo', organization=organization.name, scm_type='manual', local_path='foo_folder/', wait=False), + admin_user, + ) + assert result.pop('changed', None), result + + proj = Project.objects.get(name='foo') + assert proj.local_path == 'foo_folder/' + assert proj.organization == organization + + result.pop('invocation') + assert result == {'name': 'foo', 'id': proj.id} + + @pytest.mark.django_db def test_create_project_copy_from(run_module, admin_user, organization, silence_warning): '''Test the copy_from functionality''' From 5bd00adb59bf51eee47af154ea3b66de0b0220c2 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 12:46:50 -0400 Subject: [PATCH 022/167] Update UI_NEXT README also cleanup some small things --- .gitignore | 1 - awx/ui_next/Makefile | 4 ++-- awx/ui_next/README.md | 12 +++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 0ecdb823a2..1e48c997b8 100644 --- a/.gitignore +++ b/.gitignore @@ -157,7 +157,6 @@ use_dev_supervisor.txt *.unison.tmp *.# /awx/ui/.ui-built -/awx/ui_next/.ui-built /Dockerfile /_build/ /_build_kube_dev/ diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index 3e7f77bf9e..5e92419389 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -1,8 +1,8 @@ ## UI_NEXT_DIR: Relative path to the directory containing this Makefile UI_NEXT_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) -# ## Path to your local clone of the UI_NEXT repo -# # NOTE: you will not be able to build within the docker-compose development environment if you use this option +## Path to your local clone of the UI_NEXT repo +# NOTE: you will not be able to build within the docker-compose development environment if you use this option UI_NEXT_LOCAL ?= # Git repo and branch to the UI_NEXT repo diff --git a/awx/ui_next/README.md b/awx/ui_next/README.md index 77d719e050..8835cb3381 100644 --- a/awx/ui_next/README.md +++ b/awx/ui_next/README.md @@ -2,25 +2,27 @@ ## Set src of the ui_next repo -### via GIT +### Via GIT ```bash -export UI_NEXT_GIT_BRANCH_REPO=https:// +export UI_NEXT_GIT_REPO=https:// ``` or ```bash -export UI_NEXT_GIT_BRANCH_REPO=git@ +export UI_NEXT_GIT_REPO=git@ ``` optionally set branch (default is main) ```bash -export UI_NEXT_GIT_BRANCH_BRANCH=main +export UI_NEXT_GIT_BRANCH=main ``` -### via symlink to existing clone +### Via symlink to existing clone + +NOTE: UI_NEXT_LOCAL have higher precedence than UI_NEXT_GIT_REPO, if UI_NEXT_LOCAL is set, UI_NEXT_GIT_REPO will be ignored. ```bash export UI_NEXT_LOCAL = /path/to/your/ui_next From 39ea162aa964a9dc4ba183e316796eed2862535f Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 14:06:29 -0400 Subject: [PATCH 023/167] Update UI_NEXT help text in UI --- .../MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js | 2 +- .../screens/Setting/shared/data.allSettingOptions.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js index 909fb6ad6d..f30dd11693 100644 --- a/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js +++ b/awx/ui/src/screens/Setting/MiscSystem/MiscSystemDetail/MiscSystemDetail.test.js @@ -114,7 +114,7 @@ describe('', () => { assertVariableDetail(wrapper, 'Remote Host Headers', '[]'); assertVariableDetail(wrapper, 'Proxy IP Allowed List', '[]'); assertDetail(wrapper, 'Global default execution environment', 'Foo'); - assertDetail(wrapper, 'Enable Next Generation User Interface', 'On'); + assertDetail(wrapper, 'Enable Preview of New User Interface', 'On'); }); test('should render execution environment as not configured', async () => { diff --git a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json index 029140287c..99e2743e75 100644 --- a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json +++ b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json @@ -642,8 +642,8 @@ "UI_NEXT": { "type": "boolean", "required": false, - "label": "Enable Next Generation User Interface", - "help_text": "Enable the next generation user interface.", + "label": "Enable Preview of New User Interface", + "help_text": "'Enable preview of new user interface.", "category": "System", "category_slug": "system", "default": true @@ -4383,8 +4383,8 @@ }, "UI_NEXT": { "type": "boolean", - "label": "Enable Next Generation User Interface", - "help_text": "Enable the next generation user interface.", + "label": "Enable Preview of New User Interface", + "help_text": "Enable preview of new user interface.", "category": "System", "category_slug": "system", "defined_in_file": false From 746cd4bf77fbcfa06790574c41a1d49a6d008330 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 20 Mar 2023 14:16:37 -0400 Subject: [PATCH 024/167] Add note to indicate ui-next is imported target --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index e3d4d5c1f1..2c9798b8a7 100644 --- a/Makefile +++ b/Makefile @@ -447,6 +447,7 @@ ui-test-general: $(NPM_BIN) run --prefix awx/ui pretest $(NPM_BIN) run --prefix awx/ui/ test-general --runInBand +# NOTE: The make target ui-next is imported from awx/ui_next/Makefile HEADLESS ?= no ifeq ($(HEADLESS), yes) dist/$(SDIST_TAR_FILE): From b4163dd00fa0a09e64ea6dcfd767d79080d687ea Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 22 Mar 2023 16:54:08 -0400 Subject: [PATCH 025/167] Update node affinity description (#13741) --- docs/task_manager_system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/task_manager_system.md b/docs/task_manager_system.md index 8d50404a5f..1fb15e8eab 100644 --- a/docs/task_manager_system.md +++ b/docs/task_manager_system.md @@ -146,7 +146,7 @@ There is an important side effect to this. Because the manager `schedule()` runs ### Node Affinity Decider -The Task Manager decides which exact node a job will run on. It does so by considering user-configured group execution policy and user-configured capacity. First, the set of groups on which a job _can_ run on is constructed (see the AWX document on [Clustering](https://github.com/ansible/awx/blob/devel/docs/clustering.md)). The groups are traversed until a node within that group is found. The node with the largest remaining capacity that is idle is chosen first. If there are no idle nodes, then the node with the largest remaining capacity greater than or equal to the job capacity requirements is chosen. +The Task Manager decides which exact node a job will run on. It does so by considering user-configured group execution policy and user-configured capacity. First, the set of groups on which a job _can_ run on is constructed (see the AWX document on [Clustering](https://github.com/ansible/awx/blob/devel/docs/clustering.md)). The groups are traversed until a node within that group is found. The node with the largest remaining capacity (after accounting for the job's task impact) is chosen first. If there are no instances that can fit the job, then the largest *idle* node is chosen, regardless whether the job fits within its capacity limits. In this second case, it is possible for the instance to exceed its capacity in order to run the job. ## Managers are short-lived From 21b4755587d3712b2c8473b3848442a4c45cb045 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 22 Mar 2023 17:24:14 -0400 Subject: [PATCH 026/167] Turn make ui-next target non-PHONY this allow you to pre-build your ui_next outside of container and it won't try to rebuild when you build awx image `make ui-next` will no longer rebuild if awx/ui_next/build exist --- awx/ui_next/Makefile | 26 ++++++++++++++++++-------- awx/ui_next/README.md | 6 ++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/awx/ui_next/Makefile b/awx/ui_next/Makefile index 5e92419389..e51a085fd5 100644 --- a/awx/ui_next/Makefile +++ b/awx/ui_next/Makefile @@ -16,9 +16,10 @@ ui-next: ui-next/build .PHONY: ui-next/build ## Build ui-next/build ui-next/build: $(UI_NEXT_DIR)/build -.PHONY: $(UI_NEXT_DIR)/build + ## True build target for ui-next. -$(UI_NEXT_DIR)/build: ui-next/src/build +$(UI_NEXT_DIR)/build: + @$(MAKE) $(UI_NEXT_DIR)/src/build/awx @echo "=== Copying $(UI_NEXT_DIR)/src/build to $(UI_NEXT_DIR)/build ===" @rm -rf $(UI_NEXT_DIR)/build @cp -r $(UI_NEXT_DIR)/src/build $(UI_NEXT_DIR) @@ -26,11 +27,10 @@ $(UI_NEXT_DIR)/build: ui-next/src/build .PHONY: ui-next/src/build ## Build ui-next/src/build -ui-next/src/build: $(UI_NEXT_DIR)/src/build +ui-next/src/build: $(UI_NEXT_DIR)/src/build/awx -.PHONY: $(UI_NEXT_DIR)/src/build -## True target for ui-next/src/build. -$(UI_NEXT_DIR)/src/build: ui-next/src ui-next/src/webpack +## True target for ui-next/src/build. Build ui_next from source. +$(UI_NEXT_DIR)/src/build/awx: $(UI_NEXT_DIR)/src $(UI_NEXT_DIR)/src/node_modules/webpack @echo "=== Building ui_next ===" @cd $(UI_NEXT_DIR)/src && npm run build:awx @@ -39,7 +39,6 @@ $(UI_NEXT_DIR)/src/build: ui-next/src ui-next/src/webpack ui-next/src: $(UI_NEXT_DIR)/src # TODO: Rewrite this big bash script in a more readable way. -.PHONY: $(UI_NEXT_DIR)/src ## True target for ui-next/src. $(UI_NEXT_DIR)/src: @echo "=== Setting up $(UI_NEXT_DIR)/src ===" @@ -81,7 +80,6 @@ $(UI_NEXT_DIR)/src: ## Install webpack. ui-next/src/webpack: $(UI_NEXT_DIR)/src/node_modules/webpack -.PHONY: $(UI_NEXT_DIR)/src/node_modules/webpack ## True target for ui-next/src/webpack. $(UI_NEXT_DIR)/src/node_modules/webpack: @echo "=== Installing webpack ===" @@ -100,3 +98,15 @@ clean/ui-next/src: ## Clean ui_next build clean/ui-next/build: rm -rf $(UI_NEXT_DIR)/build + +.PHONY: $(UI_NEXT_DIR)/clean +## Alias for clean/ui-next, so we can run `make clean` directly in ui_next +$(UI_NEXT_DIR)/clean: clean/ui-next + +.PHONY: $(UI_NEXT_DIR)/clean/src +## Alias for clean/ui-next/src, so we can run `make clean/src` directly in ui_next +$(UI_NEXT_DIR)/clean/src: clean/ui-next/src + +.PHONY: $(UI_NEXT_DIR)/clean/build +## Alias for clean/ui-next/build, so we can run `make clean/build` directly in ui_next +$(UI_NEXT_DIR)/clean/build: clean/ui-next/build diff --git a/awx/ui_next/README.md b/awx/ui_next/README.md index 8835cb3381..740270feea 100644 --- a/awx/ui_next/README.md +++ b/awx/ui_next/README.md @@ -34,6 +34,12 @@ export UI_NEXT_LOCAL = /path/to/your/ui_next make ui-next ``` +## Rebuild + +```bash +make -B ui-next +``` + ## Clean ```bash From 1f9925cf519ab12a5e461c230fbe47b1183de640 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 23 Mar 2023 07:02:16 -0400 Subject: [PATCH 027/167] Fix automation analytics link in license page (#13225) --- .../Setting/Subscription/SubscriptionEdit/AnalyticsStep.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/src/screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js b/awx/ui/src/screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js index f331c1e975..89a6176a45 100644 --- a/awx/ui/src/screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js +++ b/awx/ui/src/screens/Setting/Subscription/SubscriptionEdit/AnalyticsStep.js @@ -41,7 +41,7 @@ function AnalyticsStep() { component="a" href={`${getDocsBaseUrl( config - )}/html/installandreference/user-data.html#index-0`} + )}/html/administration/usability_data_collection.html#automation-analytics`} variant="link" isInline ouiaId="tower-documentation-link" From ef4e77d78f5c1bb45040c0460c105fa4fde247a2 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Thu, 2 Feb 2023 15:17:14 +0100 Subject: [PATCH 028/167] Host Metrics List API --- awx/api/serializers.py | 9 +++++++++ awx/api/urls/host_metric.py | 10 ++++++++++ awx/api/urls/urls.py | 2 ++ awx/api/views/__init__.py | 7 +++++++ awx/main/access.py | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 awx/api/urls/host_metric.py diff --git a/awx/api/serializers.py b/awx/api/serializers.py index c2f5dfca23..7770838735 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -56,6 +56,7 @@ from awx.main.models import ( ExecutionEnvironment, Group, Host, + HostMetric, Instance, InstanceGroup, InstanceLink, @@ -5386,6 +5387,14 @@ class InstanceHealthCheckSerializer(BaseSerializer): fields = read_only_fields +class HostMetricSerializer(BaseSerializer): + show_capabilities = ['delete'] + + class Meta: + model = HostMetric + fields = ("hostname", "first_automation", "last_automation") + + class InstanceGroupSerializer(BaseSerializer): show_capabilities = ['edit', 'delete'] capacity = serializers.SerializerMethodField() diff --git a/awx/api/urls/host_metric.py b/awx/api/urls/host_metric.py new file mode 100644 index 0000000000..547c995c10 --- /dev/null +++ b/awx/api/urls/host_metric.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 Ansible, Inc. +# All Rights Reserved. + +from django.urls import re_path + +from awx.api.views import HostMetricList + +urls = [re_path(r'$^', HostMetricList.as_view(), name='host_metric_list')] + +__all__ = ['urls'] diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index 15d9fdd2ca..b9dbafca33 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -50,6 +50,7 @@ from .inventory import urls as inventory_urls from .execution_environments import urls as execution_environment_urls from .team import urls as team_urls from .host import urls as host_urls +from .host_metric import urls as host_metric_urls from .group import urls as group_urls from .inventory_source import urls as inventory_source_urls from .inventory_update import urls as inventory_update_urls @@ -118,6 +119,7 @@ v2_urls = [ re_path(r'^teams/', include(team_urls)), re_path(r'^inventories/', include(inventory_urls)), re_path(r'^hosts/', include(host_urls)), + re_path(r'^host_metrics/', include(host_metric_urls)), re_path(r'^groups/', include(group_urls)), re_path(r'^inventory_sources/', include(inventory_source_urls)), re_path(r'^inventory_updates/', include(inventory_update_urls)), diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index fc3fe52610..729f993b74 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1548,6 +1548,13 @@ class HostRelatedSearchMixin(object): return ret +class HostMetricList(ListAPIView): + always_allow_superuser = False + name = _("Host Metrics List") + model = models.HostMetric + serializer_class = serializers.HostMetricSerializer + + class HostList(HostRelatedSearchMixin, ListCreateAPIView): always_allow_superuser = False model = models.Host diff --git a/awx/main/access.py b/awx/main/access.py index 5d51ab3b91..938619119e 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -37,6 +37,7 @@ from awx.main.models import ( ExecutionEnvironment, Group, Host, + HostMetric, Instance, InstanceGroup, Inventory, @@ -883,6 +884,38 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): return super(OrganizationAccess, self).can_attach(obj, sub_obj, relationship, *args, **kwargs) +class HostMetricAccess(BaseAccess): + """ + - I can see host metrics when a super user or system auditor. + - I can delete host metrics when a super user. + """ + + model = HostMetric + + def get_queryset(self): + # if self.user.is_superuser or self.user.is_system_auditor: + # return self.model.objects.filter(Q(user__isnull=True) | Q(user=self.user)) + # else: + # return self.model.objects.filter(user=self.user) + if self.user.is_superuser or self.user.is_system_auditor: + qs = self.model.objects.all() + else: + qs = self.filtered_queryset() + return qs + + def can_read(self, obj): + return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) + + def can_add(self, data): + return False # There is no API endpoint to POST new settings. + + def can_change(self, obj, data): + return False + + def can_delete(self, obj): + return bool(self.user.is_superuser or (obj and obj.user == self.user)) + + class InventoryAccess(BaseAccess): """ I can see inventory when: From d80759cd7ac3d042bbe3ff7e37132ee56181cc98 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Fri, 3 Feb 2023 14:22:21 +0100 Subject: [PATCH 029/167] HostMetrics migration --- awx/api/serializers.py | 13 +++++- awx/api/urls/host_metric.py | 4 +- awx/api/views/__init__.py | 10 ++++- awx/main/access.py | 8 +--- .../migrations/0175_add_hostmetric_fields.py | 43 +++++++++++++++++++ awx/main/models/inventory.py | 12 +++++- 6 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 awx/main/migrations/0175_add_hostmetric_fields.py diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 7770838735..5989adb4db 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -5392,7 +5392,18 @@ class HostMetricSerializer(BaseSerializer): class Meta: model = HostMetric - fields = ("hostname", "first_automation", "last_automation") + fields = ( + "id", + "hostname", + "url", + "first_automation", + "last_automation", + "last_deleted", + "automated_counter", + "deleted_counter", + "deleted", + "used_in_inventories", + ) class InstanceGroupSerializer(BaseSerializer): diff --git a/awx/api/urls/host_metric.py b/awx/api/urls/host_metric.py index 547c995c10..d464fb82c5 100644 --- a/awx/api/urls/host_metric.py +++ b/awx/api/urls/host_metric.py @@ -3,8 +3,8 @@ from django.urls import re_path -from awx.api.views import HostMetricList +from awx.api.views import HostMetricList, HostMetricDetail -urls = [re_path(r'$^', HostMetricList.as_view(), name='host_metric_list')] +urls = [re_path(r'$^', HostMetricList.as_view(), name='host_metric_list'), re_path(r'^(?P[0-9]+)/$', HostMetricDetail.as_view(), name='host_metric_detail')] __all__ = ['urls'] diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 729f993b74..1845b55c2e 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1549,10 +1549,18 @@ class HostRelatedSearchMixin(object): class HostMetricList(ListAPIView): - always_allow_superuser = False name = _("Host Metrics List") model = models.HostMetric serializer_class = serializers.HostMetricSerializer + permission_classes = (IsSystemAdminOrAuditor,) + search_fields = ('hostname', 'deleted') + + +class HostMetricDetail(RetrieveDestroyAPIView): + name = _("Host Metric Detail") + model = models.HostMetric + serializer_class = serializers.HostMetricSerializer + permission_classes = (IsSystemAdminOrAuditor,) class HostList(HostRelatedSearchMixin, ListCreateAPIView): diff --git a/awx/main/access.py b/awx/main/access.py index 938619119e..185ab1e061 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -886,17 +886,13 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): class HostMetricAccess(BaseAccess): """ - - I can see host metrics when a super user or system auditor. - - I can delete host metrics when a super user. + - I can see host metrics when I'm a super user or system auditor. + - I can delete host metrics when I'm a super user. """ model = HostMetric def get_queryset(self): - # if self.user.is_superuser or self.user.is_system_auditor: - # return self.model.objects.filter(Q(user__isnull=True) | Q(user=self.user)) - # else: - # return self.model.objects.filter(user=self.user) if self.user.is_superuser or self.user.is_system_auditor: qs = self.model.objects.all() else: diff --git a/awx/main/migrations/0175_add_hostmetric_fields.py b/awx/main/migrations/0175_add_hostmetric_fields.py new file mode 100644 index 0000000000..d273a6b6ea --- /dev/null +++ b/awx/main/migrations/0175_add_hostmetric_fields.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.16 on 2023-02-03 09:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('main', '0174_ensure_org_ee_admin_roles'), + ] + + operations = [ + migrations.AlterField(model_name='hostmetric', name='hostname', field=models.CharField(max_length=512, primary_key=False, serialize=True, unique=True)), + migrations.AddField( + model_name='hostmetric', + name='last_deleted', + field=models.DateTimeField(db_index=True, null=True, help_text='When the host was last deleted'), + ), + migrations.AddField( + model_name='hostmetric', + name='automated_counter', + field=models.BigIntegerField(default=0, help_text='How many times was the host automated'), + ), + migrations.AddField( + model_name='hostmetric', + name='deleted_counter', + field=models.BigIntegerField(default=0, help_text='How many times was the host deleted'), + ), + migrations.AddField( + model_name='hostmetric', + name='deleted', + field=models.BooleanField( + default=False, help_text='Boolean flag saying whether the host is deleted and therefore not counted into the subscription consumption' + ), + ), + migrations.AddField( + model_name='hostmetric', + name='used_in_inventories', + field=models.BigIntegerField(null=True, help_text='How many inventories contain this host'), + ), + migrations.AddField( + model_name='hostmetric', name='id', field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID') + ), + ] diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 7b55c51851..577c03645c 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -820,9 +820,19 @@ class Group(CommonModelNameNotUnique, RelatedJobsMixin): class HostMetric(models.Model): - hostname = models.CharField(primary_key=True, max_length=512) + hostname = models.CharField(unique=True, max_length=512) first_automation = models.DateTimeField(auto_now_add=True, null=False, db_index=True, help_text=_('When the host was first automated against')) last_automation = models.DateTimeField(db_index=True, help_text=_('When the host was last automated against')) + last_deleted = models.DateTimeField(null=True, db_index=True, help_text=_('When the host was last deleted')) + automated_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host automated')) + deleted_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host deleted')) + deleted = models.BooleanField( + default=False, help_text=_('Boolean flag saying whether the host is deleted and therefore not counted into the subscription consumption') + ) + used_in_inventories = models.BigIntegerField(null=True, help_text=_('How many inventories contain this host')) + + def get_absolute_url(self, request=None): + return reverse('api:host_metric_detail', kwargs={'pk': self.pk}, request=request) class InventorySourceOptions(BaseModel): From b18ad77035a0ee58f7517a940c7ce4ceca4ddf50 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Thu, 9 Feb 2023 16:39:39 +0100 Subject: [PATCH 030/167] Host Metrics update/soft delete --- awx/api/views/__init__.py | 5 + awx/main/models/events.py | 28 +- awx/main/models/inventory.py | 12 + .../tests/functional/models/test_events.py | 357 ++++++++++-------- .../functional/models/test_host_metric.py | 50 +++ 5 files changed, 282 insertions(+), 170 deletions(-) diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 1845b55c2e..7dda3d4d44 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1562,6 +1562,11 @@ class HostMetricDetail(RetrieveDestroyAPIView): serializer_class = serializers.HostMetricSerializer permission_classes = (IsSystemAdminOrAuditor,) + def delete(self, request, *args, **kwargs): + self.get_object().soft_delete() + + return Response(status=status.HTTP_204_NO_CONTENT) + class HostList(HostRelatedSearchMixin, ListCreateAPIView): always_allow_superuser = False diff --git a/awx/main/models/events.py b/awx/main/models/events.py index 1827802812..0ba07185f4 100644 --- a/awx/main/models/events.py +++ b/awx/main/models/events.py @@ -6,7 +6,7 @@ from collections import defaultdict from django.conf import settings from django.core.exceptions import ObjectDoesNotExist -from django.db import models, DatabaseError +from django.db import connection, models, DatabaseError from django.utils.dateparse import parse_datetime from django.utils.text import Truncator from django.utils.timezone import utc, now @@ -536,7 +536,7 @@ class JobEvent(BasePlaybookEvent): return job = self.job - from awx.main.models import Host, JobHostSummary, HostMetric # circular import + from awx.main.models import Host, JobHostSummary # circular import all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name') existing_host_ids = set(h.id for h in all_hosts) @@ -575,12 +575,26 @@ class JobEvent(BasePlaybookEvent): Host.objects.bulk_update(list(updated_hosts), ['last_job_id', 'last_job_host_summary_id'], batch_size=100) - # bulk-create - current_time = now() - HostMetric.objects.bulk_create( - [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=100 + # Create/update Host Metrics + self._update_host_metrics(updated_hosts_list) + + @staticmethod + def _update_host_metrics(updated_hosts_list): + from awx.main.models import HostMetric # circular import + + # bulk-create + current_time = now() + HostMetric.objects.bulk_create( + [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=1000 + ) + # bulk-update + batch_start, batch_size = 0, 1000 + while batch_start <= len(updated_hosts_list): + batched_host_list = updated_hosts_list[batch_start : (batch_start + batch_size)] + HostMetric.objects.filter(hostname__in=batched_host_list).update( + last_automation=current_time, automated_counter=models.F('automated_counter') + 1, deleted=False ) - HostMetric.objects.filter(hostname__in=updated_hosts_list).update(last_automation=current_time) + batch_start += batch_size @property def job_verbosity(self): diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 577c03645c..4ae7ba2adb 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -834,6 +834,18 @@ class HostMetric(models.Model): def get_absolute_url(self, request=None): return reverse('api:host_metric_detail', kwargs={'pk': self.pk}, request=request) + def soft_delete(self): + if not self.deleted: + self.deleted_counter = (self.deleted_counter or 0) + 1 + self.last_deleted = now() + self.deleted = True + self.save() + + def soft_restore(self): + if self.deleted: + self.deleted = False + self.save() + class InventorySourceOptions(BaseModel): """ diff --git a/awx/main/tests/functional/models/test_events.py b/awx/main/tests/functional/models/test_events.py index 758e69b641..48adc781e7 100644 --- a/awx/main/tests/functional/models/test_events.py +++ b/awx/main/tests/functional/models/test_events.py @@ -3,178 +3,209 @@ import pytest from django.utils.timezone import now -from awx.main.models import Job, JobEvent, Inventory, Host, JobHostSummary +from django.db.models import Q + +from awx.main.models import Job, JobEvent, Inventory, Host, JobHostSummary, HostMetric @pytest.mark.django_db -@mock.patch('awx.main.models.events.emit_event_detail') -def test_parent_changed(emit): - j = Job() - j.save() - JobEvent.create_from_data(job_id=j.pk, uuid='abc123', event='playbook_on_task_start').save() - assert JobEvent.objects.count() == 1 - for e in JobEvent.objects.all(): - assert e.changed is False +class TestEvents: + def setup_method(self): + self.hostnames = [] + self.host_map = dict() + self.inventory = None + self.job = None - JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='runner_on_ok', event_data={'res': {'changed': ['localhost']}}).save() - # the `playbook_on_stats` event is where we update the parent changed linkage - JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='playbook_on_stats').save() - events = JobEvent.objects.filter(event__in=['playbook_on_task_start', 'runner_on_ok']) - assert events.count() == 2 - for e in events.all(): - assert e.changed is True + @mock.patch('awx.main.models.events.emit_event_detail') + def test_parent_changed(self, emit): + j = Job() + j.save() + JobEvent.create_from_data(job_id=j.pk, uuid='abc123', event='playbook_on_task_start').save() + assert JobEvent.objects.count() == 1 + for e in JobEvent.objects.all(): + assert e.changed is False + JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='runner_on_ok', event_data={'res': {'changed': ['localhost']}}).save() + # the `playbook_on_stats` event is where we update the parent changed linkage + JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='playbook_on_stats').save() + events = JobEvent.objects.filter(event__in=['playbook_on_task_start', 'runner_on_ok']) + assert events.count() == 2 + for e in events.all(): + assert e.changed is True -@pytest.mark.django_db -@pytest.mark.parametrize('event', JobEvent.FAILED_EVENTS) -@mock.patch('awx.main.models.events.emit_event_detail') -def test_parent_failed(emit, event): - j = Job() - j.save() - JobEvent.create_from_data(job_id=j.pk, uuid='abc123', event='playbook_on_task_start').save() - assert JobEvent.objects.count() == 1 - for e in JobEvent.objects.all(): - assert e.failed is False + @pytest.mark.parametrize('event', JobEvent.FAILED_EVENTS) + @mock.patch('awx.main.models.events.emit_event_detail') + def test_parent_failed(self, emit, event): + j = Job() + j.save() + JobEvent.create_from_data(job_id=j.pk, uuid='abc123', event='playbook_on_task_start').save() + assert JobEvent.objects.count() == 1 + for e in JobEvent.objects.all(): + assert e.failed is False - JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event=event).save() + JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event=event).save() - # the `playbook_on_stats` event is where we update the parent failed linkage - JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='playbook_on_stats').save() - events = JobEvent.objects.filter(event__in=['playbook_on_task_start', event]) - assert events.count() == 2 - for e in events.all(): - assert e.failed is True + # the `playbook_on_stats` event is where we update the parent failed linkage + JobEvent.create_from_data(job_id=j.pk, parent_uuid='abc123', event='playbook_on_stats').save() + events = JobEvent.objects.filter(event__in=['playbook_on_task_start', event]) + assert events.count() == 2 + for e in events.all(): + assert e.failed is True + def test_host_summary_generation(self): + self._generate_hosts(100) + self._create_job_event(ok=dict((hostname, len(hostname)) for hostname in self.hostnames)) -@pytest.mark.django_db -def test_host_summary_generation(): - hostnames = [f'Host {i}' for i in range(100)] - inv = Inventory() - inv.save() - Host.objects.bulk_create([Host(created=now(), modified=now(), name=h, inventory_id=inv.id) for h in hostnames]) - j = Job(inventory=inv) - j.save() - host_map = dict((host.name, host.id) for host in inv.hosts.all()) - JobEvent.create_from_data( - job_id=j.pk, + assert self.job.job_host_summaries.count() == len(self.hostnames) + assert sorted([s.host_name for s in self.job.job_host_summaries.all()]) == sorted(self.hostnames) + + for s in self.job.job_host_summaries.all(): + assert self.host_map[s.host_name] == s.host_id + assert s.ok == len(s.host_name) + assert s.changed == 0 + assert s.dark == 0 + assert s.failures == 0 + assert s.ignored == 0 + assert s.processed == 0 + assert s.rescued == 0 + assert s.skipped == 0 + + for host in Host.objects.all(): + assert host.last_job_id == self.job.id + assert host.last_job_host_summary.host == host + + def test_host_summary_generation_with_deleted_hosts(self): + self._generate_hosts(10) + + # delete half of the hosts during the playbook run + for h in self.inventory.hosts.all()[:5]: + h.delete() + + self._create_job_event(ok=dict((hostname, len(hostname)) for hostname in self.hostnames)) + + ids = sorted([s.host_id or -1 for s in self.job.job_host_summaries.order_by('id').all()]) + names = sorted([s.host_name for s in self.job.job_host_summaries.all()]) + assert ids == [-1, -1, -1, -1, -1, 6, 7, 8, 9, 10] + assert names == ['Host 0', 'Host 1', 'Host 2', 'Host 3', 'Host 4', 'Host 5', 'Host 6', 'Host 7', 'Host 8', 'Host 9'] + + def test_host_summary_generation_with_limit(self): + # Make an inventory with 10 hosts, run a playbook with a --limit + # pointed at *one* host, + # Verify that *only* that host has an associated JobHostSummary and that + # *only* that host has an updated value for .last_job. + self._generate_hosts(10) + + # by making the playbook_on_stats *only* include Host 1, we're emulating + # the behavior of a `--limit=Host 1` + matching_host = Host.objects.get(name='Host 1') + self._create_job_event(ok={matching_host.name: len(matching_host.name)}) # effectively, limit=Host 1 + + # since the playbook_on_stats only references one host, + # there should *only* be on JobHostSummary record (and it should + # be related to the appropriate Host) + assert JobHostSummary.objects.count() == 1 + for h in Host.objects.all(): + if h.name == 'Host 1': + assert h.last_job_id == self.job.id + assert h.last_job_host_summary_id == JobHostSummary.objects.first().id + else: + # all other hosts in the inventory should remain untouched + assert h.last_job_id is None + assert h.last_job_host_summary_id is None + + def test_host_metrics_insert(self): + self._generate_hosts(10) + + self._create_job_event( + ok=dict((hostname, len(hostname)) for hostname in self.hostnames[0:3]), + failures=dict((hostname, len(hostname)) for hostname in self.hostnames[3:6]), + processed=dict((hostname, len(hostname)) for hostname in self.hostnames[6:9]), + skipped=dict((hostname, len(hostname)) for hostname in [self.hostnames[9]]), + ) + + metrics = HostMetric.objects.all() + assert len(metrics) == 10 + for hm in metrics: + assert hm.automated_counter == 1 + assert hm.last_automation is not None + assert hm.deleted is False + + def test_host_metrics_update(self): + self._generate_hosts(12) + + self._create_job_event(ok=dict((hostname, len(hostname)) for hostname in self.hostnames)) + + # Soft delete 6 host metrics + for hm in HostMetric.objects.filter(id__in=[1, 3, 5, 7, 9, 11]): + hm.soft_delete() + + assert len(HostMetric.objects.filter(Q(deleted=False) & Q(deleted_counter=0) & Q(last_deleted__isnull=True))) == 6 + assert len(HostMetric.objects.filter(Q(deleted=True) & Q(deleted_counter=1) & Q(last_deleted__isnull=False))) == 6 + + # hostnames in 'ignored' and 'rescued' stats are ignored + self.job = Job(inventory=self.inventory) + self.job.save() + self._create_job_event( + ignored=dict((hostname, len(hostname)) for hostname in self.hostnames[0:6]), + rescued=dict((hostname, len(hostname)) for hostname in self.hostnames[6:11]), + ) + + assert len(HostMetric.objects.filter(Q(deleted=False) & Q(deleted_counter=0) & Q(last_deleted__isnull=True))) == 6 + assert len(HostMetric.objects.filter(Q(deleted=True) & Q(deleted_counter=1) & Q(last_deleted__isnull=False))) == 6 + + # hostnames in 'changed', 'dark', 'failures', 'ok', 'processed', 'skipped' are processed + self.job = Job(inventory=self.inventory) + self.job.save() + self._create_job_event( + changed=dict((hostname, len(hostname)) for hostname in self.hostnames[0:2]), + dark=dict((hostname, len(hostname)) for hostname in self.hostnames[2:4]), + failures=dict((hostname, len(hostname)) for hostname in self.hostnames[4:6]), + ok=dict((hostname, len(hostname)) for hostname in self.hostnames[6:8]), + processed=dict((hostname, len(hostname)) for hostname in self.hostnames[8:10]), + skipped=dict((hostname, len(hostname)) for hostname in self.hostnames[10:12]), + ) + assert len(HostMetric.objects.filter(Q(deleted=False) & Q(deleted_counter=0) & Q(last_deleted__isnull=True))) == 6 + assert len(HostMetric.objects.filter(Q(deleted=False) & Q(deleted_counter=1) & Q(last_deleted__isnull=False))) == 6 + + def _generate_hosts(self, cnt, id_from=0): + self.hostnames = [f'Host {i}' for i in range(id_from, id_from + cnt)] + self.inventory = Inventory() + self.inventory.save() + Host.objects.bulk_create([Host(created=now(), modified=now(), name=h, inventory_id=self.inventory.id) for h in self.hostnames]) + self.job = Job(inventory=self.inventory) + self.job.save() + + # host map is a data structure that tracks a mapping of host name --> ID + # for the inventory, _regardless_ of whether or not there's a limit + # applied to the actual playbook run + self.host_map = dict((host.name, host.id) for host in self.inventory.hosts.all()) + + def _create_job_event( + self, parent_uuid='abc123', event='playbook_on_stats', - event_data={ - 'ok': dict((hostname, len(hostname)) for hostname in hostnames), - 'changed': {}, - 'dark': {}, - 'failures': {}, - 'ignored': {}, - 'processed': {}, - 'rescued': {}, - 'skipped': {}, - }, - host_map=host_map, - ).save() - - assert j.job_host_summaries.count() == len(hostnames) - assert sorted([s.host_name for s in j.job_host_summaries.all()]) == sorted(hostnames) - - for s in j.job_host_summaries.all(): - assert host_map[s.host_name] == s.host_id - assert s.ok == len(s.host_name) - assert s.changed == 0 - assert s.dark == 0 - assert s.failures == 0 - assert s.ignored == 0 - assert s.processed == 0 - assert s.rescued == 0 - assert s.skipped == 0 - - for host in Host.objects.all(): - assert host.last_job_id == j.id - assert host.last_job_host_summary.host == host - - -@pytest.mark.django_db -def test_host_summary_generation_with_deleted_hosts(): - hostnames = [f'Host {i}' for i in range(10)] - inv = Inventory() - inv.save() - Host.objects.bulk_create([Host(created=now(), modified=now(), name=h, inventory_id=inv.id) for h in hostnames]) - j = Job(inventory=inv) - j.save() - host_map = dict((host.name, host.id) for host in inv.hosts.all()) - - # delete half of the hosts during the playbook run - for h in inv.hosts.all()[:5]: - h.delete() - - JobEvent.create_from_data( - job_id=j.pk, - parent_uuid='abc123', - event='playbook_on_stats', - event_data={ - 'ok': dict((hostname, len(hostname)) for hostname in hostnames), - 'changed': {}, - 'dark': {}, - 'failures': {}, - 'ignored': {}, - 'processed': {}, - 'rescued': {}, - 'skipped': {}, - }, - host_map=host_map, - ).save() - - ids = sorted([s.host_id or -1 for s in j.job_host_summaries.order_by('id').all()]) - names = sorted([s.host_name for s in j.job_host_summaries.all()]) - assert ids == [-1, -1, -1, -1, -1, 6, 7, 8, 9, 10] - assert names == ['Host 0', 'Host 1', 'Host 2', 'Host 3', 'Host 4', 'Host 5', 'Host 6', 'Host 7', 'Host 8', 'Host 9'] - - -@pytest.mark.django_db -def test_host_summary_generation_with_limit(): - # Make an inventory with 10 hosts, run a playbook with a --limit - # pointed at *one* host, - # Verify that *only* that host has an associated JobHostSummary and that - # *only* that host has an updated value for .last_job. - hostnames = [f'Host {i}' for i in range(10)] - inv = Inventory() - inv.save() - Host.objects.bulk_create([Host(created=now(), modified=now(), name=h, inventory_id=inv.id) for h in hostnames]) - j = Job(inventory=inv) - j.save() - - # host map is a data structure that tracks a mapping of host name --> ID - # for the inventory, _regardless_ of whether or not there's a limit - # applied to the actual playbook run - host_map = dict((host.name, host.id) for host in inv.hosts.all()) - - # by making the playbook_on_stats *only* include Host 1, we're emulating - # the behavior of a `--limit=Host 1` - matching_host = Host.objects.get(name='Host 1') - JobEvent.create_from_data( - job_id=j.pk, - parent_uuid='abc123', - event='playbook_on_stats', - event_data={ - 'ok': {matching_host.name: len(matching_host.name)}, # effectively, limit=Host 1 - 'changed': {}, - 'dark': {}, - 'failures': {}, - 'ignored': {}, - 'processed': {}, - 'rescued': {}, - 'skipped': {}, - }, - host_map=host_map, - ).save() - - # since the playbook_on_stats only references one host, - # there should *only* be on JobHostSummary record (and it should - # be related to the appropriate Host) - assert JobHostSummary.objects.count() == 1 - for h in Host.objects.all(): - if h.name == 'Host 1': - assert h.last_job_id == j.id - assert h.last_job_host_summary_id == JobHostSummary.objects.first().id - else: - # all other hosts in the inventory should remain untouched - assert h.last_job_id is None - assert h.last_job_host_summary_id is None + ok=None, + changed=None, + dark=None, + failures=None, + ignored=None, + processed=None, + rescued=None, + skipped=None, + ): + JobEvent.create_from_data( + job_id=self.job.pk, + parent_uuid=parent_uuid, + event=event, + event_data={ + 'ok': ok or {}, + 'changed': changed or {}, + 'dark': dark or {}, + 'failures': failures or {}, + 'ignored': ignored or {}, + 'processed': processed or {}, + 'rescued': rescued or {}, + 'skipped': skipped or {}, + }, + host_map=self.host_map, + ).save() diff --git a/awx/main/tests/functional/models/test_host_metric.py b/awx/main/tests/functional/models/test_host_metric.py index 1f560e474f..dad8295435 100644 --- a/awx/main/tests/functional/models/test_host_metric.py +++ b/awx/main/tests/functional/models/test_host_metric.py @@ -20,3 +20,53 @@ def test_host_metrics_generation(): date_today = now().strftime('%Y-%m-%d') result = HostMetric.objects.filter(first_automation__startswith=date_today).count() assert result == len(hostnames) + + +@pytest.mark.django_db +def test_soft_delete(): + hostnames = [f'Host to delete {i}' for i in range(2)] + current_time = now() + HostMetric.objects.bulk_create([HostMetric(hostname=h, last_automation=current_time, automated_counter=42) for h in hostnames]) + + hm = HostMetric.objects.get(hostname="Host to delete 0") + assert hm.last_deleted is None + + last_deleted = None + for _ in range(3): + # soft delete 1st + # 2nd/3rd delete don't have an effect + hm.soft_delete() + if last_deleted is None: + last_deleted = hm.last_deleted + + assert hm.deleted is True + assert hm.deleted_counter == 1 + assert hm.last_deleted == last_deleted + assert hm.automated_counter == 42 + + # 2nd record is not touched + hm = HostMetric.objects.get(hostname="Host to delete 1") + assert hm.deleted is False + assert hm.deleted_counter == 0 + assert hm.last_deleted is None + assert hm.automated_counter == 42 + + +@pytest.mark.django_db +def test_soft_restore(): + current_time = now() + HostMetric.objects.create(hostname="Host 1", last_automation=current_time, deleted=True) + HostMetric.objects.create(hostname="Host 2", last_automation=current_time, deleted=True, last_deleted=current_time) + HostMetric.objects.create(hostname="Host 3", last_automation=current_time, deleted=False, last_deleted=current_time) + HostMetric.objects.all().update(automated_counter=42, deleted_counter=10) + + # 1. deleted, last_deleted not null + for hm in HostMetric.objects.all(): + for _ in range(3): + hm.soft_restore() + assert hm.deleted is False + assert hm.automated_counter == 42 and hm.deleted_counter == 10 + if hm.hostname == "Host 1": + assert hm.last_deleted is None + else: + assert hm.last_deleted == current_time From 05f918e666e86b84c2d89d0a47fe60dee1b123a0 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Fri, 10 Feb 2023 10:29:28 +0100 Subject: [PATCH 031/167] HostMetric compliance computation --- awx/main/managers.py | 5 +++++ awx/main/models/inventory.py | 5 ++++- awx/main/utils/licensing.py | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/awx/main/managers.py b/awx/main/managers.py index 32d6ed7f5b..b674049b0e 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -79,6 +79,11 @@ class HostManager(models.Manager): return qs +class HostMetricActiveManager(models.Manager): + def get_queryset(self): + return super().get_queryset().filter(deleted=False) + + def get_ig_ig_mapping(ig_instance_mapping, instance_ig_mapping): # Create IG mapping by union of all groups their instances are members of ig_ig_mapping = {} diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 4ae7ba2adb..41a85b0071 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -32,7 +32,7 @@ from awx.main.fields import ( SmartFilterField, OrderedManyToManyField, ) -from awx.main.managers import HostManager +from awx.main.managers import HostManager, HostMetricActiveManager from awx.main.models.base import BaseModel, CommonModelNameNotUnique, VarsDictProperty, CLOUD_INVENTORY_SOURCES, prevent_search, accepts_json from awx.main.models.events import InventoryUpdateEvent, UnpartitionedInventoryUpdateEvent from awx.main.models.unified_jobs import UnifiedJob, UnifiedJobTemplate @@ -831,6 +831,9 @@ class HostMetric(models.Model): ) used_in_inventories = models.BigIntegerField(null=True, help_text=_('How many inventories contain this host')) + objects = models.Manager() + active_objects = HostMetricActiveManager() + def get_absolute_url(self, request=None): return reverse('api:host_metric_detail', kwargs={'pk': self.pk}, request=request) diff --git a/awx/main/utils/licensing.py b/awx/main/utils/licensing.py index bec953f822..3bc5e174e5 100644 --- a/awx/main/utils/licensing.py +++ b/awx/main/utils/licensing.py @@ -382,8 +382,8 @@ class Licenser(object): current_instances = Host.objects.active_count() license_date = int(attrs.get('license_date', 0) or 0) - automated_instances = HostMetric.objects.count() - first_host = HostMetric.objects.only('first_automation').order_by('first_automation').first() + automated_instances = HostMetric.active_objects.count() + first_host = HostMetric.active_objects.only('first_automation').order_by('first_automation').first() if first_host: automated_since = int(first_host.first_automation.timestamp()) else: From f919178734c420c6af00862ae03a653720ccfc38 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 13 Feb 2023 13:54:11 +0100 Subject: [PATCH 032/167] HostMetricSummaryMonthly API and Migrations --- awx/api/filters.py | 4 +++ awx/api/serializers.py | 8 +++++ awx/api/urls/urls.py | 2 ++ awx/api/views/__init__.py | 34 ++++++++++++++++++- awx/main/access.py | 28 +++++++++++++++ .../0176_hostmetricsummarymonthly.py | 33 ++++++++++++++++++ awx/main/models/__init__.py | 1 + awx/main/models/inventory.py | 15 +++++++- 8 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 awx/main/migrations/0176_hostmetricsummarymonthly.py diff --git a/awx/api/filters.py b/awx/api/filters.py index 1a6e3eb90e..e574fce539 100644 --- a/awx/api/filters.py +++ b/awx/api/filters.py @@ -385,6 +385,10 @@ class FieldLookupBackend(BaseFilterBackend): raise ParseError(json.dumps(e.messages, ensure_ascii=False)) +class HostMetricSummaryMonthlyFieldLookupBackend(FieldLookupBackend): + RESERVED_NAMES = ('page', 'page_size', 'format', 'order', 'order_by', 'search', 'type', 'past_months', 'count_disabled', 'no_truncate', 'limit') + + class OrderByBackend(BaseFilterBackend): """ Filter to apply ordering based on query string parameters. diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 5989adb4db..1ff00854c2 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -57,6 +57,7 @@ from awx.main.models import ( Group, Host, HostMetric, + HostMetricSummaryMonthly, Instance, InstanceGroup, InstanceLink, @@ -5406,6 +5407,13 @@ class HostMetricSerializer(BaseSerializer): ) +class HostMetricSummaryMonthlySerializer(BaseSerializer): + class Meta: + model = HostMetricSummaryMonthly + read_only_fields = ("id", "date", "license_consumed", "license_capacity", "hosts_added", "hosts_deleted", "indirectly_managed_hosts") + fields = read_only_fields + + class InstanceGroupSerializer(BaseSerializer): show_capabilities = ['edit', 'delete'] capacity = serializers.SerializerMethodField() diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index b9dbafca33..c7d73165c3 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -30,6 +30,7 @@ from awx.api.views import ( OAuth2TokenList, ApplicationOAuth2TokenList, OAuth2ApplicationDetail, + HostMetricSummaryMonthlyList, ) from awx.api.views.bulk import ( @@ -120,6 +121,7 @@ v2_urls = [ re_path(r'^inventories/', include(inventory_urls)), re_path(r'^hosts/', include(host_urls)), re_path(r'^host_metrics/', include(host_metric_urls)), + re_path(r'^host_metric_summary_monthly/$', HostMetricSummaryMonthlyList.as_view(), name='host_metric_summary_monthly_list'), re_path(r'^groups/', include(group_urls)), re_path(r'^inventory_sources/', include(inventory_source_urls)), re_path(r'^inventory_updates/', include(inventory_update_urls)), diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 7dda3d4d44..0dd0f306cd 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -3,6 +3,7 @@ # Python import dateutil +import datetime import functools import html import itertools @@ -17,7 +18,6 @@ from collections import OrderedDict from urllib3.exceptions import ConnectTimeoutError - # Django from django.conf import settings from django.core.exceptions import FieldError, ObjectDoesNotExist @@ -122,6 +122,7 @@ from awx.api.views.mixin import ( UnifiedJobDeletionMixin, NoTruncateMixin, ) +from awx.api.filters import HostMetricSummaryMonthlyFieldLookupBackend from awx.api.pagination import UnifiedJobEventPagination from awx.main.utils import set_environ @@ -1568,6 +1569,37 @@ class HostMetricDetail(RetrieveDestroyAPIView): return Response(status=status.HTTP_204_NO_CONTENT) +class HostMetricSummaryMonthlyList(ListAPIView): + name = _("Host Metrics Summary Monthly") + model = models.HostMetricSummaryMonthly + permission_classes = (IsSystemAdminOrAuditor,) + serializer_class = serializers.HostMetricSummaryMonthlySerializer + search_fields = ('date',) + filter_backends = [HostMetricSummaryMonthlyFieldLookupBackend] + + def get_queryset(self): + queryset = super().get_queryset() + past_months = self.request.query_params.get('past_months', None) + date_from = self._get_date_from(past_months) + + queryset = queryset.filter(date__gte=date_from) + return queryset + + @staticmethod + def _get_date_from(past_months, default=12, maximum=36): + try: + months_ago = int(past_months or default) + except ValueError: + months_ago = default + months_ago = min(months_ago, maximum) + months_ago = max(months_ago, 1) + + date_from = datetime.date.today() - dateutil.relativedelta.relativedelta(months=months_ago) + # Set to beginning of the month + date_from = date_from.replace(day=1).isoformat() + return date_from + + class HostList(HostRelatedSearchMixin, ListCreateAPIView): always_allow_superuser = False model = models.Host diff --git a/awx/main/access.py b/awx/main/access.py index 185ab1e061..5cca1ff133 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -38,6 +38,7 @@ from awx.main.models import ( Group, Host, HostMetric, + HostMetricSummaryMonthly, Instance, InstanceGroup, Inventory, @@ -912,6 +913,33 @@ class HostMetricAccess(BaseAccess): return bool(self.user.is_superuser or (obj and obj.user == self.user)) +class HostMetricSummaryMonthlyAccess(BaseAccess): + """ + - I can see host metrics when I'm a super user or system auditor. + """ + + model = HostMetricSummaryMonthly + + def get_queryset(self): + if self.user.is_superuser or self.user.is_system_auditor: + qs = self.model.objects.all() + else: + qs = self.filtered_queryset() + return qs + + def can_read(self, obj): + return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) + + def can_add(self, data): + return False # There is no API endpoint to POST new settings. + + def can_change(self, obj, data): + return False + + def can_delete(self, obj): + return False + + class InventoryAccess(BaseAccess): """ I can see inventory when: diff --git a/awx/main/migrations/0176_hostmetricsummarymonthly.py b/awx/main/migrations/0176_hostmetricsummarymonthly.py new file mode 100644 index 0000000000..735f46f0d6 --- /dev/null +++ b/awx/main/migrations/0176_hostmetricsummarymonthly.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.16 on 2023-02-10 12:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('main', '0175_add_hostmetric_fields'), + ] + + operations = [ + migrations.CreateModel( + name='HostMetricSummaryMonthly', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField(unique=True)), + ('license_consumed', models.BigIntegerField(default=0, help_text='How much unique hosts are consumed from the license')), + ('license_capacity', models.BigIntegerField(default=0, help_text="'License capacity as max. number of unique hosts")), + ( + 'hosts_added', + models.BigIntegerField(default=0, help_text='How many hosts were added in the associated month, consuming more license capacity'), + ), + ( + 'hosts_deleted', + models.BigIntegerField(default=0, help_text='How many hosts were deleted in the associated month, freeing the license capacity'), + ), + ( + 'indirectly_managed_hosts', + models.BigIntegerField(default=0, help_text='Manually entered number indirectly managed hosts for a certain month'), + ), + ], + ), + ] diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index ed49b98083..8a608aeead 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -16,6 +16,7 @@ from awx.main.models.inventory import ( # noqa Group, Host, HostMetric, + HostMetricSummaryMonthly, Inventory, InventorySource, InventoryUpdate, diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 41a85b0071..c937c4342d 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -53,7 +53,7 @@ from awx.main.utils.execution_environments import to_container_path from awx.main.utils.licensing import server_product_name -__all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate', 'SmartInventoryMembership'] +__all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate', 'SmartInventoryMembership', 'HostMetric', 'HostMetricSummaryMonthly'] logger = logging.getLogger('awx.main.models.inventory') @@ -850,6 +850,19 @@ class HostMetric(models.Model): self.save() +class HostMetricSummaryMonthly(models.Model): + """ + HostMetric summaries computed by scheduled task monthly + """ + + date = models.DateField(unique=True) + license_consumed = models.BigIntegerField(default=0, help_text=_("How much unique hosts are consumed from the license")) + license_capacity = models.BigIntegerField(default=0, help_text=_("'License capacity as max. number of unique hosts")) + hosts_added = models.BigIntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) + hosts_deleted = models.BigIntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) + indirectly_managed_hosts = models.BigIntegerField(default=0, help_text=("Manually entered number indirectly managed hosts for a certain month")) + + class InventorySourceOptions(BaseModel): """ Common fields for InventorySource and InventoryUpdate. From e6050804f98e7ab566f29f80970c701f96062063 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Wed, 15 Feb 2023 16:49:43 +0100 Subject: [PATCH 033/167] HostMetric review,migration,permissions --- awx/api/urls/host_metric.py | 2 +- awx/api/views/__init__.py | 7 ++- awx/api/views/root.py | 2 + awx/main/access.py | 57 ------------------- .../migrations/0175_add_hostmetric_fields.py | 6 +- .../0176_hostmetricsummarymonthly.py | 6 +- awx/main/models/events.py | 4 +- awx/main/models/inventory.py | 16 +++--- 8 files changed, 24 insertions(+), 76 deletions(-) diff --git a/awx/api/urls/host_metric.py b/awx/api/urls/host_metric.py index d464fb82c5..a5e43fefbc 100644 --- a/awx/api/urls/host_metric.py +++ b/awx/api/urls/host_metric.py @@ -5,6 +5,6 @@ from django.urls import re_path from awx.api.views import HostMetricList, HostMetricDetail -urls = [re_path(r'$^', HostMetricList.as_view(), name='host_metric_list'), re_path(r'^(?P[0-9]+)/$', HostMetricDetail.as_view(), name='host_metric_detail')] +urls = [re_path(r'^$', HostMetricList.as_view(), name='host_metric_list'), re_path(r'^(?P[0-9]+)/$', HostMetricDetail.as_view(), name='host_metric_detail')] __all__ = ['urls'] diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 0dd0f306cd..d05806afb1 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1556,6 +1556,9 @@ class HostMetricList(ListAPIView): permission_classes = (IsSystemAdminOrAuditor,) search_fields = ('hostname', 'deleted') + def get_queryset(self): + return self.model.objects.all() + class HostMetricDetail(RetrieveDestroyAPIView): name = _("Host Metric Detail") @@ -1572,13 +1575,13 @@ class HostMetricDetail(RetrieveDestroyAPIView): class HostMetricSummaryMonthlyList(ListAPIView): name = _("Host Metrics Summary Monthly") model = models.HostMetricSummaryMonthly - permission_classes = (IsSystemAdminOrAuditor,) serializer_class = serializers.HostMetricSummaryMonthlySerializer + permission_classes = (IsSystemAdminOrAuditor,) search_fields = ('date',) filter_backends = [HostMetricSummaryMonthlyFieldLookupBackend] def get_queryset(self): - queryset = super().get_queryset() + queryset = self.model.objects.all() past_months = self.request.query_params.get('past_months', None) date_from = self._get_date_from(past_months) diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 7b4eb8191e..f343d8169d 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -102,6 +102,8 @@ class ApiVersionRootView(APIView): data['inventory_updates'] = reverse('api:inventory_update_list', request=request) data['groups'] = reverse('api:group_list', request=request) data['hosts'] = reverse('api:host_list', request=request) + data['host_metrics'] = reverse('api:host_metric_list', request=request) + data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request) data['job_templates'] = reverse('api:job_template_list', request=request) data['jobs'] = reverse('api:job_list', request=request) data['ad_hoc_commands'] = reverse('api:ad_hoc_command_list', request=request) diff --git a/awx/main/access.py b/awx/main/access.py index 5cca1ff133..5d51ab3b91 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -37,8 +37,6 @@ from awx.main.models import ( ExecutionEnvironment, Group, Host, - HostMetric, - HostMetricSummaryMonthly, Instance, InstanceGroup, Inventory, @@ -885,61 +883,6 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): return super(OrganizationAccess, self).can_attach(obj, sub_obj, relationship, *args, **kwargs) -class HostMetricAccess(BaseAccess): - """ - - I can see host metrics when I'm a super user or system auditor. - - I can delete host metrics when I'm a super user. - """ - - model = HostMetric - - def get_queryset(self): - if self.user.is_superuser or self.user.is_system_auditor: - qs = self.model.objects.all() - else: - qs = self.filtered_queryset() - return qs - - def can_read(self, obj): - return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) - - def can_add(self, data): - return False # There is no API endpoint to POST new settings. - - def can_change(self, obj, data): - return False - - def can_delete(self, obj): - return bool(self.user.is_superuser or (obj and obj.user == self.user)) - - -class HostMetricSummaryMonthlyAccess(BaseAccess): - """ - - I can see host metrics when I'm a super user or system auditor. - """ - - model = HostMetricSummaryMonthly - - def get_queryset(self): - if self.user.is_superuser or self.user.is_system_auditor: - qs = self.model.objects.all() - else: - qs = self.filtered_queryset() - return qs - - def can_read(self, obj): - return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) - - def can_add(self, data): - return False # There is no API endpoint to POST new settings. - - def can_change(self, obj, data): - return False - - def can_delete(self, obj): - return False - - class InventoryAccess(BaseAccess): """ I can see inventory when: diff --git a/awx/main/migrations/0175_add_hostmetric_fields.py b/awx/main/migrations/0175_add_hostmetric_fields.py index d273a6b6ea..ee91b01fbb 100644 --- a/awx/main/migrations/0175_add_hostmetric_fields.py +++ b/awx/main/migrations/0175_add_hostmetric_fields.py @@ -18,12 +18,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='hostmetric', name='automated_counter', - field=models.BigIntegerField(default=0, help_text='How many times was the host automated'), + field=models.IntegerField(default=0, help_text='How many times was the host automated'), ), migrations.AddField( model_name='hostmetric', name='deleted_counter', - field=models.BigIntegerField(default=0, help_text='How many times was the host deleted'), + field=models.IntegerField(default=0, help_text='How many times was the host deleted'), ), migrations.AddField( model_name='hostmetric', @@ -35,7 +35,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='hostmetric', name='used_in_inventories', - field=models.BigIntegerField(null=True, help_text='How many inventories contain this host'), + field=models.IntegerField(null=True, help_text='How many inventories contain this host'), ), migrations.AddField( model_name='hostmetric', name='id', field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID') diff --git a/awx/main/migrations/0176_hostmetricsummarymonthly.py b/awx/main/migrations/0176_hostmetricsummarymonthly.py index 735f46f0d6..7631363a4c 100644 --- a/awx/main/migrations/0176_hostmetricsummarymonthly.py +++ b/awx/main/migrations/0176_hostmetricsummarymonthly.py @@ -18,15 +18,15 @@ class Migration(migrations.Migration): ('license_capacity', models.BigIntegerField(default=0, help_text="'License capacity as max. number of unique hosts")), ( 'hosts_added', - models.BigIntegerField(default=0, help_text='How many hosts were added in the associated month, consuming more license capacity'), + models.IntegerField(default=0, help_text='How many hosts were added in the associated month, consuming more license capacity'), ), ( 'hosts_deleted', - models.BigIntegerField(default=0, help_text='How many hosts were deleted in the associated month, freeing the license capacity'), + models.IntegerField(default=0, help_text='How many hosts were deleted in the associated month, freeing the license capacity'), ), ( 'indirectly_managed_hosts', - models.BigIntegerField(default=0, help_text='Manually entered number indirectly managed hosts for a certain month'), + models.IntegerField(default=0, help_text='Manually entered number indirectly managed hosts for a certain month'), ), ], ), diff --git a/awx/main/models/events.py b/awx/main/models/events.py index 0ba07185f4..2d6dee6f61 100644 --- a/awx/main/models/events.py +++ b/awx/main/models/events.py @@ -6,7 +6,7 @@ from collections import defaultdict from django.conf import settings from django.core.exceptions import ObjectDoesNotExist -from django.db import connection, models, DatabaseError +from django.db import models, DatabaseError from django.utils.dateparse import parse_datetime from django.utils.text import Truncator from django.utils.timezone import utc, now @@ -585,7 +585,7 @@ class JobEvent(BasePlaybookEvent): # bulk-create current_time = now() HostMetric.objects.bulk_create( - [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=1000 + [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=100 ) # bulk-update batch_start, batch_size = 0, 1000 diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index c937c4342d..56dea84d96 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -824,12 +824,12 @@ class HostMetric(models.Model): first_automation = models.DateTimeField(auto_now_add=True, null=False, db_index=True, help_text=_('When the host was first automated against')) last_automation = models.DateTimeField(db_index=True, help_text=_('When the host was last automated against')) last_deleted = models.DateTimeField(null=True, db_index=True, help_text=_('When the host was last deleted')) - automated_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host automated')) - deleted_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host deleted')) + automated_counter = models.IntegerField(default=0, help_text=_('How many times was the host automated')) + deleted_counter = models.IntegerField(default=0, help_text=_('How many times was the host deleted')) deleted = models.BooleanField( default=False, help_text=_('Boolean flag saying whether the host is deleted and therefore not counted into the subscription consumption') ) - used_in_inventories = models.BigIntegerField(null=True, help_text=_('How many inventories contain this host')) + used_in_inventories = models.IntegerField(null=True, help_text=_('How many inventories contain this host')) objects = models.Manager() active_objects = HostMetricActiveManager() @@ -842,12 +842,12 @@ class HostMetric(models.Model): self.deleted_counter = (self.deleted_counter or 0) + 1 self.last_deleted = now() self.deleted = True - self.save() + self.save(update_fields=['deleted', 'deleted_counter', 'last_deleted']) def soft_restore(self): if self.deleted: self.deleted = False - self.save() + self.save(update_fields=['deleted']) class HostMetricSummaryMonthly(models.Model): @@ -858,9 +858,9 @@ class HostMetricSummaryMonthly(models.Model): date = models.DateField(unique=True) license_consumed = models.BigIntegerField(default=0, help_text=_("How much unique hosts are consumed from the license")) license_capacity = models.BigIntegerField(default=0, help_text=_("'License capacity as max. number of unique hosts")) - hosts_added = models.BigIntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) - hosts_deleted = models.BigIntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) - indirectly_managed_hosts = models.BigIntegerField(default=0, help_text=("Manually entered number indirectly managed hosts for a certain month")) + hosts_added = models.IntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) + hosts_deleted = models.IntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) + indirectly_managed_hosts = models.IntegerField(default=0, help_text=("Manually entered number indirectly managed hosts for a certain month")) class InventorySourceOptions(BaseModel): From e38f87eb1d830a12a9f56ee549aa4f0244a9e7b1 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Thu, 23 Feb 2023 14:41:53 -0500 Subject: [PATCH 034/167] Remove custom API filters and suggest solution via templates --- awx/api/filters.py | 4 ---- awx/api/templates/api/host_metric_detail.md | 18 +++++++++++++++ .../api/host_metric_summary_monthly_list.md | 12 ++++++++++ awx/api/views/__init__.py | 23 +------------------ 4 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 awx/api/templates/api/host_metric_detail.md create mode 100644 awx/api/templates/api/host_metric_summary_monthly_list.md diff --git a/awx/api/filters.py b/awx/api/filters.py index e574fce539..1a6e3eb90e 100644 --- a/awx/api/filters.py +++ b/awx/api/filters.py @@ -385,10 +385,6 @@ class FieldLookupBackend(BaseFilterBackend): raise ParseError(json.dumps(e.messages, ensure_ascii=False)) -class HostMetricSummaryMonthlyFieldLookupBackend(FieldLookupBackend): - RESERVED_NAMES = ('page', 'page_size', 'format', 'order', 'order_by', 'search', 'type', 'past_months', 'count_disabled', 'no_truncate', 'limit') - - class OrderByBackend(BaseFilterBackend): """ Filter to apply ordering based on query string parameters. diff --git a/awx/api/templates/api/host_metric_detail.md b/awx/api/templates/api/host_metric_detail.md new file mode 100644 index 0000000000..0a59a1b410 --- /dev/null +++ b/awx/api/templates/api/host_metric_detail.md @@ -0,0 +1,18 @@ +{% ifmeth GET %} +# Retrieve {{ model_verbose_name|title|anora }}: + +Make GET request to this resource to retrieve a single {{ model_verbose_name }} +record containing the following fields: + +{% include "api/_result_fields_common.md" %} +{% endifmeth %} + +{% ifmeth DELETE %} +# Delete {{ model_verbose_name|title|anora }}: + +Make a DELETE request to this resource to soft-delete this {{ model_verbose_name }}. + +A soft deletion will mark the `deleted` field as true and exclude the host +metric from license calculations. +This may be undone later if the same hostname is automated again afterwards. +{% endifmeth %} diff --git a/awx/api/templates/api/host_metric_summary_monthly_list.md b/awx/api/templates/api/host_metric_summary_monthly_list.md new file mode 100644 index 0000000000..953b1827a6 --- /dev/null +++ b/awx/api/templates/api/host_metric_summary_monthly_list.md @@ -0,0 +1,12 @@ +# Intended Use Case + +To get summaries from a certain day or earlier, you can filter this +endpoint in the following way. + + ?date__gte=2023-01-01 + +This will return summaries that were produced on that date or later. +These host metric monthly summaries should be automatically produced +by a background task that runs once each month. + +{% include "api/list_api_view.md" %} diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index d05806afb1..0068eb0148 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -122,7 +122,6 @@ from awx.api.views.mixin import ( UnifiedJobDeletionMixin, NoTruncateMixin, ) -from awx.api.filters import HostMetricSummaryMonthlyFieldLookupBackend from awx.api.pagination import UnifiedJobEventPagination from awx.main.utils import set_environ @@ -1578,29 +1577,9 @@ class HostMetricSummaryMonthlyList(ListAPIView): serializer_class = serializers.HostMetricSummaryMonthlySerializer permission_classes = (IsSystemAdminOrAuditor,) search_fields = ('date',) - filter_backends = [HostMetricSummaryMonthlyFieldLookupBackend] def get_queryset(self): - queryset = self.model.objects.all() - past_months = self.request.query_params.get('past_months', None) - date_from = self._get_date_from(past_months) - - queryset = queryset.filter(date__gte=date_from) - return queryset - - @staticmethod - def _get_date_from(past_months, default=12, maximum=36): - try: - months_ago = int(past_months or default) - except ValueError: - months_ago = default - months_ago = min(months_ago, maximum) - months_ago = max(months_ago, 1) - - date_from = datetime.date.today() - dateutil.relativedelta.relativedelta(months=months_ago) - # Set to beginning of the month - date_from = date_from.replace(day=1).isoformat() - return date_from + return self.model.objects.all() class HostList(HostRelatedSearchMixin, ListCreateAPIView): From 7285d82f0000e2a25f5ae065c64b13e0e2b7c49e Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 27 Feb 2023 11:25:09 +0100 Subject: [PATCH 035/167] HostMetric migration --- awx/api/views/__init__.py | 1 - awx/main/migrations/0175_add_hostmetric_fields.py | 2 +- awx/main/migrations/0176_hostmetricsummarymonthly.py | 2 +- awx/main/models/inventory.py | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 0068eb0148..a9f2e0ce25 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -3,7 +3,6 @@ # Python import dateutil -import datetime import functools import html import itertools diff --git a/awx/main/migrations/0175_add_hostmetric_fields.py b/awx/main/migrations/0175_add_hostmetric_fields.py index ee91b01fbb..75090bd678 100644 --- a/awx/main/migrations/0175_add_hostmetric_fields.py +++ b/awx/main/migrations/0175_add_hostmetric_fields.py @@ -18,7 +18,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='hostmetric', name='automated_counter', - field=models.IntegerField(default=0, help_text='How many times was the host automated'), + field=models.BigIntegerField(default=0, help_text='How many times was the host automated'), ), migrations.AddField( model_name='hostmetric', diff --git a/awx/main/migrations/0176_hostmetricsummarymonthly.py b/awx/main/migrations/0176_hostmetricsummarymonthly.py index 7631363a4c..fe482aa416 100644 --- a/awx/main/migrations/0176_hostmetricsummarymonthly.py +++ b/awx/main/migrations/0176_hostmetricsummarymonthly.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('date', models.DateField(unique=True)), - ('license_consumed', models.BigIntegerField(default=0, help_text='How much unique hosts are consumed from the license')), + ('license_consumed', models.BigIntegerField(default=0, help_text='How many unique hosts are consumed from the license')), ('license_capacity', models.BigIntegerField(default=0, help_text="'License capacity as max. number of unique hosts")), ( 'hosts_added', diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 56dea84d96..829017ee1d 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -824,7 +824,7 @@ class HostMetric(models.Model): first_automation = models.DateTimeField(auto_now_add=True, null=False, db_index=True, help_text=_('When the host was first automated against')) last_automation = models.DateTimeField(db_index=True, help_text=_('When the host was last automated against')) last_deleted = models.DateTimeField(null=True, db_index=True, help_text=_('When the host was last deleted')) - automated_counter = models.IntegerField(default=0, help_text=_('How many times was the host automated')) + automated_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host automated')) deleted_counter = models.IntegerField(default=0, help_text=_('How many times was the host deleted')) deleted = models.BooleanField( default=False, help_text=_('Boolean flag saying whether the host is deleted and therefore not counted into the subscription consumption') @@ -856,7 +856,7 @@ class HostMetricSummaryMonthly(models.Model): """ date = models.DateField(unique=True) - license_consumed = models.BigIntegerField(default=0, help_text=_("How much unique hosts are consumed from the license")) + license_consumed = models.BigIntegerField(default=0, help_text=_("How many unique hosts are consumed from the license")) license_capacity = models.BigIntegerField(default=0, help_text=_("'License capacity as max. number of unique hosts")) hosts_added = models.IntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) hosts_deleted = models.IntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) From 9badbf0b4e45a31f5ce943785c67d7437d914b82 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 27 Feb 2023 15:20:47 +0100 Subject: [PATCH 036/167] Compliance computation settings --- awx/main/conf.py | 13 ++++++++++++- awx/main/constants.py | 4 ++++ awx/main/utils/licensing.py | 12 ++++++++++-- awx/settings/defaults.py | 6 ++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/awx/main/conf.py b/awx/main/conf.py index 6634271b93..04dd056f45 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -10,7 +10,7 @@ from rest_framework import serializers # AWX from awx.conf import fields, register, register_validate from awx.main.models import ExecutionEnvironment - +from awx.main.constants import SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY logger = logging.getLogger('awx.main.conf') @@ -805,6 +805,17 @@ register( category_slug='system', ) +register( + 'SUBSCRIPTION_USAGE_MODEL', + field_class=fields.ChoiceField, + choices=[SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY], + default='', + allow_blank=True, + label=_('Defines subscription usage model and shows Host Metrics'), + category=_('System'), + category_slug='system', +) + def logging_validate(serializer, attrs): if not serializer.instance or not hasattr(serializer.instance, 'LOG_AGGREGATOR_HOST') or not hasattr(serializer.instance, 'LOG_AGGREGATOR_TYPE'): diff --git a/awx/main/constants.py b/awx/main/constants.py index 0271d70233..8f52b62aae 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -106,3 +106,7 @@ JOB_VARIABLE_PREFIXES = [ ANSIBLE_RUNNER_NEEDS_UPDATE_MESSAGE = ( '\u001b[31m \u001b[1m This can be caused if the version of ansible-runner in your execution environment is out of date.\u001b[0m' ) + +# Values for setting SUBSCRIPTION_USAGE_MODEL +SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS = 'unique_managed_hosts' +SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY = 'unique_managed_hosts_monthly' diff --git a/awx/main/utils/licensing.py b/awx/main/utils/licensing.py index 3bc5e174e5..62c0deb56a 100644 --- a/awx/main/utils/licensing.py +++ b/awx/main/utils/licensing.py @@ -35,6 +35,7 @@ from cryptography import x509 from django.conf import settings from django.utils.translation import gettext_lazy as _ +from awx.main.constants import SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS MAX_INSTANCES = 9999999 @@ -382,8 +383,15 @@ class Licenser(object): current_instances = Host.objects.active_count() license_date = int(attrs.get('license_date', 0) or 0) - automated_instances = HostMetric.active_objects.count() - first_host = HostMetric.active_objects.only('first_automation').order_by('first_automation').first() + + model = getattr(settings, 'SUBSCRIPTION_USAGE_MODEL', '') + if model == SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS: + automated_instances = HostMetric.active_objects.count() + first_host = HostMetric.active_objects.only('first_automation').order_by('first_automation').first() + else: + automated_instances = HostMetric.objects.count() + first_host = HostMetric.objects.only('first_automation').order_by('first_automation').first() + if first_host: automated_since = int(first_host.first_automation.timestamp()) else: diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index b36dcc15ec..23d61a98a0 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -1028,3 +1028,9 @@ AWX_MOUNT_ISOLATED_PATHS_ON_K8S = False CLUSTER_HOST_ID = socket.gethostname() UI_NEXT = True + +# License compliance for total host count. Possible values: +# - '': No model - Subscription not counted from Host Metrics +# - 'unique_managed_hosts': Compliant = automated - deleted hosts (using /api/v2/host_metrics/) +# - 'unique_managed_hosts_monthly': TBD: AoC on Azure (now equal to '') +SUBSCRIPTION_USAGE_MODEL = '' From ae0c1730bb8860ab14ece76ac967eb4db94d35cb Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Wed, 8 Mar 2023 19:01:28 +0100 Subject: [PATCH 037/167] Subscription_usage_model in analytics/config.json --- awx/main/analytics/collectors.py | 3 ++- awx/main/conf.py | 10 ++++++++-- awx/main/constants.py | 1 - 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/awx/main/analytics/collectors.py b/awx/main/analytics/collectors.py index 9ee363aed1..e7655997d2 100644 --- a/awx/main/analytics/collectors.py +++ b/awx/main/analytics/collectors.py @@ -83,7 +83,7 @@ def _identify_lower(key, since, until, last_gather): return lower, last_entries -@register('config', '1.4', description=_('General platform configuration.')) +@register('config', '1.5', description=_('General platform configuration.')) def config(since, **kwargs): license_info = get_license() install_type = 'traditional' @@ -119,6 +119,7 @@ def config(since, **kwargs): 'compliant': license_info.get('compliant'), 'date_warning': license_info.get('date_warning'), 'date_expired': license_info.get('date_expired'), + 'subscription_usage_model': getattr(settings, 'SUBSCRIPTION_USAGE_MODEL', ''), # 1.5+ 'free_instances': license_info.get('free_instances', 0), 'total_licensed_instances': license_info.get('instance_count', 0), 'license_expiry': license_info.get('time_remaining', 0), diff --git a/awx/main/conf.py b/awx/main/conf.py index 04dd056f45..f983b26a31 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -10,7 +10,7 @@ from rest_framework import serializers # AWX from awx.conf import fields, register, register_validate from awx.main.models import ExecutionEnvironment -from awx.main.constants import SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY +from awx.main.constants import SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS logger = logging.getLogger('awx.main.conf') @@ -808,7 +808,13 @@ register( register( 'SUBSCRIPTION_USAGE_MODEL', field_class=fields.ChoiceField, - choices=[SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY], + choices=[ + ('', _('Default model for AWX - no subscription')), + ( + SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, + _('Usage based on unique managed nodes in a large historical time frame and delete functionality for no longer used managed nodes'), + ), + ], default='', allow_blank=True, label=_('Defines subscription usage model and shows Host Metrics'), diff --git a/awx/main/constants.py b/awx/main/constants.py index 8f52b62aae..85a14cca4c 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -109,4 +109,3 @@ ANSIBLE_RUNNER_NEEDS_UPDATE_MESSAGE = ( # Values for setting SUBSCRIPTION_USAGE_MODEL SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS = 'unique_managed_hosts' -SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS_MONTHLY = 'unique_managed_hosts_monthly' From 8d46d32944f539d4f5364aed626117520873ea7d Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Thu, 16 Feb 2023 12:26:48 +0100 Subject: [PATCH 038/167] UI --- awx/ui/src/api/index.js | 3 + awx/ui/src/api/models/HostMetrics.js | 10 +++ awx/ui/src/routeConfig.js | 6 ++ awx/ui/src/screens/HostMetrics/HostMetrics.js | 86 +++++++++++++++++++ .../HostMetrics/HostMetricsListItem.js | 27 ++++++ awx/ui/src/screens/HostMetrics/index.js | 1 + awx/ui/src/types.js | 9 ++ 7 files changed, 142 insertions(+) create mode 100644 awx/ui/src/api/models/HostMetrics.js create mode 100644 awx/ui/src/screens/HostMetrics/HostMetrics.js create mode 100644 awx/ui/src/screens/HostMetrics/HostMetricsListItem.js create mode 100644 awx/ui/src/screens/HostMetrics/index.js diff --git a/awx/ui/src/api/index.js b/awx/ui/src/api/index.js index 5281ad861d..7a03643c05 100644 --- a/awx/ui/src/api/index.js +++ b/awx/ui/src/api/index.js @@ -44,6 +44,7 @@ import WorkflowApprovalTemplates from './models/WorkflowApprovalTemplates'; import WorkflowJobTemplateNodes from './models/WorkflowJobTemplateNodes'; import WorkflowJobTemplates from './models/WorkflowJobTemplates'; import WorkflowJobs from './models/WorkflowJobs'; +import HostMetrics from './models/HostMetrics'; const ActivityStreamAPI = new ActivityStream(); const AdHocCommandsAPI = new AdHocCommands(); @@ -91,6 +92,7 @@ const WorkflowApprovalTemplatesAPI = new WorkflowApprovalTemplates(); const WorkflowJobTemplateNodesAPI = new WorkflowJobTemplateNodes(); const WorkflowJobTemplatesAPI = new WorkflowJobTemplates(); const WorkflowJobsAPI = new WorkflowJobs(); +const HostMetricsAPI = new HostMetrics(); export { ActivityStreamAPI, @@ -139,4 +141,5 @@ export { WorkflowJobTemplateNodesAPI, WorkflowJobTemplatesAPI, WorkflowJobsAPI, + HostMetricsAPI, }; diff --git a/awx/ui/src/api/models/HostMetrics.js b/awx/ui/src/api/models/HostMetrics.js new file mode 100644 index 0000000000..d8ca8f4c8c --- /dev/null +++ b/awx/ui/src/api/models/HostMetrics.js @@ -0,0 +1,10 @@ +import Base from '../Base'; + +class HostMetrics extends Base { + constructor(http) { + super(http); + this.baseUrl = 'api/v2/host_metrics/'; + } +} + +export default HostMetrics; diff --git a/awx/ui/src/routeConfig.js b/awx/ui/src/routeConfig.js index 602e804d2b..c738a352b3 100644 --- a/awx/ui/src/routeConfig.js +++ b/awx/ui/src/routeConfig.js @@ -23,6 +23,7 @@ import TopologyView from 'screens/TopologyView'; import Users from 'screens/User'; import WorkflowApprovals from 'screens/WorkflowApproval'; import { Jobs } from 'screens/Job'; +import HostMetrics from 'screens/HostMetrics'; function getRouteConfig(userProfile = {}) { let routeConfig = [ @@ -55,6 +56,11 @@ function getRouteConfig(userProfile = {}) { path: '/workflow_approvals', screen: WorkflowApprovals, }, + { + title: Host Metrics, + path: '/host_metrics', + screen: HostMetrics, + }, ], }, { diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js new file mode 100644 index 0000000000..0a397dfce3 --- /dev/null +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -0,0 +1,86 @@ +import React, {useCallback, useEffect, useState} from 'react'; +import {t} from "@lingui/macro"; +import ScreenHeader from 'components/ScreenHeader/ScreenHeader'; +import { HostMetricsAPI } from 'api'; +import useRequest from 'hooks/useRequest'; +import PaginatedTable, { + HeaderRow, + HeaderCell +} from 'components/PaginatedTable'; +import DataListToolbar from 'components/DataListToolbar'; +import { getQSConfig, parseQueryString } from 'util/qs'; +import {Card, PageSection} from "@patternfly/react-core"; +import { useLocation } from 'react-router-dom'; +import HostMetricsListItem from "./HostMetricsListItem"; + +function HostMetrics() { + + const location = useLocation(); + + const [breadcrumbConfig] = useState({ + '/host_metrics': t`Host Metrics`, + }); + const QS_CONFIG = getQSConfig('host_metrics', { + page: 1, + page_size: 20, + order_by: 'hostname', + }); + const { + result: { count, results }, + isLoading, + error, + request: readHostMetrics, + } = useRequest( + useCallback(async () => { + const params = parseQueryString(QS_CONFIG, location.search); + const list = await HostMetricsAPI.read(params); + return { + count: list.data.count, + results: list.data.results + }; + }, [location.search]), + { results: [], count: 0 } + ); + + useEffect(() => { + readHostMetrics(); + }, [readHostMetrics]); + + return( + <> + + + + ()} + qsConfig={QS_CONFIG} + toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname', isDefault: true}]} + toolbarSearchableKeys={[]} + toolbarRelatedSearchableKeys={[]} + renderToolbar={(props) => } + headerRow={ + + {t`Hostname`} + {t`First automated`} + {t`Last automated`} + {t`Automation`} + {t`Inventories`} + {t`Deleted`} + +} + /> + + + + ); +} + +export default HostMetrics; diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js new file mode 100644 index 0000000000..fe9d06a25c --- /dev/null +++ b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js @@ -0,0 +1,27 @@ +import 'styled-components/macro'; +import React from 'react'; +import { Tr, Td } from '@patternfly/react-table'; +import { formatDateString } from 'util/dates'; +import { HostMetrics } from 'types'; +import {t} from "@lingui/macro"; + +function HostMetricsListItem({ item }) { + + return ( + + + {item.hostname} + {formatDateString(item.first_automation)} + {formatDateString(item.last_automation)} + {item.automated_counter} + {item.used_in_inventories || 0} + {item.deleted_counter}< + /Tr> + ); +} + +HostMetricsListItem.propTypes = { + item: HostMetrics.isRequired, +}; + +export default HostMetricsListItem; diff --git a/awx/ui/src/screens/HostMetrics/index.js b/awx/ui/src/screens/HostMetrics/index.js new file mode 100644 index 0000000000..bb2945686c --- /dev/null +++ b/awx/ui/src/screens/HostMetrics/index.js @@ -0,0 +1 @@ +export { default } from './HostMetrics'; diff --git a/awx/ui/src/types.js b/awx/ui/src/types.js index 57fd32029d..677f4edae8 100644 --- a/awx/ui/src/types.js +++ b/awx/ui/src/types.js @@ -439,3 +439,12 @@ export const Toast = shape({ hasTimeout: bool, message: string, }); + +export const HostMetrics = shape({ + hostname: string.isRequired, + first_automation: string.isRequired, + last_automation: string.isRequired, + automated_counter: number.isRequired, + used_in_inventories: number, + deleted_counter: number, +}); From 9135ff2f77c3f1918427848517f8f1e3683913a1 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Mon, 20 Feb 2023 14:20:49 +0100 Subject: [PATCH 039/167] Add HostMetrics routes to the test --- awx/ui/src/routeConfig.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/awx/ui/src/routeConfig.test.js b/awx/ui/src/routeConfig.test.js index 0b84c670c3..cc73d96636 100644 --- a/awx/ui/src/routeConfig.test.js +++ b/awx/ui/src/routeConfig.test.js @@ -29,6 +29,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -58,6 +59,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -87,6 +89,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -117,6 +120,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -142,6 +146,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -166,6 +171,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -194,6 +200,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -223,6 +230,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', @@ -254,6 +262,7 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', + '/host_metrics', '/templates', '/credentials', '/projects', From d40fdd77ad312b71ebb1a35082e59beb8103cff6 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Mon, 20 Feb 2023 15:21:49 +0100 Subject: [PATCH 040/167] Fix filter to take only hostname__icontains and disable advance search --- .../components/DataListToolbar/DataListToolbar.js | 12 ++++++++---- awx/ui/src/screens/HostMetrics/HostMetrics.js | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/awx/ui/src/components/DataListToolbar/DataListToolbar.js b/awx/ui/src/components/DataListToolbar/DataListToolbar.js index 40deda10a1..9483989935 100644 --- a/awx/ui/src/components/DataListToolbar/DataListToolbar.js +++ b/awx/ui/src/components/DataListToolbar/DataListToolbar.js @@ -57,6 +57,7 @@ function DataListToolbar({ enableRelatedFuzzyFiltering, handleIsAnsibleFactsSelected, isFilterCleared, + advancedSearchDisabled, }) { const showExpandCollapse = onCompact && onExpand; const [isKebabOpen, setIsKebabOpen] = useState(false); @@ -86,6 +87,10 @@ function DataListToolbar({ }), [setIsKebabModalOpen] ); + const columns = [...searchColumns]; + if ( !advancedSearchDisabled ) { + columns.push({ name: t`Advanced`, key: 'advanced' }); + } return ( ()} qsConfig={QS_CONFIG} - toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname', isDefault: true}]} + toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname__icontains', isDefault: true}]} toolbarSearchableKeys={[]} toolbarRelatedSearchableKeys={[]} - renderToolbar={(props) => } + renderToolbar={(props) => {t`Hostname`} @@ -83,4 +83,5 @@ function HostMetrics() { ); } +export { HostMetrics as _HostMetrics }; export default HostMetrics; From 9f3c4f624024bd510426ed379b9af797e9a8d630 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Wed, 22 Feb 2023 15:44:34 +0100 Subject: [PATCH 041/167] RBAC: only superuse and auditor can see HostMetrics --- awx/ui/src/routeConfig.js | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/ui/src/routeConfig.js b/awx/ui/src/routeConfig.js index c738a352b3..dae4643c5d 100644 --- a/awx/ui/src/routeConfig.js +++ b/awx/ui/src/routeConfig.js @@ -187,6 +187,7 @@ function getRouteConfig(userProfile = {}) { if (userProfile?.isSuperUser || userProfile?.isSystemAuditor) return routeConfig; + deleteRoute('host_metrics'); deleteRouteGroup('settings'); deleteRoute('management_jobs'); if (userProfile?.isOrgAdmin) return routeConfig; From 179868dff2f2d9fffb611584affbe293d786eba0 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Thu, 23 Feb 2023 13:49:40 +0100 Subject: [PATCH 042/167] Add possibility to select and delete HostMetrics --- awx/ui/src/screens/HostMetrics/HostMetrics.js | 120 +++++++--- .../HostMetrics/HostMetricsDeleteButton.js | 220 ++++++++++++++++++ .../HostMetrics/HostMetricsListItem.js | 7 +- 3 files changed, 312 insertions(+), 35 deletions(-) create mode 100644 awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js index 7133bf7a18..ce43a04000 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -5,13 +5,16 @@ import { HostMetricsAPI } from 'api'; import useRequest from 'hooks/useRequest'; import PaginatedTable, { HeaderRow, - HeaderCell + HeaderCell, } from 'components/PaginatedTable'; import DataListToolbar from 'components/DataListToolbar'; import { getQSConfig, parseQueryString } from 'util/qs'; import {Card, PageSection} from "@patternfly/react-core"; import { useLocation } from 'react-router-dom'; import HostMetricsListItem from "./HostMetricsListItem"; +import HostMetricsDeleteButton from "./HostMetricsDeleteButton"; +import useSelected from 'hooks/useSelected'; + function HostMetrics() { @@ -46,40 +49,91 @@ function HostMetrics() { readHostMetrics(); }, [readHostMetrics]); + const { selected, isAllSelected, handleSelect, selectAll, clearSelected } = + useSelected(results); + return( - <> + <> - - - ()} - qsConfig={QS_CONFIG} - toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname__icontains', isDefault: true}]} - toolbarSearchableKeys={[]} - toolbarRelatedSearchableKeys={[]} - renderToolbar={(props) => - {t`Hostname`} - {t`First automated`} - {t`Last automated`} - {t`Automation`} - {t`Inventories`} - {t`Deleted`} - -} - /> - - - + streamType="none" + breadcrumbConfig={breadcrumbConfig} + /> + + + ( + row.hostname === item.hostname)} + onSelect={() => handleSelect(item)} + rowIndex={index} + /> + )} + qsConfig={QS_CONFIG} + toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname__icontains', isDefault: true}]} + toolbarSearchableKeys={[]} + toolbarRelatedSearchableKeys={[]} + renderToolbar={(props) => + + Promise.all(selected.map((hostMetric) => + HostMetricsAPI.destroy(hostMetric.id))) + .then(() => { readHostMetrics(); clearSelected(); }) + } + itemsToDelete={selected} + pluralizedItemName={t`Host Metrics`} + />]} + />} + headerRow={ + + + {t`Hostname`} + + + {t`First automated`} + + + {t`Last automated`} + + + {t`Automation`} + + + {t`Inventories`} + + + {t`Deleted`} + + + } + /> + + + ); } diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js new file mode 100644 index 0000000000..9519ca519e --- /dev/null +++ b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js @@ -0,0 +1,220 @@ +import React, { useState } from 'react'; +import { + func, + node, + string, + arrayOf, + shape, +} from 'prop-types'; +import styled from 'styled-components'; +import { + Alert, + Badge, + Button, + Tooltip, +} from '@patternfly/react-core'; +import { t } from '@lingui/macro'; +import { getRelatedResourceDeleteCounts } from 'util/getRelatedResourceDeleteDetails'; +import AlertModal from '../../components/AlertModal'; + +import ErrorDetail from '../../components/ErrorDetail'; + +const WarningMessage = styled(Alert)` + margin-top: 10px; +`; + +const Label = styled.span` + && { + margin-right: 10px; + } +`; + +const ItemToDelete = shape({ + hostname: string.isRequired, +}); + +function HostMetricsDeleteButton({ + itemsToDelete, + pluralizedItemName, + errorMessage, + onDelete, + deleteDetailsRequests, + warningMessage, + deleteMessage, +}) { + const [isModalOpen, setIsModalOpen] = useState(false); + const [deleteDetails, setDeleteDetails] = useState(null); + const [isLoading, setIsLoading] = useState(false); + + const [deleteMessageError, setDeleteMessageError] = useState(); + const handleDelete = () => { + console.log("Delete"); + onDelete(); + toggleModal(); + }; + + const toggleModal = async (isOpen) => { + setIsLoading(true); + setDeleteDetails(null); + if ( + isOpen && + itemsToDelete.length === 1 && + deleteDetailsRequests?.length > 0 + ) { + const { results, error } = await getRelatedResourceDeleteCounts( + deleteDetailsRequests + ); + + if (error) { + setDeleteMessageError(error); + } else { + setDeleteDetails(results); + } + } + setIsLoading(false); + setIsModalOpen(isOpen); + }; + + const renderTooltip = () => { + if (itemsToDelete.length) { + return t`Soft delete`; + } else { + return t`Select a row to delete`; + } + }; + + const modalTitle = t`Soft delete ${pluralizedItemName}?`; + + const isDisabled = + itemsToDelete.length === 0; + + const buildDeleteWarning = () => { + const deleteMessages = []; + if (warningMessage) { + deleteMessages.push(warningMessage); + } + if (deleteMessage) { + if (itemsToDelete.length > 1 || deleteDetails) + { + deleteMessages.push(deleteMessage); + } else if (deleteDetails || itemsToDelete.length > 1) { + deleteMessages.push(deleteMessage); + } + } + return ( +
+ {deleteMessages.map((message) => ( +
+ {message} +
+ ))} + {deleteDetails && + Object.entries(deleteDetails).map(([key, value]) => ( +
+ + {value} +
+ ))} +
+ ); + }; + + if (deleteMessageError) { + return ( + { + toggleModal(false); + setDeleteMessageError(); + }} + > + + + ); + } + const shouldShowDeleteWarning = + warningMessage || + (itemsToDelete.length === 1 && deleteDetails) || + (itemsToDelete.length > 1 && deleteMessage); + + return ( + <> + +
+ +
+
+ {isModalOpen && ( + toggleModal(false)} + actions={[ + , + , + ]} + > +
{t`This action will soft delete the following:`}
+ {itemsToDelete.map((item) => ( + + {item.hostname} +
+
+ ))} + {shouldShowDeleteWarning && ( + + )} +
+ )} + + ); +} + +HostMetricsDeleteButton.propTypes = { + onDelete: func.isRequired, + itemsToDelete: arrayOf(ItemToDelete).isRequired, + pluralizedItemName: string, + warningMessage: node, +}; + +HostMetricsDeleteButton.defaultProps = { + pluralizedItemName: 'Items', + warningMessage: null, +}; + +export default HostMetricsDeleteButton; diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js index fe9d06a25c..3fa4fb336e 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js +++ b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js @@ -4,12 +4,13 @@ import { Tr, Td } from '@patternfly/react-table'; import { formatDateString } from 'util/dates'; import { HostMetrics } from 'types'; import {t} from "@lingui/macro"; +import {bool, func} from "prop-types"; -function HostMetricsListItem({ item }) { +function HostMetricsListItem({ item, isSelected, onSelect, rowIndex }) { return ( - + {item.hostname} {formatDateString(item.first_automation)} {formatDateString(item.last_automation)} @@ -22,6 +23,8 @@ function HostMetricsListItem({ item }) { HostMetricsListItem.propTypes = { item: HostMetrics.isRequired, + isSelected: bool.isRequired, + onSelect: func.isRequired, }; export default HostMetricsListItem; From 610f75fcb1c5888b2d53826824fbcc47ca806055 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Thu, 23 Feb 2023 15:47:28 +0100 Subject: [PATCH 043/167] Update routeConfig test to be according to RBAC --- awx/ui/src/routeConfig.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/awx/ui/src/routeConfig.test.js b/awx/ui/src/routeConfig.test.js index cc73d96636..4d2a237c47 100644 --- a/awx/ui/src/routeConfig.test.js +++ b/awx/ui/src/routeConfig.test.js @@ -89,7 +89,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -120,7 +119,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -146,7 +144,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -171,7 +168,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -200,7 +196,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -230,7 +225,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', @@ -262,7 +256,6 @@ describe('getRouteConfig', () => { '/schedules', '/activity_stream', '/workflow_approvals', - '/host_metrics', '/templates', '/credentials', '/projects', From 32a56311e61cc30ef05b3a0f72f9d9f62608f382 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Tue, 28 Feb 2023 11:51:34 +0100 Subject: [PATCH 044/167] Fix linting issues --- awx/ui/src/screens/HostMetrics/HostMetrics.js | 17 +++-- .../screens/HostMetrics/HostMetrics.test.js | 68 +++++++++++++++++++ .../HostMetrics/HostMetricsDeleteButton.js | 12 +--- 3 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 awx/ui/src/screens/HostMetrics/HostMetrics.test.js diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js index ce43a04000..c85bbc6a33 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -11,23 +11,22 @@ import DataListToolbar from 'components/DataListToolbar'; import { getQSConfig, parseQueryString } from 'util/qs'; import {Card, PageSection} from "@patternfly/react-core"; import { useLocation } from 'react-router-dom'; +import useSelected from 'hooks/useSelected'; import HostMetricsListItem from "./HostMetricsListItem"; import HostMetricsDeleteButton from "./HostMetricsDeleteButton"; -import useSelected from 'hooks/useSelected'; +const QS_CONFIG = getQSConfig('host_metrics', { + page: 1, + page_size: 20, + order_by: 'hostname', +}); function HostMetrics() { - const location = useLocation(); const [breadcrumbConfig] = useState({ '/host_metrics': t`Host Metrics`, }); - const QS_CONFIG = getQSConfig('host_metrics', { - page: 1, - page_size: 20, - order_by: 'hostname', - }); const { result: { count, results }, isLoading, @@ -41,7 +40,7 @@ function HostMetrics() { count: list.data.count, results: list.data.results }; - }, [location.search]), + }, [location]), { results: [], count: 0 } ); @@ -81,7 +80,7 @@ function HostMetrics() { renderToolbar={(props) => el.find('ContentLoading').length === 0 + ); +} + +describe('', () => { + beforeEach(() => { + HostMetricsAPI.read.mockResolvedValue({ + data: { + count: mockHostMetrics.length, + results: mockHostMetrics, + }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('initially renders successfully', async () => { + await act(async () => { + mountWithContexts( + + ); + }); + }); + + test('HostMetrics are retrieved from the api and the components finishes loading', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts(); + }); + await waitForLoaded(wrapper); + + expect(HostMetricsAPI.read).toHaveBeenCalled(); + expect(wrapper.find('HostMetricsListItem')).toHaveLength(1); + }); +}); diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js index 9519ca519e..46c8fcee14 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js +++ b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js @@ -36,7 +36,6 @@ const ItemToDelete = shape({ function HostMetricsDeleteButton({ itemsToDelete, pluralizedItemName, - errorMessage, onDelete, deleteDetailsRequests, warningMessage, @@ -48,7 +47,6 @@ function HostMetricsDeleteButton({ const [deleteMessageError, setDeleteMessageError] = useState(); const handleDelete = () => { - console.log("Delete"); onDelete(); toggleModal(); }; @@ -78,9 +76,8 @@ function HostMetricsDeleteButton({ const renderTooltip = () => { if (itemsToDelete.length) { return t`Soft delete`; - } else { - return t`Select a row to delete`; } + return t`Select a row to delete`; }; const modalTitle = t`Soft delete ${pluralizedItemName}?`; @@ -94,11 +91,8 @@ function HostMetricsDeleteButton({ deleteMessages.push(warningMessage); } if (deleteMessage) { - if (itemsToDelete.length > 1 || deleteDetails) - { - deleteMessages.push(deleteMessage); - } else if (deleteDetails || itemsToDelete.length > 1) { - deleteMessages.push(deleteMessage); + if (itemsToDelete.length > 1 || deleteDetails) { + deleteMessages.push(deleteMessage); } } return ( From 5be90fd36b7c023a1e8a5df78f966ae1486e29cf Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Tue, 28 Feb 2023 11:57:13 +0100 Subject: [PATCH 045/167] Do not show deleted host metrics --- awx/ui/src/screens/HostMetrics/HostMetrics.js | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js index c85bbc6a33..04aa6ec5ef 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -19,6 +19,7 @@ const QS_CONFIG = getQSConfig('host_metrics', { page: 1, page_size: 20, order_by: 'hostname', + deleted: false, }); function HostMetrics() { From c20e8eb7120400e70924e01c7a07de5ab2aed98f Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Tue, 28 Feb 2023 12:08:06 +0100 Subject: [PATCH 046/167] Prettier --- .../DataListToolbar/DataListToolbar.js | 6 +- awx/ui/src/routeConfig.js | 10 +- awx/ui/src/screens/HostMetrics/HostMetrics.js | 148 ++++++++++-------- .../screens/HostMetrics/HostMetrics.test.js | 2 +- .../HostMetrics/HostMetricsDeleteButton.js | 55 +++---- .../HostMetrics/HostMetricsListItem.js | 30 ++-- 6 files changed, 131 insertions(+), 120 deletions(-) diff --git a/awx/ui/src/components/DataListToolbar/DataListToolbar.js b/awx/ui/src/components/DataListToolbar/DataListToolbar.js index 9483989935..39b3d6bb43 100644 --- a/awx/ui/src/components/DataListToolbar/DataListToolbar.js +++ b/awx/ui/src/components/DataListToolbar/DataListToolbar.js @@ -88,8 +88,8 @@ function DataListToolbar({ [setIsKebabModalOpen] ); const columns = [...searchColumns]; - if ( !advancedSearchDisabled ) { - columns.push({ name: t`Advanced`, key: 'advanced' }); + if (!advancedSearchDisabled) { + columns.push({ name: t`Advanced`, key: 'advanced' }); } return ( Host Metrics, - path: '/host_metrics', - screen: HostMetrics, - }, + { + title: Host Metrics, + path: '/host_metrics', + screen: HostMetrics, + }, ], }, { diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js index 04aa6ec5ef..387ed03772 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -1,5 +1,5 @@ -import React, {useCallback, useEffect, useState} from 'react'; -import {t} from "@lingui/macro"; +import React, { useCallback, useEffect, useState } from 'react'; +import { t } from '@lingui/macro'; import ScreenHeader from 'components/ScreenHeader/ScreenHeader'; import { HostMetricsAPI } from 'api'; import useRequest from 'hooks/useRequest'; @@ -9,17 +9,17 @@ import PaginatedTable, { } from 'components/PaginatedTable'; import DataListToolbar from 'components/DataListToolbar'; import { getQSConfig, parseQueryString } from 'util/qs'; -import {Card, PageSection} from "@patternfly/react-core"; +import { Card, PageSection } from '@patternfly/react-core'; import { useLocation } from 'react-router-dom'; import useSelected from 'hooks/useSelected'; -import HostMetricsListItem from "./HostMetricsListItem"; -import HostMetricsDeleteButton from "./HostMetricsDeleteButton"; +import HostMetricsListItem from './HostMetricsListItem'; +import HostMetricsDeleteButton from './HostMetricsDeleteButton'; const QS_CONFIG = getQSConfig('host_metrics', { - page: 1, - page_size: 20, - order_by: 'hostname', - deleted: false, + page: 1, + page_size: 20, + order_by: 'hostname', + deleted: false, }); function HostMetrics() { @@ -34,15 +34,15 @@ function HostMetrics() { error, request: readHostMetrics, } = useRequest( - useCallback(async () => { - const params = parseQueryString(QS_CONFIG, location.search); - const list = await HostMetricsAPI.read(params); - return { - count: list.data.count, - results: list.data.results - }; - }, [location]), - { results: [], count: 0 } + useCallback(async () => { + const params = parseQueryString(QS_CONFIG, location.search); + const list = await HostMetricsAPI.read(params); + return { + count: list.data.count, + results: list.data.results, + }; + }, [location]), + { results: [], count: 0 } ); useEffect(() => { @@ -50,14 +50,11 @@ function HostMetrics() { }, [readHostMetrics]); const { selected, isAllSelected, handleSelect, selectAll, clearSelected } = - useSelected(results); + useSelected(results); - return( + return ( <> - + ( + renderRow={(item, index) => ( row.hostname === item.hostname)} + isSelected={selected.some( + (row) => row.hostname === item.hostname + )} onSelect={() => handleSelect(item)} rowIndex={index} /> )} qsConfig={QS_CONFIG} - toolbarSearchColumns={[{name: t`Hostname`, key: 'hostname__icontains', isDefault: true}]} + toolbarSearchColumns={[ + { + name: t`Hostname`, + key: 'hostname__icontains', + isDefault: true, + }, + ]} toolbarSearchableKeys={[]} toolbarRelatedSearchableKeys={[]} - renderToolbar={(props) => + renderToolbar={(props) => ( - Promise.all(selected.map((hostMetric) => - HostMetricsAPI.destroy(hostMetric.id))) - .then(() => { readHostMetrics(); clearSelected(); }) + Promise.all( + selected.map((hostMetric) => + HostMetricsAPI.destroy(hostMetric.id) + ) + ).then(() => { + readHostMetrics(); + clearSelected(); + }) } - itemsToDelete={selected} - pluralizedItemName={t`Host Metrics`} - />]} - />} - headerRow={ - - - {t`Hostname`} - - - {t`First automated`} - - - {t`Last automated`} - - - {t`Automation`} - - - {t`Inventories`} - - - {t`Deleted`} - - + itemsToDelete={selected} + pluralizedItemName={t`Host Metrics`} + />, + ]} + /> + )} + headerRow={ + + {t`Hostname`} + + {t`First automated`} + + + {t`Last automated`} + + + {t`Automation`} + + + {t`Inventories`} + + + {t`Deleted`} + + } /> diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.test.js b/awx/ui/src/screens/HostMetrics/HostMetrics.test.js index 884f25973b..972d216712 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.test.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.test.js @@ -19,7 +19,7 @@ const mockHostMetrics = [ used_in_inventories: 1, deleted_counter: 1, id: 1, - } + }, ]; function waitForLoaded(wrapper) { diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js index 46c8fcee14..a0b439e893 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js +++ b/awx/ui/src/screens/HostMetrics/HostMetricsDeleteButton.js @@ -1,18 +1,7 @@ import React, { useState } from 'react'; -import { - func, - node, - string, - arrayOf, - shape, -} from 'prop-types'; +import { func, node, string, arrayOf, shape } from 'prop-types'; import styled from 'styled-components'; -import { - Alert, - Badge, - Button, - Tooltip, -} from '@patternfly/react-core'; +import { Alert, Badge, Button, Tooltip } from '@patternfly/react-core'; import { t } from '@lingui/macro'; import { getRelatedResourceDeleteCounts } from 'util/getRelatedResourceDeleteDetails'; import AlertModal from '../../components/AlertModal'; @@ -82,8 +71,7 @@ function HostMetricsDeleteButton({ const modalTitle = t`Soft delete ${pluralizedItemName}?`; - const isDisabled = - itemsToDelete.length === 0; + const isDisabled = itemsToDelete.length === 0; const buildDeleteWarning = () => { const deleteMessages = []; @@ -92,7 +80,7 @@ function HostMetricsDeleteButton({ } if (deleteMessage) { if (itemsToDelete.length > 1 || deleteDetails) { - deleteMessages.push(deleteMessage); + deleteMessages.push(deleteMessage); } } return ( @@ -134,21 +122,21 @@ function HostMetricsDeleteButton({ return ( <> - -
- -
-
+ +
+ +
+
{isModalOpen && (
{t`This action will soft delete the following:`}
{itemsToDelete.map((item) => ( - + {item.hostname}
diff --git a/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js index 3fa4fb336e..10a73f54fa 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js +++ b/awx/ui/src/screens/HostMetrics/HostMetricsListItem.js @@ -3,28 +3,34 @@ import React from 'react'; import { Tr, Td } from '@patternfly/react-table'; import { formatDateString } from 'util/dates'; import { HostMetrics } from 'types'; -import {t} from "@lingui/macro"; -import {bool, func} from "prop-types"; +import { t } from '@lingui/macro'; +import { bool, func } from 'prop-types'; function HostMetricsListItem({ item, isSelected, onSelect, rowIndex }) { - return ( - - + + {item.hostname} - {formatDateString(item.first_automation)} - {formatDateString(item.last_automation)} + + {formatDateString(item.first_automation)} + + + {formatDateString(item.last_automation)} + {item.automated_counter} {item.used_in_inventories || 0} - {item.deleted_counter}< - /Tr> + {item.deleted_counter} + ); } HostMetricsListItem.propTypes = { - item: HostMetrics.isRequired, - isSelected: bool.isRequired, - onSelect: func.isRequired, + item: HostMetrics.isRequired, + isSelected: bool.isRequired, + onSelect: func.isRequired, }; export default HostMetricsListItem; From c117ca66d53bc272e75accfc270890490bc73fb3 Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Thu, 2 Mar 2023 14:28:02 +0100 Subject: [PATCH 047/167] Show HostMetrics only for specific subscription SUBSCRIPTION_USAGE_MODEL: 'unique_managed_hosts' Fixes https://issues.redhat.com/browse/AA-1613 --- awx/ui/src/api/models/Settings.js | 4 ++++ awx/ui/src/contexts/Config.js | 24 +++++++++++++++++++++--- awx/ui/src/routeConfig.js | 7 ++++++- awx/ui/src/routeConfig.test.js | 1 + 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/awx/ui/src/api/models/Settings.js b/awx/ui/src/api/models/Settings.js index 89aad94c00..10bab4c3a0 100644 --- a/awx/ui/src/api/models/Settings.js +++ b/awx/ui/src/api/models/Settings.js @@ -18,6 +18,10 @@ class Settings extends Base { return this.http.get(`${this.baseUrl}all/`); } + readSystem() { + return this.http.get(`${this.baseUrl}system/`); + } + updateCategory(category, data) { return this.http.patch(`${this.baseUrl}${category}/`, data); } diff --git a/awx/ui/src/contexts/Config.js b/awx/ui/src/contexts/Config.js index 1ef355ead3..fd28208b8b 100644 --- a/awx/ui/src/contexts/Config.js +++ b/awx/ui/src/contexts/Config.js @@ -8,6 +8,7 @@ import useRequest, { useDismissableError } from 'hooks/useRequest'; import AlertModal from 'components/AlertModal'; import ErrorDetail from 'components/ErrorDetail'; import { useSession } from './Session'; +import { SettingsAPI } from '../api'; // eslint-disable-next-line import/prefer-default-export export const ConfigContext = React.createContext({}); @@ -40,6 +41,11 @@ export const ConfigProvider = ({ children }) => { }, }, ] = await Promise.all([ConfigAPI.read(), MeAPI.read()]); + let systemConfig = {}; + if (me?.is_superuser || me?.is_system_auditor) { + const { data: systemConfigResults } = await SettingsAPI.readSystem(); + systemConfig = systemConfigResults; + } const [ { @@ -62,10 +68,21 @@ export const ConfigProvider = ({ children }) => { role_level: 'execution_environment_admin_role', }), ]); - - return { ...data, me, adminOrgCount, notifAdminCount, execEnvAdminCount }; + return { + ...data, + me, + adminOrgCount, + notifAdminCount, + execEnvAdminCount, + systemConfig, + }; }, []), - { adminOrgCount: 0, notifAdminCount: 0, execEnvAdminCount: 0 } + { + adminOrgCount: 0, + notifAdminCount: 0, + execEnvAdminCount: 0, + systemConfig: {}, + } ); const { error, dismissError } = useDismissableError(configError); @@ -112,6 +129,7 @@ export const useUserProfile = () => { isOrgAdmin: config.adminOrgCount, isNotificationAdmin: config.notifAdminCount, isExecEnvAdmin: config.execEnvAdminCount, + systemConfig: config.systemConfig, }; }; diff --git a/awx/ui/src/routeConfig.js b/awx/ui/src/routeConfig.js index 9e1cac0197..1accb1fa00 100644 --- a/awx/ui/src/routeConfig.js +++ b/awx/ui/src/routeConfig.js @@ -184,7 +184,12 @@ function getRouteConfig(userProfile = {}) { const deleteRouteGroup = (name) => { routeConfig = routeConfig.filter(({ groupId }) => !groupId.includes(name)); }; - + if ( + userProfile?.systemConfig?.SUBSCRIPTION_USAGE_MODEL !== + 'unique_managed_hosts' + ) { + deleteRoute('host_metrics'); + } if (userProfile?.isSuperUser || userProfile?.isSystemAuditor) return routeConfig; deleteRoute('host_metrics'); diff --git a/awx/ui/src/routeConfig.test.js b/awx/ui/src/routeConfig.test.js index 4d2a237c47..4888537485 100644 --- a/awx/ui/src/routeConfig.test.js +++ b/awx/ui/src/routeConfig.test.js @@ -7,6 +7,7 @@ const userProfile = { isOrgAdmin: false, isNotificationAdmin: false, isExecEnvAdmin: false, + systemConfig: { SUBSCRIPTION_USAGE_MODEL: 'unique_managed_hosts' }, }; const filterPaths = (sidebar) => { From 88bb6e5a6a01f3afcad002222674f5a68b365eec Mon Sep 17 00:00:00 2001 From: Zita Nemeckova Date: Mon, 6 Mar 2023 11:26:14 +0100 Subject: [PATCH 048/167] Fix test failure --- awx/ui/src/screens/HostMetrics/HostMetrics.js | 1 + awx/ui/src/screens/HostMetrics/HostMetrics.test.js | 1 + 2 files changed, 2 insertions(+) diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.js b/awx/ui/src/screens/HostMetrics/HostMetrics.js index 387ed03772..838bbf8127 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.js @@ -65,6 +65,7 @@ function HostMetrics() { pluralizedItemName={t`Host Metrics`} renderRow={(item, index) => ( row.hostname === item.hostname diff --git a/awx/ui/src/screens/HostMetrics/HostMetrics.test.js b/awx/ui/src/screens/HostMetrics/HostMetrics.test.js index 972d216712..78d8c2bbdd 100644 --- a/awx/ui/src/screens/HostMetrics/HostMetrics.test.js +++ b/awx/ui/src/screens/HostMetrics/HostMetrics.test.js @@ -19,6 +19,7 @@ const mockHostMetrics = [ used_in_inventories: 1, deleted_counter: 1, id: 1, + url: '', }, ]; From 311cea5a4ac1c2eecd1c140da0e6170b634bb443 Mon Sep 17 00:00:00 2001 From: Aparna Karve Date: Tue, 14 Feb 2023 16:53:56 -0800 Subject: [PATCH 049/167] CLI for host usage collection --- awx/main/management/commands/host_metric.py | 214 +++++++++++++++++++- 1 file changed, 203 insertions(+), 11 deletions(-) diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index c58cea2c1b..a7be155e32 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -1,26 +1,196 @@ from django.core.management.base import BaseCommand import datetime from django.core.serializers.json import DjangoJSONEncoder -from awx.main.models.inventory import HostMetric +from awx.main.models.inventory import HostMetric, HostMetricSummaryMonthly +from awx.main.analytics.collectors import config +from awx.main.utils.encryption import get_encryption_key, Fernet256 +from django.utils.encoding import smart_str, smart_bytes +import base64 import json +import sys +import tempfile +import tarfile +import pandas as pd + +PREFERRED_ROW_COUNT = 500000 class Command(BaseCommand): help = 'This is for offline licensing usage' + def host_metric_queryset(self, result, offset=0, limit=PREFERRED_ROW_COUNT): + list_of_queryset = list( + result.values( + 'id', + 'hostname', + 'first_automation', + 'last_automation', + 'last_deleted', + 'automated_counter', + 'deleted_counter', + 'deleted', + 'used_in_inventories', + ).order_by('first_automation')[offset : offset + limit] + ) + + return list_of_queryset + + def host_metric_summary_monthly_queryset(self, result, offset=0, limit=PREFERRED_ROW_COUNT): + list_of_queryset = list( + result.values( + 'id', + 'date', + 'license_consumed', + 'license_capacity', + 'hosts_added', + 'hosts_deleted', + 'indirectly_managed_hosts', + ).order_by( + 'date' + )[offset : offset + limit] + ) + + return list_of_queryset + + def paginated_df(self, options, type, filter_kwargs, offset=0, limit=PREFERRED_ROW_COUNT): + list_of_queryset = [] + if type == 'host_metric': + result = HostMetric.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_queryset(result, offset, limit) + elif type == 'host_metric_summary_monthly': + result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_summary_monthly_queryset(result, offset, limit) + + df = pd.DataFrame(list_of_queryset) + + if options['anonymized'] and 'hostname' in df.columns: + key = get_encryption_key('hostname', options.get('anonymized')) + df['hostname'] = df.apply(lambda x: self.obfuscated_hostname(key, x['hostname']), axis=1) + + return df + + def obfuscated_hostname(self, secret_sauce, hostname): + return self.encrypt_name(secret_sauce, hostname) + + def whole_page_count(self, row_count, rows_per_file): + whole_pages = int(row_count / rows_per_file) + partial_page = row_count % rows_per_file + if partial_page: + whole_pages += 1 + return whole_pages + + def csv_for_tar(self, options, temp_dir, type, filter_kwargs, index=1, offset=0, rows_per_file=PREFERRED_ROW_COUNT): + df = self.paginated_df(options, type, filter_kwargs, offset, rows_per_file) + csv_file = f'{temp_dir}/{type}{index}.csv' + arcname_file = f'{type}{index}.csv' + df.to_csv(csv_file, index=False) + return csv_file, arcname_file + + def config_for_tar(self, options, temp_dir): + config_json = json.dumps(config(options.get('since'))) + config_file = f'{temp_dir}/config.json' + arcname_file = 'config.json' + with open(config_file, 'w') as f: + f.write(config_json) + return config_file, arcname_file + + def encrypt_name(self, key, value): + value = smart_str(value) + f = Fernet256(key) + encrypted = f.encrypt(smart_bytes(value)) + b64data = smart_str(base64.b64encode(encrypted)) + tokens = ['$encrypted', 'UTF8', 'AESCBC', b64data] + return '$'.join(tokens) + + def decrypt_name(self, encryption_key, value): + raw_data = value[len('$encrypted$') :] + # If the encrypted string contains a UTF8 marker, discard it + utf8 = raw_data.startswith('UTF8$') + if utf8: + raw_data = raw_data[len('UTF8$') :] + algo, b64data = raw_data.split('$', 1) + if algo != 'AESCBC': + raise ValueError('unsupported algorithm: %s' % algo) + encrypted = base64.b64decode(b64data) + f = Fernet256(encryption_key) + value = f.decrypt(encrypted) + return smart_str(value) + + def output_json(self, options, filter_kwargs): + if not options.get('json') or options.get('json') == 'host_metric': + result = HostMetric.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_queryset(result) + elif options.get('json') == 'host_metric_summary_monthly': + result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_summary_monthly_queryset(result) + + json_result = json.dumps(list_of_queryset, cls=DjangoJSONEncoder) + print(json_result) + + def output_csv(self, options, filter_kwargs): + with tempfile.TemporaryDirectory() as temp_dir: + if not options.get('csv') or options.get('csv') == 'host_metric': + csv_file, _arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs) + elif options.get('csv') == 'host_metric_summary_monthly': + csv_file, _arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs) + with open(csv_file) as f: + sys.stdout.write(f.read()) + + def output_tarball(self, options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count): + tar = tarfile.open("./host_metrics.tar.gz", "w:gz") + + with tempfile.TemporaryDirectory() as temp_dir: + if host_metric_row_count: + csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs) + tar.add(csv_file, arcname=arcname_file) + + if host_metric_summary_monthly_row_count: + csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs) + tar.add(csv_file, arcname=arcname_file) + + config_file, arcname_file = self.config_for_tar(options, temp_dir) + tar.add(config_file, arcname=arcname_file) + + tar.close() + + def output_rows_per_file(self, options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count): + rows_per_file = options.get('rows_per_file', PREFERRED_ROW_COUNT) + tar = tarfile.open("./host_metrics.tar.gz", "w:gz") + + host_metric_whole_pages = self.whole_page_count(host_metric_row_count, rows_per_file) + host_metric_summary_monthly_whole_pages = self.whole_page_count(host_metric_summary_monthly_row_count, rows_per_file) + + with tempfile.TemporaryDirectory() as temp_dir: + for index in range(host_metric_whole_pages): + offset = index * rows_per_file + + csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs, index + 1, offset, rows_per_file) + tar.add(csv_file, arcname=arcname_file) + + for index in range(host_metric_summary_monthly_whole_pages): + offset = index * rows_per_file + + csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs, index + 1, offset, rows_per_file) + tar.add(csv_file, arcname=arcname_file) + + config_file, arcname_file = self.config_for_tar(options, temp_dir) + tar.add(config_file, arcname=arcname_file) + + tar.close() + def add_arguments(self, parser): parser.add_argument('--since', type=datetime.datetime.fromisoformat, help='Start Date in ISO format YYYY-MM-DD') parser.add_argument('--until', type=datetime.datetime.fromisoformat, help='End Date in ISO format YYYY-MM-DD') - parser.add_argument('--json', action='store_true', help='Select output as JSON') + parser.add_argument('--json', type=str, const='host_metric', nargs='?', help='Select output as JSON for host_metric or host_metric_summary_monthly') + parser.add_argument('--csv', type=str, const='host_metric', nargs='?', help='Select output as CSV for host_metric or host_metric_summary_monthly') + parser.add_argument('--tarball', action='store_true', help=f'Package CSV files into a tar with upto {PREFERRED_ROW_COUNT} rows') + parser.add_argument('--anonymized', type=str, help='Anonymize hostnames with provided salt') + parser.add_argument('--rows_per_file', type=int, help=f'Split rows in chunks of {PREFERRED_ROW_COUNT}') def handle(self, *args, **options): since = options.get('since') until = options.get('until') - if since is None and until is None: - print("No Arguments received") - return None - if since is not None and since.tzinfo is None: since = since.replace(tzinfo=datetime.timezone.utc) @@ -33,17 +203,39 @@ class Command(BaseCommand): if until is not None: filter_kwargs['last_automation__lte'] = until - result = HostMetric.objects.filter(**filter_kwargs) + filter_kwargs_host_metrics_summary = {} + if since is not None: + filter_kwargs_host_metrics_summary['date__gte'] = since + if until is not None: + filter_kwargs_host_metrics_summary['date__lte'] = until + + host_metric_row_count = HostMetric.objects.filter(**filter_kwargs).count() + host_metric_summary_monthly_row_count = HostMetricSummaryMonthly.objects.filter(**filter_kwargs_host_metrics_summary).count() + + if (host_metric_row_count > PREFERRED_ROW_COUNT or host_metric_summary_monthly_row_count > PREFERRED_ROW_COUNT) and ( + not options.get('rows_per_file') or options.get('rows_per_file') > PREFERRED_ROW_COUNT + ): + print( + f"HostMetric / HostMetricSummaryMonthly rows exceed the allowable limit of {PREFERRED_ROW_COUNT}. " + f"Set --rows_per_file {PREFERRED_ROW_COUNT} " + f"to split the rows in chunks of {PREFERRED_ROW_COUNT}" + ) + return # if --json flag is set, output the result in json format if options['json']: - list_of_queryset = list(result.values('hostname', 'first_automation', 'last_automation')) - json_result = json.dumps(list_of_queryset, cls=DjangoJSONEncoder) - print(json_result) + self.output_json(options, filter_kwargs) + elif options['csv']: + self.output_csv(options, filter_kwargs) + elif options['tarball']: + self.output_tarball(options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count) + elif options['rows_per_file']: + self.output_rows_per_file(options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count) # --json flag is not set, output in plain text else: - print(f"Total Number of hosts automated: {len(result)}") + print(f"Total Number of hosts automated: {host_metric_row_count}") + result = HostMetric.objects.filter(**filter_kwargs) for item in result: print( "Hostname : {hostname} | first_automation : {first_automation} | last_automation : {last_automation}".format( From 132fe5e443c1bf4cc9766a591625452409360f53 Mon Sep 17 00:00:00 2001 From: Aparna Karve Date: Thu, 23 Feb 2023 12:42:01 -0800 Subject: [PATCH 050/167] Remove `pandas` use `csv`. Also, remove anonymization --- awx/main/management/commands/host_metric.py | 51 +++++---------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index a7be155e32..5cf2aef18b 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -3,14 +3,11 @@ import datetime from django.core.serializers.json import DjangoJSONEncoder from awx.main.models.inventory import HostMetric, HostMetricSummaryMonthly from awx.main.analytics.collectors import config -from awx.main.utils.encryption import get_encryption_key, Fernet256 -from django.utils.encoding import smart_str, smart_bytes -import base64 import json import sys import tempfile import tarfile -import pandas as pd +import csv PREFERRED_ROW_COUNT = 500000 @@ -52,7 +49,7 @@ class Command(BaseCommand): return list_of_queryset - def paginated_df(self, options, type, filter_kwargs, offset=0, limit=PREFERRED_ROW_COUNT): + def paginated_db_retrieval(self, type, filter_kwargs, offset=0, limit=PREFERRED_ROW_COUNT): list_of_queryset = [] if type == 'host_metric': result = HostMetric.objects.filter(**filter_kwargs) @@ -61,16 +58,7 @@ class Command(BaseCommand): result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) list_of_queryset = self.host_metric_summary_monthly_queryset(result, offset, limit) - df = pd.DataFrame(list_of_queryset) - - if options['anonymized'] and 'hostname' in df.columns: - key = get_encryption_key('hostname', options.get('anonymized')) - df['hostname'] = df.apply(lambda x: self.obfuscated_hostname(key, x['hostname']), axis=1) - - return df - - def obfuscated_hostname(self, secret_sauce, hostname): - return self.encrypt_name(secret_sauce, hostname) + return list_of_queryset def whole_page_count(self, row_count, rows_per_file): whole_pages = int(row_count / rows_per_file) @@ -80,10 +68,16 @@ class Command(BaseCommand): return whole_pages def csv_for_tar(self, options, temp_dir, type, filter_kwargs, index=1, offset=0, rows_per_file=PREFERRED_ROW_COUNT): - df = self.paginated_df(options, type, filter_kwargs, offset, rows_per_file) + list_of_queryset = self.paginated_db_retrieval(type, filter_kwargs, offset, rows_per_file) csv_file = f'{temp_dir}/{type}{index}.csv' arcname_file = f'{type}{index}.csv' - df.to_csv(csv_file, index=False) + + with open(csv_file, 'w', newline='') as output_file: + keys = list_of_queryset[0].keys() if list_of_queryset else [] + dict_writer = csv.DictWriter(output_file, keys) + dict_writer.writeheader() + dict_writer.writerows(list_of_queryset) + return csv_file, arcname_file def config_for_tar(self, options, temp_dir): @@ -94,28 +88,6 @@ class Command(BaseCommand): f.write(config_json) return config_file, arcname_file - def encrypt_name(self, key, value): - value = smart_str(value) - f = Fernet256(key) - encrypted = f.encrypt(smart_bytes(value)) - b64data = smart_str(base64.b64encode(encrypted)) - tokens = ['$encrypted', 'UTF8', 'AESCBC', b64data] - return '$'.join(tokens) - - def decrypt_name(self, encryption_key, value): - raw_data = value[len('$encrypted$') :] - # If the encrypted string contains a UTF8 marker, discard it - utf8 = raw_data.startswith('UTF8$') - if utf8: - raw_data = raw_data[len('UTF8$') :] - algo, b64data = raw_data.split('$', 1) - if algo != 'AESCBC': - raise ValueError('unsupported algorithm: %s' % algo) - encrypted = base64.b64decode(b64data) - f = Fernet256(encryption_key) - value = f.decrypt(encrypted) - return smart_str(value) - def output_json(self, options, filter_kwargs): if not options.get('json') or options.get('json') == 'host_metric': result = HostMetric.objects.filter(**filter_kwargs) @@ -184,7 +156,6 @@ class Command(BaseCommand): parser.add_argument('--json', type=str, const='host_metric', nargs='?', help='Select output as JSON for host_metric or host_metric_summary_monthly') parser.add_argument('--csv', type=str, const='host_metric', nargs='?', help='Select output as CSV for host_metric or host_metric_summary_monthly') parser.add_argument('--tarball', action='store_true', help=f'Package CSV files into a tar with upto {PREFERRED_ROW_COUNT} rows') - parser.add_argument('--anonymized', type=str, help='Anonymize hostnames with provided salt') parser.add_argument('--rows_per_file', type=int, help=f'Split rows in chunks of {PREFERRED_ROW_COUNT}') def handle(self, *args, **options): From 878008a9c559fc8dadd0edaf053f4d492214dab9 Mon Sep 17 00:00:00 2001 From: Aparna Karve Date: Fri, 3 Mar 2023 14:20:22 -0800 Subject: [PATCH 051/167] make `rows_per_file` optional parameter Removed 2 sql statements that gave the info on row count which warranted many other changes --- awx/main/management/commands/host_metric.py | 145 ++++++++------------ 1 file changed, 58 insertions(+), 87 deletions(-) diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index 5cf2aef18b..5b38cb5fd5 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -49,36 +49,41 @@ class Command(BaseCommand): return list_of_queryset - def paginated_db_retrieval(self, type, filter_kwargs, offset=0, limit=PREFERRED_ROW_COUNT): + def paginated_db_retrieval(self, type, filter_kwargs, rows_per_file): + offset = 0 list_of_queryset = [] - if type == 'host_metric': - result = HostMetric.objects.filter(**filter_kwargs) - list_of_queryset = self.host_metric_queryset(result, offset, limit) - elif type == 'host_metric_summary_monthly': - result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) - list_of_queryset = self.host_metric_summary_monthly_queryset(result, offset, limit) + while True: + if type == 'host_metric': + result = HostMetric.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_queryset(result, offset, rows_per_file) + elif type == 'host_metric_summary_monthly': + result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) + list_of_queryset = self.host_metric_summary_monthly_queryset(result, offset, rows_per_file) - return list_of_queryset + if not list_of_queryset: + break + else: + yield list_of_queryset - def whole_page_count(self, row_count, rows_per_file): - whole_pages = int(row_count / rows_per_file) - partial_page = row_count % rows_per_file - if partial_page: - whole_pages += 1 - return whole_pages + offset += len(list_of_queryset) - def csv_for_tar(self, options, temp_dir, type, filter_kwargs, index=1, offset=0, rows_per_file=PREFERRED_ROW_COUNT): - list_of_queryset = self.paginated_db_retrieval(type, filter_kwargs, offset, rows_per_file) - csv_file = f'{temp_dir}/{type}{index}.csv' - arcname_file = f'{type}{index}.csv' + def csv_for_tar(self, temp_dir, type, filter_kwargs, single_header=False, rows_per_file=PREFERRED_ROW_COUNT): + for index, list_of_queryset in enumerate(self.paginated_db_retrieval(type, filter_kwargs, rows_per_file)): + csv_file = f'{temp_dir}/{type}{index+1}.csv' + arcname_file = f'{type}{index+1}.csv' - with open(csv_file, 'w', newline='') as output_file: - keys = list_of_queryset[0].keys() if list_of_queryset else [] - dict_writer = csv.DictWriter(output_file, keys) - dict_writer.writeheader() - dict_writer.writerows(list_of_queryset) + with open(csv_file, 'w', newline='') as output_file: + try: + keys = list_of_queryset[0].keys() if list_of_queryset else [] + dict_writer = csv.DictWriter(output_file, keys) + if not single_header or index == 0: + dict_writer.writeheader() + dict_writer.writerows(list_of_queryset) - return csv_file, arcname_file + except Exception as e: + print(e) + + yield csv_file, arcname_file def config_for_tar(self, options, temp_dir): config_json = json.dumps(config(options.get('since'))) @@ -89,61 +94,37 @@ class Command(BaseCommand): return config_file, arcname_file def output_json(self, options, filter_kwargs): - if not options.get('json') or options.get('json') == 'host_metric': - result = HostMetric.objects.filter(**filter_kwargs) - list_of_queryset = self.host_metric_queryset(result) - elif options.get('json') == 'host_metric_summary_monthly': - result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) - list_of_queryset = self.host_metric_summary_monthly_queryset(result) + rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT + with tempfile.TemporaryDirectory() as temp_dir: + for csv_detail in self.csv_for_tar(temp_dir, options.get('json', 'host_metric'), filter_kwargs, False, rows_per_file): + csv_file = csv_detail[0] - json_result = json.dumps(list_of_queryset, cls=DjangoJSONEncoder) - print(json_result) + with open(csv_file) as f: + reader = csv.DictReader(f) + rows = list(reader) + json_result = json.dumps(rows, cls=DjangoJSONEncoder) + print(json_result) def output_csv(self, options, filter_kwargs): + rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT with tempfile.TemporaryDirectory() as temp_dir: - if not options.get('csv') or options.get('csv') == 'host_metric': - csv_file, _arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs) - elif options.get('csv') == 'host_metric_summary_monthly': - csv_file, _arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs) - with open(csv_file) as f: - sys.stdout.write(f.read()) + for csv_detail in self.csv_for_tar(temp_dir, options.get('csv', 'host_metric'), filter_kwargs, True, rows_per_file): + csv_file = csv_detail[0] + with open(csv_file) as f: + sys.stdout.write(f.read()) + + def output_tarball(self, options, filter_kwargs): + single_header = False if options['rows_per_file'] else True + rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT - def output_tarball(self, options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count): tar = tarfile.open("./host_metrics.tar.gz", "w:gz") with tempfile.TemporaryDirectory() as temp_dir: - if host_metric_row_count: - csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs) - tar.add(csv_file, arcname=arcname_file) + for csv_detail in self.csv_for_tar(temp_dir, 'host_metric', filter_kwargs, single_header, rows_per_file): + tar.add(csv_detail[0], arcname=csv_detail[1]) - if host_metric_summary_monthly_row_count: - csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs) - tar.add(csv_file, arcname=arcname_file) - - config_file, arcname_file = self.config_for_tar(options, temp_dir) - tar.add(config_file, arcname=arcname_file) - - tar.close() - - def output_rows_per_file(self, options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count): - rows_per_file = options.get('rows_per_file', PREFERRED_ROW_COUNT) - tar = tarfile.open("./host_metrics.tar.gz", "w:gz") - - host_metric_whole_pages = self.whole_page_count(host_metric_row_count, rows_per_file) - host_metric_summary_monthly_whole_pages = self.whole_page_count(host_metric_summary_monthly_row_count, rows_per_file) - - with tempfile.TemporaryDirectory() as temp_dir: - for index in range(host_metric_whole_pages): - offset = index * rows_per_file - - csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric', filter_kwargs, index + 1, offset, rows_per_file) - tar.add(csv_file, arcname=arcname_file) - - for index in range(host_metric_summary_monthly_whole_pages): - offset = index * rows_per_file - - csv_file, arcname_file = self.csv_for_tar(options, temp_dir, 'host_metric_summary_monthly', filter_kwargs, index + 1, offset, rows_per_file) - tar.add(csv_file, arcname=arcname_file) + for csv_detail in self.csv_for_tar(temp_dir, 'host_metric_summary_monthly', filter_kwargs, single_header, rows_per_file): + tar.add(csv_detail[0], arcname=csv_detail[1]) config_file, arcname_file = self.config_for_tar(options, temp_dir) tar.add(config_file, arcname=arcname_file) @@ -180,17 +161,8 @@ class Command(BaseCommand): if until is not None: filter_kwargs_host_metrics_summary['date__lte'] = until - host_metric_row_count = HostMetric.objects.filter(**filter_kwargs).count() - host_metric_summary_monthly_row_count = HostMetricSummaryMonthly.objects.filter(**filter_kwargs_host_metrics_summary).count() - - if (host_metric_row_count > PREFERRED_ROW_COUNT or host_metric_summary_monthly_row_count > PREFERRED_ROW_COUNT) and ( - not options.get('rows_per_file') or options.get('rows_per_file') > PREFERRED_ROW_COUNT - ): - print( - f"HostMetric / HostMetricSummaryMonthly rows exceed the allowable limit of {PREFERRED_ROW_COUNT}. " - f"Set --rows_per_file {PREFERRED_ROW_COUNT} " - f"to split the rows in chunks of {PREFERRED_ROW_COUNT}" - ) + if options['rows_per_file'] and options.get('rows_per_file') > PREFERRED_ROW_COUNT: + print(f"rows_per_file exceeds the allowable limit of {PREFERRED_ROW_COUNT}.") return # if --json flag is set, output the result in json format @@ -199,18 +171,17 @@ class Command(BaseCommand): elif options['csv']: self.output_csv(options, filter_kwargs) elif options['tarball']: - self.output_tarball(options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count) - elif options['rows_per_file']: - self.output_rows_per_file(options, filter_kwargs, host_metric_row_count, host_metric_summary_monthly_row_count) + self.output_tarball(options, filter_kwargs) # --json flag is not set, output in plain text else: - print(f"Total Number of hosts automated: {host_metric_row_count}") + print(f"Printing up to {PREFERRED_ROW_COUNT } automated hosts:") result = HostMetric.objects.filter(**filter_kwargs) - for item in result: + list_of_queryset = self.host_metric_queryset(result, 0, PREFERRED_ROW_COUNT) + for item in list_of_queryset: print( "Hostname : {hostname} | first_automation : {first_automation} | last_automation : {last_automation}".format( - hostname=item.hostname, first_automation=item.first_automation, last_automation=item.last_automation + hostname=item['hostname'], first_automation=item['first_automation'], last_automation=item['last_automation'] ) ) return From fbd5d79428751b9e30da51fbaecc5efb515350f4 Mon Sep 17 00:00:00 2001 From: Aparna Karve Date: Tue, 7 Mar 2023 13:49:24 -0800 Subject: [PATCH 052/167] Added internal batch processing for up to 10k rows For --rows_per_file if > 10k, rows would be fetched in batches of 10k --- awx/main/management/commands/host_metric.py | 106 +++++++++++++++----- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index 5b38cb5fd5..a0933b7fb9 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -9,13 +9,14 @@ import tempfile import tarfile import csv -PREFERRED_ROW_COUNT = 500000 +CSV_PREFERRED_ROW_COUNT = 500000 +BATCHED_FETCH_COUNT = 10000 class Command(BaseCommand): help = 'This is for offline licensing usage' - def host_metric_queryset(self, result, offset=0, limit=PREFERRED_ROW_COUNT): + def host_metric_queryset(self, result, offset=0, limit=BATCHED_FETCH_COUNT): list_of_queryset = list( result.values( 'id', @@ -32,7 +33,7 @@ class Command(BaseCommand): return list_of_queryset - def host_metric_summary_monthly_queryset(self, result, offset=0, limit=PREFERRED_ROW_COUNT): + def host_metric_summary_monthly_queryset(self, result, offset=0, limit=BATCHED_FETCH_COUNT): list_of_queryset = list( result.values( 'id', @@ -67,22 +68,70 @@ class Command(BaseCommand): offset += len(list_of_queryset) - def csv_for_tar(self, temp_dir, type, filter_kwargs, single_header=False, rows_per_file=PREFERRED_ROW_COUNT): + def controlled_db_retrieval(self, type, filter_kwargs, offset=0, fetch_count=BATCHED_FETCH_COUNT): + if type == 'host_metric': + result = HostMetric.objects.filter(**filter_kwargs) + return self.host_metric_queryset(result, offset, fetch_count) + elif type == 'host_metric_summary_monthly': + result = HostMetricSummaryMonthly.objects.filter(**filter_kwargs) + return self.host_metric_summary_monthly_queryset(result, offset, fetch_count) + + def write_to_csv(self, csv_file, list_of_queryset, always_header, first_write=False, mode='a'): + with open(csv_file, mode, newline='') as output_file: + try: + keys = list_of_queryset[0].keys() if list_of_queryset else [] + dict_writer = csv.DictWriter(output_file, keys) + if always_header or first_write: + dict_writer.writeheader() + dict_writer.writerows(list_of_queryset) + + except Exception as e: + print(e) + + def csv_for_tar(self, temp_dir, type, filter_kwargs, rows_per_file, always_header=True): for index, list_of_queryset in enumerate(self.paginated_db_retrieval(type, filter_kwargs, rows_per_file)): csv_file = f'{temp_dir}/{type}{index+1}.csv' arcname_file = f'{type}{index+1}.csv' - with open(csv_file, 'w', newline='') as output_file: - try: - keys = list_of_queryset[0].keys() if list_of_queryset else [] - dict_writer = csv.DictWriter(output_file, keys) - if not single_header or index == 0: - dict_writer.writeheader() - dict_writer.writerows(list_of_queryset) + first_write = True if index == 0 else False - except Exception as e: - print(e) + self.write_to_csv(csv_file, list_of_queryset, always_header, first_write, 'w') + yield csv_file, arcname_file + def csv_for_tar_batched_fetch(self, temp_dir, type, filter_kwargs, rows_per_file, always_header=True): + csv_iteration = 1 + + offset = 0 + rows_written_per_csv = 0 + to_fetch = BATCHED_FETCH_COUNT + + while True: + list_of_queryset = self.controlled_db_retrieval(type, filter_kwargs, offset, to_fetch) + + if not list_of_queryset: + break + + csv_file = f'{temp_dir}/{type}{csv_iteration}.csv' + arcname_file = f'{type}{csv_iteration}.csv' + self.write_to_csv(csv_file, list_of_queryset, always_header) + + offset += to_fetch + rows_written_per_csv += to_fetch + always_header = False + + remaining_rows_per_csv = rows_per_file - rows_written_per_csv + + if not remaining_rows_per_csv: + yield csv_file, arcname_file + + rows_written_per_csv = 0 + always_header = True + to_fetch = BATCHED_FETCH_COUNT + csv_iteration += 1 + elif remaining_rows_per_csv < BATCHED_FETCH_COUNT: + to_fetch = remaining_rows_per_csv + + if rows_written_per_csv: yield csv_file, arcname_file def config_for_tar(self, options, temp_dir): @@ -94,9 +143,8 @@ class Command(BaseCommand): return config_file, arcname_file def output_json(self, options, filter_kwargs): - rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT with tempfile.TemporaryDirectory() as temp_dir: - for csv_detail in self.csv_for_tar(temp_dir, options.get('json', 'host_metric'), filter_kwargs, False, rows_per_file): + for csv_detail in self.csv_for_tar(temp_dir, options.get('json', 'host_metric'), filter_kwargs, BATCHED_FETCH_COUNT, True): csv_file = csv_detail[0] with open(csv_file) as f: @@ -106,24 +154,28 @@ class Command(BaseCommand): print(json_result) def output_csv(self, options, filter_kwargs): - rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT with tempfile.TemporaryDirectory() as temp_dir: - for csv_detail in self.csv_for_tar(temp_dir, options.get('csv', 'host_metric'), filter_kwargs, True, rows_per_file): + for csv_detail in self.csv_for_tar(temp_dir, options.get('csv', 'host_metric'), filter_kwargs, BATCHED_FETCH_COUNT, False): csv_file = csv_detail[0] with open(csv_file) as f: sys.stdout.write(f.read()) def output_tarball(self, options, filter_kwargs): - single_header = False if options['rows_per_file'] else True - rows_per_file = options['rows_per_file'] or PREFERRED_ROW_COUNT + always_header = True + rows_per_file = options['rows_per_file'] or CSV_PREFERRED_ROW_COUNT tar = tarfile.open("./host_metrics.tar.gz", "w:gz") + if rows_per_file <= BATCHED_FETCH_COUNT: + csv_function = self.csv_for_tar + else: + csv_function = self.csv_for_tar_batched_fetch + with tempfile.TemporaryDirectory() as temp_dir: - for csv_detail in self.csv_for_tar(temp_dir, 'host_metric', filter_kwargs, single_header, rows_per_file): + for csv_detail in csv_function(temp_dir, 'host_metric', filter_kwargs, rows_per_file, always_header): tar.add(csv_detail[0], arcname=csv_detail[1]) - for csv_detail in self.csv_for_tar(temp_dir, 'host_metric_summary_monthly', filter_kwargs, single_header, rows_per_file): + for csv_detail in csv_function(temp_dir, 'host_metric_summary_monthly', filter_kwargs, rows_per_file, always_header): tar.add(csv_detail[0], arcname=csv_detail[1]) config_file, arcname_file = self.config_for_tar(options, temp_dir) @@ -136,8 +188,8 @@ class Command(BaseCommand): parser.add_argument('--until', type=datetime.datetime.fromisoformat, help='End Date in ISO format YYYY-MM-DD') parser.add_argument('--json', type=str, const='host_metric', nargs='?', help='Select output as JSON for host_metric or host_metric_summary_monthly') parser.add_argument('--csv', type=str, const='host_metric', nargs='?', help='Select output as CSV for host_metric or host_metric_summary_monthly') - parser.add_argument('--tarball', action='store_true', help=f'Package CSV files into a tar with upto {PREFERRED_ROW_COUNT} rows') - parser.add_argument('--rows_per_file', type=int, help=f'Split rows in chunks of {PREFERRED_ROW_COUNT}') + parser.add_argument('--tarball', action='store_true', help=f'Package CSV files into a tar with upto {CSV_PREFERRED_ROW_COUNT} rows') + parser.add_argument('--rows_per_file', type=int, help=f'Split rows in chunks of {CSV_PREFERRED_ROW_COUNT}') def handle(self, *args, **options): since = options.get('since') @@ -161,8 +213,8 @@ class Command(BaseCommand): if until is not None: filter_kwargs_host_metrics_summary['date__lte'] = until - if options['rows_per_file'] and options.get('rows_per_file') > PREFERRED_ROW_COUNT: - print(f"rows_per_file exceeds the allowable limit of {PREFERRED_ROW_COUNT}.") + if options['rows_per_file'] and options.get('rows_per_file') > CSV_PREFERRED_ROW_COUNT: + print(f"rows_per_file exceeds the allowable limit of {CSV_PREFERRED_ROW_COUNT}.") return # if --json flag is set, output the result in json format @@ -175,9 +227,9 @@ class Command(BaseCommand): # --json flag is not set, output in plain text else: - print(f"Printing up to {PREFERRED_ROW_COUNT } automated hosts:") + print(f"Printing up to {BATCHED_FETCH_COUNT } automated hosts:") result = HostMetric.objects.filter(**filter_kwargs) - list_of_queryset = self.host_metric_queryset(result, 0, PREFERRED_ROW_COUNT) + list_of_queryset = self.host_metric_queryset(result, 0, BATCHED_FETCH_COUNT) for item in list_of_queryset: print( "Hostname : {hostname} | first_automation : {first_automation} | last_automation : {last_automation}".format( From 382f98ceedd4f81a1692160f87358488d2a11d13 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 13 Mar 2023 22:14:56 -0400 Subject: [PATCH 053/167] Fixing migration files --- ...5_add_hostmetric_fields.py => 0180_add_hostmetric_fields.py} | 2 +- ...metricsummarymonthly.py => 0181_hostmetricsummarymonthly.py} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename awx/main/migrations/{0175_add_hostmetric_fields.py => 0180_add_hostmetric_fields.py} (96%) rename awx/main/migrations/{0176_hostmetricsummarymonthly.py => 0181_hostmetricsummarymonthly.py} (96%) diff --git a/awx/main/migrations/0175_add_hostmetric_fields.py b/awx/main/migrations/0180_add_hostmetric_fields.py similarity index 96% rename from awx/main/migrations/0175_add_hostmetric_fields.py rename to awx/main/migrations/0180_add_hostmetric_fields.py index 75090bd678..3d9048adb2 100644 --- a/awx/main/migrations/0175_add_hostmetric_fields.py +++ b/awx/main/migrations/0180_add_hostmetric_fields.py @@ -5,7 +5,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('main', '0174_ensure_org_ee_admin_roles'), + ('main', '0179_change_cyberark_plugin_names'), ] operations = [ diff --git a/awx/main/migrations/0176_hostmetricsummarymonthly.py b/awx/main/migrations/0181_hostmetricsummarymonthly.py similarity index 96% rename from awx/main/migrations/0176_hostmetricsummarymonthly.py rename to awx/main/migrations/0181_hostmetricsummarymonthly.py index fe482aa416..3dcac9c4c2 100644 --- a/awx/main/migrations/0176_hostmetricsummarymonthly.py +++ b/awx/main/migrations/0181_hostmetricsummarymonthly.py @@ -5,7 +5,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('main', '0175_add_hostmetric_fields'), + ('main', '0180_add_hostmetric_fields'), ] operations = [ From 8ec6e556a116d72c6d691848208b4422cfbbfb39 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Wed, 22 Mar 2023 11:31:12 +0100 Subject: [PATCH 054/167] HostMetricSummaryMonthly API commented out --- .../api/host_metric_summary_monthly_list.md | 12 ------------ awx/api/urls/urls.py | 5 +++-- awx/api/views/__init__.py | 19 ++++++++++--------- awx/api/views/root.py | 3 ++- awx/main/conf.py | 2 +- awx/main/management/commands/host_metric.py | 2 +- awx/main/utils/licensing.py | 4 ++-- awx/settings/defaults.py | 1 - 8 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 awx/api/templates/api/host_metric_summary_monthly_list.md diff --git a/awx/api/templates/api/host_metric_summary_monthly_list.md b/awx/api/templates/api/host_metric_summary_monthly_list.md deleted file mode 100644 index 953b1827a6..0000000000 --- a/awx/api/templates/api/host_metric_summary_monthly_list.md +++ /dev/null @@ -1,12 +0,0 @@ -# Intended Use Case - -To get summaries from a certain day or earlier, you can filter this -endpoint in the following way. - - ?date__gte=2023-01-01 - -This will return summaries that were produced on that date or later. -These host metric monthly summaries should be automatically produced -by a background task that runs once each month. - -{% include "api/list_api_view.md" %} diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index c7d73165c3..9eafb51d64 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -30,7 +30,7 @@ from awx.api.views import ( OAuth2TokenList, ApplicationOAuth2TokenList, OAuth2ApplicationDetail, - HostMetricSummaryMonthlyList, + # HostMetricSummaryMonthlyList, # It will be enabled in future version of the AWX ) from awx.api.views.bulk import ( @@ -121,7 +121,8 @@ v2_urls = [ re_path(r'^inventories/', include(inventory_urls)), re_path(r'^hosts/', include(host_urls)), re_path(r'^host_metrics/', include(host_metric_urls)), - re_path(r'^host_metric_summary_monthly/$', HostMetricSummaryMonthlyList.as_view(), name='host_metric_summary_monthly_list'), + # It will be enabled in future version of the AWX + # re_path(r'^host_metric_summary_monthly/$', HostMetricSummaryMonthlyList.as_view(), name='host_metric_summary_monthly_list'), re_path(r'^groups/', include(group_urls)), re_path(r'^inventory_sources/', include(inventory_source_urls)), re_path(r'^inventory_updates/', include(inventory_update_urls)), diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index a9f2e0ce25..c1e99a4002 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1570,15 +1570,16 @@ class HostMetricDetail(RetrieveDestroyAPIView): return Response(status=status.HTTP_204_NO_CONTENT) -class HostMetricSummaryMonthlyList(ListAPIView): - name = _("Host Metrics Summary Monthly") - model = models.HostMetricSummaryMonthly - serializer_class = serializers.HostMetricSummaryMonthlySerializer - permission_classes = (IsSystemAdminOrAuditor,) - search_fields = ('date',) - - def get_queryset(self): - return self.model.objects.all() +# It will be enabled in future version of the AWX +# class HostMetricSummaryMonthlyList(ListAPIView): +# name = _("Host Metrics Summary Monthly") +# model = models.HostMetricSummaryMonthly +# serializer_class = serializers.HostMetricSummaryMonthlySerializer +# permission_classes = (IsSystemAdminOrAuditor,) +# search_fields = ('date',) +# +# def get_queryset(self): +# return self.model.objects.all() class HostList(HostRelatedSearchMixin, ListCreateAPIView): diff --git a/awx/api/views/root.py b/awx/api/views/root.py index f343d8169d..be4d9cc44b 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -103,7 +103,8 @@ class ApiVersionRootView(APIView): data['groups'] = reverse('api:group_list', request=request) data['hosts'] = reverse('api:host_list', request=request) data['host_metrics'] = reverse('api:host_metric_list', request=request) - data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request) + # It will be enabled in future version of the AWX + # data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request) data['job_templates'] = reverse('api:job_template_list', request=request) data['jobs'] = reverse('api:job_list', request=request) data['ad_hoc_commands'] = reverse('api:ad_hoc_command_list', request=request) diff --git a/awx/main/conf.py b/awx/main/conf.py index f983b26a31..33b3b4714d 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -809,7 +809,7 @@ register( 'SUBSCRIPTION_USAGE_MODEL', field_class=fields.ChoiceField, choices=[ - ('', _('Default model for AWX - no subscription')), + ('', _('Default model for AWX - no subscription. Deletion of host_metrics will not be considered for purposes of managed host counting')), ( SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS, _('Usage based on unique managed nodes in a large historical time frame and delete functionality for no longer used managed nodes'), diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index a0933b7fb9..1d76d634b7 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -227,7 +227,7 @@ class Command(BaseCommand): # --json flag is not set, output in plain text else: - print(f"Printing up to {BATCHED_FETCH_COUNT } automated hosts:") + print(f"Printing up to {BATCHED_FETCH_COUNT} automated hosts:") result = HostMetric.objects.filter(**filter_kwargs) list_of_queryset = self.host_metric_queryset(result, 0, BATCHED_FETCH_COUNT) for item in list_of_queryset: diff --git a/awx/main/utils/licensing.py b/awx/main/utils/licensing.py index 62c0deb56a..b3ea7723e5 100644 --- a/awx/main/utils/licensing.py +++ b/awx/main/utils/licensing.py @@ -384,8 +384,8 @@ class Licenser(object): current_instances = Host.objects.active_count() license_date = int(attrs.get('license_date', 0) or 0) - model = getattr(settings, 'SUBSCRIPTION_USAGE_MODEL', '') - if model == SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS: + subscription_model = getattr(settings, 'SUBSCRIPTION_USAGE_MODEL', '') + if subscription_model == SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS: automated_instances = HostMetric.active_objects.count() first_host = HostMetric.active_objects.only('first_automation').order_by('first_automation').first() else: diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 23d61a98a0..f3b6c18eef 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -1032,5 +1032,4 @@ UI_NEXT = True # License compliance for total host count. Possible values: # - '': No model - Subscription not counted from Host Metrics # - 'unique_managed_hosts': Compliant = automated - deleted hosts (using /api/v2/host_metrics/) -# - 'unique_managed_hosts_monthly': TBD: AoC on Azure (now equal to '') SUBSCRIPTION_USAGE_MODEL = '' From c30c9cbdbecc23d98d7b98c3207a32fba45f3c08 Mon Sep 17 00:00:00 2001 From: Aparna Karve Date: Wed, 22 Mar 2023 09:00:33 -0700 Subject: [PATCH 055/167] Remove --until option --- awx/main/management/commands/host_metric.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/awx/main/management/commands/host_metric.py b/awx/main/management/commands/host_metric.py index 1d76d634b7..c0862ea1a3 100644 --- a/awx/main/management/commands/host_metric.py +++ b/awx/main/management/commands/host_metric.py @@ -185,7 +185,6 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument('--since', type=datetime.datetime.fromisoformat, help='Start Date in ISO format YYYY-MM-DD') - parser.add_argument('--until', type=datetime.datetime.fromisoformat, help='End Date in ISO format YYYY-MM-DD') parser.add_argument('--json', type=str, const='host_metric', nargs='?', help='Select output as JSON for host_metric or host_metric_summary_monthly') parser.add_argument('--csv', type=str, const='host_metric', nargs='?', help='Select output as CSV for host_metric or host_metric_summary_monthly') parser.add_argument('--tarball', action='store_true', help=f'Package CSV files into a tar with upto {CSV_PREFERRED_ROW_COUNT} rows') @@ -193,25 +192,17 @@ class Command(BaseCommand): def handle(self, *args, **options): since = options.get('since') - until = options.get('until') if since is not None and since.tzinfo is None: since = since.replace(tzinfo=datetime.timezone.utc) - if until is not None and until.tzinfo is None: - until = until.replace(tzinfo=datetime.timezone.utc) - filter_kwargs = {} if since is not None: filter_kwargs['last_automation__gte'] = since - if until is not None: - filter_kwargs['last_automation__lte'] = until filter_kwargs_host_metrics_summary = {} if since is not None: filter_kwargs_host_metrics_summary['date__gte'] = since - if until is not None: - filter_kwargs_host_metrics_summary['date__lte'] = until if options['rows_per_file'] and options.get('rows_per_file') > CSV_PREFERRED_ROW_COUNT: print(f"rows_per_file exceeds the allowable limit of {CSV_PREFERRED_ROW_COUNT}.") From 32a5186eea31c1ae51e83680c13c97a1f29e8ff5 Mon Sep 17 00:00:00 2001 From: Klaas Demter Date: Mon, 27 Mar 2023 16:30:40 +0200 Subject: [PATCH 056/167] Fixes #6556 Expose SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL (#13641) Signed-off-by: Klaas Demter --- awx/sso/conf.py | 10 ++++++++++ .../MiscAuthenticationDetail.test.js | 2 ++ .../MiscAuthenticationEdit.js | 7 ++++++- .../MiscAuthenticationEdit.test.js | 1 + .../Setting/shared/data.allSettingOptions.json | 17 +++++++++++++++++ .../Setting/shared/data.allSettings.json | 1 + 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/awx/sso/conf.py b/awx/sso/conf.py index ac9b0e76e1..ddfd80fd13 100644 --- a/awx/sso/conf.py +++ b/awx/sso/conf.py @@ -148,6 +148,16 @@ register( placeholder=['username', 'email'], ) +register( + 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL', + field_class=fields.BooleanField, + default=False, + label=_('Use Email address for usernames'), + help_text=_('Enabling this setting will tell social auth to use the full Email as username instead of the full name'), + category=_('Authentication'), + category_slug='authentication', +) + ############################################################################### # LDAP AUTHENTICATION SETTINGS ############################################################################### diff --git a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.test.js b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.test.js index dd17494386..dc08630ee5 100644 --- a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.test.js +++ b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationDetail/MiscAuthenticationDetail.test.js @@ -40,6 +40,7 @@ describe('', () => { SOCIAL_AUTH_ORGANIZATION_MAP: {}, SOCIAL_AUTH_TEAM_MAP: {}, SOCIAL_AUTH_USER_FIELDS: [], + SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL: false, }, }); await act(async () => { @@ -79,6 +80,7 @@ describe('', () => { assertVariableDetail(wrapper, 'Social Auth Organization Map', '{}'); assertVariableDetail(wrapper, 'Social Auth Team Map', '{}'); assertVariableDetail(wrapper, 'Social Auth User Fields', '[]'); + assertDetail(wrapper, 'Use Email address for usernames', 'Off'); assertDetail( wrapper, 'Allow External Users to Create OAuth2 Tokens', diff --git a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.js b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.js index f19807e842..a8b7814543 100644 --- a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.js +++ b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.js @@ -53,7 +53,8 @@ function MiscAuthenticationEdit() { 'SESSION_COOKIE_AGE', 'SOCIAL_AUTH_ORGANIZATION_MAP', 'SOCIAL_AUTH_TEAM_MAP', - 'SOCIAL_AUTH_USER_FIELDS' + 'SOCIAL_AUTH_USER_FIELDS', + 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL' ); const authenticationData = { @@ -242,6 +243,10 @@ function MiscAuthenticationEdit() { name="SOCIAL_AUTH_USER_FIELDS" config={authentication.SOCIAL_AUTH_USER_FIELDS} /> + {submitError && } {revertError && } diff --git a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.test.js b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.test.js index cf00ea5716..d84b759113 100644 --- a/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.test.js +++ b/awx/ui/src/screens/Setting/MiscAuthentication/MiscAuthenticationEdit/MiscAuthenticationEdit.test.js @@ -32,6 +32,7 @@ const authenticationData = { SOCIAL_AUTH_ORGANIZATION_MAP: null, SOCIAL_AUTH_TEAM_MAP: null, SOCIAL_AUTH_USER_FIELDS: null, + SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL: false, }; describe('', () => { diff --git a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json index 99e2743e75..c68b11474e 100644 --- a/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json +++ b/awx/ui/src/screens/Setting/shared/data.allSettingOptions.json @@ -859,6 +859,15 @@ "read_only": false } }, + "SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL": { + "type": "boolean", + "required": false, + "label": "Use Email address for usernames", + "help_text": "Enabling this setting will tell social auth to use the full Email as username instead of the full name", + "category": "Authentication", + "category_slug": "authentication", + "default": false + }, "SOCIAL_AUTH_OIDC_KEY": { "type": "string", "label": "OIDC Key", @@ -4554,6 +4563,14 @@ "type": "string" } }, + "SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL": { + "type": "boolean", + "label": "Use Email address for usernames", + "help_text": "Enabling this setting will tell social auth to use the full Email as username instead of the full name", + "category": "Authentication", + "category_slug": "authentication", + "default": false + }, "SOCIAL_AUTH_OIDC_KEY": { "type": "string", "label": "OIDC Key", diff --git a/awx/ui/src/screens/Setting/shared/data.allSettings.json b/awx/ui/src/screens/Setting/shared/data.allSettings.json index 171b2423e3..bf73ce0308 100644 --- a/awx/ui/src/screens/Setting/shared/data.allSettings.json +++ b/awx/ui/src/screens/Setting/shared/data.allSettings.json @@ -103,6 +103,7 @@ "SOCIAL_AUTH_ORGANIZATION_MAP":null, "SOCIAL_AUTH_TEAM_MAP":null, "SOCIAL_AUTH_USER_FIELDS":null, + "SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL":false, "AUTH_LDAP_SERVER_URI":"ldap://ldap.example.com", "AUTH_LDAP_BIND_DN":"cn=eng_user1", "AUTH_LDAP_BIND_PASSWORD":"$encrypted$", From db2253601da79418cbbd338749d7fa507022c043 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Mon, 27 Mar 2023 11:07:30 -0400 Subject: [PATCH 057/167] Allow TLS 1.2 for Receptor connections - Required for FIPS environment where TLS 1.3 is not supported - TLS 1.3 can still be used if the nodes both agree to use during handshake. --- awx/api/templates/instance_install_bundle/group_vars/all.yml | 1 + awx/main/tasks/receptor.py | 1 + 2 files changed, 2 insertions(+) diff --git a/awx/api/templates/instance_install_bundle/group_vars/all.yml b/awx/api/templates/instance_install_bundle/group_vars/all.yml index d0eb00f6b9..c23ed2d016 100644 --- a/awx/api/templates/instance_install_bundle/group_vars/all.yml +++ b/awx/api/templates/instance_install_bundle/group_vars/all.yml @@ -2,6 +2,7 @@ receptor_user: awx receptor_group: awx receptor_verify: true receptor_tls: true +receptor_mintls13: false receptor_work_commands: ansible-runner: command: ansible-runner diff --git a/awx/main/tasks/receptor.py b/awx/main/tasks/receptor.py index 9cb4d49efe..b1d9e0cfa8 100644 --- a/awx/main/tasks/receptor.py +++ b/awx/main/tasks/receptor.py @@ -668,6 +668,7 @@ RECEPTOR_CONFIG_STARTER = ( 'rootcas': '/etc/receptor/tls/ca/receptor-ca.crt', 'cert': '/etc/receptor/tls/receptor.crt', 'key': '/etc/receptor/tls/receptor.key', + 'mintls13': False, } }, ) From f59ced57bc9c4d15b40f6ed77105a0f67579b4bc Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Fri, 18 Nov 2022 10:48:03 -0500 Subject: [PATCH 058/167] Model and task changes for constructed inventory Add in required setting about empty groups --- awx/api/serializers.py | 14 ++-- awx/api/urls/inventory.py | 2 + awx/api/views/inventory.py | 7 ++ .../migrations/0175_constructed_inventory.py | 82 +++++++++++++++++++ awx/main/models/inventory.py | 32 ++++++++ awx/main/tasks/jobs.py | 28 +++++-- .../tests/functional/models/test_inventory.py | 3 +- awx/settings/defaults.py | 5 ++ 8 files changed, 159 insertions(+), 14 deletions(-) create mode 100644 awx/main/migrations/0175_constructed_inventory.py diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 1ff00854c2..cafd51a835 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1672,13 +1672,8 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables): res.update( dict( hosts=self.reverse('api:inventory_hosts_list', kwargs={'pk': obj.pk}), - groups=self.reverse('api:inventory_groups_list', kwargs={'pk': obj.pk}), - root_groups=self.reverse('api:inventory_root_groups_list', kwargs={'pk': obj.pk}), variable_data=self.reverse('api:inventory_variable_data', kwargs={'pk': obj.pk}), script=self.reverse('api:inventory_script_view', kwargs={'pk': obj.pk}), - tree=self.reverse('api:inventory_tree_view', kwargs={'pk': obj.pk}), - inventory_sources=self.reverse('api:inventory_inventory_sources_list', kwargs={'pk': obj.pk}), - update_inventory_sources=self.reverse('api:inventory_inventory_sources_update', kwargs={'pk': obj.pk}), activity_stream=self.reverse('api:inventory_activity_stream_list', kwargs={'pk': obj.pk}), job_templates=self.reverse('api:inventory_job_template_list', kwargs={'pk': obj.pk}), ad_hoc_commands=self.reverse('api:inventory_ad_hoc_commands_list', kwargs={'pk': obj.pk}), @@ -1689,8 +1684,17 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables): labels=self.reverse('api:inventory_label_list', kwargs={'pk': obj.pk}), ) ) + if obj.kind in ('', 'constructed'): + # links not relevant for the "old" smart inventory + res['groups'] = self.reverse('api:inventory_groups_list', kwargs={'pk': obj.pk}) + res['root_groups'] = self.reverse('api:inventory_root_groups_list', kwargs={'pk': obj.pk}) + res['update_inventory_sources'] = self.reverse('api:inventory_inventory_sources_update', kwargs={'pk': obj.pk}) + res['inventory_sources'] = self.reverse('api:inventory_inventory_sources_list', kwargs={'pk': obj.pk}) + res['tree'] = self.reverse('api:inventory_tree_view', kwargs={'pk': obj.pk}) if obj.organization: res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk}) + if obj.kind == 'constructed': + res['source_inventories'] = self.reverse('api:inventory_source_inventories', kwargs={'pk': obj.pk}) return res def to_representation(self, obj): diff --git a/awx/api/urls/inventory.py b/awx/api/urls/inventory.py index 7e2fa4ebe2..c7d3592c93 100644 --- a/awx/api/urls/inventory.py +++ b/awx/api/urls/inventory.py @@ -7,6 +7,7 @@ from awx.api.views.inventory import ( InventoryList, InventoryDetail, InventoryActivityStreamList, + InventorySourceInventoriesList, InventoryJobTemplateList, InventoryAccessList, InventoryObjectRolesList, @@ -37,6 +38,7 @@ urls = [ re_path(r'^(?P[0-9]+)/script/$', InventoryScriptView.as_view(), name='inventory_script_view'), re_path(r'^(?P[0-9]+)/tree/$', InventoryTreeView.as_view(), name='inventory_tree_view'), re_path(r'^(?P[0-9]+)/inventory_sources/$', InventoryInventorySourcesList.as_view(), name='inventory_inventory_sources_list'), + re_path(r'^(?P[0-9]+)/source_inventories/$', InventorySourceInventoriesList.as_view(), name='inventory_source_inventories'), re_path(r'^(?P[0-9]+)/update_inventory_sources/$', InventoryInventorySourcesUpdate.as_view(), name='inventory_inventory_sources_update'), re_path(r'^(?P[0-9]+)/activity_stream/$', InventoryActivityStreamList.as_view(), name='inventory_activity_stream_list'), re_path(r'^(?P[0-9]+)/job_templates/$', InventoryJobTemplateList.as_view(), name='inventory_job_template_list'), diff --git a/awx/api/views/inventory.py b/awx/api/views/inventory.py index 72b04d7d8b..032069ea1f 100644 --- a/awx/api/views/inventory.py +++ b/awx/api/views/inventory.py @@ -94,6 +94,13 @@ class InventoryDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIVie return Response(dict(error=_("{0}".format(e))), status=status.HTTP_400_BAD_REQUEST) +class InventorySourceInventoriesList(SubListAttachDetachAPIView): + model = Inventory + serializer_class = InventorySerializer + parent_model = Inventory + relationship = 'source_inventories' + + class InventoryActivityStreamList(SubListAPIView): model = ActivityStream serializer_class = ActivityStreamSerializer diff --git a/awx/main/migrations/0175_constructed_inventory.py b/awx/main/migrations/0175_constructed_inventory.py new file mode 100644 index 0000000000..1c43afc9f4 --- /dev/null +++ b/awx/main/migrations/0175_constructed_inventory.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.16 on 2022-12-07 14:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0174_ensure_org_ee_admin_roles'), + ] + + operations = [ + migrations.AddField( + model_name='inventory', + name='source_inventories', + field=models.ManyToManyField( + blank=True, + help_text='Only valid for constructed inventories, this links to the inventories that will be used.', + related_name='destination_inventories', + to='main.Inventory', + ), + ), + migrations.AlterField( + model_name='inventory', + name='kind', + field=models.CharField( + blank=True, + choices=[ + ('', 'Hosts have a direct link to this inventory.'), + ('smart', 'Hosts for inventory generated using the host_filter property.'), + ('constructed', 'Parse list of source inventories with the constructed inventory plugin.'), + ], + default='', + help_text='Kind of inventory being represented.', + max_length=32, + ), + ), + migrations.AlterField( + model_name='inventorysource', + name='source', + field=models.CharField( + choices=[ + ('file', 'File, Directory or Script'), + ('constructed', 'Template additional groups and hostvars at runtime'), + ('scm', 'Sourced from a Project'), + ('ec2', 'Amazon EC2'), + ('gce', 'Google Compute Engine'), + ('azure_rm', 'Microsoft Azure Resource Manager'), + ('vmware', 'VMware vCenter'), + ('satellite6', 'Red Hat Satellite 6'), + ('openstack', 'OpenStack'), + ('rhv', 'Red Hat Virtualization'), + ('controller', 'Red Hat Ansible Automation Platform'), + ('insights', 'Red Hat Insights'), + ], + default=None, + max_length=32, + ), + ), + migrations.AlterField( + model_name='inventoryupdate', + name='source', + field=models.CharField( + choices=[ + ('file', 'File, Directory or Script'), + ('constructed', 'Template additional groups and hostvars at runtime'), + ('scm', 'Sourced from a Project'), + ('ec2', 'Amazon EC2'), + ('gce', 'Google Compute Engine'), + ('azure_rm', 'Microsoft Azure Resource Manager'), + ('vmware', 'VMware vCenter'), + ('satellite6', 'Red Hat Satellite 6'), + ('openstack', 'OpenStack'), + ('rhv', 'Red Hat Virtualization'), + ('controller', 'Red Hat Ansible Automation Platform'), + ('insights', 'Red Hat Insights'), + ], + default=None, + max_length=32, + ), + ), + ] diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 829017ee1d..3f33420686 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -67,6 +67,7 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): KIND_CHOICES = [ ('', _('Hosts have a direct link to this inventory.')), ('smart', _('Hosts for inventory generated using the host_filter property.')), + ('constructed', _('Parse list of source inventories with the constructed inventory plugin.')), ] class Meta: @@ -139,6 +140,12 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): default=None, help_text=_('Filter that will be applied to the hosts of this inventory.'), ) + source_inventories = models.ManyToManyField( + 'Inventory', + blank=True, + related_name='destination_inventories', + help_text=_('Only valid for constructed inventories, this links to the inventories that will be used.'), + ) instance_groups = OrderedManyToManyField( 'InstanceGroup', blank=True, @@ -431,12 +438,22 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): connection.on_commit(on_commit) + def _enforce_constructed_source(self): + """ + Constructed inventory should always have exactly 1 inventory source, constructed type + this enforces that requirement + """ + if self.kind == 'constructed': + if not self.inventory_sources.exists(): + self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True) + def save(self, *args, **kwargs): self._update_host_smart_inventory_memeberships() super(Inventory, self).save(*args, **kwargs) if self.kind == 'smart' and 'host_filter' in kwargs.get('update_fields', ['host_filter']) and connection.vendor != 'sqlite': # Minimal update of host_count for smart inventory host filter changes self.update_computed_fields() + self._enforce_constructed_source() def delete(self, *args, **kwargs): self._update_host_smart_inventory_memeberships() @@ -872,6 +889,7 @@ class InventorySourceOptions(BaseModel): SOURCE_CHOICES = [ ('file', _('File, Directory or Script')), + ('constructed', _('Template additional groups and hostvars at runtime')), ('scm', _('Sourced from a Project')), ('ec2', _('Amazon EC2')), ('gce', _('Google Compute Engine')), @@ -1407,6 +1425,8 @@ class PluginFileInjector(object): env.update(injector_env) # Preserves current behavior for Ansible change in default planned for 2.10 env['ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS'] = 'never' + # All CLOUD_PROVIDERS sources implement as inventory plugin from collection + env['ANSIBLE_INVENTORY_ENABLED'] = 'auto' return env def _get_shared_env(self, inventory_update, private_data_dir, private_data_files): @@ -1590,5 +1610,17 @@ class insights(PluginFileInjector): use_fqcn = True +class constructed(PluginFileInjector): + plugin_name = 'constructed' + namespace = 'ansible' + collection = 'builtin' + + def build_env(self, *args, **kwargs): + env = super().build_env(*args, **kwargs) + # Enable all types of inventory plugins so we pick up the script files from source inventories + del env['ANSIBLE_INVENTORY_ENABLED'] + return env + + for cls in PluginFileInjector.__subclasses__(): InventorySourceOptions.injectors[cls.__name__] = cls diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index 9da4bc074b..f11d676989 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -315,17 +315,22 @@ class BaseTask(object): return env + def write_inventory_file(self, inventory, private_data_dir, file_name, script_params): + script_data = inventory.get_script_data(**script_params) + for hostname, hv in script_data.get('_meta', {}).get('hostvars', {}).items(): + # maintain a list of host_name --> host_id + # so we can associate emitted events to Host objects + self.runner_callback.host_map[hostname] = hv.pop('remote_tower_id', '') + file_content = '#! /usr/bin/env python3\n# -*- coding: utf-8 -*-\nprint(%r)\n' % json.dumps(script_data) + return self.write_private_data_file(private_data_dir, file_name, file_content, sub_dir='inventory', file_permissions=0o700) + def build_inventory(self, instance, private_data_dir): script_params = dict(hostvars=True, towervars=True) if hasattr(instance, 'job_slice_number'): script_params['slice_number'] = instance.job_slice_number script_params['slice_count'] = instance.job_slice_count - script_data = instance.inventory.get_script_data(**script_params) - # maintain a list of host_name --> host_id - # so we can associate emitted events to Host objects - self.runner_callback.host_map = {hostname: hv.pop('remote_tower_id', '') for hostname, hv in script_data.get('_meta', {}).get('hostvars', {}).items()} - file_content = '#! /usr/bin/env python3\n# -*- coding: utf-8 -*-\nprint(%r)\n' % json.dumps(script_data) - return self.write_private_data_file(private_data_dir, 'hosts', file_content, sub_dir='inventory', file_permissions=0o700) + + return self.write_inventory_file(instance.inventory, private_data_dir, 'hosts', script_params) def build_args(self, instance, private_data_dir, passwords): raise NotImplementedError @@ -1469,8 +1474,6 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): if injector is not None: env = injector.build_env(inventory_update, env, private_data_dir, private_data_files) - # All CLOUD_PROVIDERS sources implement as inventory plugin from collection - env['ANSIBLE_INVENTORY_ENABLED'] = 'auto' if inventory_update.source == 'scm': for env_k in inventory_update.source_vars_dict: @@ -1523,6 +1526,15 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): args = ['ansible-inventory', '--list', '--export'] + # special case for constructed inventories, we pass source inventories from database + # these must come in order, and in order _before_ the constructed inventory itself + if inventory_update.inventory.kind == 'constructed': + for source_inventory in inventory_update.inventory.source_inventories.all(): + args.append('-i') + script_params = dict(hostvars=True, towervars=True) + source_inv_path = self.write_inventory_file(source_inventory, private_data_dir, f'hosts_{source_inventory.id}', script_params) + args.append(to_container_path(source_inv_path, private_data_dir)) + # Add arguments for the source inventory file/script/thing rel_path = self.pseudo_build_inventory(inventory_update, private_data_dir) container_location = os.path.join(CONTAINER_ROOT, rel_path) diff --git a/awx/main/tests/functional/models/test_inventory.py b/awx/main/tests/functional/models/test_inventory.py index a1db473d3e..70b4425a06 100644 --- a/awx/main/tests/functional/models/test_inventory.py +++ b/awx/main/tests/functional/models/test_inventory.py @@ -169,7 +169,8 @@ class TestInventorySourceInjectors: CLOUD_PROVIDERS constant contains the same names as what are defined within the injectors """ - assert set(CLOUD_PROVIDERS) == set(InventorySource.injectors.keys()) + # slight exception case for constructed, because it has a FQCN but is not a cloud source + assert set(CLOUD_PROVIDERS) | set(['constructed']) == set(InventorySource.injectors.keys()) @pytest.mark.parametrize('source,filename', [('ec2', 'aws_ec2.yml'), ('openstack', 'openstack.yml'), ('gce', 'gcp_compute.yml')]) def test_plugin_filenames(self, source, filename): diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index f3b6c18eef..e8d1963b40 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -760,6 +760,11 @@ CUSTOM_EXCLUDE_EMPTY_GROUPS = False SCM_EXCLUDE_EMPTY_GROUPS = False # SCM_INSTANCE_ID_VAR = +# ---------------- +# -- Constructed -- +# ---------------- +CONSTRUCTED_EXCLUDE_EMPTY_GROUPS = False + # --------------------- # -- Activity Stream -- # --------------------- From e3d39a2728936188491de88479f9665a98c60191 Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Thu, 19 Jan 2023 12:40:14 -0500 Subject: [PATCH 059/167] push limit to inventory sources move limit field from InventorySourceSerializer to InventorySourceOptionsSerializer (#13464) InventorySourceOptionsSerializer is the parent for both InventorySourceSerializer and InventoryUpdateSerializer The limit option need to be exposed to both inventory_source and inventory_update Co-Authored-By: Hao Liu <44379968+TheRealHaoLiu@users.noreply.github.com> --- awx/api/serializers.py | 1 + awx/main/migrations/0175_constructed_inventory.py | 10 ++++++++++ awx/main/models/inventory.py | 7 ++++++- awx/main/tasks/jobs.py | 5 +++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index cafd51a835..f927347f63 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2144,6 +2144,7 @@ class InventorySourceOptionsSerializer(BaseSerializer): 'custom_virtualenv', 'timeout', 'verbosity', + 'limit', ) read_only_fields = ('*', 'custom_virtualenv') diff --git a/awx/main/migrations/0175_constructed_inventory.py b/awx/main/migrations/0175_constructed_inventory.py index 1c43afc9f4..4e3309c5df 100644 --- a/awx/main/migrations/0175_constructed_inventory.py +++ b/awx/main/migrations/0175_constructed_inventory.py @@ -79,4 +79,14 @@ class Migration(migrations.Migration): max_length=32, ), ), + migrations.AddField( + model_name='inventorysource', + name='limit', + field=models.TextField(blank=True, default='', help_text='Enter host, group or pattern match'), + ), + migrations.AddField( + model_name='inventoryupdate', + name='limit', + field=models.TextField(blank=True, default='', help_text='Enter host, group or pattern match'), + ), ] diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 3f33420686..445f76a5cf 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -969,7 +969,7 @@ class InventorySourceOptions(BaseModel): host_filter = models.TextField( blank=True, default='', - help_text=_('Regex where only matching hosts will be imported.'), + help_text=_('This field is deprecated and will be removed in a future release. Regex where only matching hosts will be imported.'), ) overwrite = models.BooleanField( default=False, @@ -989,6 +989,11 @@ class InventorySourceOptions(BaseModel): blank=True, default=1, ) + limit = models.TextField( + blank=True, + default='', + help_text=_("Enter host, group or pattern match"), + ) @staticmethod def cloud_credential_validation(source, cred): diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index f11d676989..8a68a000d4 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -1542,6 +1542,11 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): args.append('-i') args.append(container_location) + # Added this in order to allow older versions of ansible-inventory https://github.com/ansible/ansible/pull/79596 + # limit should be usable in ansible-inventory 2.15+ + if inventory_update.limit: + args.append('--limit') + args.append(inventory_update.limit) args.append('--output') args.append(os.path.join(CONTAINER_ROOT, 'artifacts', str(inventory_update.id), 'output.json')) From aad260bb412978d5bfcec588caaeae63aa1325c6 Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Thu, 19 Jan 2023 13:01:45 -0500 Subject: [PATCH 060/167] edit new migration for deprecation of host_filter --- ...ntory.py => 0182_constructed_inventory.py} | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) rename awx/main/migrations/{0175_constructed_inventory.py => 0182_constructed_inventory.py} (82%) diff --git a/awx/main/migrations/0175_constructed_inventory.py b/awx/main/migrations/0182_constructed_inventory.py similarity index 82% rename from awx/main/migrations/0175_constructed_inventory.py rename to awx/main/migrations/0182_constructed_inventory.py index 4e3309c5df..3c37fc66e4 100644 --- a/awx/main/migrations/0175_constructed_inventory.py +++ b/awx/main/migrations/0182_constructed_inventory.py @@ -6,7 +6,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('main', '0174_ensure_org_ee_admin_roles'), + ('main', '0181_hostmetricsummarymonthly'), ] operations = [ @@ -89,4 +89,22 @@ class Migration(migrations.Migration): name='limit', field=models.TextField(blank=True, default='', help_text='Enter host, group or pattern match'), ), + migrations.AlterField( + model_name='inventorysource', + name='host_filter', + field=models.TextField( + blank=True, + default='', + help_text='This field is deprecated and will be removed in a future release. Regex where only matching hosts will be imported.', + ), + ), + migrations.AlterField( + model_name='inventoryupdate', + name='host_filter', + field=models.TextField( + blank=True, + default='', + help_text='This field is deprecated and will be removed in a future release. Regex where only matching hosts will be imported.', + ), + ), ] From 57e005b7753de1c5c66a1c71ce69dfaa868b78ac Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Fri, 20 Jan 2023 09:21:59 -0500 Subject: [PATCH 061/167] Start on new constructed inventory API view Make the GET function work at most basic level Basic functionality of updating working Add functional test for the GET and PATCH views Add constructed inventory list view for direct creation Add limit field to constructed inventory serializer --- awx/api/serializers.py | 76 +++++++++++++++++++ awx/api/urls/inventory.py | 10 ++- awx/api/urls/urls.py | 3 +- awx/api/views/inventory.py | 17 ++++- awx/api/views/root.py | 1 + .../migrations/0182_constructed_inventory.py | 1 - awx/main/tasks/jobs.py | 2 +- .../tests/functional/api/test_inventory.py | 42 ++++++++++ awx/settings/defaults.py | 2 + 9 files changed, 149 insertions(+), 5 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index f927347f63..3406dca77a 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1695,6 +1695,7 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables): res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk}) if obj.kind == 'constructed': res['source_inventories'] = self.reverse('api:inventory_source_inventories', kwargs={'pk': obj.pk}) + res['url'] = self.reverse('api:constructed_inventory_detail', kwargs={'pk': obj.pk}) return res def to_representation(self, obj): @@ -1736,6 +1737,81 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables): return super(InventorySerializer, self).validate(attrs) +class ConstructedFieldMixin(serializers.Field): + def get_attribute(self, instance): + if not hasattr(instance, '_constructed_inv_src'): + instance._constructed_inv_src = instance.inventory_sources.first() + inv_src = instance._constructed_inv_src + return super().get_attribute(inv_src) # yoink + + +class ConstructedCharField(ConstructedFieldMixin, serializers.CharField): + pass + + +class ConstructedIntegerField(ConstructedFieldMixin, serializers.IntegerField): + pass + + +class ConstructedInventorySerializer(InventorySerializer): + source_vars = ConstructedCharField( + required=False, + default=None, + allow_blank=True, + help_text=_('The source_vars for the related auto-created inventory source, special to constructed inventory.'), + ) + update_cache_timeout = ConstructedIntegerField( + required=False, + allow_null=True, + min_value=0, + default=None, + help_text=_('The cache timeout for the related auto-created inventory source, special to constructed inventory'), + ) + limit = ConstructedCharField( + required=False, + default=None, + allow_blank=True, + help_text=_('The limit to restrict the returned hosts for the related auto-created inventory source, special to constructed inventory.'), + ) + + class Meta: + model = Inventory + fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit') + + def pop_inv_src_data(self, data): + inv_src_data = {} + for field in ('source_vars', 'update_cache_timeout', 'limit'): + if field in data: + # values always need to be removed, as they are not valid for Inventory model + value = data.pop(field) + # null is not valid for any of those fields, taken as not-provided + if value is not None: + inv_src_data[field] = value + return inv_src_data + + def apply_inv_src_data(self, inventory, inv_src_data): + if inv_src_data: + update_fields = [] + inv_src = inventory.inventory_sources.first() + for field, value in inv_src_data.items(): + setattr(inv_src, field, value) + update_fields.append(field) + if update_fields: + inv_src.save(update_fields=update_fields) + + def create(self, validated_data): + inv_src_data = self.pop_inv_src_data(validated_data) + inventory = super().create(validated_data) + self.apply_inv_src_data(inventory, inv_src_data) + return inventory + + def update(self, obj, validated_data): + inv_src_data = self.pop_inv_src_data(validated_data) + obj = super().update(obj, validated_data) + self.apply_inv_src_data(obj, inv_src_data) + return obj + + class InventoryScriptSerializer(InventorySerializer): class Meta: fields = () diff --git a/awx/api/urls/inventory.py b/awx/api/urls/inventory.py index c7d3592c93..3be18d5249 100644 --- a/awx/api/urls/inventory.py +++ b/awx/api/urls/inventory.py @@ -6,6 +6,8 @@ from django.urls import re_path from awx.api.views.inventory import ( InventoryList, InventoryDetail, + ConstructedInventoryDetail, + ConstructedInventoryList, InventoryActivityStreamList, InventorySourceInventoriesList, InventoryJobTemplateList, @@ -50,4 +52,10 @@ urls = [ re_path(r'^(?P[0-9]+)/copy/$', InventoryCopy.as_view(), name='inventory_copy'), ] -__all__ = ['urls'] +# Constructed inventory special views +constructed_inventory_urls = [ + re_path(r'^$', ConstructedInventoryList.as_view(), name='constructed_inventory_list'), + re_path(r'^(?P[0-9]+)/$', ConstructedInventoryDetail.as_view(), name='constructed_inventory_detail'), +] + +__all__ = ['urls', 'constructed_inventory_urls'] diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index 9eafb51d64..bb27710dcc 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -47,7 +47,7 @@ from .organization import urls as organization_urls from .user import urls as user_urls from .project import urls as project_urls from .project_update import urls as project_update_urls -from .inventory import urls as inventory_urls +from .inventory import urls as inventory_urls, constructed_inventory_urls from .execution_environments import urls as execution_environment_urls from .team import urls as team_urls from .host import urls as host_urls @@ -119,6 +119,7 @@ v2_urls = [ re_path(r'^project_updates/', include(project_update_urls)), re_path(r'^teams/', include(team_urls)), re_path(r'^inventories/', include(inventory_urls)), + re_path(r'^constructed_inventories/', include(constructed_inventory_urls)), re_path(r'^hosts/', include(host_urls)), re_path(r'^host_metrics/', include(host_metric_urls)), # It will be enabled in future version of the AWX diff --git a/awx/api/views/inventory.py b/awx/api/views/inventory.py index 032069ea1f..f18bc29fe2 100644 --- a/awx/api/views/inventory.py +++ b/awx/api/views/inventory.py @@ -31,6 +31,7 @@ from awx.api.views.labels import LabelSubListCreateAttachDetachView from awx.api.serializers import ( InventorySerializer, + ConstructedInventorySerializer, ActivityStreamSerializer, RoleSerializer, InstanceGroupSerializer, @@ -79,7 +80,9 @@ class InventoryDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIVie # Do not allow changes to an Inventory kind. if kind is not None and obj.kind != kind: - return Response(dict(error=_('You cannot turn a regular inventory into a "smart" inventory.')), status=status.HTTP_405_METHOD_NOT_ALLOWED) + return Response( + dict(error=_('You cannot turn a regular inventory into a "smart" or "constructed" inventory.')), status=status.HTTP_405_METHOD_NOT_ALLOWED + ) return super(InventoryDetail, self).update(request, *args, **kwargs) def destroy(self, request, *args, **kwargs): @@ -94,6 +97,18 @@ class InventoryDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIVie return Response(dict(error=_("{0}".format(e))), status=status.HTTP_400_BAD_REQUEST) +class ConstructedInventoryDetail(InventoryDetail): + serializer_class = ConstructedInventorySerializer + + +class ConstructedInventoryList(InventoryList): + serializer_class = ConstructedInventorySerializer + + def get_queryset(self): + r = super().get_queryset() + return r.filter(kind='constructed') + + class InventorySourceInventoriesList(SubListAttachDetachAPIView): model = Inventory serializer_class = InventorySerializer diff --git a/awx/api/views/root.py b/awx/api/views/root.py index be4d9cc44b..7f33fac4af 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -98,6 +98,7 @@ class ApiVersionRootView(APIView): data['tokens'] = reverse('api:o_auth2_token_list', request=request) data['metrics'] = reverse('api:metrics_view', request=request) data['inventory'] = reverse('api:inventory_list', request=request) + data['constructed_inventory'] = reverse('api:constructed_inventory_list', request=request) data['inventory_sources'] = reverse('api:inventory_source_list', request=request) data['inventory_updates'] = reverse('api:inventory_update_list', request=request) data['groups'] = reverse('api:group_list', request=request) diff --git a/awx/main/migrations/0182_constructed_inventory.py b/awx/main/migrations/0182_constructed_inventory.py index 3c37fc66e4..ff268d376f 100644 --- a/awx/main/migrations/0182_constructed_inventory.py +++ b/awx/main/migrations/0182_constructed_inventory.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('main', '0181_hostmetricsummarymonthly'), ] diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index 8a68a000d4..5b874e14d0 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -320,7 +320,7 @@ class BaseTask(object): for hostname, hv in script_data.get('_meta', {}).get('hostvars', {}).items(): # maintain a list of host_name --> host_id # so we can associate emitted events to Host objects - self.runner_callback.host_map[hostname] = hv.pop('remote_tower_id', '') + self.runner_callback.host_map[hostname] = hv.get('remote_tower_id', '') file_content = '#! /usr/bin/env python3\n# -*- coding: utf-8 -*-\nprint(%r)\n' % json.dumps(script_data) return self.write_private_data_file(private_data_dir, file_name, file_content, sub_dir='inventory', file_permissions=0o700) diff --git a/awx/main/tests/functional/api/test_inventory.py b/awx/main/tests/functional/api/test_inventory.py index 80357a22f9..c8139a340a 100644 --- a/awx/main/tests/functional/api/test_inventory.py +++ b/awx/main/tests/functional/api/test_inventory.py @@ -594,3 +594,45 @@ class TestControlledBySCM: rando, expect=403, ) + + +@pytest.mark.django_db +class TestConstructedInventory: + @pytest.fixture + def constructed_inventory(self, organization): + return Inventory.objects.create(name='constructed-test-inventory', kind='constructed', organization=organization) + + def test_get_constructed_inventory(self, constructed_inventory, admin_user, get): + inv_src = constructed_inventory.inventory_sources.first() + inv_src.update_cache_timeout = 53 + inv_src.save(update_fields=['update_cache_timeout']) + r = get(url=reverse('api:constructed_inventory_detail', kwargs={'pk': constructed_inventory.pk}), user=admin_user, expect=200) + assert r.data['update_cache_timeout'] == 53 + + def test_patch_constructed_inventory(self, constructed_inventory, admin_user, patch): + inv_src = constructed_inventory.inventory_sources.first() + assert inv_src.update_cache_timeout == 0 + assert inv_src.limit == '' + r = patch( + url=reverse('api:constructed_inventory_detail', kwargs={'pk': constructed_inventory.pk}), + data=dict(update_cache_timeout=54, limit='foobar'), + user=admin_user, + expect=200, + ) + assert r.data['update_cache_timeout'] == 54 + inv_src = constructed_inventory.inventory_sources.first() + assert inv_src.update_cache_timeout == 54 + assert inv_src.limit == 'foobar' + + def test_create_constructed_inventory(self, constructed_inventory, admin_user, post, organization): + r = post( + url=reverse('api:constructed_inventory_list'), + data=dict(name='constructed-inventory-just-created', kind='constructed', organization=organization.id, update_cache_timeout=55, limit='foobar'), + user=admin_user, + expect=201, + ) + pk = r.data['id'] + constructed_inventory = Inventory.objects.get(pk=pk) + inv_src = constructed_inventory.inventory_sources.first() + assert inv_src.update_cache_timeout == 55 + assert inv_src.limit == 'foobar' diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index e8d1963b40..e7720e150b 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -763,6 +763,8 @@ SCM_EXCLUDE_EMPTY_GROUPS = False # ---------------- # -- Constructed -- # ---------------- +CONSTRUCTED_INSTANCE_ID_VAR = 'remote_tower_id' + CONSTRUCTED_EXCLUDE_EMPTY_GROUPS = False # --------------------- From 510f54b90491337f4bb80cd00825d4ecd46a59fb Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Mon, 23 Jan 2023 13:28:03 -0500 Subject: [PATCH 062/167] adding limit to inventory_source collection module --- awx_collection/plugins/modules/inventory_source.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/awx_collection/plugins/modules/inventory_source.py b/awx_collection/plugins/modules/inventory_source.py index 1e6939df3f..04ee423a3b 100644 --- a/awx_collection/plugins/modules/inventory_source.py +++ b/awx_collection/plugins/modules/inventory_source.py @@ -64,6 +64,10 @@ options: description: - If specified, AWX will only import hosts that match this regular expression. type: str + limit: + description: + - Enter host, group or pattern match + type: str credential: description: - Credential to use for the source. @@ -172,6 +176,7 @@ def main(): enabled_var=dict(), enabled_value=dict(), host_filter=dict(), + limit=dict(), credential=dict(), execution_environment=dict(), custom_virtualenv=dict(), @@ -279,6 +284,7 @@ def main(): 'enabled_value', 'host_filter', 'scm_branch', + 'limit', ) # Layer in all remaining optional information From c2fe06dd95d5bc4a52c47aaf44b3192b5956b1d2 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Fri, 27 Jan 2023 13:06:55 -0500 Subject: [PATCH 063/167] [constructed-inventory] Use control plane EE for constructed inventory and hack temporary image (#13474) * Use control plane EE for constructed inventory and hack temporary image * Update page registry to work with new endpoints --- awx/main/models/inventory.py | 12 +++++++++++- awxkit/awxkit/api/pages/inventory.py | 13 +++++++++++-- awxkit/awxkit/api/resources.py | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 445f76a5cf..488bf90059 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -49,7 +49,7 @@ from awx.main.models.notifications import ( from awx.main.models.credential.injectors import _openstack_data from awx.main.utils import _inventory_updates from awx.main.utils.safe_yaml import sanitize_jinja -from awx.main.utils.execution_environments import to_container_path +from awx.main.utils.execution_environments import to_container_path, get_control_plane_execution_environment from awx.main.utils.licensing import server_product_name @@ -995,6 +995,16 @@ class InventorySourceOptions(BaseModel): help_text=_("Enter host, group or pattern match"), ) + def resolve_execution_environment(self): + """ + Project updates, themselves, will use the control plane execution environment. + Jobs using the project can use the default_environment, but the project updates + are not flexible enough to allow customizing the image they use. + """ + if self.inventory.kind == 'constructed': + return get_control_plane_execution_environment() + return super().resolve_execution_environment() + @staticmethod def cloud_credential_validation(source, cred): if not source: diff --git a/awxkit/awxkit/api/pages/inventory.py b/awxkit/awxkit/api/pages/inventory.py index eeace96bd6..f75e7f4170 100644 --- a/awxkit/awxkit/api/pages/inventory.py +++ b/awxkit/awxkit/api/pages/inventory.py @@ -125,14 +125,23 @@ class Inventory(HasCopy, HasCreate, HasInstanceGroups, HasVariables, base.Base): return inv_updates -page.register_page([resources.inventory, (resources.inventories, 'post'), (resources.inventory_copy, 'post')], Inventory) +page.register_page( + [ + resources.inventory, + resources.constructed_inventory, + (resources.inventories, 'post'), + (resources.inventory_copy, 'post'), + (resources.constructed_inventories, 'post'), + ], + Inventory, +) class Inventories(page.PageList, Inventory): pass -page.register_page([resources.inventories, resources.related_inventories], Inventories) +page.register_page([resources.inventories, resources.related_inventories, resources.constructed_inventories], Inventories) class Group(HasCreate, HasVariables, base.Base): diff --git a/awxkit/awxkit/api/resources.py b/awxkit/awxkit/api/resources.py index 448a0bb582..813f4104ee 100644 --- a/awxkit/awxkit/api/resources.py +++ b/awxkit/awxkit/api/resources.py @@ -59,7 +59,9 @@ class Resources(object): _instance_related_jobs = r'instances/\d+/jobs/' _instances = 'instances/' _inventories = 'inventories/' + _constructed_inventories = 'constructed_inventories/' _inventory = r'inventories/\d+/' + _constructed_inventory = r'constructed_inventories/\d+/' _inventory_access_list = r'inventories/\d+/access_list/' _inventory_copy = r'inventories/\d+/copy/' _inventory_labels = r'inventories/\d+/labels/' From 3e5467b472dbb8b6678986bfb37d0e741baa55e6 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Mon, 30 Jan 2023 15:12:40 -0500 Subject: [PATCH 064/167] [constructed-inventory] Add constructed inventory docs and do minor field updates (#13487) * Add constructed inventory docs and do minor field updates Add verbosity field to the constructed views automatically set update_on_launch for the auto-created constructed inventory source --- awx/api/serializers.py | 12 ++- awx/main/models/inventory.py | 2 +- .../inventory_refresh.md | 0 docs/inventory/constructed_inventory.md | 86 +++++++++++++++++++ 4 files changed, 97 insertions(+), 3 deletions(-) rename docs/{inventory => deprecated}/inventory_refresh.md (100%) create mode 100644 docs/inventory/constructed_inventory.md diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 3406dca77a..561f99e20d 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1773,14 +1773,22 @@ class ConstructedInventorySerializer(InventorySerializer): allow_blank=True, help_text=_('The limit to restrict the returned hosts for the related auto-created inventory source, special to constructed inventory.'), ) + verbosity = ConstructedIntegerField( + required=False, + allow_null=True, + min_value=0, + max_value=2, + default=None, + help_text=_('The verbosity level for the related auto-created inventory source, special to constructed inventory'), + ) class Meta: model = Inventory - fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit') + fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit', 'verbosity') def pop_inv_src_data(self, data): inv_src_data = {} - for field in ('source_vars', 'update_cache_timeout', 'limit'): + for field in ('source_vars', 'update_cache_timeout', 'limit', 'verbosity'): if field in data: # values always need to be removed, as they are not valid for Inventory model value = data.pop(field) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 488bf90059..461c467081 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -445,7 +445,7 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): """ if self.kind == 'constructed': if not self.inventory_sources.exists(): - self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True) + self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True, update_on_launch=True) def save(self, *args, **kwargs): self._update_host_smart_inventory_memeberships() diff --git a/docs/inventory/inventory_refresh.md b/docs/deprecated/inventory_refresh.md similarity index 100% rename from docs/inventory/inventory_refresh.md rename to docs/deprecated/inventory_refresh.md diff --git a/docs/inventory/constructed_inventory.md b/docs/inventory/constructed_inventory.md new file mode 100644 index 0000000000..8516723fe3 --- /dev/null +++ b/docs/inventory/constructed_inventory.md @@ -0,0 +1,86 @@ +### Constructed inventory in AWX + +Constructed inventory is a separate "kind" of inventory, along-side of +normal (manual) inventories and "smart" inventories. +The functionality overlaps with smart inventory, and it is intended that +smart inventory is sunsetted and will be eventually removed. + +#### Demo Problem + +This is branched from original demo at: + +https://github.com/AlanCoding/Ansible-inventory-file-examples/tree/master/issues/AWX371 + +Consider that we have 2 original "source" inventories named "East" and "West". + +``` +# East inventory original contents +host1 account_alias=product_dev +host2 account_alias=product_dev state=shutdown +host3 account_alias=sustaining +``` + +``` +# West inventory original contents +host4 account_alias=product_dev +host6 account_alias=product_dev state=shutdown +host5 account_alias=sustaining state=shutdown +``` + +The user's intent is to operate on _shutdown_ hosts in the _product_dev_ group. +So these are two AND conditions that we want to filter on. + +To accomplish this, the user will create a constructed inventory with +the following properties. + +`source_vars` = + +```yaml +plugin: constructed +strict: true +use_vars_plugins: true # https://github.com/ansible/ansible/issues/75365 +groups: + shutdown: resolved_state == "shutdown" + shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" +compose: + resolved_state: state | default("running") +``` + +`limit` = "shutdown_in_product_dev" + +Then when running a job template against the constructed inventory, it should +act on host2 and host6, because those are the two hosts that fit the criteria. + +#### Mechanic + +The constructed inventory contents will be materialized by an inventory update +which runs via `ansible-inventory`. +This is always configured to update-on-launch before a job, +but the user can still select a cache timeout value in case this takes too long. + +When creating a constructed inventory, the API enforces that it always has 1 +inventory source associated with it. +All inventory updates have an associated inventory source, and the fields +needed for constructed inventory (`source_vars` and `limit`) are fields +on the inventory source model normally. + +#### Capabilities + +In addition to filtering on hostvars, users will be able to filter based on +facts, which are prepared before the update in the same way as for jobs. + +For filtering on related objects in the database, users will need to use "meta" +vars that are automatically prepared by the server. +These have names such as: + - `awx_inventory_name` + - `awx_inventory_id` + +#### Best Practices + +It is very important to set the `strict` parameter to `True` so that users +can debug problems with their templates, because these can get complicated. +If the template fails to render, users will get an error in the +associated inventory update for that constructed inventory. + +When encountering errors, it may be prudent to increase `verbosity` to get +more details. From aa06940df5e1b8d9f2242789c539d1af8f6cebc0 Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Wed, 1 Feb 2023 14:22:00 -0500 Subject: [PATCH 065/167] force kind to readonly field and set kind to constructed in create --- awx/api/serializers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 561f99e20d..cceb0758bd 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1785,6 +1785,7 @@ class ConstructedInventorySerializer(InventorySerializer): class Meta: model = Inventory fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit', 'verbosity') + read_only_fields = ('*', 'kind') def pop_inv_src_data(self, data): inv_src_data = {} @@ -1808,6 +1809,7 @@ class ConstructedInventorySerializer(InventorySerializer): inv_src.save(update_fields=update_fields) def create(self, validated_data): + validated_data['kind'] = 'constructed' inv_src_data = self.pop_inv_src_data(validated_data) inventory = super().create(validated_data) self.apply_inv_src_data(inventory, inv_src_data) From df6bb5a8b8b9dedeb2723bc05b3c5a7c72a6bf0d Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Thu, 2 Feb 2023 21:51:37 -0500 Subject: [PATCH 066/167] Refactor original hosts, add related field Also rename source_inventories to input_inventories --- awx/api/serializers.py | 6 ++++-- awx/api/urls/inventory.py | 4 ++-- awx/api/views/inventory.py | 4 ++-- awx/main/migrations/0182_constructed_inventory.py | 2 +- awx/main/models/inventory.py | 2 +- awx/main/tasks/jobs.py | 4 ++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index cceb0758bd..c898bf754f 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1694,8 +1694,8 @@ class InventorySerializer(LabelsListMixin, BaseSerializerWithVariables): if obj.organization: res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization.pk}) if obj.kind == 'constructed': - res['source_inventories'] = self.reverse('api:inventory_source_inventories', kwargs={'pk': obj.pk}) - res['url'] = self.reverse('api:constructed_inventory_detail', kwargs={'pk': obj.pk}) + res['input_inventories'] = self.reverse('api:inventory_input_inventories', kwargs={'pk': obj.pk}) + res['constructed_url'] = self.reverse('api:constructed_inventory_detail', kwargs={'pk': obj.pk}) return res def to_representation(self, obj): @@ -1875,6 +1875,8 @@ class HostSerializer(BaseSerializerWithVariables): ansible_facts=self.reverse('api:host_ansible_facts_detail', kwargs={'pk': obj.pk}), ) ) + if obj.inventory.kind == 'constructed': + res['original_host'] = self.reverse('api:host_detail', kwargs={'pk': obj.instance_id}) if obj.inventory: res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk}) if obj.last_job: diff --git a/awx/api/urls/inventory.py b/awx/api/urls/inventory.py index 3be18d5249..b83b9b7208 100644 --- a/awx/api/urls/inventory.py +++ b/awx/api/urls/inventory.py @@ -9,7 +9,7 @@ from awx.api.views.inventory import ( ConstructedInventoryDetail, ConstructedInventoryList, InventoryActivityStreamList, - InventorySourceInventoriesList, + InventoryInputInventoriesList, InventoryJobTemplateList, InventoryAccessList, InventoryObjectRolesList, @@ -40,7 +40,7 @@ urls = [ re_path(r'^(?P[0-9]+)/script/$', InventoryScriptView.as_view(), name='inventory_script_view'), re_path(r'^(?P[0-9]+)/tree/$', InventoryTreeView.as_view(), name='inventory_tree_view'), re_path(r'^(?P[0-9]+)/inventory_sources/$', InventoryInventorySourcesList.as_view(), name='inventory_inventory_sources_list'), - re_path(r'^(?P[0-9]+)/source_inventories/$', InventorySourceInventoriesList.as_view(), name='inventory_source_inventories'), + re_path(r'^(?P[0-9]+)/input_inventories/$', InventoryInputInventoriesList.as_view(), name='inventory_input_inventories'), re_path(r'^(?P[0-9]+)/update_inventory_sources/$', InventoryInventorySourcesUpdate.as_view(), name='inventory_inventory_sources_update'), re_path(r'^(?P[0-9]+)/activity_stream/$', InventoryActivityStreamList.as_view(), name='inventory_activity_stream_list'), re_path(r'^(?P[0-9]+)/job_templates/$', InventoryJobTemplateList.as_view(), name='inventory_job_template_list'), diff --git a/awx/api/views/inventory.py b/awx/api/views/inventory.py index f18bc29fe2..64550e11c5 100644 --- a/awx/api/views/inventory.py +++ b/awx/api/views/inventory.py @@ -109,11 +109,11 @@ class ConstructedInventoryList(InventoryList): return r.filter(kind='constructed') -class InventorySourceInventoriesList(SubListAttachDetachAPIView): +class InventoryInputInventoriesList(SubListAttachDetachAPIView): model = Inventory serializer_class = InventorySerializer parent_model = Inventory - relationship = 'source_inventories' + relationship = 'input_inventories' class InventoryActivityStreamList(SubListAPIView): diff --git a/awx/main/migrations/0182_constructed_inventory.py b/awx/main/migrations/0182_constructed_inventory.py index ff268d376f..a41e303597 100644 --- a/awx/main/migrations/0182_constructed_inventory.py +++ b/awx/main/migrations/0182_constructed_inventory.py @@ -11,7 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.AddField( model_name='inventory', - name='source_inventories', + name='input_inventories', field=models.ManyToManyField( blank=True, help_text='Only valid for constructed inventories, this links to the inventories that will be used.', diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 461c467081..75609b91b6 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -140,7 +140,7 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): default=None, help_text=_('Filter that will be applied to the hosts of this inventory.'), ) - source_inventories = models.ManyToManyField( + input_inventories = models.ManyToManyField( 'Inventory', blank=True, related_name='destination_inventories', diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index 5b874e14d0..ef73caacf5 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -1529,10 +1529,10 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): # special case for constructed inventories, we pass source inventories from database # these must come in order, and in order _before_ the constructed inventory itself if inventory_update.inventory.kind == 'constructed': - for source_inventory in inventory_update.inventory.source_inventories.all(): + for input_inventory in inventory_update.inventory.input_inventories.all(): args.append('-i') script_params = dict(hostvars=True, towervars=True) - source_inv_path = self.write_inventory_file(source_inventory, private_data_dir, f'hosts_{source_inventory.id}', script_params) + source_inv_path = self.write_inventory_file(input_inventory, private_data_dir, f'hosts_{input_inventory.id}', script_params) args.append(to_container_path(source_inv_path, private_data_dir)) # Add arguments for the source inventory file/script/thing From e22967d28de40fe40d94fd4818aa9248942f6b4c Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 6 Feb 2023 14:09:05 -0500 Subject: [PATCH 067/167] add constructed kind to inventory module - add kind 'constructed' to inventory module - add 'input_inventories' field to inventory module Co-authored-by: Rick Elrod Signed-off-by: Rick Elrod --- awx_collection/plugins/modules/inventory.py | 17 +++++++++++++++-- awx_collection/test/awx/test_completeness.py | 4 +++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/awx_collection/plugins/modules/inventory.py b/awx_collection/plugins/modules/inventory.py index 8e739b2211..3a479bcd03 100644 --- a/awx_collection/plugins/modules/inventory.py +++ b/awx_collection/plugins/modules/inventory.py @@ -54,7 +54,7 @@ options: kind: description: - The kind field. Cannot be modified after created. - choices: ["", "smart"] + choices: ["", "smart", "constructed"] type: str host_filter: description: @@ -65,6 +65,11 @@ options: - list of Instance Groups for this Organization to run on. type: list elements: str + input_inventories: + description: + - List of Inventories to use as input for Constructed Inventory. + type: list + elements: str prevent_instance_group_fallback: description: - Prevent falling back to instance groups set on the organization @@ -111,11 +116,12 @@ def main(): description=dict(), organization=dict(required=True), variables=dict(type='dict'), - kind=dict(choices=['', 'smart']), + kind=dict(choices=['', 'smart', 'constructed']), host_filter=dict(), instance_groups=dict(type="list", elements='str'), prevent_instance_group_fallback=dict(type='bool'), state=dict(choices=['present', 'absent'], default='present'), + input_inventories=dict(type='list', elements='str'), ) # Create a module for ourselves @@ -181,6 +187,13 @@ def main(): if inventory and inventory['kind'] == '' and inventory_fields['kind'] == 'smart': module.fail_json(msg='You cannot turn a regular inventory into a "smart" inventory.') + if kind == 'constructed': + input_inventory_names = module.params.get('input_inventories') + if input_inventory_names is not None: + association_fields['input_inventories'] = [] + for item in input_inventory_names: + association_fields['input_inventories'].append(module.resolve_name_to_id('inventories', item)) + # If the state was present and we can let the module build or update the existing inventory, this will return on its own module.create_or_update_if_needed( inventory, diff --git a/awx_collection/test/awx/test_completeness.py b/awx_collection/test/awx/test_completeness.py index ef3d70727a..b4eb0ad3e4 100644 --- a/awx_collection/test/awx/test_completeness.py +++ b/awx_collection/test/awx/test_completeness.py @@ -20,7 +20,9 @@ read_only_endpoints_with_modules = ['settings', 'role', 'project_update', 'workf # If a module should not be created for an endpoint and the endpoint is not read-only add it here # THINK HARD ABOUT DOING THIS -no_module_for_endpoint = [] +no_module_for_endpoint = [ + 'constructed_inventory', # This is a view for inventory with kind=constructed +] # Some modules work on the related fields of an endpoint. These modules will not have an auto-associated endpoint no_endpoint_for_module = [ From 7a7443765180390025c93373bddcbe743867c3a1 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 2 Feb 2023 12:02:08 -0500 Subject: [PATCH 068/167] Add constructed inventory CRUD and subtab routes * Add constructed inventory API model * Add constructed inventory detail view * Add util to switch inventory url based on "kind" --- awx/ui/src/api/index.js | 3 + .../src/api/models/ConstructedInventories.js | 11 + awx/ui/src/api/models/Inventories.js | 7 + .../screens/Inventory/ConstructedInventory.js | 206 +++++++++++++ .../Inventory/ConstructedInventory.test.js | 73 +++++ .../ConstructedInventoryAdd.js | 18 ++ .../ConstructedInventoryAdd.test.js | 15 + .../ConstructedInventoryAdd/index.js | 1 + .../ConstructedInventoryDetail.js | 288 ++++++++++++++++++ .../ConstructedInventoryDetail.test.js | 66 ++++ .../ConstructedInventoryDetail/index.js | 1 + .../ConstructedInventoryEdit.js | 13 + .../ConstructedInventoryEdit.test.js | 15 + .../ConstructedInventoryEdit/index.js | 1 + .../ConstructedInventoryGroups.js | 13 + .../ConstructedInventoryGroups.test.js | 15 + .../ConstructedInventoryGroups/index.js | 1 + .../ConstructedInventoryHosts.js | 13 + .../ConstructedInventoryHosts.test.js | 15 + .../ConstructedInventoryHosts/index.js | 1 + awx/ui/src/screens/Inventory/Inventories.js | 15 +- awx/ui/src/screens/Inventory/Inventory.js | 7 +- .../Inventory/InventoryList/InventoryList.js | 16 +- .../InventoryList/InventoryListItem.js | 29 +- .../src/screens/Inventory/SmartInventory.js | 5 +- awx/ui/src/screens/Inventory/shared/utils.js | 9 + .../screens/Inventory/shared/utils.test.js | 20 +- 27 files changed, 849 insertions(+), 28 deletions(-) create mode 100644 awx/ui/src/api/models/ConstructedInventories.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventory.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventory.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryAdd/index.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryDetail/index.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryEdit/index.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js diff --git a/awx/ui/src/api/index.js b/awx/ui/src/api/index.js index 7a03643c05..5876efc6f1 100644 --- a/awx/ui/src/api/index.js +++ b/awx/ui/src/api/index.js @@ -6,6 +6,7 @@ import Config from './models/Config'; import CredentialInputSources from './models/CredentialInputSources'; import CredentialTypes from './models/CredentialTypes'; import Credentials from './models/Credentials'; +import ConstructedInventories from './models/ConstructedInventories'; import Dashboard from './models/Dashboard'; import ExecutionEnvironments from './models/ExecutionEnvironments'; import Groups from './models/Groups'; @@ -54,6 +55,7 @@ const ConfigAPI = new Config(); const CredentialInputSourcesAPI = new CredentialInputSources(); const CredentialTypesAPI = new CredentialTypes(); const CredentialsAPI = new Credentials(); +const ConstructedInventoriesAPI = new ConstructedInventories(); const DashboardAPI = new Dashboard(); const ExecutionEnvironmentsAPI = new ExecutionEnvironments(); const GroupsAPI = new Groups(); @@ -103,6 +105,7 @@ export { CredentialInputSourcesAPI, CredentialTypesAPI, CredentialsAPI, + ConstructedInventoriesAPI, DashboardAPI, ExecutionEnvironmentsAPI, GroupsAPI, diff --git a/awx/ui/src/api/models/ConstructedInventories.js b/awx/ui/src/api/models/ConstructedInventories.js new file mode 100644 index 0000000000..b62bffd3f3 --- /dev/null +++ b/awx/ui/src/api/models/ConstructedInventories.js @@ -0,0 +1,11 @@ +import Base from '../Base'; +import InstanceGroupsMixin from '../mixins/InstanceGroups.mixin'; + +class ConstructedInventories extends InstanceGroupsMixin(Base) { + constructor(http) { + super(http); + this.baseUrl = 'api/v2/constructed_inventories/'; + } +} + +export default ConstructedInventories; diff --git a/awx/ui/src/api/models/Inventories.js b/awx/ui/src/api/models/Inventories.js index fd1653045f..37654478a7 100644 --- a/awx/ui/src/api/models/Inventories.js +++ b/awx/ui/src/api/models/Inventories.js @@ -13,6 +13,7 @@ class Inventories extends InstanceGroupsMixin(Base) { this.readGroups = this.readGroups.bind(this); this.readGroupsOptions = this.readGroupsOptions.bind(this); this.promoteGroup = this.promoteGroup.bind(this); + this.readSourceInventories = this.readSourceInventories.bind(this); } readAccessList(id, params) { @@ -72,6 +73,12 @@ class Inventories extends InstanceGroupsMixin(Base) { }); } + readSourceInventories(inventoryId, params) { + return this.http.get(`${this.baseUrl}${inventoryId}/input_inventories/`, { + params, + }); + } + readSources(inventoryId, params) { return this.http.get(`${this.baseUrl}${inventoryId}/inventory_sources/`, { params, diff --git a/awx/ui/src/screens/Inventory/ConstructedInventory.js b/awx/ui/src/screens/Inventory/ConstructedInventory.js new file mode 100644 index 0000000000..58b33b96d2 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventory.js @@ -0,0 +1,206 @@ +import React, { useCallback, useEffect } from 'react'; +import { t } from '@lingui/macro'; +import { + Link, + Switch, + Route, + Redirect, + useRouteMatch, + useLocation, +} from 'react-router-dom'; +import { CaretLeftIcon } from '@patternfly/react-icons'; +import { Card, PageSection } from '@patternfly/react-core'; + +import useRequest from 'hooks/useRequest'; +import { ConstructedInventoriesAPI, InventoriesAPI } from 'api'; + +import ContentError from 'components/ContentError'; +import ContentLoading from 'components/ContentLoading'; +import JobList from 'components/JobList'; +import RelatedTemplateList from 'components/RelatedTemplateList'; +import { ResourceAccessList } from 'components/ResourceAccessList'; +import RoutedTabs from 'components/RoutedTabs'; +import ConstructedInventoryDetail from './ConstructedInventoryDetail'; +import ConstructedInventoryEdit from './ConstructedInventoryEdit'; +import ConstructedInventoryGroups from './ConstructedInventoryGroups'; +import ConstructedInventoryHosts from './ConstructedInventoryHosts'; +import { getInventoryPath } from './shared/utils'; + +function ConstructedInventory({ setBreadcrumb }) { + const location = useLocation(); + const match = useRouteMatch('/inventories/constructed_inventory/:id'); + + const { + result: inventory, + error: contentError, + isLoading: hasContentLoading, + request: fetchInventory, + } = useRequest( + useCallback(async () => { + const { data } = await ConstructedInventoriesAPI.readDetail( + match.params.id + ); + return data; + }, [match.params.id]), + + null + ); + + useEffect(() => { + fetchInventory(); + }, [fetchInventory, location.pathname]); + + useEffect(() => { + if (inventory) { + setBreadcrumb(inventory); + } + }, [inventory, setBreadcrumb]); + + const tabsArray = [ + { + name: ( + <> + + {t`Back to Inventories`} + + ), + link: `/inventories`, + id: 99, + }, + { name: t`Details`, link: `${match.url}/details`, id: 0 }, + { name: t`Access`, link: `${match.url}/access`, id: 1 }, + { name: t`Hosts`, link: `${match.url}/hosts`, id: 2 }, + { name: t`Groups`, link: `${match.url}/groups`, id: 3 }, + { + name: t`Jobs`, + link: `${match.url}/jobs`, + id: 4, + }, + { name: t`Job Templates`, link: `${match.url}/job_templates`, id: 5 }, + ]; + + if (hasContentLoading) { + return ( + + + + + + ); + } + + if (contentError) { + return ( + + + + {contentError?.response?.status === 404 && ( + + {t`Constructed Inventory not found.`}{' '} + {t`View all Inventories.`} + + )} + + + + ); + } + + if (inventory && inventory?.kind !== 'constructed') { + return ; + } + + let showCardHeader = true; + if (['edit'].some((name) => location.pathname.includes(name))) { + showCardHeader = false; + } + + return ( + + + {showCardHeader && } + + + {inventory && [ + + + , + + + , + + + , + + + , + + + , + + + , + + + , + ]} + + + {match.params.id && ( + + {t`View Constructed Inventory Details`} + + )} + + + + + + ); +} + +export { ConstructedInventory as _ConstructedInventory }; +export default ConstructedInventory; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventory.test.js b/awx/ui/src/screens/Inventory/ConstructedInventory.test.js new file mode 100644 index 0000000000..da4cd56c34 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventory.test.js @@ -0,0 +1,73 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { createMemoryHistory } from 'history'; +import { ConstructedInventoriesAPI } from 'api'; +import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; +import mockInventory from './shared/data.inventory.json'; +import ConstructedInventory from './ConstructedInventory'; + +jest.mock('../../api'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useRouteMatch: () => ({ + url: '/constructed_inventories/1', + params: { id: 1 }, + }), +})); + +describe('', () => { + let wrapper; + + beforeEach(async () => { + ConstructedInventoriesAPI.readDetail.mockResolvedValue({ + data: mockInventory, + }); + }); + + test('should render expected tabs', async () => { + const expectedTabs = [ + 'Back to Inventories', + 'Details', + 'Access', + 'Hosts', + 'Groups', + 'Jobs', + 'Job Templates', + ]; + await act(async () => { + wrapper = mountWithContexts( + {}} /> + ); + }); + wrapper.find('RoutedTabs li').forEach((tab, index) => { + expect(tab.text()).toEqual(expectedTabs[index]); + }); + }); + + test('should show content error when user attempts to navigate to erroneous route', async () => { + const history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/1/foobar'], + }); + await act(async () => { + wrapper = mountWithContexts( + {}} />, + { + context: { + router: { + history, + route: { + location: history.location, + match: { + params: { id: 1 }, + url: '/inventories/constructed_inventory/1/foobar', + path: '/inventories/constructed_inventory/1/foobar', + }, + }, + }, + }, + } + ); + }); + expect(wrapper.find('ContentError').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js new file mode 100644 index 0000000000..1aaa2b7679 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js @@ -0,0 +1,18 @@ +/* eslint i18next/no-literal-string: "off" */ +import React from 'react'; +import { Card, PageSection } from '@patternfly/react-core'; +import { CardBody } from 'components/Card'; + +function ConstructedInventoryAdd() { + return ( + + + +
Coming Soon!
+
+
+
+ ); +} + +export default ConstructedInventoryAdd; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js new file mode 100644 index 0000000000..0a9a6eedd5 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryAdd from './ConstructedInventoryAdd'; + +describe('', () => { + test('initially renders successfully', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts(); + }); + expect(wrapper.length).toBe(1); + expect(wrapper.find('ConstructedInventoryAdd').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/index.js new file mode 100644 index 0000000000..438115593a --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/index.js @@ -0,0 +1 @@ +export { default } from './ConstructedInventoryAdd'; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js new file mode 100644 index 0000000000..914e86b0b1 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js @@ -0,0 +1,288 @@ +import React, { useCallback, useEffect } from 'react'; +import { Link, useHistory } from 'react-router-dom'; + +import { t } from '@lingui/macro'; +import { + Button, + Chip, + TextList, + TextListItem, + TextListItemVariants, + TextListVariants, +} from '@patternfly/react-core'; +import AlertModal from 'components/AlertModal'; +import { CardBody, CardActionsRow } from 'components/Card'; +import { DetailList, Detail, UserDateDetail } from 'components/DetailList'; +import { VariablesDetail } from 'components/CodeEditor'; +import DeleteButton from 'components/DeleteButton'; +import ErrorDetail from 'components/ErrorDetail'; +import ContentError from 'components/ContentError'; +import ContentLoading from 'components/ContentLoading'; +import ChipGroup from 'components/ChipGroup'; +import Popover from 'components/Popover'; +import { InventoriesAPI, ConstructedInventoriesAPI } from 'api'; +import useRequest, { useDismissableError } from 'hooks/useRequest'; +import { Inventory } from 'types'; +import { relatedResourceDeleteRequests } from 'util/getRelatedResourceDeleteDetails'; +import InstanceGroupLabels from 'components/InstanceGroupLabels'; +import getHelpText from '../shared/Inventory.helptext'; + +function ConstructedInventoryDetail({ inventory }) { + const history = useHistory(); + const helpText = getHelpText(); + + const { + result: { instanceGroups, sourceInventories, actions }, + request: fetchRelatedDetails, + error: contentError, + isLoading, + } = useRequest( + useCallback(async () => { + const [response, sourceInvResponse, options] = await Promise.all([ + InventoriesAPI.readInstanceGroups(inventory.id), + InventoriesAPI.readSourceInventories(inventory.id), + ConstructedInventoriesAPI.readOptions(inventory.id), + ]); + + return { + instanceGroups: response.data.results, + sourceInventories: sourceInvResponse.data.results, + actions: options.data.actions.GET, + }; + }, [inventory.id]), + { + instanceGroups: [], + sourceInventories: [], + actions: {}, + isLoading: true, + } + ); + + useEffect(() => { + fetchRelatedDetails(); + }, [fetchRelatedDetails]); + + const { request: deleteInventory, error: deleteError } = useRequest( + useCallback(async () => { + await InventoriesAPI.destroy(inventory.id); + history.push(`/inventories`); + }, [inventory.id, history]) + ); + + const { error, dismissError } = useDismissableError(deleteError); + + const { organization, user_capabilities: userCapabilities } = + inventory.summary_fields; + + const deleteDetailsRequests = + relatedResourceDeleteRequests.inventory(inventory); + + if (isLoading) { + return ; + } + + if (contentError) { + return ; + } + + return ( + + + + + + + + {organization.name} + + } + /> + + + + + + + {instanceGroups && ( + } + isEmpty={instanceGroups.length === 0} + dataCy="constructed-inventory-instance-groups" + /> + )} + {inventory.prevent_instance_group_fallback && ( + + {inventory.prevent_instance_group_fallback && ( + + {t`Prevent Instance Group Fallback`} + + + )} + + } + /> + )} + + {inventory.summary_fields.labels?.results?.map((l) => ( + + {l.name} + + ))} + + } + isEmpty={inventory.summary_fields.labels?.results?.length === 0} + /> + + {sourceInventories?.map((sourceInventory) => ( + + + {sourceInventory.name} + + + ))} + + } + isEmpty={sourceInventories?.length === 0} + /> + + + + + + {userCapabilities.edit && ( + + )} + {userCapabilities.delete && ( + + {t`Delete`} + + )} + + {error && ( + + {t`Failed to delete inventory.`} + + + )} + + ); +} + +ConstructedInventoryDetail.propTypes = { + inventory: Inventory.isRequired, +}; + +export default ConstructedInventoryDetail; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.test.js new file mode 100644 index 0000000000..5d924a2790 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.test.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { InventoriesAPI, CredentialTypesAPI } from 'api'; + +import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryDetail from './ConstructedInventoryDetail'; + +jest.mock('../../../api'); + +const mockInventory = { + id: 1, + type: 'inventory', + summary_fields: { + organization: { + id: 1, + name: 'The Organization', + description: '', + }, + created_by: { + username: 'the_creator', + id: 2, + }, + modified_by: { + username: 'the_modifier', + id: 3, + }, + user_capabilities: { + edit: true, + delete: true, + copy: true, + adhoc: true, + }, + }, + created: '2019-10-04T16:56:48.025455Z', + modified: '2019-10-04T16:56:48.025468Z', + name: 'Constructed Inv', + description: '', + organization: 1, + kind: 'constructed', + has_active_failures: false, + total_hosts: 0, + hosts_with_active_failures: 0, + total_groups: 0, + groups_with_active_failures: 0, + has_inventory_sources: false, + total_inventory_sources: 0, + inventory_sources_with_failures: 0, + pending_deletion: false, + prevent_instance_group_fallback: false, + update_cache_timeout: 0, + limit: '', + verbosity: 1, +}; + +describe('', () => { + test('initially renders successfully', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + expect(wrapper.length).toBe(1); + expect(wrapper.find('ConstructedInventoryDetail').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/index.js new file mode 100644 index 0000000000..efe8b49508 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/index.js @@ -0,0 +1 @@ +export { default } from './ConstructedInventoryDetail'; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js new file mode 100644 index 0000000000..a49e7eaaed --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js @@ -0,0 +1,13 @@ +/* eslint i18next/no-literal-string: "off" */ +import React from 'react'; +import { CardBody } from 'components/Card'; + +function ConstructedInventoryEdit() { + return ( + +
Coming Soon!
+
+ ); +} + +export default ConstructedInventoryEdit; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js new file mode 100644 index 0000000000..02b0747880 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryEdit from './ConstructedInventoryEdit'; + +describe('', () => { + test('initially renders successfully', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts(); + }); + expect(wrapper.length).toBe(1); + expect(wrapper.find('ConstructedInventoryEdit').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/index.js new file mode 100644 index 0000000000..55030e87ab --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/index.js @@ -0,0 +1 @@ +export { default } from './ConstructedInventoryEdit'; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js new file mode 100644 index 0000000000..964dfa9062 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js @@ -0,0 +1,13 @@ +/* eslint i18next/no-literal-string: "off" */ +import React from 'react'; +import { CardBody } from 'components/Card'; + +function ConstructedInventoryGroups() { + return ( + +
Coming Soon!
+
+ ); +} + +export default ConstructedInventoryGroups; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js new file mode 100644 index 0000000000..db2720ff44 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryGroups from './ConstructedInventoryGroups'; + +describe('', () => { + test('initially renders successfully', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts(); + }); + expect(wrapper.length).toBe(1); + expect(wrapper.find('ConstructedInventoryGroups').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js new file mode 100644 index 0000000000..7f1b4343b2 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js @@ -0,0 +1 @@ +export { default } from './ConstructedInventoryGroups'; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js new file mode 100644 index 0000000000..56f0c801b8 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js @@ -0,0 +1,13 @@ +/* eslint i18next/no-literal-string: "off" */ +import React from 'react'; +import { CardBody } from 'components/Card'; + +function ConstructedInventoryHosts() { + return ( + +
Coming Soon!
+
+ ); +} + +export default ConstructedInventoryHosts; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js new file mode 100644 index 0000000000..0d6b3d6f13 --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryHosts from './ConstructedInventoryHosts'; + +describe('', () => { + test('initially renders successfully', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts(); + }); + expect(wrapper.length).toBe(1); + expect(wrapper.find('ConstructedInventoryHosts').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js new file mode 100644 index 0000000000..68464720fb --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js @@ -0,0 +1 @@ +export { default } from './ConstructedInventoryHosts'; diff --git a/awx/ui/src/screens/Inventory/Inventories.js b/awx/ui/src/screens/Inventory/Inventories.js index 49bf4d7710..dfb04a0229 100644 --- a/awx/ui/src/screens/Inventory/Inventories.js +++ b/awx/ui/src/screens/Inventory/Inventories.js @@ -9,14 +9,18 @@ import PersistentFilters from 'components/PersistentFilters'; import { InventoryList } from './InventoryList'; import Inventory from './Inventory'; import SmartInventory from './SmartInventory'; +import ConstructedInventory from './ConstructedInventory'; import InventoryAdd from './InventoryAdd'; import SmartInventoryAdd from './SmartInventoryAdd'; +import ConstructedInventoryAdd from './ConstructedInventoryAdd'; +import { getInventoryPath } from './shared/utils'; function Inventories() { const initScreenHeader = useRef({ '/inventories': t`Inventories`, '/inventories/inventory/add': t`Create new inventory`, '/inventories/smart_inventory/add': t`Create new smart inventory`, + '/inventories/constructed_inventory/add': t`Create new constructed inventory`, }); const [breadcrumbConfig, setScreenHeader] = useState( @@ -45,10 +49,7 @@ function Inventories() { return; } - const inventoryKind = - inventory.kind === 'smart' ? 'smart_inventory' : 'inventory'; - - const inventoryPath = `/inventories/${inventoryKind}/${inventory.id}`; + const inventoryPath = getInventoryPath(inventory); const inventoryHostsPath = `${inventoryPath}/hosts`; const inventoryGroupsPath = `${inventoryPath}/groups`; const inventorySourcesPath = `${inventoryPath}/sources`; @@ -109,6 +110,9 @@ function Inventories() { + + + {({ me }) => ( @@ -119,6 +123,9 @@ function Inventories() { + + + diff --git a/awx/ui/src/screens/Inventory/Inventory.js b/awx/ui/src/screens/Inventory/Inventory.js index 53da122cd6..c35a92d375 100644 --- a/awx/ui/src/screens/Inventory/Inventory.js +++ b/awx/ui/src/screens/Inventory/Inventory.js @@ -23,6 +23,7 @@ import InventoryEdit from './InventoryEdit'; import InventoryGroups from './InventoryGroups'; import InventoryHosts from './InventoryHosts/InventoryHosts'; import InventorySources from './InventorySources'; +import { getInventoryPath } from './shared/utils'; function Inventory({ setBreadcrumb }) { const [contentError, setContentError] = useState(null); @@ -111,10 +112,8 @@ function Inventory({ setBreadcrumb }) { showCardHeader = false; } - if (inventory?.kind === 'smart') { - return ( - - ); + if (inventory && inventory?.kind !== '') { + return ; } return ( diff --git a/awx/ui/src/screens/Inventory/InventoryList/InventoryList.js b/awx/ui/src/screens/Inventory/InventoryList/InventoryList.js index 0ad6dcc01b..aac6071260 100644 --- a/awx/ui/src/screens/Inventory/InventoryList/InventoryList.js +++ b/awx/ui/src/screens/Inventory/InventoryList/InventoryList.js @@ -135,6 +135,7 @@ function InventoryList() { const addInventory = t`Add inventory`; const addSmartInventory = t`Add smart inventory`; + const addConstructedInventory = t`Add constructed inventory`; const addButton = ( {addSmartInventory} , + + {addConstructedInventory} + , ]} /> ); @@ -185,6 +195,7 @@ function InventoryList() { options: [ ['', t`Inventory`], ['smart', t`Smart Inventory`], + ['constructed', t`Constructed Inventory`], ], }, { @@ -261,11 +272,6 @@ function InventoryList() { inventory={inventory} rowIndex={index} fetchInventories={fetchInventories} - detailUrl={ - inventory.kind === 'smart' - ? `${match.url}/smart_inventory/${inventory.id}/details` - : `${match.url}/inventory/${inventory.id}/details` - } onSelect={() => { if (!inventory.pending_deletion) { handleSelect(inventory); diff --git a/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js b/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js index c692c32f51..3828401045 100644 --- a/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js +++ b/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js @@ -1,5 +1,5 @@ import React, { useState, useCallback } from 'react'; -import { string, bool, func } from 'prop-types'; +import { bool, func } from 'prop-types'; import { Button, Label } from '@patternfly/react-core'; import { Tr, Td } from '@patternfly/react-table'; @@ -12,6 +12,7 @@ import { Inventory } from 'types'; import { ActionsTd, ActionItem, TdBreakWord } from 'components/PaginatedTable'; import CopyButton from 'components/CopyButton'; import StatusLabel from 'components/StatusLabel'; +import { getInventoryPath } from '../shared/utils'; function InventoryListItem({ inventory, @@ -19,12 +20,10 @@ function InventoryListItem({ isSelected, onSelect, onCopy, - detailUrl, fetchInventories, }) { InventoryListItem.propTypes = { inventory: Inventory.isRequired, - detailUrl: string.isRequired, isSelected: bool.isRequired, onSelect: func.isRequired, }; @@ -50,6 +49,12 @@ function InventoryListItem({ const labelId = `check-action-${inventory.id}`; + const typeLabel = { + '': t`Inventory`, + smart: t`Smart Inventory`, + constructed: t`Constructed Inventory`, + }; + let syncStatus = 'disabled'; if (inventory.isSourceSyncRunning) { syncStatus = 'syncing'; @@ -93,16 +98,20 @@ function InventoryListItem({ {inventory.pending_deletion ? ( {inventory.name} ) : ( - + {inventory.name} )} - {inventory.kind !== 'smart' && + {inventory.kind === '' && (inventory.has_inventory_sources ? ( ))} - - {inventory.kind === 'smart' ? t`Smart Inventory` : t`Inventory`} - + {typeLabel[inventory.kind]} diff --git a/awx/ui/src/screens/Inventory/SmartInventory.js b/awx/ui/src/screens/Inventory/SmartInventory.js index 952cf5dc31..b91d253dc6 100644 --- a/awx/ui/src/screens/Inventory/SmartInventory.js +++ b/awx/ui/src/screens/Inventory/SmartInventory.js @@ -23,6 +23,7 @@ import RelatedTemplateList from 'components/RelatedTemplateList'; import SmartInventoryDetail from './SmartInventoryDetail'; import SmartInventoryEdit from './SmartInventoryEdit'; import SmartInventoryHosts from './SmartInventoryHosts'; +import { getInventoryPath } from './shared/utils'; function SmartInventory({ setBreadcrumb }) { const location = useLocation(); @@ -101,8 +102,8 @@ function SmartInventory({ setBreadcrumb }) { ); } - if (inventory?.kind === '') { - return ; + if (inventory && inventory?.kind !== 'smart') { + return ; } let showCardHeader = true; diff --git a/awx/ui/src/screens/Inventory/shared/utils.js b/awx/ui/src/screens/Inventory/shared/utils.js index c08710327f..5e335beeed 100644 --- a/awx/ui/src/screens/Inventory/shared/utils.js +++ b/awx/ui/src/screens/Inventory/shared/utils.js @@ -8,3 +8,12 @@ const parseHostFilter = (value) => { return value; }; export default parseHostFilter; + +export function getInventoryPath(inventory) { + const url = { + '': `/inventories/inventory/${inventory.id}`, + smart: `/inventories/smart_inventory/${inventory.id}`, + constructed: `/inventories/constructed_inventory/${inventory.id}`, + }; + return url[inventory.kind]; +} diff --git a/awx/ui/src/screens/Inventory/shared/utils.test.js b/awx/ui/src/screens/Inventory/shared/utils.test.js index 4d659932f7..ccbf44aff1 100644 --- a/awx/ui/src/screens/Inventory/shared/utils.test.js +++ b/awx/ui/src/screens/Inventory/shared/utils.test.js @@ -1,4 +1,4 @@ -import parseHostFilter from './utils'; +import parseHostFilter, { getInventoryPath } from './utils'; describe('parseHostFilter', () => { test('parse host filter', () => { @@ -19,3 +19,21 @@ describe('parseHostFilter', () => { }); }); }); + +describe('getInventoryPath', () => { + test('should return inventory path', () => { + expect(getInventoryPath({ id: 1, kind: '' })).toMatch( + '/inventories/inventory/1' + ); + }); + test('should return smart inventory path', () => { + expect(getInventoryPath({ id: 2, kind: 'smart' })).toMatch( + '/inventories/smart_inventory/2' + ); + }); + test('should return constructed inventory path', () => { + expect(getInventoryPath({ id: 3, kind: 'constructed' })).toMatch( + '/inventories/constructed_inventory/3' + ); + }); +}); From 7112da9cdcc85882232049ffef83c2165e142c23 Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Thu, 9 Feb 2023 12:56:33 -0500 Subject: [PATCH 069/167] Various validations for const. inv. serialization - prevent constructed inventory host,group,inventory_source creation - disable deleting constructed inventory hosts - remove the ability to add constructed inventory sources - remove ability to add constructed inventories to constructed inventories - block updates to constructed source type - added tests for group/host/source creation --- awx/api/serializers.py | 16 +++-- awx/api/views/__init__.py | 2 + awx/api/views/inventory.py | 9 +++ .../test_inventory_input_constructed.py | 70 +++++++++++++++++++ 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 awx/main/tests/functional/test_inventory_input_constructed.py diff --git a/awx/api/serializers.py b/awx/api/serializers.py index c898bf754f..d02a486f5c 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1933,8 +1933,8 @@ class HostSerializer(BaseSerializerWithVariables): return value def validate_inventory(self, value): - if value.kind == 'smart': - raise serializers.ValidationError({"detail": _("Cannot create Host for Smart Inventory")}) + if value.kind in ('constructed', 'smart'): + raise serializers.ValidationError({"detail": _("Cannot create Host for Smart or Constructed Inventories")}) return value def validate_variables(self, value): @@ -2032,8 +2032,8 @@ class GroupSerializer(BaseSerializerWithVariables): return value def validate_inventory(self, value): - if value.kind == 'smart': - raise serializers.ValidationError({"detail": _("Cannot create Group for Smart Inventory")}) + if value.kind in ('constructed', 'smart'): + raise serializers.ValidationError({"detail": _("Cannot create Group for Smart or Constructed Inventories")}) return value def to_representation(self, obj): @@ -2339,8 +2339,8 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt return value def validate_inventory(self, value): - if value and value.kind == 'smart': - raise serializers.ValidationError({"detail": _("Cannot create Inventory Source for Smart Inventory")}) + if value and value.kind in ('constructed', 'smart'): + raise serializers.ValidationError({"detail": _("Cannot create Inventory Source for Smart or Constructed Inventories")}) return value # TODO: remove when old 'credential' fields are removed @@ -2361,6 +2361,8 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt obj = super(InventorySourceSerializer, self).update(obj, validated_data) if deprecated_fields: self._update_deprecated_fields(deprecated_fields, obj) + if obj.source == 'constructed': + raise serializers.ValidationError({'error': _("Cannot edit source of type constructed.")}) return obj # TODO: remove when old 'credential' fields are removed @@ -2387,6 +2389,8 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt if get_field_from_model_or_attrs('source') == 'scm': if ('source' in attrs or 'source_project' in attrs) and get_field_from_model_or_attrs('source_project') is None: raise serializers.ValidationError({"source_project": _("Project required for scm type sources.")}) + elif (get_field_from_model_or_attrs('source') == 'constructed') and (self.instance and self.instance.source != 'constructed'): + raise serializers.ValidationError({"Error": _('constructed not a valid source for inventory')}) else: redundant_scm_fields = list(filter(lambda x: attrs.get(x, None), ['source_project', 'source_path', 'scm_branch'])) if redundant_scm_fields: diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index c1e99a4002..d023f92984 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1610,6 +1610,8 @@ class HostDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPIView): def delete(self, request, *args, **kwargs): if self.get_object().inventory.pending_deletion: return Response({"error": _("The inventory for this host is already being deleted.")}, status=status.HTTP_400_BAD_REQUEST) + if self.get_object().inventory.kind == 'constructed': + return Response({"error": _("Delete constructed inventory hosts from input inventory.")}, status=status.HTTP_400_BAD_REQUEST) return super(HostDetail, self).delete(request, *args, **kwargs) diff --git a/awx/api/views/inventory.py b/awx/api/views/inventory.py index 64550e11c5..453f9c6072 100644 --- a/awx/api/views/inventory.py +++ b/awx/api/views/inventory.py @@ -115,6 +115,15 @@ class InventoryInputInventoriesList(SubListAttachDetachAPIView): parent_model = Inventory relationship = 'input_inventories' + # Specifically overriding the post method on this view to disallow constructed inventories as input inventories + def post(self, request, *args, **kwargs): + obj = Inventory.objects.get(id=request.data.get('id')) + if obj.kind == 'constructed': + return Response( + dict(error=_('You cannot add a constructed inventory to another constructed inventory.')), status=status.HTTP_405_METHOD_NOT_ALLOWED + ) + return super(InventoryInputInventoriesList, self).post(request, *args, **kwargs) + class InventoryActivityStreamList(SubListAPIView): model = ActivityStream diff --git a/awx/main/tests/functional/test_inventory_input_constructed.py b/awx/main/tests/functional/test_inventory_input_constructed.py new file mode 100644 index 0000000000..e677d46f46 --- /dev/null +++ b/awx/main/tests/functional/test_inventory_input_constructed.py @@ -0,0 +1,70 @@ +import pytest +from awx.main.models import Inventory +from awx.api.versioning import reverse + + +@pytest.fixture +def constructed_inventory(organization): + """ + creates a new constructed inventory source + """ + return Inventory.objects.create(name='dummy2', kind='constructed', organization=organization) + + +@pytest.mark.django_db +def test_constructed_inventory_post(post, organization, admin_user): + inventory1 = Inventory.objects.create(name='dummy1', kind='constructed', organization=organization) + inventory2 = Inventory.objects.create(name='dummy2', kind='constructed', organization=organization) + resp = post( + url=reverse('api:inventory_input_inventories', kwargs={'pk': inventory1.pk}), + data={'id': inventory2.pk}, + user=admin_user, + expect=405, + ) + assert resp.status_code == 405 + + +@pytest.mark.django_db +def test_add_constructed_inventory_source(post, admin_user, constructed_inventory): + resp = post( + url=reverse('api:inventory_inventory_sources_list', kwargs={'pk': constructed_inventory.pk}), + data={'name': 'dummy1', 'source': 'constructed'}, + user=admin_user, + expect=400, + ) + assert resp.status_code == 400 + + +@pytest.mark.django_db +def test_add_constructed_inventory_host(post, admin_user, constructed_inventory): + resp = post( + url=reverse('api:inventory_hosts_list', kwargs={'pk': constructed_inventory.pk}), + data={'name': 'dummy1'}, + user=admin_user, + expect=400, + ) + assert resp.status_code == 400 + + +@pytest.mark.django_db +def test_add_constructed_inventory_group(post, admin_user, constructed_inventory): + resp = post( + reverse('api:inventory_groups_list', kwargs={'pk': constructed_inventory.pk}), + data={'name': 'group-test'}, + user=admin_user, + expect=400, + ) + assert resp.status_code == 400 + + +@pytest.mark.django_db +def test_edit_constructed_inventory_source(patch, admin_user, inventory): + inventory.inventory_sources.create(name="dummysrc", source="constructed") + inv_id = inventory.inventory_sources.get(name='dummysrc').id + resp = patch( + reverse('api:inventory_source_detail', kwargs={'pk': inv_id}), + data={'description': inventory.name}, + user=admin_user, + expect=400, + ) + assert resp.status_code == 400 From 8c4e943af0f4ff1e235e0c883f49a33a925e454b Mon Sep 17 00:00:00 2001 From: Gabe Muniz Date: Tue, 14 Feb 2023 00:07:49 -0500 Subject: [PATCH 070/167] refactored to use is_valid_relation instead of post --- awx/api/views/inventory.py | 12 +++---- awx/main/tests/functional/conftest.py | 8 +++++ .../test_inventory_input_constructed.py | 31 +++++++------------ 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/awx/api/views/inventory.py b/awx/api/views/inventory.py index 453f9c6072..4085cf9bff 100644 --- a/awx/api/views/inventory.py +++ b/awx/api/views/inventory.py @@ -14,6 +14,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response from rest_framework import status +from rest_framework import serializers # AWX from awx.main.models import ActivityStream, Inventory, JobTemplate, Role, User, InstanceGroup, InventoryUpdateEvent, InventoryUpdate @@ -115,14 +116,9 @@ class InventoryInputInventoriesList(SubListAttachDetachAPIView): parent_model = Inventory relationship = 'input_inventories' - # Specifically overriding the post method on this view to disallow constructed inventories as input inventories - def post(self, request, *args, **kwargs): - obj = Inventory.objects.get(id=request.data.get('id')) - if obj.kind == 'constructed': - return Response( - dict(error=_('You cannot add a constructed inventory to another constructed inventory.')), status=status.HTTP_405_METHOD_NOT_ALLOWED - ) - return super(InventoryInputInventoriesList, self).post(request, *args, **kwargs) + def is_valid_relation(self, parent, sub, created=False): + if sub.kind == 'constructed': + raise serializers.ValidationError({'error': 'You cannot add a constructed inventory to another constructed inventory.'}) class InventoryActivityStreamList(SubListAPIView): diff --git a/awx/main/tests/functional/conftest.py b/awx/main/tests/functional/conftest.py index 4f8b6bc83c..e1284ce87c 100644 --- a/awx/main/tests/functional/conftest.py +++ b/awx/main/tests/functional/conftest.py @@ -511,6 +511,14 @@ def group(inventory): return inventory.groups.create(name='single-group') +@pytest.fixture +def constructed_inventory(organization): + """ + creates a new constructed inventory source + """ + return Inventory.objects.create(name='dummy1', kind='constructed', organization=organization) + + @pytest.fixture def inventory_source(inventory): # by making it ec2, the credential is not required diff --git a/awx/main/tests/functional/test_inventory_input_constructed.py b/awx/main/tests/functional/test_inventory_input_constructed.py index e677d46f46..2602cf2947 100644 --- a/awx/main/tests/functional/test_inventory_input_constructed.py +++ b/awx/main/tests/functional/test_inventory_input_constructed.py @@ -3,25 +3,17 @@ from awx.main.models import Inventory from awx.api.versioning import reverse -@pytest.fixture -def constructed_inventory(organization): - """ - creates a new constructed inventory source - """ - return Inventory.objects.create(name='dummy2', kind='constructed', organization=organization) - - @pytest.mark.django_db -def test_constructed_inventory_post(post, organization, admin_user): - inventory1 = Inventory.objects.create(name='dummy1', kind='constructed', organization=organization) - inventory2 = Inventory.objects.create(name='dummy2', kind='constructed', organization=organization) +def test_constructed_inventory_post(post, admin_user, organization): + inv1 = Inventory.objects.create(name='dummy1', kind='constructed', organization=organization) + inv2 = Inventory.objects.create(name='dummy2', kind='constructed', organization=organization) resp = post( - url=reverse('api:inventory_input_inventories', kwargs={'pk': inventory1.pk}), - data={'id': inventory2.pk}, + url=reverse('api:inventory_input_inventories', kwargs={'pk': inv1.pk}), + data={'id': inv2.pk}, user=admin_user, - expect=405, + expect=400, ) - assert resp.status_code == 405 + assert resp.status_code == 400 @pytest.mark.django_db @@ -58,12 +50,11 @@ def test_add_constructed_inventory_group(post, admin_user, constructed_inventory @pytest.mark.django_db -def test_edit_constructed_inventory_source(patch, admin_user, inventory): - inventory.inventory_sources.create(name="dummysrc", source="constructed") - inv_id = inventory.inventory_sources.get(name='dummysrc').id +def test_edit_constructed_inventory_source(patch, admin_user, inventory_source_factory): + inv_src = inventory_source_factory(name='dummy1', source='constructed') resp = patch( - reverse('api:inventory_source_detail', kwargs={'pk': inv_id}), - data={'description': inventory.name}, + reverse('api:inventory_source_detail', kwargs={'pk': inv_src.pk}), + data={'description': inv_src.name}, user=admin_user, expect=400, ) From 7dd1bc04c40ab868c11ca0d154b7081f5d25dd5a Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Sat, 18 Feb 2023 11:33:44 -0500 Subject: [PATCH 071/167] Add constructed inventory detail's sync button --- awx/ui/src/api/models/Inventories.js | 4 +- .../ConstructedInventoryDetail.js | 140 +++++++++--- .../ConstructedInventoryDetail.test.js | 210 ++++++++++++++++-- .../ConstructedInventorySyncButton.js | 59 +++++ .../ConstructedInventorySyncButton.test.js | 41 ++++ .../InventorySourceDetail.js | 2 +- .../useWsInventorySourcesDetails.js | 0 .../useWsInventorySourcesDetails.test.js | 0 8 files changed, 407 insertions(+), 49 deletions(-) create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventorySyncButton.js create mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventorySyncButton.test.js rename awx/ui/src/screens/Inventory/{InventorySources => shared}/useWsInventorySourcesDetails.js (100%) rename awx/ui/src/screens/Inventory/{InventorySources => shared}/useWsInventorySourcesDetails.test.js (100%) diff --git a/awx/ui/src/api/models/Inventories.js b/awx/ui/src/api/models/Inventories.js index 37654478a7..4fd145e178 100644 --- a/awx/ui/src/api/models/Inventories.js +++ b/awx/ui/src/api/models/Inventories.js @@ -13,7 +13,7 @@ class Inventories extends InstanceGroupsMixin(Base) { this.readGroups = this.readGroups.bind(this); this.readGroupsOptions = this.readGroupsOptions.bind(this); this.promoteGroup = this.promoteGroup.bind(this); - this.readSourceInventories = this.readSourceInventories.bind(this); + this.readInputInventories = this.readInputInventories.bind(this); } readAccessList(id, params) { @@ -73,7 +73,7 @@ class Inventories extends InstanceGroupsMixin(Base) { }); } - readSourceInventories(inventoryId, params) { + readInputInventories(inventoryId, params) { return this.http.get(`${this.baseUrl}${inventoryId}/input_inventories/`, { params, }); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js index 914e86b0b1..d8e136646b 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js @@ -9,50 +9,97 @@ import { TextListItem, TextListItemVariants, TextListVariants, + Tooltip, } from '@patternfly/react-core'; +import { InventoriesAPI, ConstructedInventoriesAPI } from 'api'; +import { Inventory } from 'types'; +import { formatDateString } from 'util/dates'; +import { relatedResourceDeleteRequests } from 'util/getRelatedResourceDeleteDetails'; +import useRequest, { useDismissableError } from 'hooks/useRequest'; import AlertModal from 'components/AlertModal'; import { CardBody, CardActionsRow } from 'components/Card'; -import { DetailList, Detail, UserDateDetail } from 'components/DetailList'; +import ChipGroup from 'components/ChipGroup'; import { VariablesDetail } from 'components/CodeEditor'; -import DeleteButton from 'components/DeleteButton'; -import ErrorDetail from 'components/ErrorDetail'; import ContentError from 'components/ContentError'; import ContentLoading from 'components/ContentLoading'; -import ChipGroup from 'components/ChipGroup'; -import Popover from 'components/Popover'; -import { InventoriesAPI, ConstructedInventoriesAPI } from 'api'; -import useRequest, { useDismissableError } from 'hooks/useRequest'; -import { Inventory } from 'types'; -import { relatedResourceDeleteRequests } from 'util/getRelatedResourceDeleteDetails'; +import { DetailList, Detail, UserDateDetail } from 'components/DetailList'; +import DeleteButton from 'components/DeleteButton'; +import ErrorDetail from 'components/ErrorDetail'; import InstanceGroupLabels from 'components/InstanceGroupLabels'; +import JobCancelButton from 'components/JobCancelButton'; +import Popover from 'components/Popover'; +import StatusLabel from 'components/StatusLabel'; +import ConstructedInventorySyncButton from './ConstructedInventorySyncButton'; +import useWsInventorySourcesDetails from '../shared/useWsInventorySourcesDetails'; import getHelpText from '../shared/Inventory.helptext'; +function JobStatusLabel({ job }) { + if (!job) { + return null; + } + + return ( + +
{t`MOST RECENT SYNC`}
+
+ {t`JOB ID:`} {job.id} +
+
+ {t`STATUS:`} {job.status.toUpperCase()} +
+ {job.finished && ( +
+ {t`FINISHED:`} {formatDateString(job.finished)} +
+ )} + + } + key={job.id} + > + + + +
+ ); +} + function ConstructedInventoryDetail({ inventory }) { const history = useHistory(); const helpText = getHelpText(); const { - result: { instanceGroups, sourceInventories, actions }, + result: { instanceGroups, inputInventories, inventorySource, actions }, request: fetchRelatedDetails, error: contentError, isLoading, } = useRequest( useCallback(async () => { - const [response, sourceInvResponse, options] = await Promise.all([ + const [ + instanceGroupsResponse, + inputInventoriesResponse, + inventorySourceResponse, + optionsResponse, + ] = await Promise.all([ InventoriesAPI.readInstanceGroups(inventory.id), - InventoriesAPI.readSourceInventories(inventory.id), - ConstructedInventoriesAPI.readOptions(inventory.id), + InventoriesAPI.readInputInventories(inventory.id), + InventoriesAPI.readSources(inventory.id), + ConstructedInventoriesAPI.readOptions(), ]); return { - instanceGroups: response.data.results, - sourceInventories: sourceInvResponse.data.results, - actions: options.data.actions.GET, + instanceGroups: instanceGroupsResponse.data.results, + inputInventories: inputInventoriesResponse.data.results, + inventorySource: inventorySourceResponse.data.results[0], + actions: optionsResponse.data.actions.GET, }; }, [inventory.id]), { instanceGroups: [], - sourceInventories: [], + inputInventories: [], + inventorySource: {}, actions: {}, isLoading: true, } @@ -62,6 +109,12 @@ function ConstructedInventoryDetail({ inventory }) { fetchRelatedDetails(); }, [fetchRelatedDetails]); + const wsInventorySource = useWsInventorySourcesDetails(inventorySource); + const inventorySourceSyncJob = + wsInventorySource.summary_fields?.current_job || + wsInventorySource.summary_fields?.last_job || + null; + const { request: deleteInventory, error: deleteError } = useRequest( useCallback(async () => { await InventoriesAPI.destroy(inventory.id); @@ -71,9 +124,6 @@ function ConstructedInventoryDetail({ inventory }) { const { error, dismissError } = useDismissableError(deleteError); - const { organization, user_capabilities: userCapabilities } = - inventory.summary_fields; - const deleteDetailsRequests = relatedResourceDeleteRequests.inventory(inventory); @@ -93,6 +143,14 @@ function ConstructedInventoryDetail({ inventory }) { value={inventory.name} dataCy="constructed-inventory-name" /> + + ) + } + /> - {organization.name} + + {inventory.summary_fields?.organization.name} } /> @@ -204,26 +264,26 @@ function ConstructedInventoryDetail({ inventory }) { /> - {sourceInventories?.map((sourceInventory) => ( + {inputInventories?.map((inputInventory) => ( - - {sourceInventory.name} + + {inputInventory.name} ))} } - isEmpty={sourceInventories?.length === 0} + isEmpty={inputInventories?.length === 0} /> - {userCapabilities.edit && ( + {inventory?.summary_fields?.user_capabilities?.edit && ( + + {startError && ( + + {t`Failed to sync constructed inventory source`} + + + )} + + ); +} + +ConstructedInventorySyncButton.propTypes = { + inventoryId: PropTypes.number.isRequired, +}; + +export default ConstructedInventorySyncButton; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventorySyncButton.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventorySyncButton.test.js new file mode 100644 index 0000000000..75a5900abb --- /dev/null +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventorySyncButton.test.js @@ -0,0 +1,41 @@ +import React from 'react'; +import { InventoriesAPI } from 'api'; +import ConstructedInventorySyncButton from './ConstructedInventorySyncButton'; +import { render, fireEvent, screen, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; + +jest.mock('../../../api'); + +const inventory = { id: 100, name: 'Constructed Inventory' }; + +describe('', () => { + const Component = () => ( + + ); + + test('should render start sync button', () => { + render(); + expect( + screen.getByRole('button', { name: 'Start inventory source sync' }) + ).toBeInTheDocument(); + }); + + test('should make expected api request on sync', async () => { + render(); + const syncButton = screen.queryByText('Sync'); + fireEvent.click(syncButton); + await waitFor(() => + expect(InventoriesAPI.syncAllSources).toHaveBeenCalledWith(100) + ); + }); + + test('should show alert modal on throw', async () => { + InventoriesAPI.syncAllSources.mockRejectedValueOnce(new Error()); + render(); + await waitFor(() => { + const syncButton = screen.queryByText('Sync'); + fireEvent.click(syncButton); + }); + expect(screen.getByRole('dialog', { name: 'Alert modal Error!' })); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventorySourceDetail/InventorySourceDetail.js b/awx/ui/src/screens/Inventory/InventorySourceDetail/InventorySourceDetail.js index cf5d1354af..75280a64e4 100644 --- a/awx/ui/src/screens/Inventory/InventorySourceDetail/InventorySourceDetail.js +++ b/awx/ui/src/screens/Inventory/InventorySourceDetail/InventorySourceDetail.js @@ -31,7 +31,7 @@ import { formatDateString } from 'util/dates'; import Popover from 'components/Popover'; import { VERBOSITY } from 'components/VerbositySelectField'; import InventorySourceSyncButton from '../shared/InventorySourceSyncButton'; -import useWsInventorySourcesDetails from '../InventorySources/useWsInventorySourcesDetails'; +import useWsInventorySourcesDetails from '../shared/useWsInventorySourcesDetails'; import getHelpText from '../shared/Inventory.helptext'; function InventorySourceDetail({ inventorySource }) { diff --git a/awx/ui/src/screens/Inventory/InventorySources/useWsInventorySourcesDetails.js b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js similarity index 100% rename from awx/ui/src/screens/Inventory/InventorySources/useWsInventorySourcesDetails.js rename to awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js diff --git a/awx/ui/src/screens/Inventory/InventorySources/useWsInventorySourcesDetails.test.js b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js similarity index 100% rename from awx/ui/src/screens/Inventory/InventorySources/useWsInventorySourcesDetails.test.js rename to awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js From ab3a9a0364fd048d320687649ec27bf3ab135a6a Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Tue, 21 Feb 2023 17:47:56 -0500 Subject: [PATCH 072/167] Update inventory details after inventory source sync --- .../ConstructedInventoryDetail.js | 41 +++++++++------ .../shared/useWsInventorySourcesDetails.js | 50 ++++++++++++------- .../useWsInventorySourcesDetails.test.js | 24 +++++++++ 3 files changed, 82 insertions(+), 33 deletions(-) diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js index d8e136646b..6108dc2330 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryDetail/ConstructedInventoryDetail.js @@ -5,6 +5,8 @@ import { t } from '@lingui/macro'; import { Button, Chip, + Label, + LabelGroup, TextList, TextListItem, TextListItemVariants, @@ -114,6 +116,10 @@ function ConstructedInventoryDetail({ inventory }) { wsInventorySource.summary_fields?.current_job || wsInventorySource.summary_fields?.last_job || null; + const wsInventory = { + ...inventory, + ...wsInventorySource?.summary_fields?.inventory, + }; const { request: deleteInventory, error: deleteError } = useRequest( useCallback(async () => { @@ -180,19 +186,19 @@ function ConstructedInventoryDetail({ inventory }) { /> @@ -204,7 +210,7 @@ function ConstructedInventoryDetail({ inventory }) { /> @@ -266,22 +272,25 @@ function ConstructedInventoryDetail({ inventory }) { fullWidth label={t`Input Inventories`} value={ - + {inputInventories?.map((inputInventory) => ( - ( + + {content} + + )} > - - {inputInventory.name} - - + {inputInventory.name} + ))} - + } isEmpty={inputInventories?.length === 0} /> diff --git a/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js index e93f28f58b..e010b8916a 100644 --- a/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js +++ b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.js @@ -1,16 +1,17 @@ import { useState, useEffect } from 'react'; import useWebsocket from 'hooks/useWebsocket'; +import { InventorySourcesAPI } from 'api'; -export default function useWsInventorySourcesDetails(initialSources) { - const [sources, setSources] = useState(initialSources); +export default function useWsInventorySourcesDetails(initialSource) { + const [source, setSource] = useState(initialSource); const lastMessage = useWebsocket({ jobs: ['status_changed'], control: ['limit_reached_1'], }); useEffect(() => { - setSources(initialSources); - }, [initialSources]); + setSource(initialSource); + }, [initialSource]); useEffect( () => { @@ -21,22 +22,37 @@ export default function useWsInventorySourcesDetails(initialSources) { ) { return; } - const updateSource = { - ...sources, - summary_fields: { - ...sources.summary_fields, - current_job: { - id: lastMessage.unified_job_id, - status: lastMessage.status, - finished: lastMessage.finished, - }, - }, - }; - setSources(updateSource); + if ( + ['successful', 'failed', 'error', 'cancelled'].includes( + lastMessage.status + ) + ) { + fetchSource(); + } + setSource(updateSource(source, lastMessage)); }, [lastMessage] // eslint-disable-line react-hooks/exhaustive-deps ); - return sources; + async function fetchSource() { + const { data } = await InventorySourcesAPI.readDetail(source.id); + setSource(data); + } + + return source; +} + +function updateSource(source, message) { + return { + ...source, + summary_fields: { + ...source.summary_fields, + current_job: { + id: message.unified_job_id, + status: message.status, + finished: message.finished, + }, + }, + }; } diff --git a/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js index 25fb97850b..d1f1e17009 100644 --- a/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js +++ b/awx/ui/src/screens/Inventory/shared/useWsInventorySourcesDetails.test.js @@ -1,9 +1,12 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import WS from 'jest-websocket-mock'; +import { InventorySourcesAPI } from 'api'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import useWsInventorySourceDetails from './useWsInventorySourcesDetails'; +jest.mock('../../../api/models/InventorySources'); + function TestInner() { return
@@ -171,12 +187,16 @@ VariablesField.propTypes = { promptId: string, initialMode: oneOf([YAML_MODE, JSON_MODE]), onModeChange: func, + isRequired: bool, + validators: shape({}), }; VariablesField.defaultProps = { readOnly: false, promptId: null, initialMode: YAML_MODE, onModeChange: () => {}, + isRequired: false, + validators: {}, }; function VariablesFieldInternals({ @@ -192,6 +212,7 @@ function VariablesFieldInternals({ onExpand, setShouldValidate, handleChange, + isRequired, }) { const [field, meta, helpers] = useField(name); @@ -213,6 +234,12 @@ function VariablesFieldInternals({ {tooltip && } diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js index 1aaa2b7679..4263088d5f 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.js @@ -1,14 +1,54 @@ -/* eslint i18next/no-literal-string: "off" */ -import React from 'react'; +import React, { useState } from 'react'; +import { useHistory } from 'react-router-dom'; import { Card, PageSection } from '@patternfly/react-core'; +import { ConstructedInventoriesAPI, InventoriesAPI } from 'api'; import { CardBody } from 'components/Card'; +import ConstructedInventoryForm from '../shared/ConstructedInventoryForm'; function ConstructedInventoryAdd() { + const history = useHistory(); + const [submitError, setSubmitError] = useState(null); + + const handleCancel = () => { + history.push('/inventories'); + }; + + const handleSubmit = async (values) => { + try { + const { + data: { id: inventoryId }, + } = await ConstructedInventoriesAPI.create({ + ...values, + organization: values.organization?.id, + kind: 'constructed', + }); + /* eslint-disable no-await-in-loop, no-restricted-syntax */ + for (const inputInventory of values.inputInventories) { + await InventoriesAPI.associateInventory(inventoryId, inputInventory.id); + } + for (const instanceGroup of values.instanceGroups) { + await InventoriesAPI.associateInstanceGroup( + inventoryId, + instanceGroup.id + ); + } + /* eslint-enable no-await-in-loop, no-restricted-syntax */ + + history.push(`/inventories/constructed_inventory/${inventoryId}/details`); + } catch (error) { + setSubmitError(error); + } + }; + return ( -
Coming Soon!
+
diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js index 0a9a6eedd5..1272bf3b2e 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryAdd/ConstructedInventoryAdd.test.js @@ -1,15 +1,120 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import { createMemoryHistory } from 'history'; +import { + mountWithContexts, + waitForElement, +} from '../../../../testUtils/enzymeHelpers'; +import '@testing-library/jest-dom'; +import { ConstructedInventoriesAPI, InventoriesAPI } from 'api'; import ConstructedInventoryAdd from './ConstructedInventoryAdd'; +jest.mock('api'); + describe('', () => { - test('initially renders successfully', async () => { - let wrapper; + let wrapper; + let history; + + const formData = { + name: 'Mock', + description: 'Foo', + organization: { id: 1 }, + kind: 'constructed', + source_vars: 'plugin: constructed', + inputInventories: [{ id: 2 }], + instanceGroups: [], + }; + + beforeEach(async () => { + ConstructedInventoriesAPI.readOptions.mockResolvedValue({ + data: { + related: {}, + actions: { + POST: { + limit: { + label: 'Limit', + help_text: '', + }, + update_cache_timeout: { + label: 'Update cache timeout', + help_text: 'help', + }, + verbosity: { + label: 'Verbosity', + help_text: '', + }, + }, + }, + }, + }); + history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/add'], + }); + await act(async () => { + wrapper = mountWithContexts(, { + context: { router: { history } }, + }); + }); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('should navigate to inventories list on cancel', async () => { + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/add' + ); + await act(async () => { + wrapper.find('button[aria-label="Cancel"]').invoke('onClick')(); + }); + expect(history.location.pathname).toEqual('/inventories'); + }); + + test('should navigate to constructed inventory detail after successful submission', async () => { + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + ConstructedInventoriesAPI.create.mockResolvedValueOnce({ data: { id: 1 } }); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/add' + ); + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')(formData); + }); + wrapper.update(); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/1/details' + ); + }); + + test('should make expected api requests on submit', async () => { + ConstructedInventoriesAPI.create.mockResolvedValueOnce({ data: { id: 1 } }); + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')(formData); + }); + expect(ConstructedInventoriesAPI.create).toHaveBeenCalledTimes(1); + expect(InventoriesAPI.associateInventory).toHaveBeenCalledTimes(1); + expect(InventoriesAPI.associateInventory).toHaveBeenCalledWith(1, 2); + expect(InventoriesAPI.associateInstanceGroup).not.toHaveBeenCalled(); + }); + + test('unsuccessful form submission should show an error message', async () => { + const error = { + response: { + data: { detail: 'An error occurred' }, + }, + }; + ConstructedInventoriesAPI.create.mockImplementationOnce(() => + Promise.reject(error) + ); await act(async () => { wrapper = mountWithContexts(); }); - expect(wrapper.length).toBe(1); - expect(wrapper.find('ConstructedInventoryAdd').length).toBe(1); + expect(wrapper.find('FormSubmitError').length).toBe(0); + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')(formData); + }); + wrapper.update(); + expect(wrapper.find('FormSubmitError').length).toBe(1); }); }); diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js index a8cba4aeac..3dad28809f 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js @@ -323,7 +323,7 @@ describe(' for constructed inventories', () => { }); const history = createMemoryHistory({ initialEntries: [ - '/inventories/constructed_inventory/1/groups/2/nested_groupss', + '/inventories/constructed_inventory/1/groups/2/nested_groups', ], }); await act(async () => { diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js new file mode 100644 index 0000000000..6c1832c1d1 --- /dev/null +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js @@ -0,0 +1,229 @@ +import React, { useCallback, useEffect } from 'react'; +import { Formik, useField, useFormikContext } from 'formik'; +import { func, shape } from 'prop-types'; +import { t } from '@lingui/macro'; +import { ConstructedInventoriesAPI } from 'api'; +import { minMaxValue, required } from 'util/validators'; +import useRequest from 'hooks/useRequest'; +import { Form, FormGroup } from '@patternfly/react-core'; +import { VariablesField } from 'components/CodeEditor'; +import ContentError from 'components/ContentError'; +import ContentLoading from 'components/ContentLoading'; +import FormActionGroup from 'components/FormActionGroup/FormActionGroup'; +import FormField, { FormSubmitError } from 'components/FormField'; +import { FormFullWidthLayout, FormColumnLayout } from 'components/FormLayout'; +import InstanceGroupsLookup from 'components/Lookup/InstanceGroupsLookup'; +import InventoryLookup from 'components/Lookup/InventoryLookup'; +import OrganizationLookup from 'components/Lookup/OrganizationLookup'; +import Popover from 'components/Popover'; +import { VerbositySelectField } from 'components/VerbositySelectField'; + +import ConstructedInventoryHint from './ConstructedInventoryHint'; +import getInventoryHelpTextStrings from './Inventory.helptext'; + +const constructedPluginValidator = { + plugin: required(t`The plugin parameter is required.`), +}; + +function ConstructedInventoryFormFields({ inventory = {}, options }) { + const helpText = getInventoryHelpTextStrings(); + const { setFieldValue, setFieldTouched } = useFormikContext(); + + const [instanceGroupsField, , instanceGroupsHelpers] = + useField('instanceGroups'); + const [organizationField, organizationMeta, organizationHelpers] = + useField('organization'); + const [inputInventoriesField, inputInventoriesMeta, inputInventoriesHelpers] = + useField({ + name: 'inputInventories', + validate: (value) => { + if (value.length === 0) { + return t`This field must not be blank`; + } + return undefined; + }, + }); + const handleOrganizationUpdate = useCallback( + (value) => { + setFieldValue('organization', value); + setFieldTouched('organization', true, false); + }, + [setFieldValue, setFieldTouched] + ); + const handleInputInventoriesUpdate = useCallback( + (value) => { + setFieldValue('inputInventories', value); + setFieldTouched('inputInventories', true, false); + }, + [setFieldValue, setFieldTouched] + ); + + return ( + <> + + + organizationHelpers.setTouched()} + onChange={handleOrganizationUpdate} + validate={required(t`Select a value for this field`)} + value={organizationField.value} + required + /> + { + instanceGroupsHelpers.setValue(value); + }} + tooltip={t`Select the Instance Groups for this Inventory to run on.`} + /> + + } + validated={ + !inputInventoriesMeta.touched || !inputInventoriesMeta.error + ? 'default' + : 'error' + } + > + inputInventoriesHelpers.setTouched()} + onChange={handleInputInventoriesUpdate} + touched={inputInventoriesMeta.touched} + value={inputInventoriesField.value} + hideAdvancedInventories + multiple + required + /> + + + + + + + + + + + + ); +} + +function ConstructedInventoryForm({ onCancel, onSubmit, submitError }) { + const initialValues = { + description: '', + instanceGroups: [], + kind: 'constructed', + inputInventories: [], + limit: '', + name: '', + organization: null, + source_vars: '---', + update_cache_timeout: 0, + verbosity: 0, + }; + + const { + isLoading, + error, + request: fetchOptions, + result: options, + } = useRequest( + useCallback(async () => { + const res = await ConstructedInventoriesAPI.readOptions(); + const { data } = res; + return data.actions.POST; + }, []), + null + ); + + useEffect(() => { + fetchOptions(); + }, [fetchOptions]); + + if (isLoading || (!options && !error)) { + return ; + } + + if (error) { + return ; + } + + return ( + + {(formik) => ( +
+ + + + + +
+ )} +
+ ); +} + +ConstructedInventoryForm.propTypes = { + onCancel: func.isRequired, + onSubmit: func.isRequired, + submitError: shape({}), +}; + +ConstructedInventoryForm.defaultProps = { + submitError: null, +}; + +export default ConstructedInventoryForm; diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.test.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.test.js new file mode 100644 index 0000000000..e3f50f1b93 --- /dev/null +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.test.js @@ -0,0 +1,123 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { ConstructedInventoriesAPI } from 'api'; +import { + mountWithContexts, + waitForElement, +} from '../../../../testUtils/enzymeHelpers'; +import ConstructedInventoryForm from './ConstructedInventoryForm'; + +jest.mock('../../../api'); + +const mockFormValues = { + kind: 'constructed', + name: 'new constructed inventory', + description: '', + organization: { id: 1, name: 'mock organization' }, + instanceGroups: [], + source_vars: 'plugin: constructed', + inputInventories: [{ id: 100, name: 'East' }], +}; + +describe('', () => { + let wrapper; + const onSubmit = jest.fn(); + + beforeEach(async () => { + ConstructedInventoriesAPI.readOptions.mockResolvedValue({ + data: { + related: {}, + actions: { + POST: { + limit: { + label: 'Limit', + help_text: '', + }, + update_cache_timeout: { + label: 'Update cache timeout', + help_text: 'help', + }, + verbosity: { + label: 'Verbosity', + help_text: '', + }, + }, + }, + }, + }); + await act(async () => { + wrapper = mountWithContexts( + {}} onSubmit={onSubmit} /> + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('should show expected form fields', () => { + expect(wrapper.find('FormGroup[label="Name"]')).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Description"]')).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Organization"]')).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Instance Groups"]')).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Input Inventories"]')).toHaveLength( + 1 + ); + expect( + wrapper.find('FormGroup[label="Cache timeout (seconds)"]') + ).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Verbosity"]')).toHaveLength(1); + expect(wrapper.find('FormGroup[label="Limit"]')).toHaveLength(1); + expect(wrapper.find('VariablesField[label="Source vars"]')).toHaveLength(1); + expect(wrapper.find('ConstructedInventoryHint')).toHaveLength(1); + expect(wrapper.find('Button[aria-label="Save"]')).toHaveLength(1); + expect(wrapper.find('Button[aria-label="Cancel"]')).toHaveLength(1); + }); + + test('should show field error when form is saved without a input inventories', async () => { + const inventoryErrorHelper = 'div#input-inventories-lookup-helper'; + expect(wrapper.find(inventoryErrorHelper).length).toBe(0); + wrapper.find('input#name').simulate('change', { + target: { value: mockFormValues.name, name: 'name' }, + }); + await act(async () => { + wrapper.find('button[aria-label="Save"]').simulate('click'); + }); + wrapper.update(); + expect(wrapper.find(inventoryErrorHelper).length).toBe(1); + expect(wrapper.find(inventoryErrorHelper).text()).toContain( + 'This field must not be blank' + ); + expect(onSubmit).not.toHaveBeenCalled(); + }); + + test('should show field error when form is saved without constructed plugin parameter', async () => { + expect(wrapper.find('VariablesField .pf-m-error').length).toBe(0); + await act(async () => { + wrapper.find('VariablesField CodeEditor').invoke('onBlur')(''); + }); + wrapper.update(); + expect(wrapper.find('VariablesField .pf-m-error').length).toBe(1); + expect(wrapper.find('VariablesField .pf-m-error').text()).toBe( + 'The plugin parameter is required.' + ); + }); + + test('should throw content error when option request fails', async () => { + let newWrapper; + ConstructedInventoriesAPI.readOptions.mockImplementationOnce(() => + Promise.reject(new Error()) + ); + await act(async () => { + newWrapper = mountWithContexts( + {}} onSubmit={() => {}} /> + ); + }); + expect(newWrapper.find('ContentError').length).toBe(0); + newWrapper.update(); + expect(newWrapper.find('ContentError').length).toBe(1); + jest.clearAllMocks(); + }); +}); diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js new file mode 100644 index 0000000000..34a3ca48f1 --- /dev/null +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js @@ -0,0 +1,164 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import { + Alert, + AlertActionLink, + CodeBlock, + CodeBlockAction, + CodeBlockCode, + ClipboardCopyButton, +} from '@patternfly/react-core'; +import { + TableComposable, + Thead, + Tr, + Th, + Tbody, + Td, +} from '@patternfly/react-table'; +import { ExternalLinkAltIcon } from '@patternfly/react-icons'; +import getDocsBaseUrl from 'util/getDocsBaseUrl'; +import { useConfig } from 'contexts/Config'; + +function ConstructedInventoryHint() { + const config = useConfig(); + const [copied, setCopied] = React.useState(false); + + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const pluginSample = `plugin: constructed +strict: true +use_vars_plugins: true +groups: + shutdown: resolved_state == "shutdown" + shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" +compose: + resolved_state: state | default("running")`; + + return ( + + {t`View constructed plugin documentation here`}{' '} + + + } + > + {t`WIP - More to come...`} +
+
+ + + + {t`Parameter`} + {t`Description`} + + + + + + plugin +

{t`string`}

+

{t`required`}

+ + + {t`Token that ensures this is a source file + for the ‘constructed’ plugin.`} + + + + + strict +

{t`boolean`}

+ + + {t`If yes make invalid entries a fatal error, otherwise skip and + continue.`}{' '} +
+ {t`If users need feedback about the correctness + of their constructed groups, it is highly recommended + to use strict: true in the plugin configuration.`} + + + + + use_vars_plugins +

{t`string`}

+ + + {t`Normally, for performance reasons, vars plugins get + executed after the inventory sources complete the + base inventory, this option allows for getting vars + related to hosts/groups from those plugins.`} + + + + + groups +

{t`dictionary`}

+ + + {t`Add hosts to group based on Jinja2 conditionals.`} + + + + + compose +

{t`dictionary`}

+ + + {t`Create vars from jinja2 expressions.`} + + + +
+
+
+ {t`Sample constructed inventory plugin:`} + + onClick(e, pluginSample)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + {pluginSample} + +
+ ); +} + +export default ConstructedInventoryHint; diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js new file mode 100644 index 0000000000..e4745773f4 --- /dev/null +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js @@ -0,0 +1,46 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import ConstructedInventoryHint from './ConstructedInventoryHint'; + +jest.mock('../../../api'); + +describe('', () => { + test('should render link to docs', () => { + render(); + expect( + screen.getByRole('link', { + name: 'View constructed plugin documentation here', + }) + ).toBeInTheDocument(); + }); + + test('should expand hint details', () => { + const { container } = render(); + + expect(container.querySelector('table')).not.toBeInTheDocument(); + expect(container.querySelector('code')).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: 'Info alert details' })); + expect(container.querySelector('table')).toBeInTheDocument(); + expect(container.querySelector('code')).toBeInTheDocument(); + }); + + test('should copy sample plugin code block', () => { + Object.assign(navigator, { + clipboard: { + writeText: () => {}, + }, + }); + jest.spyOn(navigator.clipboard, 'writeText'); + + const { container } = render(); + fireEvent.click(screen.getByRole('button', { name: 'Info alert details' })); + fireEvent.click( + container.querySelector('button[aria-label="Copy to clipboard"]') + ); + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + expect.stringContaining('plugin: constructed') + ); + }); +}); diff --git a/awx/ui/src/screens/Inventory/shared/Inventory.helptext.js b/awx/ui/src/screens/Inventory/shared/Inventory.helptext.js index 158eaf62df..5345c115bb 100644 --- a/awx/ui/src/screens/Inventory/shared/Inventory.helptext.js +++ b/awx/ui/src/screens/Inventory/shared/Inventory.helptext.js @@ -19,6 +19,8 @@ const ansibleDocUrls = { rhv: 'https://docs.ansible.com/ansible/latest/collections/ovirt/ovirt/ovirt_inventory.html', vmware: 'https://docs.ansible.com/ansible/latest/collections/community/vmware/vmware_vm_inventory_inventory.html', + constructed: + 'https://docs.ansible.com/ansible/latest/collections/ansible/builtin/constructed_inventory.html', }; const getInventoryHelpTextStrings = () => ({ @@ -189,6 +191,42 @@ const getInventoryHelpTextStrings = () => ({ ); }, + constructedInventorySourceVars: () => { + const yamlExample = ` + --- + plugin: constructed + strict: true + use_vars_plugins: true + `; + return ( + <> + + Variables used to configure the constructed inventory plugin. For a + detailed description of how to configure this plugin, see{' '} + + constructed inventory + {' '} + plugin configuration guide. + +
+
+
+
+ + Variables must be in JSON or YAML syntax. Use the radio button to + toggle between the two. + +
+
+ YAML: +
{yamlExample}
+ + ); + }, sourcePath: t`The inventory file to be synced by this source. You can select from the dropdown or enter a file within the input.`, From 2bffddb5fb06ed74e483a911ed0ce096a0d9f1ca Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 23 Feb 2023 19:16:12 -0500 Subject: [PATCH 077/167] Add constructed inventory edit form --- awx/ui/src/api/models/Inventories.js | 8 + .../screens/Inventory/ConstructedInventory.js | 13 +- .../ConstructedInventoryAdd.test.js | 1 + .../ConstructedInventoryEdit.js | 119 ++++++++++- .../ConstructedInventoryEdit.test.js | 195 +++++++++++++++++- .../InventoryList/InventoryListItem.js | 2 +- .../shared/ConstructedInventoryForm.js | 29 ++- awx/ui/src/screens/Inventory/shared/utils.js | 1 + 8 files changed, 337 insertions(+), 31 deletions(-) diff --git a/awx/ui/src/api/models/Inventories.js b/awx/ui/src/api/models/Inventories.js index 8e586201b5..7e53e161d1 100644 --- a/awx/ui/src/api/models/Inventories.js +++ b/awx/ui/src/api/models/Inventories.js @@ -15,6 +15,7 @@ class Inventories extends InstanceGroupsMixin(Base) { this.promoteGroup = this.promoteGroup.bind(this); this.readInputInventories = this.readInputInventories.bind(this); this.associateInventory = this.associateInventory.bind(this); + this.disassociateInventory = this.disassociateInventory.bind(this); } readAccessList(id, params) { @@ -144,6 +145,13 @@ class Inventories extends InstanceGroupsMixin(Base) { id: inputInventoryId, }); } + + disassociateInventory(id, inputInventoryId) { + return this.http.post(`${this.baseUrl}${id}/input_inventories/`, { + id: inputInventoryId, + disassociate: true, + }); + } } export default Inventories; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventory.js b/awx/ui/src/screens/Inventory/ConstructedInventory.js index 086c755adb..ff02136101 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventory.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventory.js @@ -33,8 +33,8 @@ function ConstructedInventory({ setBreadcrumb }) { const { result: inventory, error: contentError, - isLoading: hasContentLoading, request: fetchInventory, + isLoading, } = useRequest( useCallback(async () => { const { data } = await ConstructedInventoriesAPI.readDetail( @@ -42,7 +42,7 @@ function ConstructedInventory({ setBreadcrumb }) { ); return data; }, [match.params.id]), - { isLoading: true } + { inventory: null, isLoading: true } ); useEffect(() => { @@ -78,7 +78,7 @@ function ConstructedInventory({ setBreadcrumb }) { { name: t`Job Templates`, link: `${match.url}/job_templates`, id: 5 }, ]; - if (hasContentLoading) { + if (isLoading) { return ( @@ -133,16 +133,13 @@ function ConstructedInventory({ setBreadcrumb }) { path="/inventories/constructed_inventory/:id/details" key="details" > - + , - + , ', () => { await act(async () => { wrapper = mountWithContexts(); }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); expect(wrapper.find('FormSubmitError').length).toBe(0); await act(async () => { wrapper.find('ConstructedInventoryForm').invoke('onSubmit')(formData); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js index a49e7eaaed..bb87534379 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.js @@ -1,11 +1,122 @@ -/* eslint i18next/no-literal-string: "off" */ -import React from 'react'; +import React, { useState, useCallback, useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; +import { ConstructedInventoriesAPI, InventoriesAPI } from 'api'; +import useRequest from 'hooks/useRequest'; import { CardBody } from 'components/Card'; +import ContentError from 'components/ContentError'; +import ContentLoading from 'components/ContentLoading'; +import ConstructedInventoryForm from '../shared/ConstructedInventoryForm'; + +function isEqual(array1, array2) { + return ( + array1.length === array2.length && + array1.every((element, index) => element.id === array2[index].id) + ); +} + +function ConstructedInventoryEdit({ inventory }) { + const history = useHistory(); + const [submitError, setSubmitError] = useState(null); + const detailsUrl = `/inventories/constructed_inventory/${inventory.id}/details`; + const constructedInventoryId = inventory.id; + + const { + result: { initialInstanceGroups, initialInputInventories }, + request: fetchedRelatedData, + error: contentError, + isLoading, + } = useRequest( + useCallback(async () => { + const [instanceGroupsResponse, inputInventoriesResponse] = + await Promise.all([ + InventoriesAPI.readInstanceGroups(constructedInventoryId), + InventoriesAPI.readInputInventories(constructedInventoryId), + ]); + + return { + initialInstanceGroups: instanceGroupsResponse.data.results, + initialInputInventories: inputInventoriesResponse.data.results, + }; + }, [constructedInventoryId]), + { + initialInstanceGroups: [], + initialInputInventories: [], + isLoading: true, + } + ); + useEffect(() => { + fetchedRelatedData(); + }, [fetchedRelatedData]); + + const handleSubmit = async (values) => { + const { + instanceGroups, + inputInventories, + organization, + ...remainingValues + } = values; + + remainingValues.organization = organization.id; + remainingValues.kind = 'constructed'; + + try { + await Promise.all([ + ConstructedInventoriesAPI.update( + constructedInventoryId, + remainingValues + ), + InventoriesAPI.orderInstanceGroups( + constructedInventoryId, + instanceGroups, + initialInstanceGroups + ), + ]); + /* eslint-disable no-await-in-loop, no-restricted-syntax */ + // Resolve Promises sequentially to avoid race condition + if (!isEqual(initialInputInventories, values.inputInventories)) { + for (const inputInventory of initialInputInventories) { + await InventoriesAPI.disassociateInventory( + constructedInventoryId, + inputInventory.id + ); + } + for (const inputInventory of values.inputInventories) { + await InventoriesAPI.associateInventory( + constructedInventoryId, + inputInventory.id + ); + } + } + /* eslint-enable no-await-in-loop, no-restricted-syntax */ + + history.push( + `/inventories/constructed_inventory/${constructedInventoryId}/details` + ); + } catch (error) { + setSubmitError(error); + } + }; + + const handleCancel = () => history.push(detailsUrl); + + if (isLoading) { + return ; + } + + if (contentError) { + return ; + } -function ConstructedInventoryEdit() { return ( -
Coming Soon!
+
); } diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js index 02b0747880..ee52a8ca1b 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventoryEdit/ConstructedInventoryEdit.test.js @@ -1,15 +1,196 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; +import { createMemoryHistory } from 'history'; + +import { + mountWithContexts, + waitForElement, +} from '../../../../testUtils/enzymeHelpers'; +import { ConstructedInventoriesAPI, InventoriesAPI } from 'api'; + import ConstructedInventoryEdit from './ConstructedInventoryEdit'; +jest.mock('api'); describe('', () => { - test('initially renders successfully', async () => { - let wrapper; - await act(async () => { - wrapper = mountWithContexts(); + let wrapper; + let history; + + const mockInv = { + name: 'Mock', + id: 7, + description: 'Foo', + organization: { id: 1 }, + kind: 'constructed', + source_vars: 'plugin: constructed', + limit: 'product_dev', + }; + const associatedInstanceGroups = [ + { + id: 1, + name: 'Foo', + }, + ]; + const associatedInputInventories = [ + { + id: 123, + name: 'input_inventory_123', + }, + { + id: 456, + name: 'input_inventory_456', + }, + ]; + const mockFormValues = { + kind: 'constructed', + name: 'new constructed inventory', + description: '', + organization: { id: 1, name: 'mock organization' }, + instanceGroups: associatedInstanceGroups, + source_vars: 'plugin: constructed', + inputInventories: associatedInputInventories, + }; + + beforeEach(async () => { + ConstructedInventoriesAPI.readOptions.mockResolvedValue({ + data: { + related: {}, + actions: { + POST: { + limit: { + label: 'Limit', + help_text: '', + }, + update_cache_timeout: { + label: 'Update cache timeout', + help_text: 'help', + }, + verbosity: { + label: 'Verbosity', + help_text: '', + }, + }, + }, + }, }); - expect(wrapper.length).toBe(1); - expect(wrapper.find('ConstructedInventoryEdit').length).toBe(1); + InventoriesAPI.readInstanceGroups.mockResolvedValue({ + data: { + results: associatedInstanceGroups, + }, + }); + InventoriesAPI.readInputInventories.mockResolvedValue({ + data: { + results: [ + { + id: 456, + name: 'input_inventory_456', + }, + ], + }, + }); + history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/7/edit'], + }); + await act(async () => { + wrapper = mountWithContexts( + , + { + context: { router: { history } }, + } + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('should navigate to inventories details on cancel', async () => { + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/7/edit' + ); + await act(async () => { + wrapper.find('button[aria-label="Cancel"]').invoke('onClick')(); + }); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/7/details' + ); + }); + + test('should navigate to constructed inventory detail after successful submission', async () => { + ConstructedInventoriesAPI.update.mockResolvedValueOnce({ data: { id: 1 } }); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/7/edit' + ); + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')( + mockFormValues + ); + }); + wrapper.update(); + expect(history.location.pathname).toEqual( + '/inventories/constructed_inventory/7/details' + ); + }); + + test('should make expected api requests on submit', async () => { + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')( + mockFormValues + ); + }); + expect(ConstructedInventoriesAPI.update).toHaveBeenCalledTimes(1); + expect(InventoriesAPI.associateInstanceGroup).not.toHaveBeenCalled(); + expect(InventoriesAPI.disassociateInventory).toHaveBeenCalledTimes(1); + expect(InventoriesAPI.associateInventory).toHaveBeenCalledTimes(2); + expect(InventoriesAPI.associateInventory).toHaveBeenNthCalledWith( + 1, + 7, + 123 + ); + expect(InventoriesAPI.associateInventory).toHaveBeenNthCalledWith( + 2, + 7, + 456 + ); + }); + + test('should throw content error', async () => { + expect(wrapper.find('ContentError').length).toBe(0); + InventoriesAPI.readInstanceGroups.mockImplementationOnce(() => + Promise.reject(new Error()) + ); + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + expect(wrapper.find('ContentError').length).toBe(1); + }); + + test('unsuccessful form submission should show an error message', async () => { + const error = { + response: { + data: { detail: 'An error occurred' }, + }, + }; + ConstructedInventoriesAPI.update.mockImplementationOnce(() => + Promise.reject(error) + ); + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + expect(wrapper.find('FormSubmitError').length).toBe(0); + await act(async () => { + wrapper.find('ConstructedInventoryForm').invoke('onSubmit')( + mockFormValues + ); + }); + wrapper.update(); + expect(wrapper.find('FormSubmitError').length).toBe(1); }); }); diff --git a/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js b/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js index 3828401045..b0a8bdfc38 100644 --- a/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js +++ b/awx/ui/src/screens/Inventory/InventoryList/InventoryListItem.js @@ -146,7 +146,7 @@ function InventoryListItem({ aria-label={t`Edit Inventory`} variant="plain" component={Link} - to={`${getInventoryPath(inventory)}edit`} + to={`${getInventoryPath(inventory)}/edit`} > diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js index 6c1832c1d1..470ab61366 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js @@ -158,18 +158,25 @@ function ConstructedInventoryFormFields({ inventory = {}, options }) { ); } -function ConstructedInventoryForm({ onCancel, onSubmit, submitError }) { +function ConstructedInventoryForm({ + constructedInventory, + instanceGroups, + inputInventories, + onCancel, + onSubmit, + submitError, +}) { const initialValues = { - description: '', - instanceGroups: [], kind: 'constructed', - inputInventories: [], - limit: '', - name: '', - organization: null, - source_vars: '---', - update_cache_timeout: 0, - verbosity: 0, + description: constructedInventory?.description || '', + instanceGroups: instanceGroups || [], + inputInventories: inputInventories || [], + limit: constructedInventory?.limit || '', + name: constructedInventory?.name || '', + organization: constructedInventory?.summary_fields?.organization || null, + update_cache_timeout: constructedInventory?.update_cache_timeout || 0, + verbosity: constructedInventory?.verbosity || 0, + source_vars: constructedInventory?.source_vars || '---', }; const { @@ -204,7 +211,7 @@ function ConstructedInventoryForm({ onCancel, onSubmit, submitError }) {
- + {submitError && } { export default parseHostFilter; export function getInventoryPath(inventory) { + if (!inventory) return '/inventories'; const url = { '': `/inventories/inventory/${inventory.id}`, smart: `/inventories/smart_inventory/${inventory.id}`, From ab0463bf2a8bbdd456b14d76979d23701ce1967f Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 3 Mar 2023 08:28:56 -0800 Subject: [PATCH 078/167] Ordered m2m for Inventory/Inventory relationship (#13602) Including changes to our custom Ordered m2m field which previously broke if the source and target model was the same. Signed-off-by: Rick Elrod Co-authored-by: Alan Rominger --- awx/main/fields.py | 23 ++++++---- .../migrations/0182_constructed_inventory.py | 18 +++++++- awx/main/models/__init__.py | 1 + awx/main/models/inventory.py | 14 ++++++- .../test_instance_group_ordering.py | 42 ++++++++++++++++++- awx/main/tests/functional/test_instances.py | 3 +- 6 files changed, 90 insertions(+), 11 deletions(-) diff --git a/awx/main/fields.py b/awx/main/fields.py index 5d3710ed51..ce548fb58c 100644 --- a/awx/main/fields.py +++ b/awx/main/fields.py @@ -954,6 +954,16 @@ class OrderedManyToManyDescriptor(ManyToManyDescriptor): def get_queryset(self): return super(OrderedManyRelatedManager, self).get_queryset().order_by('%s__position' % self.through._meta.model_name) + def add(self, *objects): + if len(objects) > 1: + raise RuntimeError('Ordered many-to-many fields do not support multiple objects') + return super().add(*objects) + + def remove(self, *objects): + if len(objects) > 1: + raise RuntimeError('Ordered many-to-many fields do not support multiple objects') + return super().remove(*objects) + return OrderedManyRelatedManager return add_custom_queryset_to_many_related_manager( @@ -971,13 +981,12 @@ class OrderedManyToManyField(models.ManyToManyField): by a special `position` column on the M2M table """ - def _update_m2m_position(self, sender, **kwargs): - if kwargs.get('action') in ('post_add', 'post_remove'): - order_with_respect_to = None - for field in sender._meta.local_fields: - if isinstance(field, models.ForeignKey) and isinstance(kwargs['instance'], field.related_model): - order_with_respect_to = field.name - for i, ig in enumerate(sender.objects.filter(**{order_with_respect_to: kwargs['instance'].pk})): + def _update_m2m_position(self, sender, instance, action, **kwargs): + if action in ('post_add', 'post_remove'): + descriptor = getattr(instance, self.name) + order_with_respect_to = descriptor.source_field_name + + for i, ig in enumerate(sender.objects.filter(**{order_with_respect_to: instance.pk})): if ig.position != i: ig.position = i ig.save() diff --git a/awx/main/migrations/0182_constructed_inventory.py b/awx/main/migrations/0182_constructed_inventory.py index a41e303597..10ece7b2f4 100644 --- a/awx/main/migrations/0182_constructed_inventory.py +++ b/awx/main/migrations/0182_constructed_inventory.py @@ -1,6 +1,8 @@ # Generated by Django 3.2.16 on 2022-12-07 14:20 +import awx.main.fields from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -9,13 +11,27 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='InventoryConstructedInventoryMembership', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('position', models.PositiveIntegerField(db_index=True, default=None, null=True)), + ( + 'constructed_inventory', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.inventory', related_name='constructed_inventory_memberships'), + ), + ('input_inventory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.inventory')), + ], + ), migrations.AddField( model_name='inventory', name='input_inventories', - field=models.ManyToManyField( + field=awx.main.fields.OrderedManyToManyField( blank=True, + through_fields=('constructed_inventory', 'input_inventory'), help_text='Only valid for constructed inventories, this links to the inventories that will be used.', related_name='destination_inventories', + through='main.InventoryConstructedInventoryMembership', to='main.Inventory', ), ), diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 8a608aeead..19a422740c 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -18,6 +18,7 @@ from awx.main.models.inventory import ( # noqa HostMetric, HostMetricSummaryMonthly, Inventory, + InventoryConstructedInventoryMembership, InventorySource, InventoryUpdate, SmartInventoryMembership, diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 75609b91b6..978e520278 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -58,6 +58,16 @@ __all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate', ' logger = logging.getLogger('awx.main.models.inventory') +class InventoryConstructedInventoryMembership(models.Model): + constructed_inventory = models.ForeignKey('Inventory', on_delete=models.CASCADE, related_name='constructed_inventory_memberships') + input_inventory = models.ForeignKey('Inventory', on_delete=models.CASCADE) + position = models.PositiveIntegerField( + null=True, + default=None, + db_index=True, + ) + + class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): """ an inventory source contains lists and hosts. @@ -140,11 +150,13 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): default=None, help_text=_('Filter that will be applied to the hosts of this inventory.'), ) - input_inventories = models.ManyToManyField( + input_inventories = OrderedManyToManyField( 'Inventory', blank=True, + through_fields=('constructed_inventory', 'input_inventory'), related_name='destination_inventories', help_text=_('Only valid for constructed inventories, this links to the inventories that will be used.'), + through='InventoryConstructedInventoryMembership', ) instance_groups = OrderedManyToManyField( 'InstanceGroup', diff --git a/awx/main/tests/functional/test_instance_group_ordering.py b/awx/main/tests/functional/test_instance_group_ordering.py index 42c69ffc7f..fb8c0db168 100644 --- a/awx/main/tests/functional/test_instance_group_ordering.py +++ b/awx/main/tests/functional/test_instance_group_ordering.py @@ -1,6 +1,6 @@ import pytest -from awx.main.models import InstanceGroup +from awx.main.models import InstanceGroup, Inventory @pytest.fixture(scope='function') @@ -38,6 +38,16 @@ def test_instance_group_ordering(source_model): assert source_model.instance_groups.through.objects.count() == 0 +@pytest.mark.django_db +@pytest.mark.parametrize('source_model', ['job_template', 'inventory', 'organization'], indirect=True) +def test_instance_group_bulk_add(source_model): + groups = [InstanceGroup.objects.create(name='host-%d' % i) for i in range(5)] + groups.reverse() + with pytest.raises(RuntimeError) as err: + source_model.instance_groups.add(*groups) + assert 'Ordered many-to-many fields do not support multiple objects' in str(err) + + @pytest.mark.django_db @pytest.mark.parametrize('source_model', ['job_template', 'inventory', 'organization'], indirect=True) def test_instance_group_middle_deletion(source_model): @@ -66,3 +76,33 @@ def test_explicit_ordering(source_model): assert [g.name for g in source_model.instance_groups.all()] == ['host-4', 'host-3', 'host-2', 'host-1', 'host-0'] assert [g.name for g in source_model.instance_groups.order_by('name').all()] == ['host-0', 'host-1', 'host-2', 'host-3', 'host-4'] + + +@pytest.mark.django_db +def test_input_inventories_ordering(): + constructed_inventory = Inventory.objects.create(name='my_constructed', kind='constructed') + input_inventories = [Inventory.objects.create(name='inv-%d' % i) for i in range(5)] + input_inventories.reverse() + for inv in input_inventories: + constructed_inventory.input_inventories.add(inv) + + assert [g.name for g in constructed_inventory.input_inventories.all()] == ['inv-4', 'inv-3', 'inv-2', 'inv-1', 'inv-0'] + assert [(row.position, row.input_inventory.name) for row in constructed_inventory.input_inventories.through.objects.all()] == [ + (0, 'inv-4'), + (1, 'inv-3'), + (2, 'inv-2'), + (3, 'inv-1'), + (4, 'inv-0'), + ] + + constructed_inventory.input_inventories.remove(input_inventories[0]) + assert [g.name for g in constructed_inventory.input_inventories.all()] == ['inv-3', 'inv-2', 'inv-1', 'inv-0'] + assert [(row.position, row.input_inventory.name) for row in constructed_inventory.input_inventories.through.objects.all()] == [ + (0, 'inv-3'), + (1, 'inv-2'), + (2, 'inv-1'), + (3, 'inv-0'), + ] + + constructed_inventory.input_inventories.clear() + assert constructed_inventory.input_inventories.through.objects.count() == 0 diff --git a/awx/main/tests/functional/test_instances.py b/awx/main/tests/functional/test_instances.py index 9db370225c..4ed652179d 100644 --- a/awx/main/tests/functional/test_instances.py +++ b/awx/main/tests/functional/test_instances.py @@ -94,7 +94,8 @@ def test_instance_dup(org_admin, organization, project, instance_factory, instan 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) + project.organization.instance_groups.add(ig_all) + project.organization.instance_groups.add(ig_dup) actual_num_instances = Instance.objects.count() list_response = get(reverse('api:instance_list'), user=system_auditor) api_num_instances_auditor = list(list_response.data.items())[0][1] From 054a70bda48f18cc55f9e2d2d6201aae7f8a93a2 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Tue, 28 Feb 2023 16:03:35 -0500 Subject: [PATCH 079/167] Filter constructed inventory hosts from smart inventory host lookup --- awx/ui/src/components/Lookup/HostFilterLookup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/ui/src/components/Lookup/HostFilterLookup.js b/awx/ui/src/components/Lookup/HostFilterLookup.js index 46e0a3dd1f..ce02a9802b 100644 --- a/awx/ui/src/components/Lookup/HostFilterLookup.js +++ b/awx/ui/src/components/Lookup/HostFilterLookup.js @@ -84,6 +84,7 @@ const QS_CONFIG = getQSConfig( page: 1, page_size: 5, order_by: 'name', + not__inventory__kind: 'constructed', }, ['id', 'page', 'page_size', 'inventory'] ); From ce4c1c11b3e818ca17d7cf4db2bad6ba08becf17 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 14 Mar 2023 15:26:00 -0400 Subject: [PATCH 080/167] Remove towervars from constructed inventory hosts (#13686) --- awx/main/management/commands/inventory_import.py | 8 +++++++- awx/main/models/inventory.py | 13 ++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py index 6fa5b59346..8150936054 100644 --- a/awx/main/management/commands/inventory_import.py +++ b/awx/main/management/commands/inventory_import.py @@ -654,13 +654,19 @@ class Command(BaseCommand): mem_host = self.all_group.all_hosts[mem_host_name] import_vars = mem_host.variables host_desc = import_vars.pop('_awx_description', 'imported') - host_attrs = dict(variables=json.dumps(import_vars), description=host_desc) + host_attrs = dict(description=host_desc) enabled = self._get_enabled(mem_host.variables) if enabled is not None: host_attrs['enabled'] = enabled if self.instance_id_var: instance_id = self._get_instance_id(mem_host.variables) host_attrs['instance_id'] = instance_id + if self.inventory.kind == 'constructed': + # remote towervars so the constructed hosts do not have extra variables + for prefix in ('host', 'tower'): + for var in ('remote_{}_enabled', 'remote_{}_id'): + import_vars.pop(var.format(prefix), None) + host_attrs['variables'] = json.dumps(import_vars) try: sanitize_jinja(mem_host_name) except ValueError as e: diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 978e520278..010cfaa342 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -357,13 +357,12 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): for host in hosts: data['_meta']['hostvars'][host.name] = host.variables_dict if towervars: - tower_dict = dict( - remote_tower_enabled=str(host.enabled).lower(), - remote_tower_id=host.id, - remote_host_enabled=str(host.enabled).lower(), - remote_host_id=host.id, - ) - data['_meta']['hostvars'][host.name].update(tower_dict) + for prefix in ('host', 'tower'): + tower_dict = { + f'remote_{prefix}_enabled': str(host.enabled).lower(), + f'remote_{prefix}_id': host.id, + } + data['_meta']['hostvars'][host.name].update(tower_dict) return data From 771b831da81b08d5348c59c56e0acec14f57cb7b Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 14 Mar 2023 14:17:45 -0400 Subject: [PATCH 081/167] Fail constructed inventory if ANY source is unparsed --- awx/main/models/inventory.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 010cfaa342..c8f609b2ca 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -1643,8 +1643,9 @@ class constructed(PluginFileInjector): def build_env(self, *args, **kwargs): env = super().build_env(*args, **kwargs) - # Enable all types of inventory plugins so we pick up the script files from source inventories - del env['ANSIBLE_INVENTORY_ENABLED'] + # Enable script inventory plugin so we pick up the script files from source inventories + env['ANSIBLE_INVENTORY_ENABLED'] += ',script' + env['ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED'] = 'True' return env From aa631a1ba7a6451830c9f4fd55c2d17248584146 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Wed, 15 Mar 2023 10:35:12 -0400 Subject: [PATCH 082/167] [constructed-inventory] Allow filtering based on facts (#13678) * initial functional filter-on-facts functionality * Move facts to its own module to make interface more coherent * Update test --- awx/main/models/jobs.py | 115 +-------------------- awx/main/tasks/facts.py | 126 ++++++++++++++++++++++++ awx/main/tasks/jobs.py | 37 +++++-- awx/main/tests/unit/models/test_jobs.py | 32 +++--- 4 files changed, 176 insertions(+), 134 deletions(-) create mode 100644 awx/main/tasks/facts.py diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 61b87f4807..ae9e66ae5f 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -2,12 +2,8 @@ # All Rights Reserved. # Python -import codecs -import datetime import logging -import os import time -import json from urllib.parse import urljoin @@ -15,11 +11,8 @@ from urllib.parse import urljoin from django.conf import settings from django.core.exceptions import ValidationError from django.db import models -from django.db.models.query import QuerySet # from django.core.cache import cache -from django.utils.encoding import smart_str -from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from django.core.exceptions import FieldDoesNotExist @@ -44,7 +37,7 @@ from awx.main.models.notifications import ( NotificationTemplate, JobNotificationMixin, ) -from awx.main.utils import parse_yaml_or_json, getattr_dne, NullablePromptPseudoField, polymorphic, log_excess_runtime +from awx.main.utils import parse_yaml_or_json, getattr_dne, NullablePromptPseudoField, polymorphic from awx.main.fields import ImplicitRoleField, AskForField, JSONBlob, OrderedManyToManyField from awx.main.models.mixins import ( ResourceMixin, @@ -60,8 +53,6 @@ from awx.main.constants import JOB_VARIABLE_PREFIXES logger = logging.getLogger('awx.main.models.jobs') -analytics_logger = logging.getLogger('awx.analytics.job_events') -system_tracking_logger = logging.getLogger('awx.analytics.system_tracking') __all__ = ['JobTemplate', 'JobLaunchConfig', 'Job', 'JobHostSummary', 'SystemJobTemplate', 'SystemJob'] @@ -848,110 +839,6 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana def get_notification_friendly_name(self): return "Job" - def _get_inventory_hosts(self, only=('name', 'ansible_facts', 'ansible_facts_modified', 'modified', 'inventory_id'), **filters): - """Return value is an iterable for the relevant hosts for this job""" - if not self.inventory: - return [] - host_queryset = self.inventory.hosts.only(*only) - if filters: - host_queryset = host_queryset.filter(**filters) - host_queryset = self.inventory.get_sliced_hosts(host_queryset, self.job_slice_number, self.job_slice_count) - if isinstance(host_queryset, QuerySet): - return host_queryset.iterator() - return host_queryset - - @log_excess_runtime(logger, debug_cutoff=0.01, msg='Job {job_id} host facts prepared for {written_ct} hosts, took {delta:.3f} s', add_log_data=True) - def start_job_fact_cache(self, destination, log_data, timeout=None): - self.log_lifecycle("start_job_fact_cache") - log_data['job_id'] = self.id - log_data['written_ct'] = 0 - os.makedirs(destination, mode=0o700) - - if timeout is None: - timeout = settings.ANSIBLE_FACT_CACHE_TIMEOUT - if timeout > 0: - # exclude hosts with fact data older than `settings.ANSIBLE_FACT_CACHE_TIMEOUT seconds` - timeout = now() - datetime.timedelta(seconds=timeout) - hosts = self._get_inventory_hosts(ansible_facts_modified__gte=timeout) - else: - hosts = self._get_inventory_hosts() - - last_filepath_written = None - for host in hosts: - filepath = os.sep.join(map(str, [destination, host.name])) - if not os.path.realpath(filepath).startswith(destination): - system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) - continue - try: - with codecs.open(filepath, 'w', encoding='utf-8') as f: - os.chmod(f.name, 0o600) - json.dump(host.ansible_facts, f) - log_data['written_ct'] += 1 - last_filepath_written = filepath - except IOError: - system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) - continue - # make note of the time we wrote the last file so we can check if any file changed later - if last_filepath_written: - return os.path.getmtime(last_filepath_written) - return None - - @log_excess_runtime( - logger, - debug_cutoff=0.01, - msg='Job {job_id} host facts: updated {updated_ct}, cleared {cleared_ct}, unchanged {unmodified_ct}, took {delta:.3f} s', - add_log_data=True, - ) - def finish_job_fact_cache(self, destination, facts_write_time, log_data): - self.log_lifecycle("finish_job_fact_cache") - log_data['job_id'] = self.id - log_data['updated_ct'] = 0 - log_data['unmodified_ct'] = 0 - log_data['cleared_ct'] = 0 - hosts_to_update = [] - for host in self._get_inventory_hosts(): - filepath = os.sep.join(map(str, [destination, host.name])) - if not os.path.realpath(filepath).startswith(destination): - system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) - continue - if os.path.exists(filepath): - # If the file changed since we wrote the last facts file, pre-playbook run... - modified = os.path.getmtime(filepath) - if (not facts_write_time) or modified > facts_write_time: - with codecs.open(filepath, 'r', encoding='utf-8') as f: - try: - ansible_facts = json.load(f) - except ValueError: - continue - host.ansible_facts = ansible_facts - host.ansible_facts_modified = now() - hosts_to_update.append(host) - system_tracking_logger.info( - 'New fact for inventory {} host {}'.format(smart_str(host.inventory.name), smart_str(host.name)), - extra=dict( - inventory_id=host.inventory.id, - host_name=host.name, - ansible_facts=host.ansible_facts, - ansible_facts_modified=host.ansible_facts_modified.isoformat(), - job_id=self.id, - ), - ) - log_data['updated_ct'] += 1 - else: - log_data['unmodified_ct'] += 1 - else: - # if the file goes missing, ansible removed it (likely via clear_facts) - host.ansible_facts = {} - host.ansible_facts_modified = now() - hosts_to_update.append(host) - system_tracking_logger.info('Facts cleared for inventory {} host {}'.format(smart_str(host.inventory.name), smart_str(host.name))) - log_data['cleared_ct'] += 1 - if len(hosts_to_update) > 100: - self.inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) - hosts_to_update = [] - if hosts_to_update: - self.inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) - class LaunchTimeConfigBase(BaseModel): """ diff --git a/awx/main/tasks/facts.py b/awx/main/tasks/facts.py new file mode 100644 index 0000000000..ba48bc2249 --- /dev/null +++ b/awx/main/tasks/facts.py @@ -0,0 +1,126 @@ +import codecs +import datetime +import os +import json +import logging + +# Django +from django.conf import settings +from django.db.models.query import QuerySet +from django.utils.encoding import smart_str +from django.utils.timezone import now + +# AWX +from awx.main.utils.common import log_excess_runtime + + +logger = logging.getLogger('awx.main.tasks.facts') +system_tracking_logger = logging.getLogger('awx.analytics.system_tracking') + + +def _get_inventory_hosts(inventory, slice_number, slice_count, only=('name', 'ansible_facts', 'ansible_facts_modified', 'modified', 'inventory_id'), **filters): + """Return value is an iterable for the relevant hosts for this job""" + if not inventory: + return [] + host_queryset = inventory.hosts.only(*only) + if filters: + host_queryset = host_queryset.filter(**filters) + host_queryset = inventory.get_sliced_hosts(host_queryset, slice_number, slice_count) + if isinstance(host_queryset, QuerySet): + return host_queryset.iterator() + return host_queryset + + +@log_excess_runtime(logger, debug_cutoff=0.01, msg='Inventory {inventory_id} host facts prepared for {written_ct} hosts, took {delta:.3f} s', add_log_data=True) +def start_fact_cache(inventory, destination, log_data, timeout=None, slice_number=0, slice_count=1): + log_data['inventory_id'] = inventory.id + log_data['written_ct'] = 0 + try: + os.makedirs(destination, mode=0o700) + except FileExistsError: + pass + + if timeout is None: + timeout = settings.ANSIBLE_FACT_CACHE_TIMEOUT + if timeout > 0: + # exclude hosts with fact data older than `settings.ANSIBLE_FACT_CACHE_TIMEOUT seconds` + timeout = now() - datetime.timedelta(seconds=timeout) + hosts = _get_inventory_hosts(inventory, slice_number, slice_count, ansible_facts_modified__gte=timeout) + else: + hosts = _get_inventory_hosts(inventory, slice_number, slice_count) + + last_filepath_written = None + for host in hosts: + filepath = os.sep.join(map(str, [destination, host.name])) + if not os.path.realpath(filepath).startswith(destination): + system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) + continue + try: + with codecs.open(filepath, 'w', encoding='utf-8') as f: + os.chmod(f.name, 0o600) + json.dump(host.ansible_facts, f) + log_data['written_ct'] += 1 + last_filepath_written = filepath + except IOError: + system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) + continue + # make note of the time we wrote the last file so we can check if any file changed later + if last_filepath_written: + return os.path.getmtime(last_filepath_written) + return None + + +@log_excess_runtime( + logger, + debug_cutoff=0.01, + msg='Inventory {inventory_id} host facts: updated {updated_ct}, cleared {cleared_ct}, unchanged {unmodified_ct}, took {delta:.3f} s', + add_log_data=True, +) +def finish_fact_cache(inventory, destination, facts_write_time, log_data, slice_number=0, slice_count=1, job_id=None): + log_data['inventory_id'] = inventory.id + log_data['updated_ct'] = 0 + log_data['unmodified_ct'] = 0 + log_data['cleared_ct'] = 0 + hosts_to_update = [] + for host in _get_inventory_hosts(inventory, slice_number, slice_count): + filepath = os.sep.join(map(str, [destination, host.name])) + if not os.path.realpath(filepath).startswith(destination): + system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) + continue + if os.path.exists(filepath): + # If the file changed since we wrote the last facts file, pre-playbook run... + modified = os.path.getmtime(filepath) + if (not facts_write_time) or modified > facts_write_time: + with codecs.open(filepath, 'r', encoding='utf-8') as f: + try: + ansible_facts = json.load(f) + except ValueError: + continue + host.ansible_facts = ansible_facts + host.ansible_facts_modified = now() + hosts_to_update.append(host) + system_tracking_logger.info( + 'New fact for inventory {} host {}'.format(smart_str(host.inventory.name), smart_str(host.name)), + extra=dict( + inventory_id=host.inventory.id, + host_name=host.name, + ansible_facts=host.ansible_facts, + ansible_facts_modified=host.ansible_facts_modified.isoformat(), + job_id=job_id, + ), + ) + log_data['updated_ct'] += 1 + else: + log_data['unmodified_ct'] += 1 + else: + # if the file goes missing, ansible removed it (likely via clear_facts) + host.ansible_facts = {} + host.ansible_facts_modified = now() + hosts_to_update.append(host) + system_tracking_logger.info('Facts cleared for inventory {} host {}'.format(smart_str(host.inventory.name), smart_str(host.name))) + log_data['cleared_ct'] += 1 + if len(hosts_to_update) > 100: + inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) + hosts_to_update = [] + if hosts_to_update: + inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index ef73caacf5..1bb886a557 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -63,6 +63,7 @@ from awx.main.tasks.callback import ( ) from awx.main.tasks.signals import with_signal_handling, signal_callback from awx.main.tasks.receptor import AWXReceptorJob +from awx.main.tasks.facts import start_fact_cache, finish_fact_cache from awx.main.exceptions import AwxTaskError, PostRunError, ReceptorNodeNotFound from awx.main.utils.ansible import read_ansible_config from awx.main.utils.execution_environments import CONTAINER_ROOT, to_container_path @@ -455,6 +456,9 @@ class BaseTask(object): instance.ansible_version = ansible_version_info instance.save(update_fields=['ansible_version']) + def should_use_fact_cache(self): + return False + @with_path_cleanup @with_signal_handling def run(self, pk, **kwargs): @@ -553,7 +557,8 @@ class BaseTask(object): params['module'] = self.build_module_name(self.instance) params['module_args'] = self.build_module_args(self.instance) - if getattr(self.instance, 'use_fact_cache', False): + # TODO: refactor into a better BasTask method + if self.should_use_fact_cache(): # Enable Ansible fact cache. params['fact_cache_type'] = 'jsonfile' else: @@ -1008,6 +1013,9 @@ class RunJob(SourceControlMixin, BaseTask): return args + def should_use_fact_cache(self): + return self.instance.use_fact_cache + def build_playbook_path_relative_to_cwd(self, job, private_data_dir): return job.playbook @@ -1073,8 +1081,14 @@ class RunJob(SourceControlMixin, BaseTask): # Fetch "cached" fact data from prior runs and put on the disk # where ansible expects to find it - if job.use_fact_cache: - self.facts_write_time = self.instance.start_job_fact_cache(os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache')) + if self.should_use_fact_cache(): + job.log_lifecycle("start_job_fact_cache") + self.facts_write_time = start_fact_cache( + job.inventory, + os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache'), + slice_number=job.job_slice_number, + slice_count=job.job_slice_count, + ) def build_project_dir(self, job, private_data_dir): self.sync_and_copy(job.project, private_data_dir, scm_branch=job.scm_branch) @@ -1088,10 +1102,15 @@ class RunJob(SourceControlMixin, BaseTask): # actual `run()` call; this _usually_ means something failed in # the pre_run_hook method return - if job.use_fact_cache: - job.finish_job_fact_cache( + if self.should_use_fact_cache(): + job.log_lifecycle("finish_job_fact_cache") + finish_fact_cache( + job.inventory, os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache'), - self.facts_write_time, + facts_write_time=self.facts_write_time, + slice_number=job.job_slice_number, + slice_count=job.job_slice_count, + job_id=job.id, ) def final_run_hook(self, job, status, private_data_dir): @@ -1529,11 +1548,14 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): # special case for constructed inventories, we pass source inventories from database # these must come in order, and in order _before_ the constructed inventory itself if inventory_update.inventory.kind == 'constructed': + inventory_update.log_lifecycle("start_job_fact_cache") for input_inventory in inventory_update.inventory.input_inventories.all(): args.append('-i') script_params = dict(hostvars=True, towervars=True) source_inv_path = self.write_inventory_file(input_inventory, private_data_dir, f'hosts_{input_inventory.id}', script_params) args.append(to_container_path(source_inv_path, private_data_dir)) + # Include any facts from input inventories so they can be used in filters + start_fact_cache(input_inventory, os.path.join(private_data_dir, 'artifacts', str(inventory_update.id), 'fact_cache')) # Add arguments for the source inventory file/script/thing rel_path = self.pseudo_build_inventory(inventory_update, private_data_dir) @@ -1562,6 +1584,9 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): return args + def should_use_fact_cache(self): + return bool(self.instance.source == 'constructed') + def build_inventory(self, inventory_update, private_data_dir): return None # what runner expects in order to not deal with inventory diff --git a/awx/main/tests/unit/models/test_jobs.py b/awx/main/tests/unit/models/test_jobs.py index 2f030a57c3..d17a434fb1 100644 --- a/awx/main/tests/unit/models/test_jobs.py +++ b/awx/main/tests/unit/models/test_jobs.py @@ -10,10 +10,12 @@ from awx.main.models import ( Inventory, Host, ) +from awx.main.tasks.facts import start_fact_cache, finish_fact_cache @pytest.fixture -def hosts(inventory): +def hosts(): + inventory = Inventory(id=5) return [ Host(name='host1', ansible_facts={"a": 1, "b": 2}, inventory=inventory), Host(name='host2', ansible_facts={"a": 1, "b": 2}, inventory=inventory), @@ -23,20 +25,21 @@ def hosts(inventory): @pytest.fixture -def inventory(): +def inventory(mocker, hosts): + mocker.patch('awx.main.tasks.facts._get_inventory_hosts', return_value=hosts) return Inventory(id=5) @pytest.fixture -def job(mocker, hosts, inventory): +def job(mocker, inventory): j = Job(inventory=inventory, id=2) - j._get_inventory_hosts = mocker.Mock(return_value=hosts) + # j._get_inventory_hosts = mocker.Mock(return_value=hosts) return j def test_start_job_fact_cache(hosts, job, inventory, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = job.start_job_fact_cache(fact_cache, timeout=0) + last_modified = start_fact_cache(inventory, fact_cache, timeout=0) for host in hosts: filepath = os.path.join(fact_cache, host.name) @@ -47,24 +50,25 @@ def test_start_job_fact_cache(hosts, job, inventory, tmpdir): def test_fact_cache_with_invalid_path_traversal(job, inventory, tmpdir, mocker): - job._get_inventory_hosts = mocker.Mock( + mocker.patch( + 'awx.main.tasks.facts._get_inventory_hosts', return_value=[ Host( name='../foo', ansible_facts={"a": 1, "b": 2}, ), - ] + ], ) fact_cache = os.path.join(tmpdir, 'facts') - job.start_job_fact_cache(fact_cache, timeout=0) + start_fact_cache(inventory, fact_cache, timeout=0) # a file called "foo" should _not_ be written outside the facts dir assert os.listdir(os.path.join(fact_cache, '..')) == ['facts'] def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = job.start_job_fact_cache(fact_cache, timeout=0) + last_modified = start_fact_cache(inventory, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') @@ -80,7 +84,7 @@ def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, new_modification_time = time.time() + 3600 os.utime(filepath, (new_modification_time, new_modification_time)) - job.finish_job_fact_cache(fact_cache, last_modified) + finish_fact_cache(inventory, fact_cache, last_modified) for host in (hosts[0], hosts[2], hosts[3]): assert host.ansible_facts == {"a": 1, "b": 2} @@ -91,7 +95,7 @@ def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, def test_finish_job_fact_cache_with_bad_data(job, hosts, inventory, mocker, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = job.start_job_fact_cache(fact_cache, timeout=0) + last_modified = start_fact_cache(inventory, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') @@ -103,19 +107,19 @@ def test_finish_job_fact_cache_with_bad_data(job, hosts, inventory, mocker, tmpd new_modification_time = time.time() + 3600 os.utime(filepath, (new_modification_time, new_modification_time)) - job.finish_job_fact_cache(fact_cache, last_modified) + finish_fact_cache(inventory, fact_cache, last_modified) bulk_update.assert_not_called() def test_finish_job_fact_cache_clear(job, hosts, inventory, mocker, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = job.start_job_fact_cache(fact_cache, timeout=0) + last_modified = start_fact_cache(inventory, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') os.remove(os.path.join(fact_cache, hosts[1].name)) - job.finish_job_fact_cache(fact_cache, last_modified) + finish_fact_cache(inventory, fact_cache, last_modified) for host in (hosts[0], hosts[2], hosts[3]): assert host.ansible_facts == {"a": 1, "b": 2} From 84edbed5ec5db7342af6137f1c9fbd9632097f33 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Tue, 21 Mar 2023 13:14:44 -0500 Subject: [PATCH 083/167] [constructed-inventory] Fix some validation for constructed inv sources (#13727) - When updating, we need the original object so we can make sure we aren't changing things we shouldn't be. - We want to allow source_vars and limit, but not much else. - We want to block everything else (at least, if it doesn't match what is in the original object...to allow the collection to work properly). - Add two functional tests. Signed-off-by: Rick Elrod --- awx/api/serializers.py | 22 +++++++--- .../tests/functional/api/test_inventory.py | 44 +++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index d02a486f5c..0e0ad53aff 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -191,6 +191,11 @@ SUMMARIZABLE_FK_FIELDS = { } +# These fields can be edited on a constructed inventory's generated source (possibly by using the constructed +# inventory's special API endpoint, but also by using the inventory sources endpoint). +CONSTRUCTED_INVENTORY_SOURCE_EDITABLE_FIELDS = ('source_vars', 'update_cache_timeout', 'limit', 'verbosity') + + def reverse_gfk(content_object, request): """ Computes a reverse for a GenericForeignKey field. @@ -1784,12 +1789,12 @@ class ConstructedInventorySerializer(InventorySerializer): class Meta: model = Inventory - fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit', 'verbosity') + fields = ('*', '-host_filter') + CONSTRUCTED_INVENTORY_SOURCE_EDITABLE_FIELDS read_only_fields = ('*', 'kind') def pop_inv_src_data(self, data): inv_src_data = {} - for field in ('source_vars', 'update_cache_timeout', 'limit', 'verbosity'): + for field in CONSTRUCTED_INVENTORY_SOURCE_EDITABLE_FIELDS: if field in data: # values always need to be removed, as they are not valid for Inventory model value = data.pop(field) @@ -2361,8 +2366,6 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt obj = super(InventorySourceSerializer, self).update(obj, validated_data) if deprecated_fields: self._update_deprecated_fields(deprecated_fields, obj) - if obj.source == 'constructed': - raise serializers.ValidationError({'error': _("Cannot edit source of type constructed.")}) return obj # TODO: remove when old 'credential' fields are removed @@ -2386,11 +2389,16 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt def get_field_from_model_or_attrs(fd): return attrs.get(fd, self.instance and getattr(self.instance, fd) or None) - if get_field_from_model_or_attrs('source') == 'scm': + if self.instance and self.instance.source == 'constructed': + allowed_fields = CONSTRUCTED_INVENTORY_SOURCE_EDITABLE_FIELDS + for field in attrs: + if attrs[field] != getattr(self.instance, field) and field not in allowed_fields: + raise serializers.ValidationError({"error": _("Cannot change field '{}' on a constructed inventory source.").format(field)}) + elif get_field_from_model_or_attrs('source') == 'scm': if ('source' in attrs or 'source_project' in attrs) and get_field_from_model_or_attrs('source_project') is None: raise serializers.ValidationError({"source_project": _("Project required for scm type sources.")}) - elif (get_field_from_model_or_attrs('source') == 'constructed') and (self.instance and self.instance.source != 'constructed'): - raise serializers.ValidationError({"Error": _('constructed not a valid source for inventory')}) + elif get_field_from_model_or_attrs('source') == 'constructed': + raise serializers.ValidationError({"error": _('constructed not a valid source for inventory')}) else: redundant_scm_fields = list(filter(lambda x: attrs.get(x, None), ['source_project', 'source_path', 'scm_branch'])) if redundant_scm_fields: diff --git a/awx/main/tests/functional/api/test_inventory.py b/awx/main/tests/functional/api/test_inventory.py index c8139a340a..ab84ff236d 100644 --- a/awx/main/tests/functional/api/test_inventory.py +++ b/awx/main/tests/functional/api/test_inventory.py @@ -624,6 +624,50 @@ class TestConstructedInventory: assert inv_src.update_cache_timeout == 54 assert inv_src.limit == 'foobar' + def test_patch_constructed_inventory_generated_source_limits_editable_fields(self, constructed_inventory, admin_user, project, patch): + inv_src = constructed_inventory.inventory_sources.first() + r = patch( + url=inv_src.get_absolute_url(), + data={ + 'source': 'scm', + 'source_project': project.pk, + 'source_path': '', + 'source_vars': 'plugin: a.b.c', + }, + expect=400, + user=admin_user, + ) + assert str(r.data['error'][0]) == "Cannot change field 'source' on a constructed inventory source." + + # Make sure it didn't get updated before we got the error + inv_src_after_err = constructed_inventory.inventory_sources.first() + assert inv_src.id == inv_src_after_err.id + assert inv_src.source == inv_src_after_err.source + assert inv_src.source_project == inv_src_after_err.source_project + assert inv_src.source_path == inv_src_after_err.source_path + assert inv_src.source_vars == inv_src_after_err.source_vars + + def test_patch_constructed_inventory_generated_source_allows_source_vars_edit(self, constructed_inventory, admin_user, patch): + inv_src = constructed_inventory.inventory_sources.first() + patch( + url=inv_src.get_absolute_url(), + data={ + 'source_vars': 'plugin: a.b.c', + }, + expect=200, + user=admin_user, + ) + + inv_src_after_patch = constructed_inventory.inventory_sources.first() + + # sanity checks + assert inv_src.id == inv_src_after_patch.id + assert inv_src.source == 'constructed' + assert inv_src_after_patch.source == 'constructed' + assert inv_src.source_vars == '' + + assert inv_src_after_patch.source_vars == 'plugin: a.b.c' + def test_create_constructed_inventory(self, constructed_inventory, admin_user, post, organization): r = post( url=reverse('api:constructed_inventory_list'), From be5a2bbe612f50f61cd6f7e06d4ef2d0e1355ce8 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 21 Mar 2023 14:15:28 -0400 Subject: [PATCH 084/167] Fail inventory updates with unmatched limits (#13726) --- awx/main/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/main/constants.py b/awx/main/constants.py index 85a14cca4c..8450c9145e 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -38,6 +38,8 @@ STANDARD_INVENTORY_UPDATE_ENV = { 'ANSIBLE_INVENTORY_EXPORT': 'True', # Redirecting output to stderr allows JSON parsing to still work with -vvv 'ANSIBLE_VERBOSE_TO_STDERR': 'True', + # if ansible-inventory --limit is used for an inventory import, unmatched should be a failure + 'ANSIBLE_HOST_PATTERN_MISMATCH': 'error', } CAN_CANCEL = ('new', 'pending', 'waiting', 'running') ACTIVE_STATES = CAN_CANCEL From 62b79b19594a24d6344384f0fc5774140085fabc Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 21 Mar 2023 14:54:03 -0400 Subject: [PATCH 085/167] Point constructed inventory URL to special view (#13730) --- awx/main/models/inventory.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index c8f609b2ca..6bc03190a2 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -206,6 +206,8 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): ) def get_absolute_url(self, request=None): + if self.kind == 'constructed': + return reverse('api:constructed_inventory_detail', kwargs={'pk': self.pk}, request=request) return reverse('api:inventory_detail', kwargs={'pk': self.pk}, request=request) variables_dict = VarsDictProperty('variables') From b88d9f47315cf9d4d303c4d3f7ca7da2180f36a2 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 21 Mar 2023 14:55:24 -0400 Subject: [PATCH 086/167] Force overwrite all vars for constructed inventory (#13731) --- .../management/commands/inventory_import.py | 51 ++++++++++++------- awx/main/models/inventory.py | 4 +- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py index 8150936054..582af9d03b 100644 --- a/awx/main/management/commands/inventory_import.py +++ b/awx/main/management/commands/inventory_import.py @@ -458,12 +458,19 @@ class Command(BaseCommand): # TODO: We disable variable overwrite here in case user-defined inventory variables get # mangled. But we still need to figure out a better way of processing multiple inventory # update variables mixing with each other. - all_obj = self.inventory - db_variables = all_obj.variables_dict - db_variables.update(self.all_group.variables) - if db_variables != all_obj.variables_dict: - all_obj.variables = json.dumps(db_variables) - all_obj.save(update_fields=['variables']) + # issue for this: https://github.com/ansible/awx/issues/11623 + + if self.inventory.kind == 'constructed' and self.inventory_source.overwrite_vars: + # NOTE: we had to add a exception case to not merge variables + # to make constructed inventory coherent + db_variables = self.all_group.variables + else: + db_variables = self.inventory.variables_dict + db_variables.update(self.all_group.variables) + + if db_variables != self.inventory.variables_dict: + self.inventory.variables = json.dumps(db_variables) + self.inventory.save(update_fields=['variables']) logger.debug('Inventory variables updated from "all" group') else: logger.debug('Inventory variables unmodified') @@ -522,16 +529,32 @@ class Command(BaseCommand): def _update_db_host_from_mem_host(self, db_host, mem_host): # Update host variables. db_variables = db_host.variables_dict - if self.overwrite_vars: - db_variables = mem_host.variables - else: - db_variables.update(mem_host.variables) + mem_variables = mem_host.variables update_fields = [] + + # Update host instance_id. + instance_id = self._get_instance_id(mem_variables) + if instance_id != db_host.instance_id: + old_instance_id = db_host.instance_id + db_host.instance_id = instance_id + update_fields.append('instance_id') + + if self.inventory.kind == 'constructed': + # remote towervars so the constructed hosts do not have extra variables + for prefix in ('host', 'tower'): + for var in ('remote_{}_enabled', 'remote_{}_id'): + mem_variables.pop(var.format(prefix), None) + + if self.overwrite_vars: + db_variables = mem_variables + else: + db_variables.update(mem_variables) + if db_variables != db_host.variables_dict: db_host.variables = json.dumps(db_variables) update_fields.append('variables') # Update host enabled flag. - enabled = self._get_enabled(mem_host.variables) + enabled = self._get_enabled(mem_variables) if enabled is not None and db_host.enabled != enabled: db_host.enabled = enabled update_fields.append('enabled') @@ -540,12 +563,6 @@ class Command(BaseCommand): old_name = db_host.name db_host.name = mem_host.name update_fields.append('name') - # Update host instance_id. - instance_id = self._get_instance_id(mem_host.variables) - if instance_id != db_host.instance_id: - old_instance_id = db_host.instance_id - db_host.instance_id = instance_id - update_fields.append('instance_id') # Update host and display message(s) on what changed. if update_fields: db_host.save(update_fields=update_fields) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 6bc03190a2..a4ddaabafd 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -458,7 +458,9 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): """ if self.kind == 'constructed': if not self.inventory_sources.exists(): - self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True, update_on_launch=True) + self.inventory_sources.create( + source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True, overwrite_vars=True, update_on_launch=True + ) def save(self, *args, **kwargs): self._update_host_smart_inventory_memeberships() From 3f5a4cb6f104825656880eccc014f90dd478f2b6 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Wed, 22 Mar 2023 14:04:25 -0400 Subject: [PATCH 087/167] [constructed-inventory] Backlink events to real hosts and summaries to both hosts (#13718) * Backlink events to real hosts and summaries to both hosts * Prevent error when original host is deleted during job run * No duplicate entries, review suggestion from Rick * Change word tense in help text, dict style adjustments From code review Co-authored-by: Rick Elrod * Back out new variable for constructed host id --------- Co-authored-by: Rick Elrod --- awx/api/serializers.py | 8 +++++++- .../migrations/0182_constructed_inventory.py | 13 ++++++++++++ awx/main/models/events.py | 20 ++++++++++++++++--- awx/main/models/jobs.py | 16 +++++++++------ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 0e0ad53aff..de5c0661fc 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -158,6 +158,7 @@ SUMMARIZABLE_FK_FIELDS = { 'kind', ), 'host': DEFAULT_SUMMARY_FIELDS, + 'constructed_host': DEFAULT_SUMMARY_FIELDS, 'group': DEFAULT_SUMMARY_FIELDS, 'default_environment': DEFAULT_SUMMARY_FIELDS + ('image',), 'execution_environment': DEFAULT_SUMMARY_FIELDS + ('image',), @@ -1903,6 +1904,10 @@ class HostSerializer(BaseSerializerWithVariables): group_list = [{'id': g.id, 'name': g.name} for g in obj.groups.all().order_by('id')[:5]] group_cnt = obj.groups.count() d.setdefault('groups', {'count': group_cnt, 'results': group_list}) + if obj.inventory.kind == 'constructed': + summaries_qs = obj.constructed_host_summaries + else: + summaries_qs = obj.job_host_summaries d.setdefault( 'recent_jobs', [ @@ -1913,7 +1918,7 @@ class HostSerializer(BaseSerializerWithVariables): 'status': j.job.status, 'finished': j.job.finished, } - for j in obj.job_host_summaries.select_related('job__job_template').order_by('-created').defer('job__extra_vars', 'job__artifacts')[:5] + for j in summaries_qs.select_related('job__job_template').order_by('-created').defer('job__extra_vars', 'job__artifacts')[:5] ], ) return d @@ -4140,6 +4145,7 @@ class JobHostSummarySerializer(BaseSerializer): '-description', 'job', 'host', + 'constructed_host', 'host_name', 'changed', 'dark', diff --git a/awx/main/migrations/0182_constructed_inventory.py b/awx/main/migrations/0182_constructed_inventory.py index 10ece7b2f4..54ef7f1328 100644 --- a/awx/main/migrations/0182_constructed_inventory.py +++ b/awx/main/migrations/0182_constructed_inventory.py @@ -122,4 +122,17 @@ class Migration(migrations.Migration): help_text='This field is deprecated and will be removed in a future release. Regex where only matching hosts will be imported.', ), ), + migrations.AddField( + model_name='jobhostsummary', + name='constructed_host', + field=models.ForeignKey( + default=None, + editable=False, + help_text='Only for jobs run against constructed inventories, this links to the host inside the constructed inventory.', + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='constructed_host_summaries', + to='main.host', + ), + ), ] diff --git a/awx/main/models/events.py b/awx/main/models/events.py index 2d6dee6f61..c28c5de89b 100644 --- a/awx/main/models/events.py +++ b/awx/main/models/events.py @@ -7,6 +7,7 @@ from collections import defaultdict from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.db import models, DatabaseError +from django.db.models.functions import Cast from django.utils.dateparse import parse_datetime from django.utils.text import Truncator from django.utils.timezone import utc, now @@ -538,23 +539,36 @@ class JobEvent(BasePlaybookEvent): from awx.main.models import Host, JobHostSummary # circular import - all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name') + if self.job.inventory.kind == 'constructed': + all_hosts = Host.objects.filter(id__in=self.job.inventory.hosts.values_list(Cast('instance_id', output_field=models.IntegerField()))).only( + 'id', 'name' + ) + constructed_host_map = self.host_map + host_map = {host.name: host.id for host in all_hosts} + else: + all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name') + constructed_host_map = {} + host_map = self.host_map + existing_host_ids = set(h.id for h in all_hosts) summaries = dict() updated_hosts_list = list() for host in hostnames: updated_hosts_list.append(host.lower()) - host_id = self.host_map.get(host, None) + host_id = host_map.get(host) if host_id not in existing_host_ids: host_id = None + constructed_host_id = constructed_host_map.get(host) host_stats = {} for stat in ('changed', 'dark', 'failures', 'ignored', 'ok', 'processed', 'rescued', 'skipped'): try: host_stats[stat] = self.event_data.get(stat, {}).get(host, 0) except AttributeError: # in case event_data[stat] isn't a dict. pass - summary = JobHostSummary(created=now(), modified=now(), job_id=job.id, host_id=host_id, host_name=host, **host_stats) + summary = JobHostSummary( + created=now(), modified=now(), job_id=job.id, host_id=host_id, constructed_host_id=constructed_host_id, host_name=host, **host_stats + ) summary.failed = bool(summary.dark or summary.failures) summaries[(host_id, host)] = summary diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index ae9e66ae5f..daad187d97 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -569,12 +569,7 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana default=None, on_delete=models.SET_NULL, ) - hosts = models.ManyToManyField( - 'Host', - related_name='jobs', - editable=False, - through='JobHostSummary', - ) + hosts = models.ManyToManyField('Host', related_name='jobs', editable=False, through='JobHostSummary', through_fields=('job', 'host')) artifacts = JSONBlob( default=dict, blank=True, @@ -1059,6 +1054,15 @@ class JobHostSummary(CreatedModifiedModel): editable=False, ) host = models.ForeignKey('Host', related_name='job_host_summaries', null=True, default=None, on_delete=models.SET_NULL, editable=False) + constructed_host = models.ForeignKey( + 'Host', + related_name='constructed_host_summaries', + null=True, + default=None, + on_delete=models.SET_NULL, + editable=False, + help_text='Only for jobs run against constructed inventories, this links to the host inside the constructed inventory.', + ) host_name = models.CharField( max_length=1024, From 16ad27099ea3d886ddc4b2637908398383e92559 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Sat, 25 Mar 2023 21:43:41 -0400 Subject: [PATCH 088/167] [constructed-inventory] Save facts on model for original host (#13700) * Save facts on model for original host Redirect to original host for ansible facts Use current inventory hosts for facts instance_id filter Thanks for Gabe for identifying this bug * Fix spelling of queryset Co-authored-by: Rick Elrod * Fix sign error with facts expiry - from review --------- Co-authored-by: Rick Elrod --- awx/api/serializers.py | 1 + awx/api/views/__init__.py | 10 ++- awx/main/constants.py | 3 + awx/main/models/jobs.py | 23 ++++++ awx/main/tasks/facts.py | 43 ++++------ awx/main/tasks/jobs.py | 17 ++-- awx/main/tests/unit/models/test_jobs.py | 100 ++++++++++++++---------- 7 files changed, 119 insertions(+), 78 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index de5c0661fc..4b3a62c841 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1883,6 +1883,7 @@ class HostSerializer(BaseSerializerWithVariables): ) if obj.inventory.kind == 'constructed': res['original_host'] = self.reverse('api:host_detail', kwargs={'pk': obj.instance_id}) + res['ansible_facts'] = self.reverse('api:host_ansible_facts_detail', kwargs={'pk': obj.instance_id}) if obj.inventory: res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk}) if obj.last_job: diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index d023f92984..e7f1d5cf8a 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -29,7 +29,7 @@ from django.utils.safestring import mark_safe from django.utils.timezone import now from django.views.decorators.csrf import csrf_exempt from django.template.loader import render_to_string -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseRedirect from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ @@ -1619,6 +1619,14 @@ class HostAnsibleFactsDetail(RetrieveAPIView): model = models.Host serializer_class = serializers.AnsibleFactsSerializer + def get(self, request, *args, **kwargs): + obj = self.get_object() + if obj.inventory.kind == 'constructed': + # If this is a constructed inventory host, it is not the source of truth about facts + # redirect to the original input inventory host instead + return HttpResponseRedirect(reverse('api:host_ansible_facts_detail', kwargs={'pk': obj.instance_id}, request=self.request)) + return super().get(request, *args, **kwargs) + class InventoryHostsList(HostRelatedSearchMixin, SubListCreateAttachDetachAPIView): model = models.Host diff --git a/awx/main/constants.py b/awx/main/constants.py index 8450c9145e..32d8a2184c 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -111,3 +111,6 @@ ANSIBLE_RUNNER_NEEDS_UPDATE_MESSAGE = ( # Values for setting SUBSCRIPTION_USAGE_MODEL SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS = 'unique_managed_hosts' + +# Shared prefetch to use for creating a queryset for the purpose of writing or saving facts +HOST_FACTS_FIELDS = ('name', 'ansible_facts', 'ansible_facts_modified', 'modified', 'inventory_id') diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index daad187d97..5e55683c20 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -11,6 +11,7 @@ from urllib.parse import urljoin from django.conf import settings from django.core.exceptions import ValidationError from django.db import models +from django.db.models.functions import Cast # from django.core.cache import cache from django.utils.translation import gettext_lazy as _ @@ -21,6 +22,7 @@ from rest_framework.exceptions import ParseError # AWX from awx.api.versioning import reverse +from awx.main.constants import HOST_FACTS_FIELDS from awx.main.models.base import ( BaseModel, CreatedModifiedModel, @@ -834,6 +836,27 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana def get_notification_friendly_name(self): return "Job" + def get_hosts_for_fact_cache(self): + """ + Builds the queryset to use for writing or finalizing the fact cache + these need to be the 'real' hosts associated with the job. + For constructed inventories, that means the original (input inventory) hosts + when slicing, that means only returning hosts in that slice + """ + Host = JobHostSummary._meta.get_field('host').related_model + if not self.inventory_id: + return Host.objects.none() + + if self.inventory.kind == 'constructed': + id_field = Host._meta.get_field('id') + host_qs = Host.objects.filter(id__in=self.inventory.hosts.exclude(instance_id='').values_list(Cast('instance_id', output_field=id_field))) + else: + host_qs = self.inventory.hosts + + host_qs = host_qs.only(*HOST_FACTS_FIELDS) + host_qs = self.inventory.get_sliced_hosts(host_qs, self.job_slice_number, self.job_slice_count) + return host_qs + class LaunchTimeConfigBase(BaseModel): """ diff --git a/awx/main/tasks/facts.py b/awx/main/tasks/facts.py index ba48bc2249..3db5f13091 100644 --- a/awx/main/tasks/facts.py +++ b/awx/main/tasks/facts.py @@ -12,28 +12,16 @@ from django.utils.timezone import now # AWX from awx.main.utils.common import log_excess_runtime +from awx.main.models.inventory import Host logger = logging.getLogger('awx.main.tasks.facts') system_tracking_logger = logging.getLogger('awx.analytics.system_tracking') -def _get_inventory_hosts(inventory, slice_number, slice_count, only=('name', 'ansible_facts', 'ansible_facts_modified', 'modified', 'inventory_id'), **filters): - """Return value is an iterable for the relevant hosts for this job""" - if not inventory: - return [] - host_queryset = inventory.hosts.only(*only) - if filters: - host_queryset = host_queryset.filter(**filters) - host_queryset = inventory.get_sliced_hosts(host_queryset, slice_number, slice_count) - if isinstance(host_queryset, QuerySet): - return host_queryset.iterator() - return host_queryset - - @log_excess_runtime(logger, debug_cutoff=0.01, msg='Inventory {inventory_id} host facts prepared for {written_ct} hosts, took {delta:.3f} s', add_log_data=True) -def start_fact_cache(inventory, destination, log_data, timeout=None, slice_number=0, slice_count=1): - log_data['inventory_id'] = inventory.id +def start_fact_cache(hosts, destination, log_data, timeout=None, inventory_id=None): + log_data['inventory_id'] = inventory_id log_data['written_ct'] = 0 try: os.makedirs(destination, mode=0o700) @@ -42,15 +30,14 @@ def start_fact_cache(inventory, destination, log_data, timeout=None, slice_numbe if timeout is None: timeout = settings.ANSIBLE_FACT_CACHE_TIMEOUT - if timeout > 0: - # exclude hosts with fact data older than `settings.ANSIBLE_FACT_CACHE_TIMEOUT seconds` - timeout = now() - datetime.timedelta(seconds=timeout) - hosts = _get_inventory_hosts(inventory, slice_number, slice_count, ansible_facts_modified__gte=timeout) - else: - hosts = _get_inventory_hosts(inventory, slice_number, slice_count) + + if isinstance(hosts, QuerySet): + hosts = hosts.iterator() last_filepath_written = None for host in hosts: + if (not host.ansible_facts_modified) or (timeout and host.ansible_facts_modified < now() - datetime.timedelta(seconds=timeout)): + continue # facts are expired - do not write them filepath = os.sep.join(map(str, [destination, host.name])) if not os.path.realpath(filepath).startswith(destination): system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) @@ -76,13 +63,17 @@ def start_fact_cache(inventory, destination, log_data, timeout=None, slice_numbe msg='Inventory {inventory_id} host facts: updated {updated_ct}, cleared {cleared_ct}, unchanged {unmodified_ct}, took {delta:.3f} s', add_log_data=True, ) -def finish_fact_cache(inventory, destination, facts_write_time, log_data, slice_number=0, slice_count=1, job_id=None): - log_data['inventory_id'] = inventory.id +def finish_fact_cache(hosts, destination, facts_write_time, log_data, job_id=None, inventory_id=None): + log_data['inventory_id'] = inventory_id log_data['updated_ct'] = 0 log_data['unmodified_ct'] = 0 log_data['cleared_ct'] = 0 + + if isinstance(hosts, QuerySet): + hosts = hosts.iterator() + hosts_to_update = [] - for host in _get_inventory_hosts(inventory, slice_number, slice_count): + for host in hosts: filepath = os.sep.join(map(str, [destination, host.name])) if not os.path.realpath(filepath).startswith(destination): system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) @@ -120,7 +111,7 @@ def finish_fact_cache(inventory, destination, facts_write_time, log_data, slice_ system_tracking_logger.info('Facts cleared for inventory {} host {}'.format(smart_str(host.inventory.name), smart_str(host.name))) log_data['cleared_ct'] += 1 if len(hosts_to_update) > 100: - inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) + Host.objects.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) hosts_to_update = [] if hosts_to_update: - inventory.hosts.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) + Host.objects.bulk_update(hosts_to_update, ['ansible_facts', 'ansible_facts_modified']) diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index 1bb886a557..74286faa20 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -37,6 +37,7 @@ from awx.main.constants import ( MAX_ISOLATED_PATH_COLON_DELIMITER, CONTAINER_VOLUMES_MOUNT_TYPES, ACTIVE_STATES, + HOST_FACTS_FIELDS, ) from awx.main.models import ( Instance, @@ -1084,10 +1085,7 @@ class RunJob(SourceControlMixin, BaseTask): if self.should_use_fact_cache(): job.log_lifecycle("start_job_fact_cache") self.facts_write_time = start_fact_cache( - job.inventory, - os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache'), - slice_number=job.job_slice_number, - slice_count=job.job_slice_count, + job.get_hosts_for_fact_cache(), os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache'), inventory_id=job.inventory_id ) def build_project_dir(self, job, private_data_dir): @@ -1105,12 +1103,11 @@ class RunJob(SourceControlMixin, BaseTask): if self.should_use_fact_cache(): job.log_lifecycle("finish_job_fact_cache") finish_fact_cache( - job.inventory, + job.get_hosts_for_fact_cache(), os.path.join(private_data_dir, 'artifacts', str(job.id), 'fact_cache'), facts_write_time=self.facts_write_time, - slice_number=job.job_slice_number, - slice_count=job.job_slice_count, job_id=job.id, + inventory_id=job.inventory_id, ) def final_run_hook(self, job, status, private_data_dir): @@ -1555,7 +1552,11 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): source_inv_path = self.write_inventory_file(input_inventory, private_data_dir, f'hosts_{input_inventory.id}', script_params) args.append(to_container_path(source_inv_path, private_data_dir)) # Include any facts from input inventories so they can be used in filters - start_fact_cache(input_inventory, os.path.join(private_data_dir, 'artifacts', str(inventory_update.id), 'fact_cache')) + start_fact_cache( + input_inventory.hosts.only(*HOST_FACTS_FIELDS), + os.path.join(private_data_dir, 'artifacts', str(inventory_update.id), 'fact_cache'), + inventory_id=input_inventory.id, + ) # Add arguments for the source inventory file/script/thing rel_path = self.pseudo_build_inventory(inventory_update, private_data_dir) diff --git a/awx/main/tests/unit/models/test_jobs.py b/awx/main/tests/unit/models/test_jobs.py index d17a434fb1..4f05a82535 100644 --- a/awx/main/tests/unit/models/test_jobs.py +++ b/awx/main/tests/unit/models/test_jobs.py @@ -6,40 +6,35 @@ import time import pytest from awx.main.models import ( - Job, Inventory, Host, ) from awx.main.tasks.facts import start_fact_cache, finish_fact_cache +from django.utils.timezone import now + +from datetime import timedelta + @pytest.fixture -def hosts(): +def ref_time(): + return now() - timedelta(seconds=5) + + +@pytest.fixture +def hosts(ref_time): inventory = Inventory(id=5) return [ - Host(name='host1', ansible_facts={"a": 1, "b": 2}, inventory=inventory), - Host(name='host2', ansible_facts={"a": 1, "b": 2}, inventory=inventory), - Host(name='host3', ansible_facts={"a": 1, "b": 2}, inventory=inventory), - Host(name=u'Iñtërnâtiônàlizætiøn', ansible_facts={"a": 1, "b": 2}, inventory=inventory), + Host(name='host1', ansible_facts={"a": 1, "b": 2}, ansible_facts_modified=ref_time, inventory=inventory), + Host(name='host2', ansible_facts={"a": 1, "b": 2}, ansible_facts_modified=ref_time, inventory=inventory), + Host(name='host3', ansible_facts={"a": 1, "b": 2}, ansible_facts_modified=ref_time, inventory=inventory), + Host(name=u'Iñtërnâtiônàlizætiøn', ansible_facts={"a": 1, "b": 2}, ansible_facts_modified=ref_time, inventory=inventory), ] -@pytest.fixture -def inventory(mocker, hosts): - mocker.patch('awx.main.tasks.facts._get_inventory_hosts', return_value=hosts) - return Inventory(id=5) - - -@pytest.fixture -def job(mocker, inventory): - j = Job(inventory=inventory, id=2) - # j._get_inventory_hosts = mocker.Mock(return_value=hosts) - return j - - -def test_start_job_fact_cache(hosts, job, inventory, tmpdir): +def test_start_job_fact_cache(hosts, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = start_fact_cache(inventory, fact_cache, timeout=0) + last_modified = start_fact_cache(hosts, fact_cache, timeout=0) for host in hosts: filepath = os.path.join(fact_cache, host.name) @@ -49,26 +44,43 @@ def test_start_job_fact_cache(hosts, job, inventory, tmpdir): assert os.path.getmtime(filepath) <= last_modified -def test_fact_cache_with_invalid_path_traversal(job, inventory, tmpdir, mocker): - mocker.patch( - 'awx.main.tasks.facts._get_inventory_hosts', - return_value=[ - Host( - name='../foo', - ansible_facts={"a": 1, "b": 2}, - ), - ], - ) +def test_fact_cache_with_invalid_path_traversal(tmpdir): + hosts = [ + Host( + name='../foo', + ansible_facts={"a": 1, "b": 2}, + ), + ] fact_cache = os.path.join(tmpdir, 'facts') - start_fact_cache(inventory, fact_cache, timeout=0) + start_fact_cache(hosts, fact_cache, timeout=0) # a file called "foo" should _not_ be written outside the facts dir assert os.listdir(os.path.join(fact_cache, '..')) == ['facts'] -def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, tmpdir): +def test_start_job_fact_cache_past_timeout(hosts, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = start_fact_cache(inventory, fact_cache, timeout=0) + # the hosts fixture was modified 5s ago, which is more than 2s + last_modified = start_fact_cache(hosts, fact_cache, timeout=2) + assert last_modified is None + + for host in hosts: + assert not os.path.exists(os.path.join(fact_cache, host.name)) + + +def test_start_job_fact_cache_within_timeout(hosts, tmpdir): + fact_cache = os.path.join(tmpdir, 'facts') + # the hosts fixture was modified 5s ago, which is less than 7s + last_modified = start_fact_cache(hosts, fact_cache, timeout=7) + assert last_modified + + for host in hosts: + assert os.path.exists(os.path.join(fact_cache, host.name)) + + +def test_finish_job_fact_cache_with_existing_data(hosts, mocker, tmpdir, ref_time): + fact_cache = os.path.join(tmpdir, 'facts') + last_modified = start_fact_cache(hosts, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') @@ -84,18 +96,19 @@ def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, new_modification_time = time.time() + 3600 os.utime(filepath, (new_modification_time, new_modification_time)) - finish_fact_cache(inventory, fact_cache, last_modified) + finish_fact_cache(hosts, fact_cache, last_modified) for host in (hosts[0], hosts[2], hosts[3]): assert host.ansible_facts == {"a": 1, "b": 2} - assert host.ansible_facts_modified is None + assert host.ansible_facts_modified == ref_time assert hosts[1].ansible_facts == ansible_facts_new + assert hosts[1].ansible_facts_modified > ref_time bulk_update.assert_called_once_with([hosts[1]], ['ansible_facts', 'ansible_facts_modified']) -def test_finish_job_fact_cache_with_bad_data(job, hosts, inventory, mocker, tmpdir): +def test_finish_job_fact_cache_with_bad_data(hosts, mocker, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = start_fact_cache(inventory, fact_cache, timeout=0) + last_modified = start_fact_cache(hosts, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') @@ -107,22 +120,23 @@ def test_finish_job_fact_cache_with_bad_data(job, hosts, inventory, mocker, tmpd new_modification_time = time.time() + 3600 os.utime(filepath, (new_modification_time, new_modification_time)) - finish_fact_cache(inventory, fact_cache, last_modified) + finish_fact_cache(hosts, fact_cache, last_modified) bulk_update.assert_not_called() -def test_finish_job_fact_cache_clear(job, hosts, inventory, mocker, tmpdir): +def test_finish_job_fact_cache_clear(hosts, mocker, ref_time, tmpdir): fact_cache = os.path.join(tmpdir, 'facts') - last_modified = start_fact_cache(inventory, fact_cache, timeout=0) + last_modified = start_fact_cache(hosts, fact_cache, timeout=0) bulk_update = mocker.patch('django.db.models.query.QuerySet.bulk_update') os.remove(os.path.join(fact_cache, hosts[1].name)) - finish_fact_cache(inventory, fact_cache, last_modified) + finish_fact_cache(hosts, fact_cache, last_modified) for host in (hosts[0], hosts[2], hosts[3]): assert host.ansible_facts == {"a": 1, "b": 2} - assert host.ansible_facts_modified is None + assert host.ansible_facts_modified == ref_time assert hosts[1].ansible_facts == {} + assert hosts[1].ansible_facts_modified > ref_time bulk_update.assert_called_once_with([hosts[1]], ['ansible_facts', 'ansible_facts_modified']) From f792fea048c26678491b81a2e50cfec2919ddfce Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Mon, 27 Mar 2023 15:01:35 -0400 Subject: [PATCH 089/167] Add more constructed inventory hint examples --- .../shared/ConstructedInventoryHint.js | 317 ++++++++++++++---- .../shared/ConstructedInventoryHint.test.js | 18 +- 2 files changed, 268 insertions(+), 67 deletions(-) diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js index 34a3ca48f1..be22d4ba13 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js @@ -3,10 +3,17 @@ import { t } from '@lingui/macro'; import { Alert, AlertActionLink, + ClipboardCopyButton, CodeBlock, CodeBlockAction, CodeBlockCode, - ClipboardCopyButton, + ClipboardCopy, + Form, + FormFieldGroupExpandable, + FormFieldGroupHeader, + FormGroup, + Panel, + CardBody, } from '@patternfly/react-core'; import { TableComposable, @@ -22,25 +29,6 @@ import { useConfig } from 'contexts/Config'; function ConstructedInventoryHint() { const config = useConfig(); - const [copied, setCopied] = React.useState(false); - - const clipboardCopyFunc = (event, text) => { - navigator.clipboard.writeText(text.toString()); - }; - - const onClick = (event, text) => { - clipboardCopyFunc(event, text); - setCopied(true); - }; - - const pluginSample = `plugin: constructed -strict: true -use_vars_plugins: true -groups: - shutdown: resolved_state == "shutdown" - shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" -compose: - resolved_state: state | default("running")`; return ( - {t`View constructed plugin documentation here`}{' '} + {t`View constructed inventory documentation here`}{' '} } > - {t`WIP - More to come...`} + + {t`This table gives a few useful parameters of the constructed + inventory plugin. For the full list of parameters `}{' '} + {t`view the constructed inventory plugin docs here.`} +

{t`required`}

- {t`Token that ensures this is a source file + {t`Token that ensures this is a source file for the ‘constructed’ plugin.`} @@ -95,23 +89,11 @@ compose: {t`If yes make invalid entries a fatal error, otherwise skip and continue.`}{' '}
- {t`If users need feedback about the correctness - of their constructed groups, it is highly recommended + {t`If users need feedback about the correctness + of their constructed groups, it is highly recommended to use strict: true in the plugin configuration.`} - - - use_vars_plugins -

{t`string`}

- - - {t`Normally, for performance reasons, vars plugins get - executed after the inventory sources complete the - base inventory, this option allows for getting vars - related to hosts/groups from those plugins.`} - - groups @@ -127,38 +109,251 @@ compose:

{t`dictionary`}

- {t`Create vars from jinja2 expressions.`} + {t`Create vars from jinja2 expressions. This can be useful + if the constructed groups you define do not contain the expected + hosts. This can be used to add hostvars from expressions so + that you know what the resultant values of those expressions are.`}


- {t`Sample constructed inventory plugin:`} - - onClick(e, pluginSample)} - exitDelay={copied ? 1500 : 600} - maxWidth="110px" - variant="plain" - onTooltipHidden={() => setCopied(false)} - > - {copied - ? t`Successfully copied to clipboard!` - : t`Copy to clipboard`} - - - } - > - {pluginSample} - + + + + {t`Constructed inventory examples`} + + + + + +
); } +function LimitToIntersectionExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const limitToIntersectionLimit = `is_shutdown:&product_dev`; + const limitToIntersectionCode = `plugin: constructed +strict: true +groups: + shutdown_in_product_dev: state | default("running") == "shutdown" and account_alias == "product_dev"`; + + return ( + + } + > + + + {limitToIntersectionLimit} + + + + + onClick(e, limitToIntersectionCode)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {limitToIntersectionCode} + + + + + ); +} +function FilterOnNestedGroupExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const nestedGroupsInventoryLimit = `groupA`; + const nestedGroupsInventorySourceVars = `plugin: constructed`; + const nestedGroupsInventory = `all: + children: + groupA: + children: + groupB: + hosts: + host1: {} + vars: + filter_var: filter_val + ungrouped: + hosts: + host2: {}`; + + return ( + + } + > + +

{t`Nested groups inventory definition:`}

+ + + {nestedGroupsInventory} + + +
+ + + {nestedGroupsInventoryLimit} + + + + + onClick(e, nestedGroupsInventorySourceVars)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {nestedGroupsInventorySourceVars} + + + +
+ ); +} +function HostsByProcessorTypeExample() { + const [copied, setCopied] = React.useState(false); + const clipboardCopyFunc = (event, text) => { + navigator.clipboard.writeText(text.toString()); + }; + + const onClick = (event, text) => { + clipboardCopyFunc(event, text); + setCopied(true); + }; + + const hostsByProcessorLimit = `intel_hosts`; + const hostsByProcessorSourceVars = `plugin: constructed + strict: true + groups: + intel_hosts: "GenuineIntel" in ansible_processor`; + + return ( + + } + > + + + {hostsByProcessorLimit} + + + + + onClick(e, hostsByProcessorSourceVars)} + exitDelay={copied ? 1500 : 600} + maxWidth="110px" + variant="plain" + onTooltipHidden={() => setCopied(false)} + > + {copied + ? t`Successfully copied to clipboard!` + : t`Copy to clipboard`} + + + } + > + + {hostsByProcessorSourceVars} + + + + + ); +} + export default ConstructedInventoryHint; diff --git a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js index e4745773f4..6132f107a9 100644 --- a/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js +++ b/awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, within } from '@testing-library/react'; import '@testing-library/jest-dom'; import ConstructedInventoryHint from './ConstructedInventoryHint'; @@ -10,7 +10,7 @@ describe('', () => { render(); expect( screen.getByRole('link', { - name: 'View constructed plugin documentation here', + name: 'View constructed inventory documentation here', }) ).toBeInTheDocument(); }); @@ -33,14 +33,20 @@ describe('', () => { }); jest.spyOn(navigator.clipboard, 'writeText'); - const { container } = render(); + render(); fireEvent.click(screen.getByRole('button', { name: 'Info alert details' })); fireEvent.click( - container.querySelector('button[aria-label="Copy to clipboard"]') + screen.getByRole('button', { name: 'Hosts by processor type' }) + ); + fireEvent.click( + screen.getByRole('button', { + name: 'Copy to clipboard', + }) ); - expect(navigator.clipboard.writeText).toHaveBeenCalledWith( - expect.stringContaining('plugin: constructed') + expect.stringContaining( + 'intel_hosts: "GenuineIntel" in ansible_processor' + ) ); }); }); From 77743ef406369b40a3c03a2e778eac5ef9ea9bd7 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Tue, 28 Mar 2023 09:19:01 -0500 Subject: [PATCH 090/167] [collection] Example for constructed inventories (#13755) Signed-off-by: Rick Elrod --- awx_collection/plugins/modules/inventory.py | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/awx_collection/plugins/modules/inventory.py b/awx_collection/plugins/modules/inventory.py index 3a479bcd03..3de24bf1ba 100644 --- a/awx_collection/plugins/modules/inventory.py +++ b/awx_collection/plugins/modules/inventory.py @@ -100,6 +100,35 @@ EXAMPLES = ''' description: "Our Foo Cloud Servers" organization: Foo state: present + +# You can create and modify constructed inventories by creating an inventory +# of kind "constructed" and then editing the automatically generated inventory +# source for that inventory. +- name: Add constructed inventory with two existing input inventories + inventory: + name: My Constructed Inventory + organization: Default + kind: constructed + input_inventories: + - "West Datacenter" + - "East Datacenter" + +- name: Edit the constructed inventory source + inventory_source: + # The constructed inventory source will always be in the format: + # "Auto-created source for: " + name: "Auto-created source for: My Constructed Inventory" + inventory: My Constructed Inventory + limit: host3,host4,host6 + source_vars: + plugin: constructed + strict: true + use_vars_plugins: true + groups: + shutdown: resolved_state == "shutdown" + shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" + compose: + resolved_state: state | default("running") ''' From b5e04a4cb3312a24687d626d72348275fbb81645 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Wed, 4 Jan 2023 13:54:53 -0500 Subject: [PATCH 091/167] AWX code changes for rsyslog decoupling (#13222) * add management command and logging for new daemon * switch tasks over to calling pg_notify * add daemon to docker-compose and supervisor * renamed handle_setting_changes and moved notify call * removed initial rsyslog configure from dispatcher * add logging and clear cache before reconfigure * add notify to delete * moved pg_notify to own function * update tests impacted by rsyslog change * changed over to new pg_notify method Signed-off-by: Jessica Mack --- Makefile | 6 +++ awx/conf/tests/functional/test_api.py | 18 ++++----- awx/conf/views.py | 13 +++++-- .../commands/run_rsyslog_configurer.py | 38 +++++++++++++++++++ awx/main/tasks/system.py | 9 +---- .../tests/functional/api/test_settings.py | 8 +++- awx/main/utils/external_logging.py | 6 +++ awx/settings/defaults.py | 2 + tools/docker-compose/supervisor.conf | 10 +++++ 9 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 awx/main/management/commands/run_rsyslog_configurer.py diff --git a/Makefile b/Makefile index 2c9798b8a7..5165ad577b 100644 --- a/Makefile +++ b/Makefile @@ -238,6 +238,12 @@ receiver: fi; \ $(PYTHON) manage.py run_callback_receiver +rsyslog-configurer: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_rsyslog_configurer + nginx: nginx -g "daemon off;" diff --git a/awx/conf/tests/functional/test_api.py b/awx/conf/tests/functional/test_api.py index 2d09423386..b600c3766d 100644 --- a/awx/conf/tests/functional/test_api.py +++ b/awx/conf/tests/functional/test_api.py @@ -94,9 +94,7 @@ def test_setting_singleton_retrieve_readonly(api_request, dummy_setting): @pytest.mark.django_db def test_setting_singleton_update(api_request, dummy_setting): - with dummy_setting('FOO_BAR', field_class=fields.IntegerField, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' - ): + with dummy_setting('FOO_BAR', field_class=fields.IntegerField, category='FooBar', category_slug='foobar'), mock.patch('awx.conf.views.clear_setting_cache'): api_request('patch', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'}), data={'FOO_BAR': 3}) response = api_request('get', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) assert response.data['FOO_BAR'] == 3 @@ -112,7 +110,7 @@ def test_setting_singleton_update_hybriddictfield_with_forbidden(api_request, du # sure that the _Forbidden validator doesn't get used for the # fields. See also https://github.com/ansible/awx/issues/4099. with dummy_setting('FOO_BAR', field_class=sso_fields.SAMLOrgAttrField, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' + 'awx.conf.views.clear_setting_cache' ): api_request( 'patch', @@ -126,7 +124,7 @@ def test_setting_singleton_update_hybriddictfield_with_forbidden(api_request, du @pytest.mark.django_db def test_setting_singleton_update_dont_change_readonly_fields(api_request, dummy_setting): with dummy_setting('FOO_BAR', field_class=fields.IntegerField, read_only=True, default=4, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' + 'awx.conf.views.clear_setting_cache' ): api_request('patch', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'}), data={'FOO_BAR': 5}) response = api_request('get', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) @@ -136,7 +134,7 @@ def test_setting_singleton_update_dont_change_readonly_fields(api_request, dummy @pytest.mark.django_db def test_setting_singleton_update_dont_change_encrypted_mark(api_request, dummy_setting): with dummy_setting('FOO_BAR', field_class=fields.CharField, encrypted=True, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' + 'awx.conf.views.clear_setting_cache' ): api_request('patch', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'}), data={'FOO_BAR': 'password'}) assert Setting.objects.get(key='FOO_BAR').value.startswith('$encrypted$') @@ -155,16 +153,14 @@ def test_setting_singleton_update_runs_custom_validate(api_request, dummy_settin with dummy_setting('FOO_BAR', field_class=fields.IntegerField, category='FooBar', category_slug='foobar'), dummy_validate( 'foobar', func_raising_exception - ), mock.patch('awx.conf.views.handle_setting_changes'): + ), mock.patch('awx.conf.views.clear_setting_cache'): response = api_request('patch', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'}), data={'FOO_BAR': 23}) assert response.status_code == 400 @pytest.mark.django_db def test_setting_singleton_delete(api_request, dummy_setting): - with dummy_setting('FOO_BAR', field_class=fields.IntegerField, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' - ): + with dummy_setting('FOO_BAR', field_class=fields.IntegerField, category='FooBar', category_slug='foobar'), mock.patch('awx.conf.views.clear_setting_cache'): api_request('delete', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) response = api_request('get', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) assert not response.data['FOO_BAR'] @@ -173,7 +169,7 @@ def test_setting_singleton_delete(api_request, dummy_setting): @pytest.mark.django_db def test_setting_singleton_delete_no_read_only_fields(api_request, dummy_setting): with dummy_setting('FOO_BAR', field_class=fields.IntegerField, read_only=True, default=23, category='FooBar', category_slug='foobar'), mock.patch( - 'awx.conf.views.handle_setting_changes' + 'awx.conf.views.clear_setting_cache' ): api_request('delete', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) response = api_request('get', reverse('api:setting_singleton_detail', kwargs={'category_slug': 'foobar'})) diff --git a/awx/conf/views.py b/awx/conf/views.py index 5231cd86bd..e4a8375122 100644 --- a/awx/conf/views.py +++ b/awx/conf/views.py @@ -26,10 +26,11 @@ from awx.api.generics import APIView, GenericAPIView, ListAPIView, RetrieveUpdat from awx.api.permissions import IsSystemAdminOrAuditor from awx.api.versioning import reverse from awx.main.utils import camelcase_to_underscore -from awx.main.tasks.system import handle_setting_changes +from awx.main.tasks.system import clear_setting_cache from awx.conf.models import Setting from awx.conf.serializers import SettingCategorySerializer, SettingSingletonSerializer from awx.conf import settings_registry +from awx.main.utils.external_logging import send_pg_notify SettingCategory = collections.namedtuple('SettingCategory', ('url', 'slug', 'name')) @@ -118,7 +119,10 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): setting.save(update_fields=['value']) settings_change_list.append(key) if settings_change_list: - connection.on_commit(lambda: handle_setting_changes.delay(settings_change_list)) + connection.on_commit(lambda: clear_setting_cache.delay(settings_change_list)) + if any([setting.startswith('LOG_AGGREGATOR') for setting in settings_change_list]): + # call notify to rsyslog. no data is need so payload is empty + send_pg_notify('rsyslog_configurer', "") def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -133,7 +137,10 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): setting.delete() settings_change_list.append(setting.key) if settings_change_list: - connection.on_commit(lambda: handle_setting_changes.delay(settings_change_list)) + connection.on_commit(lambda: clear_setting_cache.delay(settings_change_list)) + if any([setting.startswith('LOG_AGGREGATOR') for setting in settings_change_list]): + # call notify to rsyslog. no data is need so payload is empty + send_pg_notify('rsyslog_configurer', "") # When TOWER_URL_BASE is deleted from the API, reset it to the hostname # used to make the request as a default. diff --git a/awx/main/management/commands/run_rsyslog_configurer.py b/awx/main/management/commands/run_rsyslog_configurer.py new file mode 100644 index 0000000000..5cc214ced9 --- /dev/null +++ b/awx/main/management/commands/run_rsyslog_configurer.py @@ -0,0 +1,38 @@ +import logging + +from django.core.management.base import BaseCommand +from django.conf import settings +from django.core.cache import cache +from awx.main.dispatch import pg_bus_conn +from awx.main.utils.external_logging import reconfigure_rsyslog + +logger = logging.getLogger('awx.main.rsyslog_configurer') + + +class Command(BaseCommand): + """ + Rsyslog Configurer + Runs as a management command and starts rsyslog configurer daemon. Daemon listens + for pg_notify then calls reconfigure_rsyslog + """ + + help = 'Launch the rsyslog_configurer daemon' + + def handle(self, *arg, **options): + try: + with pg_bus_conn(new_connection=True) as conn: + conn.listen("rsyslog_configurer") + # reconfigure rsyslog on start up + reconfigure_rsyslog() + for e in conn.events(yield_timeouts=True): + if e is not None: + logger.info("Change in logging settings found. Restarting rsyslogd") + # clear the cache of relevant settings then restart + setting_keys = [k for k in dir(settings) if k.startswith('LOG_AGGREGATOR')] + cache.delete_many(setting_keys) + settings._awx_conf_memoizedcache.clear() + reconfigure_rsyslog() + except Exception: + # Log unanticipated exception in addition to writing to stderr to get timestamps and other metadata + logger.exception('Encountered unhandled error in rsyslog_configurer main loop') + raise diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index ddff6b4ec4..ac0e0c32bf 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -59,7 +59,6 @@ from awx.main.utils.common import ( ScheduleTaskManager, ) -from awx.main.utils.external_logging import reconfigure_rsyslog from awx.main.utils.reload import stop_local_services from awx.main.utils.pglock import advisory_lock from awx.main.tasks.receptor import get_receptor_ctl, worker_info, worker_cleanup, administrative_workunit_reaper, write_receptor_config @@ -115,9 +114,6 @@ def dispatch_startup(): m = Metrics() m.reset_values() - # Update Tower's rsyslog.conf file based on loggins settings in the db - reconfigure_rsyslog() - def inform_cluster_of_shutdown(): try: @@ -245,7 +241,7 @@ def apply_cluster_membership_policies(): @task(queue='tower_broadcast_all') -def handle_setting_changes(setting_keys): +def clear_setting_cache(setting_keys): orig_len = len(setting_keys) for i in range(orig_len): for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): @@ -254,9 +250,6 @@ def handle_setting_changes(setting_keys): logger.debug('cache delete_many(%r)', cache_keys) cache.delete_many(cache_keys) - if any([setting.startswith('LOG_AGGREGATOR') for setting in setting_keys]): - reconfigure_rsyslog() - @task(queue='tower_broadcast_all') def delete_project_files(project_path): diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py index a1ae7398a5..bcfa499af3 100644 --- a/awx/main/tests/functional/api/test_settings.py +++ b/awx/main/tests/functional/api/test_settings.py @@ -279,7 +279,7 @@ def test_logging_aggregator_missing_settings(put, post, admin, key, value, error ], ) @pytest.mark.django_db -def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, username, password): +def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, username, password, mocker): _, mock_settings = _mock_logging_defaults() # type = 'splunk' # host = 'https://yoursplunk:8088/services/collector/event' @@ -292,6 +292,8 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u mock_settings['LOG_AGGREGATOR_USERNAME'] = username if password: mock_settings['LOG_AGGREGATOR_PASSWORD'] = password + # mock testing pg_notify + mocker.patch("awx.conf.views.send_pg_notify", return_value=None) url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) response = put(url, data=mock_settings, user=admin, expect=200) assert type in response.data.get('LOG_AGGREGATOR_TYPE') @@ -305,13 +307,15 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u @pytest.mark.django_db -def test_logging_aggregator_connection_test_valid(put, post, admin): +def test_logging_aggregator_connection_test_valid(put, post, admin, mocker): _, mock_settings = _mock_logging_defaults() type = 'other' host = 'https://localhost' mock_settings['LOG_AGGREGATOR_ENABLED'] = True mock_settings['LOG_AGGREGATOR_TYPE'] = type mock_settings['LOG_AGGREGATOR_HOST'] = host + # mock testing pg_notify + mocker.patch("awx.conf.views.send_pg_notify", return_value=None) # POST to save these mock settings url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) put(url, data=mock_settings, user=admin, expect=200) diff --git a/awx/main/utils/external_logging.py b/awx/main/utils/external_logging.py index 26f434a4e4..e3e0a3d1c8 100644 --- a/awx/main/utils/external_logging.py +++ b/awx/main/utils/external_logging.py @@ -6,6 +6,7 @@ import urllib.parse as urlparse from django.conf import settings from awx.main.utils.reload import supervisor_service_command +from awx.main.dispatch import pg_bus_conn def construct_rsyslog_conf_template(settings=settings): @@ -124,3 +125,8 @@ def reconfigure_rsyslog(): f.write(tmpl + '\n') shutil.move(path, '/var/lib/awx/rsyslog/rsyslog.conf') supervisor_service_command(command='restart', service='awx-rsyslogd') + + +def send_pg_notify(channel: str, payload: str) -> None: + with pg_bus_conn() as conn: + conn.notify(channel, payload) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index e7720e150b..6c1c765a27 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -867,6 +867,7 @@ LOGGING = { 'awx.main.dispatch': {'handlers': ['dispatcher']}, 'awx.main.consumers': {'handlers': ['console', 'file', 'tower_warnings'], 'level': 'INFO'}, 'awx.main.wsbroadcast': {'handlers': ['wsbroadcast']}, + 'awx.main.rsyslog_configurer': {'handlers': ['rsyslog_configurer']}, 'awx.main.commands.inventory_import': {'handlers': ['inventory_import'], 'propagate': False}, 'awx.main.tasks': {'handlers': ['task_system', 'external_logger'], 'propagate': False}, 'awx.main.analytics': {'handlers': ['task_system', 'external_logger'], 'level': 'INFO', 'propagate': False}, @@ -897,6 +898,7 @@ handler_config = { 'task_system': {'filename': 'task_system.log'}, 'rbac_migrations': {'filename': 'tower_rbac_migrations.log'}, 'job_lifecycle': {'filename': 'job_lifecycle.log', 'formatter': 'job_lifecycle'}, + 'rsyslog_configurer': {'filename': 'rsyslog_configurer.log'}, } # If running on a VM, we log to files. When running in a container, we log to stdout. diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 0e2441a47e..5107b463de 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -34,6 +34,16 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 +[program:awx-rsyslog-configurer] +command = make rsyslog-configurer +autorestart = true +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [program:awx-uwsgi] command = make uwsgi autorestart = true From 65b3e0226d1d4bd725f4752218b9170634d381a6 Mon Sep 17 00:00:00 2001 From: Lila Yasin Date: Wed, 4 Jan 2023 14:29:40 -0500 Subject: [PATCH 092/167] Created new rsyslog launch file. (#13327) * Created new rsyslog launch file. * Rsyslog conf work. * Refining how we're calling rsyslog conf. * Removed rsyslog so it no longer launches in the web container. * Added the new launch_awx_rsyslog.sh to the /usr/bin --- .../dockerfile/files/launch_awx_rsyslog.sh | 28 +++++++++ tools/ansible/roles/dockerfile/tasks/main.yml | 1 + .../roles/dockerfile/templates/Dockerfile.j2 | 4 +- .../dockerfile/templates/supervisor.conf.j2 | 13 +--- .../templates/supervisor_rsyslog.conf.j2 | 59 +++++++++++++++++++ 5 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh create mode 100644 tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh b/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh new file mode 100644 index 0000000000..53ef60f544 --- /dev/null +++ b/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +if [ `id -u` -ge 500 ]; then + echo "awx:x:`id -u`:`id -g`:,,,:/var/lib/awx:/bin/bash" >> /tmp/passwd + cat /tmp/passwd > /etc/passwd + rm /tmp/passwd +fi + +if [ -n "${AWX_KUBE_DEVEL}" ]; then + pushd /awx_devel + make awx-link + popd + + export SDB_NOTIFY_HOST=$MY_POD_IP +fi + +set -e + +wait-for-migrations + +# This file will be re-written when the dispatcher calls reconfigure_rsyslog(), +# but it needs to exist when supervisor initially starts rsyslog to prevent the +# container from crashing. This was the most minimal config I could get working. +cat << EOF > /var/lib/awx/rsyslog/rsyslog.conf +action(type="omfile" file="/dev/null") +EOF + +exec supervisord -c /etc/supervisor_rsyslog.conf + diff --git a/tools/ansible/roles/dockerfile/tasks/main.yml b/tools/ansible/roles/dockerfile/tasks/main.yml index 1f2a2bac73..7a3953e7ed 100644 --- a/tools/ansible/roles/dockerfile/tasks/main.yml +++ b/tools/ansible/roles/dockerfile/tasks/main.yml @@ -11,6 +11,7 @@ with_items: - "supervisor.conf" - "supervisor_task.conf" + - "supervisor_rsyslog.conf" - name: Render Dockerfile template: diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index 2477153678..a74129905b 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -194,8 +194,6 @@ ENV _CONTAINERS_USERNS_CONFIGURED="" RUN mkdir -p /etc/containers/registries.conf.d/ && echo "unqualified-search-registries = []" >> /etc/containers/registries.conf.d/force-fully-qualified-images.conf && chmod 644 /etc/containers/registries.conf.d/force-fully-qualified-images.conf {% endif %} -# Create default awx rsyslog config -ADD tools/ansible/roles/dockerfile/files/rsyslog.conf /var/lib/awx/rsyslog/rsyslog.conf ADD tools/ansible/roles/dockerfile/files/wait-for-migrations /usr/local/bin/wait-for-migrations ADD tools/ansible/roles/dockerfile/files/stop-supervisor /usr/local/bin/stop-supervisor @@ -213,8 +211,10 @@ ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/ {% else %} ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh +ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh ADD {{ template_dest }}/supervisor.conf /etc/supervisord.conf ADD {{ template_dest }}/supervisor_task.conf /etc/supervisord_task.conf +ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisor_rsyslog.conf {% endif %} {% if (build_dev|bool) or (kube_dev|bool) %} ADD tools/docker-compose/awx.egg-link /tmp/awx.egg-link diff --git a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 index 6cd821b9d0..f72b4a6c26 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 @@ -75,19 +75,8 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:awx-rsyslogd] -command = rsyslogd -n -i /var/run/awx-rsyslog/rsyslog.pid -f /var/lib/awx/rsyslog/rsyslog.conf -autorestart = true -startsecs = 30 -stopasgroup=true -killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - [group:tower-processes] -programs=nginx,uwsgi,daphne,wsbroadcast,awx-rsyslogd +programs=nginx,uwsgi,daphne,wsbroadcast priority=5 [eventlistener:superwatcher] diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 new file mode 100644 index 0000000000..8f689e91a0 --- /dev/null +++ b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 @@ -0,0 +1,59 @@ +; needs to launch rsyslog +; needs to launch rsyslog-configurer + +[supervisord] +nodaemon = True +umask = 022 +logfile = /dev/stdout +logfile_maxbytes = 0 +pidfile = /var/run/supervisor/supervisor.rsyslog.pid + +[program:awx-rsyslogd] +command = rsyslogd -n -i /var/run/awx-rsyslog/rsyslog.pid -f /var/lib/awx/rsyslog/rsyslog.conf +autorestart = true +startsecs = 30 +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:awx-rsyslog-configurer] +{% if kube_dev | bool %} +command = make rsyslog-configurer +directory = /awx_devel +{% else %} +command = awx-manage run_rsyslog_configurer +directory = /var/lib/awx +{% endif %} +autorestart = true +startsecs = 30 +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[group:tower-processes] +programs=awx-rsyslog-configurer,awx-rsyslogd +priority=5 + +[eventlistener:superwatcher] +command=stop-supervisor +events=PROCESS_STATE_FATAL +autorestart = true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[unix_http_server] +file=/var/run/supervisor/supervisor.rsyslog.sock + +[supervisorctl] +serverurl=unix:///var/run/supervisor/supervisor.rsyslog.sock ; use a unix:// URL for a unix socket + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface From 38cc193aea8ae6347430b3d00e4d78d3ab85296e Mon Sep 17 00:00:00 2001 From: Hao Liu <44379968+TheRealHaoLiu@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:08:31 -0500 Subject: [PATCH 093/167] update permission to launch_awx_rsyslog.sh permission to +x (#13399) Signed-off-by: Hao Liu --- tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh b/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh old mode 100644 new mode 100755 From d8e591cd6946a0b34b015497d2605e04dd9bd846 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Tue, 17 Jan 2023 12:00:21 -0500 Subject: [PATCH 094/167] added cache-clear service. update dispatcher queues Signed-off-by: Jessica Mack --- Makefile | 6 +++ .../management/commands/run_cache_clear.py | 39 +++++++++++++++++++ .../management/commands/run_dispatcher.py | 2 +- awx/main/tasks/system.py | 13 ++----- awx/settings/defaults.py | 2 + tools/docker-compose/supervisor.conf | 10 +++++ 6 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 awx/main/management/commands/run_cache_clear.py diff --git a/Makefile b/Makefile index 5165ad577b..addcca9243 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,12 @@ I18N_FLAG_FILE = .i18n_built VERSION PYTHON_VERSION docker-compose-sources \ .git/hooks/pre-commit github_ci_setup github_ci_runner +cache-clear: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_cache_clear + clean-tmp: rm -rf tmp/ diff --git a/awx/main/management/commands/run_cache_clear.py b/awx/main/management/commands/run_cache_clear.py new file mode 100644 index 0000000000..5e27172d38 --- /dev/null +++ b/awx/main/management/commands/run_cache_clear.py @@ -0,0 +1,39 @@ +import logging + +from django.core.management.base import BaseCommand +from django.conf import settings +from django.core.cache import cache +from awx.main.dispatch import pg_bus_conn +from awx.conf import settings_registry + +logger = logging.getLogger('awx.main.cache_clear') + + +class Command(BaseCommand): + """ + Cache Clear + Runs as a management command and starts a daemon that listens for a pg_notify message to clear the cache. + """ + + help = 'Launch the cache clear daemon' + + def handle(self, *arg, **options): + try: + with pg_bus_conn(new_connection=True) as conn: + conn.listen("tower_settings_change") + for e in conn.events(yield_timeouts=True): + if e is not None: + logger.info("Cache clear request received. Clearing now") + # clear the cache of the keys in the payload + setting_keys = e.payload + orig_len = len(setting_keys) + for i in range(orig_len): + for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): + setting_keys.append(dependent_key) + cache_keys = set(setting_keys) + logger.info('cache delete_many(%r)', cache_keys) + cache.delete_many(cache_keys) + except Exception: + # Log unanticipated exception in addition to writing to stderr to get timestamps and other metadata + logger.exception('Encountered unhandled error in cache clear main loop') + raise diff --git a/awx/main/management/commands/run_dispatcher.py b/awx/main/management/commands/run_dispatcher.py index 74a8ac3f94..72fbfbedba 100644 --- a/awx/main/management/commands/run_dispatcher.py +++ b/awx/main/management/commands/run_dispatcher.py @@ -76,7 +76,7 @@ class Command(BaseCommand): consumer = None try: - queues = ['tower_broadcast_all', get_local_queuename()] + queues = ['tower_broadcast_all', 'tower_settings_change', 'rsyslog_configurer', get_local_queuename()] consumer = AWXConsumerPG('dispatcher', TaskWorker(), queues, AutoscalePool(min_workers=4)) consumer.run() except KeyboardInterrupt: diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index ac0e0c32bf..069ac745cd 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -61,10 +61,10 @@ from awx.main.utils.common import ( from awx.main.utils.reload import stop_local_services from awx.main.utils.pglock import advisory_lock +from awx.main.utils.external_logging import send_pg_notify from awx.main.tasks.receptor import get_receptor_ctl, worker_info, worker_cleanup, administrative_workunit_reaper, write_receptor_config from awx.main.consumers import emit_channel_notification from awx.main import analytics -from awx.conf import settings_registry from awx.main.analytics.subsystem_metrics import Metrics from rest_framework.exceptions import PermissionDenied @@ -240,15 +240,10 @@ def apply_cluster_membership_policies(): logger.debug('Cluster policy computation finished in {} seconds'.format(time.time() - started_compute)) -@task(queue='tower_broadcast_all') +@task(queue='tower_settings_change') def clear_setting_cache(setting_keys): - orig_len = len(setting_keys) - for i in range(orig_len): - for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): - setting_keys.append(dependent_key) - cache_keys = set(setting_keys) - logger.debug('cache delete_many(%r)', cache_keys) - cache.delete_many(cache_keys) + # notify the service to clear the cache + send_pg_notify('tower_settings_change', setting_keys) @task(queue='tower_broadcast_all') diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 6c1c765a27..33c6eda725 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -868,6 +868,7 @@ LOGGING = { 'awx.main.consumers': {'handlers': ['console', 'file', 'tower_warnings'], 'level': 'INFO'}, 'awx.main.wsbroadcast': {'handlers': ['wsbroadcast']}, 'awx.main.rsyslog_configurer': {'handlers': ['rsyslog_configurer']}, + 'awx.main.cache_clear': {'handlers': ['cache_clear']}, 'awx.main.commands.inventory_import': {'handlers': ['inventory_import'], 'propagate': False}, 'awx.main.tasks': {'handlers': ['task_system', 'external_logger'], 'propagate': False}, 'awx.main.analytics': {'handlers': ['task_system', 'external_logger'], 'level': 'INFO', 'propagate': False}, @@ -899,6 +900,7 @@ handler_config = { 'rbac_migrations': {'filename': 'tower_rbac_migrations.log'}, 'job_lifecycle': {'filename': 'job_lifecycle.log', 'formatter': 'job_lifecycle'}, 'rsyslog_configurer': {'filename': 'rsyslog_configurer.log'}, + 'cache_clear': {'filename': 'cache_clear.log'}, } # If running on a VM, we log to files. When running in a container, we log to stdout. diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 5107b463de..234f1b69f4 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -44,6 +44,16 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 +[program:awx-cache-clear] +command = make cache-clear +autorestart = true +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [program:awx-uwsgi] command = make uwsgi autorestart = true From 026b8f05d79a144a18d08eabf682938c0bc690d0 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Thu, 19 Jan 2023 13:44:29 -0500 Subject: [PATCH 095/167] added launch file, docker, and supervisor changes Signed-off-by: Jessica Mack --- .../files/launch_awx_cache_clear.sh | 22 +++++++++++++++++++ .../roles/dockerfile/templates/Dockerfile.j2 | 1 + .../dockerfile/templates/supervisor.conf.j2 | 13 ++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh b/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh new file mode 100644 index 0000000000..8a1a3e87fd --- /dev/null +++ b/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +if [ `id -u` -ge 500 ]; then + echo "awx:x:`id -u`:`id -g`:,,,:/var/lib/awx:/bin/bash" >> /tmp/passwd + cat /tmp/passwd > /etc/passwd + rm /tmp/passwd +fi + +if [ -n "${AWX_KUBE_DEVEL}" ]; then + pushd /awx_devel + make awx-link + popd + + export SDB_NOTIFY_HOST=$MY_POD_IP +fi + +set -e + +wait-for-migrations + +awx-manage provision_instance + +exec supervisord -c /etc/supervisord_task.conf \ No newline at end of file diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index a74129905b..c6fd7bf044 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -212,6 +212,7 @@ ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/ ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh +ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_cache_clear.sh ADD {{ template_dest }}/supervisor.conf /etc/supervisord.conf ADD {{ template_dest }}/supervisor_task.conf /etc/supervisord_task.conf ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisor_rsyslog.conf diff --git a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 index f72b4a6c26..d1d902a16c 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 @@ -75,8 +75,19 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 +[program:awx-cache-clear] +command = awx-manage run_cache_clear +autorestart = true +startsecs = 30 +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [group:tower-processes] -programs=nginx,uwsgi,daphne,wsbroadcast +programs=nginx,uwsgi,daphne,wsbroadcast,awx-cache-clear priority=5 [eventlistener:superwatcher] From 8b70fef74367c7bceeec3b2d3d4eceaaade44fe3 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Thu, 19 Jan 2023 13:44:50 -0500 Subject: [PATCH 096/167] removed unused import Signed-off-by: Jessica Mack --- awx/main/management/commands/run_cache_clear.py | 1 - 1 file changed, 1 deletion(-) diff --git a/awx/main/management/commands/run_cache_clear.py b/awx/main/management/commands/run_cache_clear.py index 5e27172d38..8ae2615086 100644 --- a/awx/main/management/commands/run_cache_clear.py +++ b/awx/main/management/commands/run_cache_clear.py @@ -1,7 +1,6 @@ import logging from django.core.management.base import BaseCommand -from django.conf import settings from django.core.cache import cache from awx.main.dispatch import pg_bus_conn from awx.conf import settings_registry From 454d6d28e72d8399b3150dd5c7e4000a0eae1794 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Thu, 19 Jan 2023 13:53:27 -0500 Subject: [PATCH 097/167] mock additional pg_notify use in test Signed-off-by: Jessica Mack --- awx/main/tests/functional/api/test_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py index bcfa499af3..eb57f27e14 100644 --- a/awx/main/tests/functional/api/test_settings.py +++ b/awx/main/tests/functional/api/test_settings.py @@ -294,6 +294,7 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u mock_settings['LOG_AGGREGATOR_PASSWORD'] = password # mock testing pg_notify mocker.patch("awx.conf.views.send_pg_notify", return_value=None) + mocker.patch("awx.main.tasks.system.send_pg_notify", return_value=None) url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) response = put(url, data=mock_settings, user=admin, expect=200) assert type in response.data.get('LOG_AGGREGATOR_TYPE') @@ -316,6 +317,7 @@ def test_logging_aggregator_connection_test_valid(put, post, admin, mocker): mock_settings['LOG_AGGREGATOR_HOST'] = host # mock testing pg_notify mocker.patch("awx.conf.views.send_pg_notify", return_value=None) + mocker.patch("awx.main.tasks.system.send_pg_notify", return_value=None) # POST to save these mock settings url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) put(url, data=mock_settings, user=admin, expect=200) From 9f959ca3d428469e9af5e65c8823c6df4f93fda8 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Thu, 26 Jan 2023 11:12:50 -0500 Subject: [PATCH 098/167] removed unneeded launch file and Dockerfile change Signed-off-by: Jessica Mack --- .../files/launch_awx_cache_clear.sh | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh b/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh deleted file mode 100644 index 8a1a3e87fd..0000000000 --- a/tools/ansible/roles/dockerfile/files/launch_awx_cache_clear.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -if [ `id -u` -ge 500 ]; then - echo "awx:x:`id -u`:`id -g`:,,,:/var/lib/awx:/bin/bash" >> /tmp/passwd - cat /tmp/passwd > /etc/passwd - rm /tmp/passwd -fi - -if [ -n "${AWX_KUBE_DEVEL}" ]; then - pushd /awx_devel - make awx-link - popd - - export SDB_NOTIFY_HOST=$MY_POD_IP -fi - -set -e - -wait-for-migrations - -awx-manage provision_instance - -exec supervisord -c /etc/supervisord_task.conf \ No newline at end of file From cb31973d59de20aab45c8b44d3340dacd7777ac7 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Mon, 30 Jan 2023 10:37:28 -0500 Subject: [PATCH 099/167] switched to using the built in task processing Signed-off-by: Jessica Mack --- .../management/commands/run_cache_clear.py | 20 ++++++++----------- awx/main/tasks/system.py | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/awx/main/management/commands/run_cache_clear.py b/awx/main/management/commands/run_cache_clear.py index 8ae2615086..d058b8bd6e 100644 --- a/awx/main/management/commands/run_cache_clear.py +++ b/awx/main/management/commands/run_cache_clear.py @@ -1,9 +1,9 @@ import logging +import json from django.core.management.base import BaseCommand -from django.core.cache import cache from awx.main.dispatch import pg_bus_conn -from awx.conf import settings_registry +from awx.main.dispatch.worker.task import TaskWorker logger = logging.getLogger('awx.main.cache_clear') @@ -22,16 +22,12 @@ class Command(BaseCommand): conn.listen("tower_settings_change") for e in conn.events(yield_timeouts=True): if e is not None: - logger.info("Cache clear request received. Clearing now") - # clear the cache of the keys in the payload - setting_keys = e.payload - orig_len = len(setting_keys) - for i in range(orig_len): - for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): - setting_keys.append(dependent_key) - cache_keys = set(setting_keys) - logger.info('cache delete_many(%r)', cache_keys) - cache.delete_many(cache_keys) + body = json.loads(e.payload) + logger.warning(f"Cache clear request received. Clearing now, payload: {e.payload}") + TaskWorker.run_callable(body) + else: + logger.info('run_clear_cache got timeout') + except Exception: # Log unanticipated exception in addition to writing to stderr to get timestamps and other metadata logger.exception('Encountered unhandled error in cache clear main loop') diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index 069ac745cd..30f5ae785f 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -242,8 +242,8 @@ def apply_cluster_membership_policies(): @task(queue='tower_settings_change') def clear_setting_cache(setting_keys): - # notify the service to clear the cache - send_pg_notify('tower_settings_change', setting_keys) + # log that cache is being cleared + logger.info(f"clear_setting_cache of keys {setting_keys}") @task(queue='tower_broadcast_all') From 43f4872fec8df6a1d267312c58d7bb40aa085fb4 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Mon, 30 Jan 2023 10:38:28 -0500 Subject: [PATCH 100/167] these methods don't need to be class methods Signed-off-by: Jessica Mack --- awx/main/dispatch/worker/task.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/awx/main/dispatch/worker/task.py b/awx/main/dispatch/worker/task.py index 04f63002c5..6726aaeae3 100644 --- a/awx/main/dispatch/worker/task.py +++ b/awx/main/dispatch/worker/task.py @@ -26,8 +26,8 @@ class TaskWorker(BaseWorker): `awx.main.dispatch.publish`. """ - @classmethod - def resolve_callable(cls, task): + @staticmethod + def resolve_callable(task): """ Transform a dotted notation task into an imported, callable function, e.g., @@ -46,7 +46,8 @@ class TaskWorker(BaseWorker): return _call - def run_callable(self, body): + @staticmethod + def run_callable(body): """ Given some AMQP message, import the correct Python code and run it. """ From c4ce5d0afa5b25e481f96f5c92ded9a25fb3dd5c Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Mon, 30 Jan 2023 10:38:49 -0500 Subject: [PATCH 101/167] updated supervisor to include cache-clear Signed-off-by: Jessica Mack --- tools/docker-compose/supervisor.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 234f1b69f4..76d7d0dba4 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -106,7 +106,7 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [group:tower-processes] -programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsbroadcast,awx-rsyslogd +programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsbroadcast,awx-rsyslogd, awx-cache-clear priority=5 [program:awx-autoreload] From ab6d56c24ee0feab7acf0825bf3f309217e4d7bd Mon Sep 17 00:00:00 2001 From: Shane McDonald Date: Tue, 6 Sep 2022 17:19:15 -0400 Subject: [PATCH 102/167] initial PoC for wsrelay Checkpoint --- Makefile | 4 +- awx/conf/settings.py | 23 ++- awx/main/analytics/broadcast_websocket.py | 6 +- awx/main/analytics/subsystem_metrics.py | 9 +- awx/main/consumers.py | 44 ++++-- awx/main/db/profiled_pg/base.py | 2 +- .../{run_wsbroadcast.py => run_wsrelay.py} | 25 ++-- awx/main/routing.py | 4 +- awx/main/{wsbroadcast.py => wsrelay.py} | 134 +++++++++++------- awx/settings/defaults.py | 4 +- docs/websockets.md | 12 +- .../dockerfile/templates/supervisor.conf.j2 | 11 +- .../templates/supervisor_task.conf.j2 | 17 +++ tools/docker-compose/README.md | 2 +- .../roles/sources/templates/haproxy.cfg.j2 | 4 +- tools/docker-compose/supervisor.conf | 55 +++---- 16 files changed, 207 insertions(+), 149 deletions(-) rename awx/main/management/commands/{run_wsbroadcast.py => run_wsrelay.py} (87%) rename awx/main/{wsbroadcast.py => wsrelay.py} (62%) diff --git a/Makefile b/Makefile index addcca9243..ee434fc0b7 100644 --- a/Makefile +++ b/Makefile @@ -223,11 +223,11 @@ daphne: fi; \ daphne -b 127.0.0.1 -p 8051 awx.asgi:channel_layer -wsbroadcast: +wsrelay: @if [ "$(VENV_BASE)" ]; then \ . $(VENV_BASE)/awx/bin/activate; \ fi; \ - $(PYTHON) manage.py run_wsbroadcast + $(PYTHON) manage.py run_wsrelay ## Run to start the background task dispatcher for development. dispatcher: diff --git a/awx/conf/settings.py b/awx/conf/settings.py index 3f364dc058..27b7847ae9 100644 --- a/awx/conf/settings.py +++ b/awx/conf/settings.py @@ -5,6 +5,8 @@ import threading import time import os +from concurrent.futures import ThreadPoolExecutor + # Django from django.conf import LazySettings from django.conf import settings, UserSettingsHolder @@ -157,7 +159,7 @@ class EncryptedCacheProxy(object): obj_id = self.cache.get(Setting.get_cache_id_key(key), default=empty) if obj_id is empty: logger.info('Efficiency notice: Corresponding id not stored in cache %s', Setting.get_cache_id_key(key)) - obj_id = getattr(self._get_setting_from_db(key), 'pk', None) + obj_id = getattr(_get_setting_from_db(self.registry, key), 'pk', None) elif obj_id == SETTING_CACHE_NONE: obj_id = None return method(TransientSetting(pk=obj_id, value=value), 'value') @@ -166,11 +168,6 @@ class EncryptedCacheProxy(object): # a no-op; it just returns the provided value return value - def _get_setting_from_db(self, key): - field = self.registry.get_setting_field(key) - if not field.read_only: - return Setting.objects.filter(key=key, user__isnull=True).order_by('pk').first() - def __getattr__(self, name): return getattr(self.cache, name) @@ -186,6 +183,18 @@ def get_settings_to_cache(registry): return dict([(key, SETTING_CACHE_NOTSET) for key in get_writeable_settings(registry)]) +# HACK: runs in thread in order to work in an asyncio context +def _get_setting_from_db(registry, key): + def wrapped(registry, key): + field = registry.get_setting_field(key) + if not field.read_only: + return Setting.objects.filter(key=key, user__isnull=True).order_by('pk').first() + + with ThreadPoolExecutor(max_workers=1) as executor: + future = executor.submit(wrapped, registry, key) + return future.result() + + def get_cache_value(value): """Returns the proper special cache setting for a value based on instance type. @@ -345,7 +354,7 @@ class SettingsWrapper(UserSettingsHolder): setting_id = None # this value is read-only, however we *do* want to fetch its value from the database if not field.read_only or name == 'INSTALL_UUID': - setting = Setting.objects.filter(key=name, user__isnull=True).order_by('pk').first() + setting = _get_setting_from_db(self.registry, name) if setting: if getattr(field, 'encrypted', False): value = decrypt_field(setting, 'value') diff --git a/awx/main/analytics/broadcast_websocket.py b/awx/main/analytics/broadcast_websocket.py index 37b64361d3..21567402f3 100644 --- a/awx/main/analytics/broadcast_websocket.py +++ b/awx/main/analytics/broadcast_websocket.py @@ -65,7 +65,7 @@ class FixedSlidingWindow: return sum(self.buckets.values()) or 0 -class BroadcastWebsocketStatsManager: +class RelayWebsocketStatsManager: def __init__(self, event_loop, local_hostname): self._local_hostname = local_hostname @@ -74,7 +74,7 @@ class BroadcastWebsocketStatsManager: self._redis_key = BROADCAST_WEBSOCKET_REDIS_KEY_NAME def new_remote_host_stats(self, remote_hostname): - self._stats[remote_hostname] = BroadcastWebsocketStats(self._local_hostname, remote_hostname) + self._stats[remote_hostname] = RelayWebsocketStats(self._local_hostname, remote_hostname) return self._stats[remote_hostname] def delete_remote_host_stats(self, remote_hostname): @@ -107,7 +107,7 @@ class BroadcastWebsocketStatsManager: return parser.text_string_to_metric_families(stats_str.decode('UTF-8')) -class BroadcastWebsocketStats: +class RelayWebsocketStats: def __init__(self, local_hostname, remote_hostname): self._local_hostname = local_hostname self._remote_hostname = remote_hostname diff --git a/awx/main/analytics/subsystem_metrics.py b/awx/main/analytics/subsystem_metrics.py index 4b023db315..439f084c5b 100644 --- a/awx/main/analytics/subsystem_metrics.py +++ b/awx/main/analytics/subsystem_metrics.py @@ -311,7 +311,14 @@ class Metrics: } # store a local copy as well self.store_metrics(json.dumps(payload)) - emit_channel_notification("metrics", payload) + + # 🚨🚨🚨🚨🚨🚨🚨🚨 + # TODO: rework how metrics are emitted and recorded. we used to exploit wsbroadcast's behavior of + # sending the same data out to every other node. + # Should we increment this data in redis but ultimately just store it in the database? + # emit_channel_notification("metrics", payload) + # 🚨🚨🚨🚨🚨🚨🚨🚨 + self.previous_send_metrics.set(current_time) self.previous_send_metrics.store_value(self.conn) finally: diff --git a/awx/main/consumers.py b/awx/main/consumers.py index ad1740c362..433ffe6e2b 100644 --- a/awx/main/consumers.py +++ b/awx/main/consumers.py @@ -80,7 +80,7 @@ class WebsocketSecretAuthHelper: WebsocketSecretAuthHelper.verify_secret(secret) -class BroadcastConsumer(AsyncJsonWebsocketConsumer): +class RelayConsumer(AsyncJsonWebsocketConsumer): async def connect(self): try: WebsocketSecretAuthHelper.is_authorized(self.scope) @@ -100,6 +100,16 @@ class BroadcastConsumer(AsyncJsonWebsocketConsumer): async def internal_message(self, event): await self.send(event['text']) + async def receive_json(self, data): + (group, message) = unwrap_broadcast_msg(data) + await self.channel_layer.group_send(group, message) + + async def consumer_subscribe(self, event): + await self.send_json(event) + + async def consumer_unsubscribe(self, event): + await self.send_json(event) + class EventConsumer(AsyncJsonWebsocketConsumer): async def connect(self): @@ -128,6 +138,11 @@ class EventConsumer(AsyncJsonWebsocketConsumer): self.channel_name, ) + await self.channel_layer.group_send( + settings.BROADCAST_WEBSOCKET_GROUP_NAME, + {"type": "consumer.unsubscribe", "groups": list(current_groups), "origin_channel": self.channel_name}, + ) + @database_sync_to_async def user_can_see_object_id(self, user_access, oid): # At this point user is a channels.auth.UserLazyObject object @@ -176,9 +191,20 @@ class EventConsumer(AsyncJsonWebsocketConsumer): self.channel_name, ) + if len(old_groups): + await self.channel_layer.group_send( + settings.BROADCAST_WEBSOCKET_GROUP_NAME, + {"type": "consumer.unsubscribe", "groups": list(old_groups), "origin_channel": self.channel_name}, + ) + new_groups_exclusive = new_groups - current_groups for group_name in new_groups_exclusive: await self.channel_layer.group_add(group_name, self.channel_name) + + await self.channel_layer.group_send( + settings.BROADCAST_WEBSOCKET_GROUP_NAME, + {"type": "consumer.subscribe", "groups": list(new_groups), "origin_channel": self.channel_name}, + ) self.scope['session']['groups'] = new_groups await self.send_json({"groups_current": list(new_groups), "groups_left": list(old_groups), "groups_joined": list(new_groups_exclusive)}) @@ -200,9 +226,11 @@ def _dump_payload(payload): return None -def emit_channel_notification(group, payload): - from awx.main.wsbroadcast import wrap_broadcast_msg # noqa +def unwrap_broadcast_msg(payload: dict): + return (payload['group'], payload['message']) + +def emit_channel_notification(group, payload): payload_dumped = _dump_payload(payload) if payload_dumped is None: return @@ -215,13 +243,3 @@ def emit_channel_notification(group, payload): {"type": "internal.message", "text": payload_dumped}, ) ) - - run_sync( - channel_layer.group_send( - settings.BROADCAST_WEBSOCKET_GROUP_NAME, - { - "type": "internal.message", - "text": wrap_broadcast_msg(group, payload_dumped), - }, - ) - ) diff --git a/awx/main/db/profiled_pg/base.py b/awx/main/db/profiled_pg/base.py index 5df1341428..583c12ff53 100644 --- a/awx/main/db/profiled_pg/base.py +++ b/awx/main/db/profiled_pg/base.py @@ -63,7 +63,7 @@ class RecordedQueryLog(object): if not os.path.isdir(self.dest): os.makedirs(self.dest) progname = ' '.join(sys.argv) - for match in ('uwsgi', 'dispatcher', 'callback_receiver', 'wsbroadcast'): + for match in ('uwsgi', 'dispatcher', 'callback_receiver', 'wsrelay'): if match in progname: progname = match break diff --git a/awx/main/management/commands/run_wsbroadcast.py b/awx/main/management/commands/run_wsrelay.py similarity index 87% rename from awx/main/management/commands/run_wsbroadcast.py rename to awx/main/management/commands/run_wsrelay.py index cb2b7efcdb..ce778b8356 100644 --- a/awx/main/management/commands/run_wsbroadcast.py +++ b/awx/main/management/commands/run_wsrelay.py @@ -13,13 +13,13 @@ from django.db import connection from django.db.migrations.executor import MigrationExecutor from awx.main.analytics.broadcast_websocket import ( - BroadcastWebsocketStatsManager, + RelayWebsocketStatsManager, safe_name, ) -from awx.main.wsbroadcast import BroadcastWebsocketManager +from awx.main.wsrelay import WebSocketRelayManager -logger = logging.getLogger('awx.main.wsbroadcast') +logger = logging.getLogger('awx.main.wsrelay') class Command(BaseCommand): @@ -99,7 +99,7 @@ class Command(BaseCommand): executor = MigrationExecutor(connection) migrating = bool(executor.migration_plan(executor.loader.graph.leaf_nodes())) except Exception as exc: - logger.info(f'Error on startup of run_wsbroadcast (error: {exc}), retry in 10s...') + logger.info(f'Error on startup of run_wsrelay (error: {exc}), retry in 10s...') time.sleep(10) return @@ -130,9 +130,9 @@ class Command(BaseCommand): if options.get('status'): try: - stats_all = BroadcastWebsocketStatsManager.get_stats_sync() + stats_all = RelayWebsocketStatsManager.get_stats_sync() except redis.exceptions.ConnectionError as e: - print(f"Unable to get Broadcast Websocket Status. Failed to connect to redis {e}") + print(f"Unable to get Relay Websocket Status. Failed to connect to redis {e}") return data = {} @@ -151,22 +151,19 @@ class Command(BaseCommand): host_stats = Command.get_connection_status(hostnames, data) lines = Command._format_lines(host_stats) - print(f'Broadcast websocket connection status from "{my_hostname}" to:') + print(f'Relay websocket connection status from "{my_hostname}" to:') print('\n'.join(lines)) host_stats = Command.get_connection_stats(hostnames, data) lines = Command._format_lines(host_stats) - print(f'\nBroadcast websocket connection stats from "{my_hostname}" to:') + print(f'\nRelay websocket connection stats from "{my_hostname}" to:') print('\n'.join(lines)) return try: - broadcast_websocket_mgr = BroadcastWebsocketManager() - task = broadcast_websocket_mgr.start() - - loop = asyncio.get_event_loop() - loop.run_until_complete(task) + websocket_relay_manager = WebSocketRelayManager() + asyncio.run(websocket_relay_manager.run()) except KeyboardInterrupt: - logger.debug('Terminating Websocket Broadcaster') + logger.debug('Terminating Websocket Relayer') diff --git a/awx/main/routing.py b/awx/main/routing.py index 100347f64e..e45bf0a537 100644 --- a/awx/main/routing.py +++ b/awx/main/routing.py @@ -27,8 +27,8 @@ class AWXProtocolTypeRouter(ProtocolTypeRouter): websocket_urlpatterns = [ - re_path(r'websocket/$', consumers.EventConsumer.as_asgi()), - re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer.as_asgi()), + re_path(r'websocket/$', consumers.EventConsumer), + re_path(r'websocket/relay/$', consumers.RelayConsumer), ] application = AWXProtocolTypeRouter( diff --git a/awx/main/wsbroadcast.py b/awx/main/wsrelay.py similarity index 62% rename from awx/main/wsbroadcast.py rename to awx/main/wsrelay.py index 2c1f228785..4794ee9ea2 100644 --- a/awx/main/wsbroadcast.py +++ b/awx/main/wsrelay.py @@ -7,28 +7,24 @@ from aiohttp import client_exceptions from asgiref.sync import sync_to_async from channels.layers import get_channel_layer +from channels.db import database_sync_to_async from django.conf import settings from django.apps import apps -from django.core.serializers.json import DjangoJSONEncoder from awx.main.analytics.broadcast_websocket import ( - BroadcastWebsocketStats, - BroadcastWebsocketStatsManager, + RelayWebsocketStats, + RelayWebsocketStatsManager, ) import awx.main.analytics.subsystem_metrics as s_metrics -logger = logging.getLogger('awx.main.wsbroadcast') +logger = logging.getLogger('awx.main.wsrelay') def wrap_broadcast_msg(group, message: str): # TODO: Maybe wrap as "group","message" so that we don't need to # encode/decode as json. - return json.dumps(dict(group=group, message=message), cls=DjangoJSONEncoder) - - -def unwrap_broadcast_msg(payload: dict): - return (payload['group'], payload['message']) + return dict(group=group, message=message) @sync_to_async @@ -50,28 +46,26 @@ def get_local_host(): return Instance.objects.my_hostname() -class WebsocketTask: +class WebsocketRelayConnection: def __init__( self, name, - event_loop, - stats: BroadcastWebsocketStats, + stats: RelayWebsocketStats, remote_host: str, remote_port: int = settings.BROADCAST_WEBSOCKET_PORT, protocol: str = settings.BROADCAST_WEBSOCKET_PROTOCOL, verify_ssl: bool = settings.BROADCAST_WEBSOCKET_VERIFY_CERT, - endpoint: str = 'broadcast', ): self.name = name - self.event_loop = event_loop + self.event_loop = asyncio.get_event_loop() self.stats = stats self.remote_host = remote_host self.remote_port = remote_port - self.endpoint = endpoint self.protocol = protocol self.verify_ssl = verify_ssl self.channel_layer = None self.subsystem_metrics = s_metrics.Metrics(instance_name=name) + self.producers = dict() async def run_loop(self, websocket: aiohttp.ClientWebSocketResponse): raise RuntimeError("Implement me") @@ -95,7 +89,7 @@ class WebsocketTask: logger.warning(f"Connection from {self.name} to {self.remote_host} cancelled") raise - uri = f"{self.protocol}://{self.remote_host}:{self.remote_port}/websocket/{self.endpoint}/" + uri = f"{self.protocol}://{self.remote_host}:{self.remote_port}/websocket/relay/" timeout = aiohttp.ClientTimeout(total=10) secret_val = WebsocketSecretAuthHelper.construct_secret() @@ -105,7 +99,7 @@ class WebsocketTask: logger.info(f"Connection from {self.name} to {self.remote_host} established.") self.stats.record_connection_established() attempt = 0 - await self.run_loop(websocket) + await self.run_connection(websocket) except asyncio.CancelledError: # TODO: Check if connected and disconnect # Possibly use run_until_complete() if disconnect is async @@ -128,12 +122,12 @@ class WebsocketTask: def start(self, attempt=0): self.async_task = self.event_loop.create_task(self.connect(attempt=attempt)) + return self.async_task + def cancel(self): self.async_task.cancel() - -class BroadcastWebsocketTask(WebsocketTask): - async def run_loop(self, websocket: aiohttp.ClientWebSocketResponse): + async def run_connection(self, websocket: aiohttp.ClientWebSocketResponse): async for msg in websocket: self.stats.record_message_received() @@ -148,38 +142,79 @@ class BroadcastWebsocketTask(WebsocketTask): logmsg = "{} {}".format(logmsg, payload) logger.warning(logmsg) continue - (group, message) = unwrap_broadcast_msg(payload) - if group == "metrics": - self.subsystem_metrics.store_metrics(message) + + from remote_pdb import RemotePdb + + RemotePdb('127.0.0.1', 4444).set_trace() + + if payload.get("type") == "consumer.subscribe": + for group in payload['groups']: + name = f"{self.remote_host}-{group}" + origin_channel = payload['origin_channel'] + if not self.producers.get(name): + producer = self.event_loop.create_task(self.run_producer(name, websocket, group)) + + self.producers[name] = {"task": producer, "subscriptions": {origin_channel}} + else: + self.producers[name]["subscriptions"].add(origin_channel) + + if payload.get("type") == "consumer.unsubscribe": + for group in payload['groups']: + name = f"{self.remote_host}-{group}" + origin_channel = payload['origin_channel'] + self.producers[name]["subscriptions"].remove(origin_channel) + + async def run_producer(self, name, websocket, group): + try: + logger.info(f"Starting producer for {name}") + + consumer_channel = await self.channel_layer.new_channel() + await self.channel_layer.group_add(group, consumer_channel) + + while True: + try: + msg = await asyncio.wait_for(self.channel_layer.receive(consumer_channel), timeout=10) + except asyncio.TimeoutError: + current_subscriptions = self.producers[name]["subscriptions"] + if len(current_subscriptions) == 0: + logger.info(f"Producer {name} has no subscribers, shutting down.") + return + continue - await self.channel_layer.group_send(group, {"type": "internal.message", "text": message}) + + await websocket.send_json(wrap_broadcast_msg(group, msg)) + except Exception: + # Note, this is very intentional and important since we do not otherwise + # ever check the result of this future. Without this line you will not see an error if + # something goes wrong in here. + logger.exception(f"Event relay producer {name} crashed") + finally: + await self.channel_layer.group_discard(group, consumer_channel) + del self.producers[name] -class BroadcastWebsocketManager(object): +class WebSocketRelayManager(object): def __init__(self): - self.event_loop = asyncio.get_event_loop() - ''' - { - 'hostname1': BroadcastWebsocketTask(), - 'hostname2': BroadcastWebsocketTask(), - 'hostname3': BroadcastWebsocketTask(), - } - ''' - self.broadcast_tasks = dict() - self.local_hostname = get_local_host() - self.stats_mgr = BroadcastWebsocketStatsManager(self.event_loop, self.local_hostname) - async def run_per_host_websocket(self): + self.relay_connections = dict() + self.local_hostname = get_local_host() + self.event_loop = asyncio.get_event_loop() + self.stats_mgr = RelayWebsocketStatsManager(self.event_loop, self.local_hostname) + + async def run(self): + self.stats_mgr.start() + + # Establishes a websocket connection to /websocket/relay on all API servers while True: known_hosts = await get_broadcast_hosts() future_remote_hosts = known_hosts.keys() - current_remote_hosts = self.broadcast_tasks.keys() + current_remote_hosts = self.relay_connections.keys() deleted_remote_hosts = set(current_remote_hosts) - set(future_remote_hosts) new_remote_hosts = set(future_remote_hosts) - set(current_remote_hosts) - remote_addresses = {k: v.remote_host for k, v in self.broadcast_tasks.items()} + remote_addresses = {k: v.remote_host for k, v in self.relay_connections.items()} for hostname, address in known_hosts.items(): - if hostname in self.broadcast_tasks and address != remote_addresses[hostname]: + if hostname in self.relay_connections and address != remote_addresses[hostname]: deleted_remote_hosts.add(hostname) new_remote_hosts.add(hostname) @@ -189,20 +224,17 @@ class BroadcastWebsocketManager(object): logger.warning(f"Adding {new_remote_hosts} to websocket broadcast list") for h in deleted_remote_hosts: - self.broadcast_tasks[h].cancel() - del self.broadcast_tasks[h] + self.relay_connections[h].cancel() + del self.relay_connections[h] self.stats_mgr.delete_remote_host_stats(h) for h in new_remote_hosts: stats = self.stats_mgr.new_remote_host_stats(h) - broadcast_task = BroadcastWebsocketTask(name=self.local_hostname, event_loop=self.event_loop, stats=stats, remote_host=known_hosts[h]) - broadcast_task.start() - self.broadcast_tasks[h] = broadcast_task + relay_connection = WebsocketRelayConnection(name=self.local_hostname, stats=stats, remote_host=known_hosts[h]) + relay_connection.start() + self.relay_connections[h] = relay_connection + + # for host, conn in self.relay_connections.items(): + # logger.info(f"Current producers for {host}: {conn.producers}") await asyncio.sleep(settings.BROADCAST_WEBSOCKET_NEW_INSTANCE_POLL_RATE_SECONDS) - - def start(self): - self.stats_mgr.start() - - self.async_task = self.event_loop.create_task(self.run_per_host_websocket()) - return self.async_task diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 33c6eda725..de00503978 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -866,9 +866,9 @@ LOGGING = { 'awx.main.commands.run_callback_receiver': {'handlers': ['callback_receiver']}, # level handled by dynamic_level_filter 'awx.main.dispatch': {'handlers': ['dispatcher']}, 'awx.main.consumers': {'handlers': ['console', 'file', 'tower_warnings'], 'level': 'INFO'}, - 'awx.main.wsbroadcast': {'handlers': ['wsbroadcast']}, 'awx.main.rsyslog_configurer': {'handlers': ['rsyslog_configurer']}, 'awx.main.cache_clear': {'handlers': ['cache_clear']}, + 'awx.main.wsrelay': {'handlers': ['wsrelay']}, 'awx.main.commands.inventory_import': {'handlers': ['inventory_import'], 'propagate': False}, 'awx.main.tasks': {'handlers': ['task_system', 'external_logger'], 'propagate': False}, 'awx.main.analytics': {'handlers': ['task_system', 'external_logger'], 'level': 'INFO', 'propagate': False}, @@ -895,7 +895,7 @@ handler_config = { 'tower_warnings': {'filename': 'tower.log'}, 'callback_receiver': {'filename': 'callback_receiver.log'}, 'dispatcher': {'filename': 'dispatcher.log', 'formatter': 'dispatcher'}, - 'wsbroadcast': {'filename': 'wsbroadcast.log'}, + 'wsrelay': {'filename': 'wsrelay.log'}, 'task_system': {'filename': 'task_system.log'}, 'rbac_migrations': {'filename': 'tower_rbac_migrations.log'}, 'job_lifecycle': {'filename': 'job_lifecycle.log', 'formatter': 'job_lifecycle'}, diff --git a/docs/websockets.md b/docs/websockets.md index a9fcd43926..84e1226594 100644 --- a/docs/websockets.md +++ b/docs/websockets.md @@ -10,13 +10,13 @@ To communicate between our different services we use websockets. Every AWX node Inside AWX we use the `emit_channel_notification` function which places messages onto the queue. The messages are given an explicit event group and event type which we later use in our wire protocol to control message delivery to the client. -### Broadcast Backplane +### Relay Backplane -Previously, AWX leveraged RabbitMQ to deliver Ansible events that emanated from one AWX node to all other AWX nodes so that any client listening and subscribed to the Websockets could get events from any running playbook. We are since moved off of RabbitMQ and onto a per-node local Redis instance. To maintain the requirement that any Websocket connection can receive events from any playbook running on any AWX node we still need to deliver every event to every AWX node. AWX does this via a fully connected Websocket backplane. +Previously, AWX leveraged RabbitMQ to deliver Ansible events that emanated from one AWX node to all other AWX nodes so that any client listening and subscribed to the Websockets could get events from any running playbook. We are since moved off of RabbitMQ and onto a per-node local Redis instance. To maintain the requirement that any Websocket connection can receive events from any playbook running on any AWX node we still need to deliver every event to every AWX node. AWX does this via a fully connected Websocket backplane. -#### Broadcast Backplane Token +#### Relay Backplane Token -AWX node(s) connect to every other node via the Websocket backplane. The backplane websockets initiate from the `wsbroadcast` process and connect to other nodes via the same nginx process that serves webpage websocket connections and marshalls incoming web/API requests. If you have configured AWX to run with an ssl terminated connection in front of nginx then you likely will have nginx configured to handle http traffic and thus the websocket connection will flow unencrypted over http. If you have nginx configured with ssl enabled, then the websocket traffic will flow encrypted. +AWX node(s) connect to every other node via the Websocket backplane. The backplane websockets initiate from the `wsrelay` process and connect to other nodes via the same nginx process that serves webpage websocket connections and marshalls incoming web/API requests. If you have configured AWX to run with an ssl terminated connection in front of nginx then you likely will have nginx configured to handle http traffic and thus the websocket connection will flow unencrypted over http. If you have nginx configured with ssl enabled, then the websocket traffic will flow encrypted. Authentication is accomplished via a shared secret that is generated and set at playbook install time. The shared secret is used to derive a payload that is exchanged via the http(s) header `secret`. The shared secret payload consists of a a `secret`, containing the shared secret, and a `nonce` which is used to mitigate replay attack windows. @@ -65,14 +65,14 @@ This section will specifically discuss deployment in the context of websockets a | `nginx` | listens on ports 80/443, handles HTTPS proxying, serves static assets, routes requests for `daphne` and `uwsgi` | | `uwsgi` | listens on port 8050, handles API requests | | `daphne` | listens on port 8051, handles websocket requests | -| `wsbroadcast` | no listening port, forwards all group messages to all cluster nodes | +| `wsrelay` | no listening port, forwards all group messages to all cluster nodes | | `supervisord` | (production-only) handles the process management of all the services except `nginx` | When a request comes in to `nginx` and has the `Upgrade` header and is for the path `/websocket`, then `nginx` knows that it should be routing that request to our `daphne` service. `daphne` handles websocket connections proxied by nginx. -`wsbroadcast` fully connects all cluster nodes via the `/websocket/broadcast/` endpoint to every other cluster nodes. Sends a copy of all group websocket messages to all other cluster nodes (i.e. job event type messages). +`wsrelay` fully connects all cluster nodes via the `/websocket/broadcast/` endpoint to every other cluster nodes. Sends a copy of all group websocket messages to all other cluster nodes (i.e. job event type messages). ### Development - `nginx` listens on 8013/8043 instead of 80/443 diff --git a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 index d1d902a16c..c622d15645 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 @@ -22,12 +22,11 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:uwsgi] - {% if kube_dev | bool %} command = make uwsgi directory = /awx_devel environment = - DEV_RELOAD_COMMAND='supervisorctl -c /etc/supervisord_task.conf restart all; supervisorctl restart tower-processes:daphne tower-processes:wsbroadcast' + DEV_RELOAD_COMMAND='supervisorctl -c /etc/supervisord_task.conf restart all; supervisorctl restart tower-processes:daphne' {% else %} command = /var/lib/awx/venv/awx/bin/uwsgi /etc/tower/uwsgi.ini {% endif %} @@ -58,12 +57,12 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:wsbroadcast] +[program:heartbeet] {% if kube_dev | bool %} -command = make wsbroadcast +command = make heartbeet directory = /awx_devel {% else %} -command = awx-manage run_wsbroadcast +command = awx-manage run_heartbeet directory = /var/lib/awx {% endif %} autorestart = true @@ -87,7 +86,7 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [group:tower-processes] -programs=nginx,uwsgi,daphne,wsbroadcast,awx-cache-clear +programs=nginx,uwsgi,daphne,awx-cache-clear,heartbeet priority=5 [eventlistener:superwatcher] diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 index a2f2bd5298..9abd6b49b4 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 @@ -22,6 +22,23 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 +[program:wsrelay] +{% if kube_dev | bool %} +command = make wsrelay +directory = /awx_devel +{% else %} +command = awx-manage run_wsrelay +directory = /var/lib/awx +{% endif %} +autorestart = true +startsecs = 30 +stopasgroup=true +killasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [program:callback-receiver] {% if kube_dev | bool %} command = make receiver diff --git a/tools/docker-compose/README.md b/tools/docker-compose/README.md index e2018b9adc..b450398ee0 100644 --- a/tools/docker-compose/README.md +++ b/tools/docker-compose/README.md @@ -293,7 +293,7 @@ Certain features or bugs are only applicable when running a cluster of AWX nodes `CONTROL_PLANE_NODE_COUNT` is configurable and defaults to 1, effectively a non-clustered AWX. -Note that you may see multiple messages of the form `2021-03-04 20:11:47,666 WARNING [-] awx.main.wsbroadcast Connection from awx_2 to awx_5 failed: 'Cannot connect to host awx_5:8013 ssl:False [Name or service not known]'.`. This can happen when you bring up a cluster of many nodes, say 10, then you bring up a cluster of less nodes, say 3. In this example, there will be 7 `Instance` records in the database that represent AWX instances. The AWX development environment mimics the VM deployment (vs. kubernetes) and expects the missing nodes to be brought back to healthy by the admin. The warning message you are seeing is all of the AWX nodes trying to connect the websocket backplane. You can manually delete the `Instance` records from the database i.e. `Instance.objects.get(hostname='awx_9').delete()` to stop the warnings. +Note that you may see multiple messages of the form `2021-03-04 20:11:47,666 WARNING [-] awx.main.wsrelay Connection from awx_2 to awx_5 failed: 'Cannot connect to host awx_5:8013 ssl:False [Name or service not known]'.`. This can happen when you bring up a cluster of many nodes, say 10, then you bring up a cluster of less nodes, say 3. In this example, there will be 7 `Instance` records in the database that represent AWX instances. The AWX development environment mimics the VM deployment (vs. kubernetes) and expects the missing nodes to be brought back to healthy by the admin. The warning message you are seeing is all of the AWX nodes trying to connect the websocket backplane. You can manually delete the `Instance` records from the database i.e. `Instance.objects.get(hostname='awx_9').delete()` to stop the warnings. ### Start with Minikube diff --git a/tools/docker-compose/ansible/roles/sources/templates/haproxy.cfg.j2 b/tools/docker-compose/ansible/roles/sources/templates/haproxy.cfg.j2 index fab09ffc8e..f2aa3b4ec2 100644 --- a/tools/docker-compose/ansible/roles/sources/templates/haproxy.cfg.j2 +++ b/tools/docker-compose/ansible/roles/sources/templates/haproxy.cfg.j2 @@ -32,7 +32,7 @@ backend nodes option httpchk HEAD / HTTP/1.1\r\nHost:localhost {% for i in range(control_plane_node_count|int) %} {% set container_postfix = loop.index %} - server tools_awx_{{ container_postfix }} tools_awx_{{ container_postfix }}:8013 check + server tools_awx_{{ container_postfix }} tools_awx_{{ container_postfix }}:8013 check inter 10s {% endfor %} backend nodes_ssl @@ -40,7 +40,7 @@ backend nodes_ssl balance roundrobin {% for i in range(control_plane_node_count|int) %} {% set container_postfix = loop.index %} - server tools_awx_{{ container_postfix }} tools_awx_{{ container_postfix }}:8043 check + server tools_awx_{{ container_postfix }} tools_awx_{{ container_postfix }}:8043 check inter 10s {% endfor %} listen stats diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 76d7d0dba4..367a2cef53 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -8,31 +8,25 @@ command = make dispatcher autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [program:awx-receiver] command = make receiver autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true -[program:awx-wsbroadcast] -command = make wsbroadcast +[program:awx-wsrelay] +command = make wsrelay autorestart = true autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [program:awx-rsyslog-configurer] command = make rsyslog-configurer @@ -61,30 +55,24 @@ stopwaitsecs = 1 stopsignal=KILL stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [program:awx-daphne] command = make daphne autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [program:awx-nginx] command = make nginx autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [program:awx-rsyslogd] command = rsyslogd -n -i /var/run/awx-rsyslog/rsyslog.pid -f /var/lib/awx/rsyslog/rsyslog.conf @@ -100,13 +88,11 @@ command = receptor --config /etc/receptor/receptor.conf autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 +stdout_events_enabled = true +stderr_events_enabled = true [group:tower-processes] -programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsbroadcast,awx-rsyslogd, awx-cache-clear +programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsrelay,awx-rsyslogd,awx-cache-clear priority=5 [program:awx-autoreload] @@ -115,10 +101,6 @@ autostart = true autorestart = true stopasgroup=true killasgroup=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 stdout_events_enabled = true stderr_events_enabled = true @@ -127,9 +109,6 @@ command=stop-supervisor events=PROCESS_STATE_FATAL autorestart = true stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 [unix_http_server] file=/var/run/supervisor/supervisor.sock From a987249ca65411243d13d5ab9c6da8eab21a7e1e Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Wed, 30 Nov 2022 13:41:46 -0600 Subject: [PATCH 103/167] dedent a block that was clearly meant to be de-dented Signed-off-by: Rick Elrod --- awx/main/consumers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/awx/main/consumers.py b/awx/main/consumers.py index 433ffe6e2b..d830c03a52 100644 --- a/awx/main/consumers.py +++ b/awx/main/consumers.py @@ -201,10 +201,10 @@ class EventConsumer(AsyncJsonWebsocketConsumer): for group_name in new_groups_exclusive: await self.channel_layer.group_add(group_name, self.channel_name) - await self.channel_layer.group_send( - settings.BROADCAST_WEBSOCKET_GROUP_NAME, - {"type": "consumer.subscribe", "groups": list(new_groups), "origin_channel": self.channel_name}, - ) + await self.channel_layer.group_send( + settings.BROADCAST_WEBSOCKET_GROUP_NAME, + {"type": "consumer.subscribe", "groups": list(new_groups), "origin_channel": self.channel_name}, + ) self.scope['session']['groups'] = new_groups await self.send_json({"groups_current": list(new_groups), "groups_left": list(old_groups), "groups_joined": list(new_groups_exclusive)}) From 1c2eb229566693e82239c87ad6ec5e351834edf9 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Tue, 6 Dec 2022 19:16:59 -0600 Subject: [PATCH 104/167] Remove some debug code and modify logging a bit Signed-off-by: Rick Elrod --- awx/main/wsrelay.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 4794ee9ea2..1f97690c6d 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -107,12 +107,12 @@ class WebsocketRelayConnection: self.stats.record_connection_lost() raise except client_exceptions.ClientConnectorError as e: - logger.warning(f"Connection from {self.name} to {self.remote_host} failed: '{e}'.") + logger.warning(f"Connection from {self.name} to {self.remote_host} failed: '{e}'.", exc_info=True) except asyncio.TimeoutError: logger.warning(f"Connection from {self.name} to {self.remote_host} timed out.") except Exception as e: # Early on, this is our canary. I'm not sure what exceptions we can really encounter. - logger.exception(f"Connection from {self.name} to {self.remote_host} failed for unknown reason: '{e}'.") + logger.warning(f"Connection from {self.name} to {self.remote_host} failed for unknown reason: '{e}'.", exc_info=True) else: logger.warning(f"Connection from {self.name} to {self.remote_host} list.") @@ -143,10 +143,6 @@ class WebsocketRelayConnection: logger.warning(logmsg) continue - from remote_pdb import RemotePdb - - RemotePdb('127.0.0.1', 4444).set_trace() - if payload.get("type") == "consumer.subscribe": for group in payload['groups']: name = f"{self.remote_host}-{group}" @@ -155,14 +151,20 @@ class WebsocketRelayConnection: producer = self.event_loop.create_task(self.run_producer(name, websocket, group)) self.producers[name] = {"task": producer, "subscriptions": {origin_channel}} + logger.debug(f"Producer {name} started.") else: self.producers[name]["subscriptions"].add(origin_channel) + logger.debug(f"Connection from {self.name} to {self.remote_host} added subscription to {group}.") if payload.get("type") == "consumer.unsubscribe": for group in payload['groups']: name = f"{self.remote_host}-{group}" origin_channel = payload['origin_channel'] - self.producers[name]["subscriptions"].remove(origin_channel) + try: + self.producers[name]["subscriptions"].remove(origin_channel) + logger.debug(f"Unsubscribed {origin_channel} from {name}") + except KeyError: + logger.warning(f"Producer {name} not found.") async def run_producer(self, name, websocket, group): try: From a9e7508e92e182dde921b207e951ed7c4624d70a Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Thu, 8 Dec 2022 03:22:20 -0600 Subject: [PATCH 105/167] WIP: Make wsrelay listen for pg_notify heartbeat Signed-off-by: Rick Elrod --- awx/main/wsrelay.py | 89 ++++++++++++++++++++++++----------- requirements/requirements.in | 1 + requirements/requirements.txt | 4 +- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 1f97690c6d..735386a48a 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -12,6 +12,8 @@ from channels.db import database_sync_to_async from django.conf import settings from django.apps import apps +import psycopg + from awx.main.analytics.broadcast_websocket import ( RelayWebsocketStats, RelayWebsocketStatsManager, @@ -20,27 +22,12 @@ import awx.main.analytics.subsystem_metrics as s_metrics logger = logging.getLogger('awx.main.wsrelay') - def wrap_broadcast_msg(group, message: str): # TODO: Maybe wrap as "group","message" so that we don't need to # encode/decode as json. return dict(group=group, message=message) -@sync_to_async -def get_broadcast_hosts(): - Instance = apps.get_model('main', 'Instance') - instances = ( - Instance.objects.exclude(hostname=Instance.objects.my_hostname()) - .exclude(node_type='execution') - .exclude(node_type='hop') - .order_by('hostname') - .values('hostname', 'ip_address') - .distinct() - ) - return {i['hostname']: i['ip_address'] or i['hostname'] for i in instances} - - def get_local_host(): Instance = apps.get_model('main', 'Instance') return Instance.objects.my_hostname() @@ -198,41 +185,89 @@ class WebsocketRelayConnection: class WebSocketRelayManager(object): def __init__(self): - self.relay_connections = dict() self.local_hostname = get_local_host() - self.event_loop = asyncio.get_event_loop() - self.stats_mgr = RelayWebsocketStatsManager(self.event_loop, self.local_hostname) + self.relay_connections = dict() + # hostname -> ip + self.known_hosts: Dict[str, str] = dict() + + async def pg_consumer(self, conn): + try: + await conn.execute("LISTEN wsrelay_rx_from_web") + async for notif in conn.notifies(): + if notif is not None and notif.channel == "wsrelay_rx_from_web": + try: + payload = json.loads(notif.payload) + except json.JSONDecodeError: + logmsg = "Failed to decode message from pg_notify channel `wsrelay_rx_from_web`" + if logger.isEnabledFor(logging.DEBUG): + logmsg = "{} {}".format(logmsg, payload) + logger.warning(logmsg) + continue + + if payload.get("action") == "online": + hostname = payload["hostname"] + ip = payload["ip"] + self.known_hosts[hostname] = ip + logger.info(f"Web host {hostname} ({ip}) is online.") + elif payload.get("action") == "offline": + hostname = payload["hostname"] + del self.known_hosts[hostname] + logger.info(f"Web host {host} ({ip}) is offline.") + except Exception as e: + # This catch-all is the same as the one above. asyncio will NOT log exceptions anywhere, so we need to do so ourselves. + logger.exception(f"pg_consumer exception") async def run(self): - self.stats_mgr.start() + event_loop = asyncio.get_running_loop() + + stats_mgr = RelayWebsocketStatsManager(event_loop, self.local_hostname) + stats_mgr.start() + + # Set up a pg_notify consumer for allowing web nodes to "provision" and "deprovision" themselves gracefully. + database_conf = settings.DATABASES['default'] + async_conn = await psycopg.AsyncConnection.connect( + dbname=database_conf['NAME'], + host=database_conf['HOST'], + user=database_conf['USER'], + password=database_conf['PASSWORD'], + port=database_conf['PORT'], + **database_conf.get("OPTIONS", {}), + ) + await async_conn.set_autocommit(True) + event_loop.create_task(self.pg_consumer(async_conn)) # Establishes a websocket connection to /websocket/relay on all API servers while True: - known_hosts = await get_broadcast_hosts() - future_remote_hosts = known_hosts.keys() + logger.info("Current known hosts: {}".format(self.known_hosts)) + future_remote_hosts = self.known_hosts.keys() current_remote_hosts = self.relay_connections.keys() deleted_remote_hosts = set(current_remote_hosts) - set(future_remote_hosts) new_remote_hosts = set(future_remote_hosts) - set(current_remote_hosts) remote_addresses = {k: v.remote_host for k, v in self.relay_connections.items()} - for hostname, address in known_hosts.items(): + for hostname, address in self.known_hosts.items(): if hostname in self.relay_connections and address != remote_addresses[hostname]: deleted_remote_hosts.add(hostname) new_remote_hosts.add(hostname) if deleted_remote_hosts: - logger.warning(f"Removing {deleted_remote_hosts} from websocket broadcast list") + logger.info(f"Removing {deleted_remote_hosts} from websocket broadcast list") + if new_remote_hosts: - logger.warning(f"Adding {new_remote_hosts} to websocket broadcast list") + logger.info(f"Adding {new_remote_hosts} to websocket broadcast list") for h in deleted_remote_hosts: self.relay_connections[h].cancel() del self.relay_connections[h] - self.stats_mgr.delete_remote_host_stats(h) + stats_mgr.delete_remote_host_stats(h) + logger.error(f"New remote hosts: {new_remote_hosts}") for h in new_remote_hosts: - stats = self.stats_mgr.new_remote_host_stats(h) - relay_connection = WebsocketRelayConnection(name=self.local_hostname, stats=stats, remote_host=known_hosts[h]) + logger.error("we are here once") + stats = stats_mgr.new_remote_host_stats(h) + logger.error("but now we are not?") + logger.info(f"Starting relay connection to {h}") + relay_connection = WebsocketRelayConnection(name=self.local_hostname, stats=stats, remote_host=self.known_hosts[h]) relay_connection.start() self.relay_connections[h] = relay_connection diff --git a/requirements/requirements.in b/requirements/requirements.in index e66ce702cc..e7d7722f28 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -36,6 +36,7 @@ openshift pexpect==4.7.0 # see library notes prometheus_client psycopg2 +psycopg psutil pygerduty pyparsing==2.4.6 # Upgrading to v3 of pyparsing introduce errors on smart host filtering: Expected 'or' term, found 'or' (at char 15), (line:1, col:16) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index a8bd03a801..f45e0acb87 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -265,6 +265,8 @@ prometheus-client==0.15.0 # via -r /awx_devel/requirements/requirements.in psutil==5.9.4 # via -r /awx_devel/requirements/requirements.in +psycopg==3.1.4 + # via -r /awx_devel/requirements/requirements.in psycopg2==2.9.5 # via -r /awx_devel/requirements/requirements.in ptyprocess==0.7.0 @@ -425,7 +427,7 @@ txaio==22.2.1 typing-extensions==4.4.0 # via # azure-core - # pydantic + # psycopg # setuptools-rust # setuptools-scm # twisted From 4f5bc992a0d3d59a89911e4b64bbeb3b90fe1327 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 9 Dec 2022 00:54:40 -0600 Subject: [PATCH 106/167] fix merge from devel - wsbroadcast -> wsrelay Signed-off-by: Rick Elrod --- awx/settings/defaults.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index de00503978..a9d9a13925 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -877,7 +877,7 @@ LOGGING = { 'awx.main.signals': {'level': 'INFO'}, # very verbose debug-level logs 'awx.api.permissions': {'level': 'INFO'}, # very verbose debug-level logs 'awx.analytics': {'handlers': ['external_logger'], 'level': 'INFO', 'propagate': False}, - 'awx.analytics.broadcast_websocket': {'handlers': ['console', 'file', 'wsbroadcast', 'external_logger'], 'level': 'INFO', 'propagate': False}, + 'awx.analytics.broadcast_websocket': {'handlers': ['console', 'file', 'wsrelay', 'external_logger'], 'level': 'INFO', 'propagate': False}, 'awx.analytics.performance': {'handlers': ['console', 'file', 'tower_warnings', 'external_logger'], 'level': 'DEBUG', 'propagate': False}, 'awx.analytics.job_lifecycle': {'handlers': ['console', 'job_lifecycle'], 'level': 'DEBUG', 'propagate': False}, 'django_auth_ldap': {'handlers': ['console', 'file', 'tower_warnings'], 'level': 'DEBUG'}, From 2e0f25150c09f6cf6c653b20b8df2917d772f337 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 9 Dec 2022 00:17:31 -0600 Subject: [PATCH 107/167] Start of heartbeet daemon Signed-off-by: Rick Elrod --- Makefile | 6 ++ awx/main/management/commands/run_heartbeet.py | 70 +++++++++++++++++++ awx/main/wsrelay.py | 24 ++++--- awx/settings/defaults.py | 3 + tools/docker-compose/supervisor.conf | 11 ++- 5 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 awx/main/management/commands/run_heartbeet.py diff --git a/Makefile b/Makefile index ee434fc0b7..97071b8f0b 100644 --- a/Makefile +++ b/Makefile @@ -229,6 +229,12 @@ wsrelay: fi; \ $(PYTHON) manage.py run_wsrelay +heartbeet: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_heartbeet + ## Run to start the background task dispatcher for development. dispatcher: @if [ "$(VENV_BASE)" ]; then \ diff --git a/awx/main/management/commands/run_heartbeet.py b/awx/main/management/commands/run_heartbeet.py new file mode 100644 index 0000000000..3d6d4aaa82 --- /dev/null +++ b/awx/main/management/commands/run_heartbeet.py @@ -0,0 +1,70 @@ +import json +import logging +import os +import time + +from django.core.management.base import BaseCommand +from django.conf import settings + +from awx.main.dispatch import pg_bus_conn + +logger = logging.getLogger('awx.main.commands.run_heartbeet') + + +class Command(BaseCommand): + help = 'Launch the web server beacon (heartbeet)' + + # def add_arguments(self, parser): + # parser.add_argument('--status', dest='status', action='store_true', help='print the internal state of any running broadcast websocket') + + def print_banner(self): + heartbeet = """ + ********** ********** + ************* ************* +***************************** + ***********HEART*********** + ************************* + ******************* + *************** _._ + *********** /`._ `'. __ + ******* \ .\| \ _'` `) + *** (``_) \| ).'` /`- / + * `\ `;\_ `\\//`-'` / + \ `'.'.| / __/` + `'--v_|/`'` + __||-._ + /'` `-`` `'\\ + / .'` ) + \ BEET ' ) + \. / + '. /'` + `) | + // + '(. + `\`. + ``""" + print(heartbeet) + + def construct_payload(self, action='online'): + payload = { + 'hostname': settings.CLUSTER_HOST_ID, + 'ip': os.environ.get('MY_POD_IP'), + 'action': action, + } + return json.dumps(payload) + + def do_hearbeat_loop(self): + with pg_bus_conn(new_connection=True) as conn: + while True: + logger.debug('Sending heartbeat') + conn.notify('web_heartbeet', self.construct_payload()) + time.sleep(settings.BROADCAST_WEBSOCKET_BEACON_FROM_WEB_RATE_SECONDS) + + # TODO: Send a message with action=offline if we notice a SIGTERM or SIGINT + # (wsrelay can use this to remove the node quicker) + def handle(self, *arg, **options): + self.print_banner() + + # Note: We don't really try any reconnect logic to pg_notify here, + # just let supervisor restart if we fail. + self.do_hearbeat_loop() diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 735386a48a..a1abc3ec3d 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -22,6 +22,7 @@ import awx.main.analytics.subsystem_metrics as s_metrics logger = logging.getLogger('awx.main.wsrelay') + def wrap_broadcast_msg(group, message: str): # TODO: Maybe wrap as "group","message" so that we don't need to # encode/decode as json. @@ -192,27 +193,35 @@ class WebSocketRelayManager(object): async def pg_consumer(self, conn): try: - await conn.execute("LISTEN wsrelay_rx_from_web") + await conn.execute("LISTEN web_heartbeet") async for notif in conn.notifies(): - if notif is not None and notif.channel == "wsrelay_rx_from_web": + if notif is not None and notif.channel == "web_heartbeet": try: payload = json.loads(notif.payload) except json.JSONDecodeError: - logmsg = "Failed to decode message from pg_notify channel `wsrelay_rx_from_web`" + logmsg = "Failed to decode message from pg_notify channel `web_heartbeet`" if logger.isEnabledFor(logging.DEBUG): logmsg = "{} {}".format(logmsg, payload) logger.warning(logmsg) continue + # Skip if the message comes from the same host we are running on + # In this case, we'll be sharing a redis, no need to relay. + if payload.get("hostname") == self.local_hostname: + continue + if payload.get("action") == "online": hostname = payload["hostname"] ip = payload["ip"] + if ip is None: + # If we don't get an IP, just try the hostname, maybe it resolves + ip = hostname self.known_hosts[hostname] = ip - logger.info(f"Web host {hostname} ({ip}) is online.") + logger.debug(f"Web host {hostname} ({ip}) online heartbeat received.") elif payload.get("action") == "offline": hostname = payload["hostname"] del self.known_hosts[hostname] - logger.info(f"Web host {host} ({ip}) is offline.") + logger.debug(f"Web host {hostname} ({ip}) offline heartbeat received.") except Exception as e: # This catch-all is the same as the one above. asyncio will NOT log exceptions anywhere, so we need to do so ourselves. logger.exception(f"pg_consumer exception") @@ -261,12 +270,9 @@ class WebSocketRelayManager(object): del self.relay_connections[h] stats_mgr.delete_remote_host_stats(h) - logger.error(f"New remote hosts: {new_remote_hosts}") for h in new_remote_hosts: - logger.error("we are here once") stats = stats_mgr.new_remote_host_stats(h) - logger.error("but now we are not?") - logger.info(f"Starting relay connection to {h}") + logger.debug(f"Starting relay connection to {h}") relay_connection = WebsocketRelayConnection(name=self.local_hostname, stats=stats, remote_host=self.known_hosts[h]) relay_connection.start() self.relay_connections[h] = relay_connection diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index a9d9a13925..085309de13 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -1011,6 +1011,9 @@ BROADCAST_WEBSOCKET_NEW_INSTANCE_POLL_RATE_SECONDS = 10 # How often websocket process will generate stats BROADCAST_WEBSOCKET_STATS_POLL_RATE_SECONDS = 5 +# How often should web instances advertise themselves? +BROADCAST_WEBSOCKET_BEACON_FROM_WEB_RATE_SECONDS = 15 + DJANGO_GUID = {'GUID_HEADER_NAME': 'X-API-Request-Id'} # Name of the default task queue diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 367a2cef53..a843edf342 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -28,6 +28,15 @@ killasgroup=true stdout_events_enabled = true stderr_events_enabled = true +[program:awx-heartbeet] +command = make heartbeet +autorestart = true +autorestart = true +stopasgroup=true +killasgroup=true +stdout_events_enabled = true +stderr_events_enabled = true + [program:awx-rsyslog-configurer] command = make rsyslog-configurer autorestart = true @@ -92,7 +101,7 @@ stdout_events_enabled = true stderr_events_enabled = true [group:tower-processes] -programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsrelay,awx-rsyslogd,awx-cache-clear +programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsrelay,awx-rsyslogd,awx-heartbeet priority=5 [program:awx-autoreload] From 5f41003fb111791d54170a2e20e6f3aef91d2251 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sat, 10 Dec 2022 02:40:48 -0600 Subject: [PATCH 108/167] Prevent looping issue when task/web share a Redis Signed-off-by: Rick Elrod --- awx/main/consumers.py | 2 +- awx/main/wsrelay.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/awx/main/consumers.py b/awx/main/consumers.py index d830c03a52..e2d47a96fb 100644 --- a/awx/main/consumers.py +++ b/awx/main/consumers.py @@ -240,6 +240,6 @@ def emit_channel_notification(group, payload): run_sync( channel_layer.group_send( group, - {"type": "internal.message", "text": payload_dumped}, + {"type": "internal.message", "text": payload_dumped, "needs_relay": True}, ) ) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index a1abc3ec3d..e935850514 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -164,6 +164,14 @@ class WebsocketRelayConnection: while True: try: msg = await asyncio.wait_for(self.channel_layer.receive(consumer_channel), timeout=10) + if not msg.get("needs_relay"): + # This is added in by emit_channel_notification(). It prevents us from looping + # in the event that we are sharing a redis with a web instance. We'll see the + # message once (it'll have needs_relay=True), we'll delete that, and then forward + # the message along. The web instance will add it back to the same channels group, + # but it won't have needs_relay=True, so we'll ignore it. + continue + del msg["needs_relay"] except asyncio.TimeoutError: current_subscriptions = self.producers[name]["subscriptions"] if len(current_subscriptions) == 0: From 513f433f17af2813304edc886a73a3f914f07e7b Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sat, 10 Dec 2022 03:47:11 -0600 Subject: [PATCH 109/167] Add comment for new psycopg dep Signed-off-by: Rick Elrod --- requirements/requirements.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.in b/requirements/requirements.in index e7d7722f28..72bdfd6db0 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -36,7 +36,7 @@ openshift pexpect==4.7.0 # see library notes prometheus_client psycopg2 -psycopg +psycopg # psycopg3 is used to listen for pg_notify messages from web servers in awx.main.wsrelay where asyncio is used psutil pygerduty pyparsing==2.4.6 # Upgrading to v3 of pyparsing introduce errors on smart host filtering: Expected 'or' term, found 'or' (at char 15), (line:1, col:16) From 704759d29a5e86e61815e1e3f2beec99eff2b27a Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sun, 11 Dec 2022 01:29:24 -0600 Subject: [PATCH 110/167] add wsrelay to tower-processes Signed-off-by: Rick Elrod --- .../ansible/roles/dockerfile/templates/supervisor_task.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 index 9abd6b49b4..8c3a46342e 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 @@ -57,7 +57,7 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [group:tower-processes] -programs=dispatcher,callback-receiver +programs=dispatcher,callback-receiver,wsrelay priority=5 [eventlistener:superwatcher] From 91bf49cdb3db48046435b43de765eb1e14f7a58d Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sun, 11 Dec 2022 01:34:12 -0600 Subject: [PATCH 111/167] Remove auto-reconnect logic from wsrelay We no longer need to do this from wsrelay, as it will automatically try to reconnect when it hears the next beacon from heartbeet. This also cleans up the logic for what we do when we want to delete a node we previously knew about. Signed-off-by: Rick Elrod --- awx/main/wsrelay.py | 55 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index e935850514..29d6218a93 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -54,11 +54,12 @@ class WebsocketRelayConnection: self.channel_layer = None self.subsystem_metrics = s_metrics.Metrics(instance_name=name) self.producers = dict() + self.connected = False async def run_loop(self, websocket: aiohttp.ClientWebSocketResponse): raise RuntimeError("Implement me") - async def connect(self, attempt): + async def connect(self): from awx.main.consumers import WebsocketSecretAuthHelper # noqa logger.debug(f"Connection from {self.name} to {self.remote_host} attempt number {attempt}.") @@ -70,13 +71,6 @@ class WebsocketRelayConnection: if not self.channel_layer: self.channel_layer = get_channel_layer() - try: - if attempt > 0: - await asyncio.sleep(settings.BROADCAST_WEBSOCKET_RECONNECT_RETRY_RATE_SECONDS) - except asyncio.CancelledError: - logger.warning(f"Connection from {self.name} to {self.remote_host} cancelled") - raise - uri = f"{self.protocol}://{self.remote_host}:{self.remote_port}/websocket/relay/" timeout = aiohttp.ClientTimeout(total=10) @@ -86,14 +80,12 @@ class WebsocketRelayConnection: async with session.ws_connect(uri, ssl=self.verify_ssl, heartbeat=20) as websocket: logger.info(f"Connection from {self.name} to {self.remote_host} established.") self.stats.record_connection_established() - attempt = 0 + self.connected = True await self.run_connection(websocket) except asyncio.CancelledError: # TODO: Check if connected and disconnect # Possibly use run_until_complete() if disconnect is async logger.warning(f"Connection from {self.name} to {self.remote_host} cancelled.") - self.stats.record_connection_lost() - raise except client_exceptions.ClientConnectorError as e: logger.warning(f"Connection from {self.name} to {self.remote_host} failed: '{e}'.", exc_info=True) except asyncio.TimeoutError: @@ -102,14 +94,13 @@ class WebsocketRelayConnection: # Early on, this is our canary. I'm not sure what exceptions we can really encounter. logger.warning(f"Connection from {self.name} to {self.remote_host} failed for unknown reason: '{e}'.", exc_info=True) else: - logger.warning(f"Connection from {self.name} to {self.remote_host} list.") - - self.stats.record_connection_lost() - self.start(attempt=attempt + 1) - - def start(self, attempt=0): - self.async_task = self.event_loop.create_task(self.connect(attempt=attempt)) + logger.info(f"Connection from {self.name} to {self.remote_host} lost, but no exception was raised.") + finally: + self.connected = False + self.stats.record_connection_lost() + def start(self): + self.async_task = self.event_loop.create_task(self.connect()) return self.async_task def cancel(self): @@ -137,7 +128,6 @@ class WebsocketRelayConnection: origin_channel = payload['origin_channel'] if not self.producers.get(name): producer = self.event_loop.create_task(self.run_producer(name, websocket, group)) - self.producers[name] = {"task": producer, "subscriptions": {origin_channel}} logger.debug(f"Producer {name} started.") else: @@ -181,6 +171,12 @@ class WebsocketRelayConnection: continue await websocket.send_json(wrap_broadcast_msg(group, msg)) + except ConnectionResetError: + # This can be hit when a web node is scaling down and we try to write to it. + # There's really nothing to do in this case and it's a fairly typical thing to happen. + # We'll log it as debug, but it's not really a problem. + logger.debug(f"Producer {name} connection reset.") + pass except Exception: # Note, this is very intentional and important since we do not otherwise # ever check the result of this future. Without this line you will not see an error if @@ -231,7 +227,8 @@ class WebSocketRelayManager(object): del self.known_hosts[hostname] logger.debug(f"Web host {hostname} ({ip}) offline heartbeat received.") except Exception as e: - # This catch-all is the same as the one above. asyncio will NOT log exceptions anywhere, so we need to do so ourselves. + # This catch-all is the same as the one above. asyncio will eat the exception + # but we want to know about it. logger.exception(f"pg_consumer exception") async def run(self): @@ -261,12 +258,22 @@ class WebSocketRelayManager(object): deleted_remote_hosts = set(current_remote_hosts) - set(future_remote_hosts) new_remote_hosts = set(future_remote_hosts) - set(current_remote_hosts) - remote_addresses = {k: v.remote_host for k, v in self.relay_connections.items()} + # This loop handles if we get an advertisement from a host we already know about but + # the advertisement has a different IP than we are currently connected to. for hostname, address in self.known_hosts.items(): - if hostname in self.relay_connections and address != remote_addresses[hostname]: + if hostname not in self.relay_connections: + # We've picked up a new hostname that we don't know about yet. + continue + + if address != self.relay_connections[hostname].remote_host: deleted_remote_hosts.add(hostname) new_remote_hosts.add(hostname) + # Delete any hosts with closed connections + for hostname, relay_conn in self.relay_connections.items(): + if not relay_conn.connected: + deleted_remote_hosts.add(hostname) + if deleted_remote_hosts: logger.info(f"Removing {deleted_remote_hosts} from websocket broadcast list") @@ -276,6 +283,7 @@ class WebSocketRelayManager(object): for h in deleted_remote_hosts: self.relay_connections[h].cancel() del self.relay_connections[h] + del self.known_hosts[h] stats_mgr.delete_remote_host_stats(h) for h in new_remote_hosts: @@ -285,7 +293,4 @@ class WebSocketRelayManager(object): relay_connection.start() self.relay_connections[h] = relay_connection - # for host, conn in self.relay_connections.items(): - # logger.info(f"Current producers for {host}: {conn.producers}") - await asyncio.sleep(settings.BROADCAST_WEBSOCKET_NEW_INSTANCE_POLL_RATE_SECONDS) From 93c2c5661210fb91434cd1e27f4bb6a28168f693 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sun, 11 Dec 2022 01:36:34 -0600 Subject: [PATCH 112/167] [wsrelay] Copy the message payload before we relay We internally manipulate the message payload a bit (to know whether we are originating it on the task side or the web system is originating it). But when we get the message, we actually get a reference to the dict containing the payload. Other producers in wsrelay might still be acting on the message and deciding whether or not to relay it. So we need to manipulate and send a *copy* of the message, and leave the original alone. Signed-off-by: Rick Elrod --- awx/main/wsrelay.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 29d6218a93..38f5f6ddbf 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -161,6 +161,11 @@ class WebsocketRelayConnection: # the message along. The web instance will add it back to the same channels group, # but it won't have needs_relay=True, so we'll ignore it. continue + + # We need to copy the message because we're going to delete the needs_relay key + # and we don't want to modify the original message because other producers may + # still need to act on it. It seems weird, but it's necessary. + msg = dict(msg) del msg["needs_relay"] except asyncio.TimeoutError: current_subscriptions = self.producers[name]["subscriptions"] From 44463402a84ff1a21072b2c71c619d402999e954 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Sun, 11 Dec 2022 01:38:44 -0600 Subject: [PATCH 113/167] [wsrelay] attempt to standardize logging levels This needs some work, but it's a start. Signed-off-by: Rick Elrod --- awx/main/wsrelay.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 38f5f6ddbf..43840e1691 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -62,7 +62,7 @@ class WebsocketRelayConnection: async def connect(self): from awx.main.consumers import WebsocketSecretAuthHelper # noqa - logger.debug(f"Connection from {self.name} to {self.remote_host} attempt number {attempt}.") + logger.debug(f"Connection attempt from {self.name} to {self.remote_host}") ''' Can not put get_channel_layer() in the init code because it is in the init @@ -116,7 +116,7 @@ class WebsocketRelayConnection: try: payload = json.loads(msg.data) except json.JSONDecodeError: - logmsg = "Failed to decode broadcast message" + logmsg = "Failed to decode message from web node" if logger.isEnabledFor(logging.DEBUG): logmsg = "{} {}".format(logmsg, payload) logger.warning(logmsg) @@ -150,6 +150,7 @@ class WebsocketRelayConnection: consumer_channel = await self.channel_layer.new_channel() await self.channel_layer.group_add(group, consumer_channel) + logger.debug(f"Producer {name} added to group {group} and is now awaiting messages.") while True: try: @@ -257,7 +258,7 @@ class WebSocketRelayManager(object): # Establishes a websocket connection to /websocket/relay on all API servers while True: - logger.info("Current known hosts: {}".format(self.known_hosts)) + # logger.info("Current known hosts: {}".format(self.known_hosts)) future_remote_hosts = self.known_hosts.keys() current_remote_hosts = self.relay_connections.keys() deleted_remote_hosts = set(current_remote_hosts) - set(future_remote_hosts) @@ -293,7 +294,6 @@ class WebSocketRelayManager(object): for h in new_remote_hosts: stats = stats_mgr.new_remote_host_stats(h) - logger.debug(f"Starting relay connection to {h}") relay_connection = WebsocketRelayConnection(name=self.local_hostname, stats=stats, remote_host=self.known_hosts[h]) relay_connection.start() self.relay_connections[h] = relay_connection From 33f070081cb3963beb80df6b07e3c9b2fa3213ad Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Wed, 14 Dec 2022 12:33:54 -0500 Subject: [PATCH 114/167] Send subsystem metrics via wsrelay (#13333) Works by adding a dedicated producer in wsrelay that looks for local django channels message with group "metrics". The producer sends this to the consumer running in the web container. The consumer running in the web container handles the message by pushing it into the local redis instance. The django view that handles a request at the /api/v2/metrics endpoint will load this data from redis, format it, and return the response. --- awx/main/analytics/subsystem_metrics.py | 18 ++---------------- awx/main/consumers.py | 8 +++++++- awx/main/wsrelay.py | 6 ++++++ awx/settings/defaults.py | 3 +++ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/awx/main/analytics/subsystem_metrics.py b/awx/main/analytics/subsystem_metrics.py index 439f084c5b..d8836b332f 100644 --- a/awx/main/analytics/subsystem_metrics.py +++ b/awx/main/analytics/subsystem_metrics.py @@ -9,7 +9,7 @@ from django.apps import apps from awx.main.consumers import emit_channel_notification from awx.main.utils import is_testing -root_key = 'awx_metrics' +root_key = settings.SUBSYSTEM_METRICS_REDIS_KEY_PREFIX logger = logging.getLogger('awx.main.analytics') @@ -264,13 +264,6 @@ class Metrics: data[field] = self.METRICS[field].decode(self.conn) return data - def store_metrics(self, data_json): - # called when receiving metrics from other instances - data = json.loads(data_json) - if self.instance_name != data['instance']: - logger.debug(f"{self.instance_name} received subsystem metrics from {data['instance']}") - self.conn.set(root_key + "_instance_" + data['instance'], data['metrics']) - def should_pipe_execute(self): if self.metrics_have_changed is False: return False @@ -309,15 +302,8 @@ class Metrics: 'instance': self.instance_name, 'metrics': self.serialize_local_metrics(), } - # store a local copy as well - self.store_metrics(json.dumps(payload)) - # 🚨🚨🚨🚨🚨🚨🚨🚨 - # TODO: rework how metrics are emitted and recorded. we used to exploit wsbroadcast's behavior of - # sending the same data out to every other node. - # Should we increment this data in redis but ultimately just store it in the database? - # emit_channel_notification("metrics", payload) - # 🚨🚨🚨🚨🚨🚨🚨🚨 + emit_channel_notification("metrics", payload) self.previous_send_metrics.set(current_time) self.previous_send_metrics.store_value(self.conn) diff --git a/awx/main/consumers.py b/awx/main/consumers.py index e2d47a96fb..f856ca915e 100644 --- a/awx/main/consumers.py +++ b/awx/main/consumers.py @@ -3,6 +3,7 @@ import logging import time import hmac import asyncio +import redis from django.core.serializers.json import DjangoJSONEncoder from django.conf import settings @@ -102,7 +103,12 @@ class RelayConsumer(AsyncJsonWebsocketConsumer): async def receive_json(self, data): (group, message) = unwrap_broadcast_msg(data) - await self.channel_layer.group_send(group, message) + if group == "metrics": + message = json.loads(message['text']) + conn = redis.Redis.from_url(settings.BROKER_URL) + conn.set(settings.SUBSYSTEM_METRICS_REDIS_KEY_PREFIX + "_instance_" + message['instance'], message['metrics']) + else: + await self.channel_layer.group_send(group, message) async def consumer_subscribe(self, event): await self.send_json(event) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 43840e1691..be0ea04162 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -107,6 +107,12 @@ class WebsocketRelayConnection: self.async_task.cancel() async def run_connection(self, websocket: aiohttp.ClientWebSocketResponse): + # create a dedicated subsystem metric producer to handle local subsystem + # metrics messages + # the "metrics" group is not subscribed to in the typical fashion, so we + # just explicitly create it + producer = self.event_loop.create_task(self.run_producer("metrics", websocket, "metrics")) + self.producers["metrics"] = {"task": producer, "subscriptions": {"metrics"}} async for msg in websocket: self.stats.record_message_received() diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 085309de13..61fb2df764 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -228,6 +228,9 @@ JOB_EVENT_MAX_QUEUE_SIZE = 10000 # The number of job events to migrate per-transaction when moving from int -> bigint JOB_EVENT_MIGRATION_CHUNK_SIZE = 1000000 +# The prefix of the redis key that stores metrics +SUBSYSTEM_METRICS_REDIS_KEY_PREFIX = "awx_metrics" + # Histogram buckets for the callback_receiver_batch_events_insert_db metric SUBSYSTEM_METRICS_BATCH_INSERT_BUCKETS = [10, 50, 150, 350, 650, 2000] From e7fa730f81cec163340cfbd86ecba099f257ef35 Mon Sep 17 00:00:00 2001 From: Lila Yasin Date: Tue, 24 Jan 2023 19:16:17 -0500 Subject: [PATCH 115/167] Removed some commented out code and adjusted a few loggers to make more sense contextually. (#13424) --- awx/main/management/commands/run_heartbeet.py | 3 --- awx/main/management/commands/run_wsrelay.py | 4 ++-- awx/main/wsrelay.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/awx/main/management/commands/run_heartbeet.py b/awx/main/management/commands/run_heartbeet.py index 3d6d4aaa82..199412dfab 100644 --- a/awx/main/management/commands/run_heartbeet.py +++ b/awx/main/management/commands/run_heartbeet.py @@ -14,9 +14,6 @@ logger = logging.getLogger('awx.main.commands.run_heartbeet') class Command(BaseCommand): help = 'Launch the web server beacon (heartbeet)' - # def add_arguments(self, parser): - # parser.add_argument('--status', dest='status', action='store_true', help='print the internal state of any running broadcast websocket') - def print_banner(self): heartbeet = """ ********** ********** diff --git a/awx/main/management/commands/run_wsrelay.py b/awx/main/management/commands/run_wsrelay.py index ce778b8356..8bdf6ea0a3 100644 --- a/awx/main/management/commands/run_wsrelay.py +++ b/awx/main/management/commands/run_wsrelay.py @@ -99,7 +99,7 @@ class Command(BaseCommand): executor = MigrationExecutor(connection) migrating = bool(executor.migration_plan(executor.loader.graph.leaf_nodes())) except Exception as exc: - logger.info(f'Error on startup of run_wsrelay (error: {exc}), retry in 10s...') + logger.warning(f'Error on startup of run_wsrelay (error: {exc}), retry in 10s...') time.sleep(10) return @@ -166,4 +166,4 @@ class Command(BaseCommand): websocket_relay_manager = WebSocketRelayManager() asyncio.run(websocket_relay_manager.run()) except KeyboardInterrupt: - logger.debug('Terminating Websocket Relayer') + logger.info('Terminating Websocket Relayer') diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index be0ea04162..77b2c8a393 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -94,7 +94,7 @@ class WebsocketRelayConnection: # Early on, this is our canary. I'm not sure what exceptions we can really encounter. logger.warning(f"Connection from {self.name} to {self.remote_host} failed for unknown reason: '{e}'.", exc_info=True) else: - logger.info(f"Connection from {self.name} to {self.remote_host} lost, but no exception was raised.") + logger.debug(f"Connection from {self.name} to {self.remote_host} lost, but no exception was raised.") finally: self.connected = False self.stats.record_connection_lost() From 29d222be83b99a951b24b87bd366c610a2b22f19 Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Wed, 1 Feb 2023 15:47:27 -0500 Subject: [PATCH 116/167] removed rsyslog queue, updated logger level Signed-off-by: Jessica Mack --- awx/main/management/commands/run_cache_clear.py | 2 +- awx/main/management/commands/run_dispatcher.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/main/management/commands/run_cache_clear.py b/awx/main/management/commands/run_cache_clear.py index d058b8bd6e..dcb5c08aa9 100644 --- a/awx/main/management/commands/run_cache_clear.py +++ b/awx/main/management/commands/run_cache_clear.py @@ -23,7 +23,7 @@ class Command(BaseCommand): for e in conn.events(yield_timeouts=True): if e is not None: body = json.loads(e.payload) - logger.warning(f"Cache clear request received. Clearing now, payload: {e.payload}") + logger.info(f"Cache clear request received. Clearing now, payload: {e.payload}") TaskWorker.run_callable(body) else: logger.info('run_clear_cache got timeout') diff --git a/awx/main/management/commands/run_dispatcher.py b/awx/main/management/commands/run_dispatcher.py index 72fbfbedba..f7079c6a3c 100644 --- a/awx/main/management/commands/run_dispatcher.py +++ b/awx/main/management/commands/run_dispatcher.py @@ -76,7 +76,7 @@ class Command(BaseCommand): consumer = None try: - queues = ['tower_broadcast_all', 'tower_settings_change', 'rsyslog_configurer', get_local_queuename()] + queues = ['tower_broadcast_all', 'tower_settings_change', get_local_queuename()] consumer = AWXConsumerPG('dispatcher', TaskWorker(), queues, AutoscalePool(min_workers=4)) consumer.run() except KeyboardInterrupt: From 78652bdd7116a8ae82a44b6728cfc85fc213740d Mon Sep 17 00:00:00 2001 From: Jessica Mack Date: Wed, 1 Feb 2023 16:10:41 -0500 Subject: [PATCH 117/167] add functionality back to cache clear method Signed-off-by: Jessica Mack --- awx/main/tasks/system.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index 30f5ae785f..1a3d1fa591 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -65,6 +65,7 @@ from awx.main.utils.external_logging import send_pg_notify from awx.main.tasks.receptor import get_receptor_ctl, worker_info, worker_cleanup, administrative_workunit_reaper, write_receptor_config from awx.main.consumers import emit_channel_notification from awx.main import analytics +from awx.conf import settings_registry from awx.main.analytics.subsystem_metrics import Metrics from rest_framework.exceptions import PermissionDenied @@ -244,6 +245,13 @@ def apply_cluster_membership_policies(): def clear_setting_cache(setting_keys): # log that cache is being cleared logger.info(f"clear_setting_cache of keys {setting_keys}") + orig_len = len(setting_keys) + for i in range(orig_len): + for dependent_key in settings_registry.get_dependent_settings(setting_keys[i]): + setting_keys.append(dependent_key) + cache_keys = set(setting_keys) + logger.debug('cache delete_many(%r)', cache_keys) + cache.delete_many(cache_keys) @task(queue='tower_broadcast_all') From 7cb890b603ef36aeb8d03377fc00b73f0005245b Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 6 Feb 2023 15:49:57 -0500 Subject: [PATCH 118/167] minor fix-up due to merge conflict --- awx/main/routing.py | 4 ++-- awx_collection/plugins/modules/project_update.py | 3 +-- tools/ansible/roles/dockerfile/templates/Dockerfile.j2 | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/awx/main/routing.py b/awx/main/routing.py index e45bf0a537..9625b23176 100644 --- a/awx/main/routing.py +++ b/awx/main/routing.py @@ -27,8 +27,8 @@ class AWXProtocolTypeRouter(ProtocolTypeRouter): websocket_urlpatterns = [ - re_path(r'websocket/$', consumers.EventConsumer), - re_path(r'websocket/relay/$', consumers.RelayConsumer), + re_path(r'websocket/$', consumers.EventConsumer.as_asgi()), + re_path(r'websocket/relay/$', consumers.RelayConsumer.as_asgi()), ] application = AWXProtocolTypeRouter( diff --git a/awx_collection/plugins/modules/project_update.py b/awx_collection/plugins/modules/project_update.py index 6cbcd39b6d..9d5a8841a7 100644 --- a/awx_collection/plugins/modules/project_update.py +++ b/awx_collection/plugins/modules/project_update.py @@ -116,8 +116,7 @@ def main(): if result['status_code'] == 405: module.fail_json( - msg="Unable to trigger a project update because the project scm_type ({0}) does not support it.".format(project['scm_type']), - response=result + msg="Unable to trigger a project update because the project scm_type ({0}) does not support it.".format(project['scm_type']), response=result ) elif result['status_code'] != 202: module.fail_json(msg="Failed to update project, see response for details", response=result) diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index c6fd7bf044..a74129905b 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -212,7 +212,6 @@ ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/ ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh -ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_cache_clear.sh ADD {{ template_dest }}/supervisor.conf /etc/supervisord.conf ADD {{ template_dest }}/supervisor_task.conf /etc/supervisord_task.conf ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisor_rsyslog.conf From 52a8a90c0ef99c910faab392a2c9b4c1bdb2777c Mon Sep 17 00:00:00 2001 From: jessicamack Date: Thu, 9 Feb 2023 14:30:44 -0500 Subject: [PATCH 119/167] remove changes used for dev testing Signed-off-by: jessicamack --- awx/main/management/commands/run_cache_clear.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/awx/main/management/commands/run_cache_clear.py b/awx/main/management/commands/run_cache_clear.py index dcb5c08aa9..61e4b03c49 100644 --- a/awx/main/management/commands/run_cache_clear.py +++ b/awx/main/management/commands/run_cache_clear.py @@ -25,8 +25,6 @@ class Command(BaseCommand): body = json.loads(e.payload) logger.info(f"Cache clear request received. Clearing now, payload: {e.payload}") TaskWorker.run_callable(body) - else: - logger.info('run_clear_cache got timeout') except Exception: # Log unanticipated exception in addition to writing to stderr to get timestamps and other metadata From b29f2f88d0f07310c67ec1afce3e47248d11ac63 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Thu, 9 Feb 2023 14:32:16 -0500 Subject: [PATCH 120/167] updated tests to be in line with clear_setting_cache changes Signed-off-by: jessicamack --- awx/main/tests/functional/api/test_settings.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py index eb57f27e14..bcfa499af3 100644 --- a/awx/main/tests/functional/api/test_settings.py +++ b/awx/main/tests/functional/api/test_settings.py @@ -294,7 +294,6 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u mock_settings['LOG_AGGREGATOR_PASSWORD'] = password # mock testing pg_notify mocker.patch("awx.conf.views.send_pg_notify", return_value=None) - mocker.patch("awx.main.tasks.system.send_pg_notify", return_value=None) url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) response = put(url, data=mock_settings, user=admin, expect=200) assert type in response.data.get('LOG_AGGREGATOR_TYPE') @@ -317,7 +316,6 @@ def test_logging_aggregator_connection_test_valid(put, post, admin, mocker): mock_settings['LOG_AGGREGATOR_HOST'] = host # mock testing pg_notify mocker.patch("awx.conf.views.send_pg_notify", return_value=None) - mocker.patch("awx.main.tasks.system.send_pg_notify", return_value=None) # POST to save these mock settings url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) put(url, data=mock_settings, user=admin, expect=200) From da004da68a11a910ade1da880a614f3019474862 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Thu, 9 Feb 2023 16:18:43 -0500 Subject: [PATCH 121/167] make reconfigure_rsyslog a task Signed-off-by: jessicamack --- awx/conf/views.py | 6 +++--- awx/main/management/commands/run_rsyslog_configurer.py | 5 ++++- awx/main/utils/external_logging.py | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/awx/conf/views.py b/awx/conf/views.py index e4a8375122..f12075148b 100644 --- a/awx/conf/views.py +++ b/awx/conf/views.py @@ -30,7 +30,7 @@ from awx.main.tasks.system import clear_setting_cache from awx.conf.models import Setting from awx.conf.serializers import SettingCategorySerializer, SettingSingletonSerializer from awx.conf import settings_registry -from awx.main.utils.external_logging import send_pg_notify +from awx.main.utils.external_logging import reconfigure_rsyslog SettingCategory = collections.namedtuple('SettingCategory', ('url', 'slug', 'name')) @@ -122,7 +122,7 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): connection.on_commit(lambda: clear_setting_cache.delay(settings_change_list)) if any([setting.startswith('LOG_AGGREGATOR') for setting in settings_change_list]): # call notify to rsyslog. no data is need so payload is empty - send_pg_notify('rsyslog_configurer', "") + reconfigure_rsyslog.delay() def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -140,7 +140,7 @@ class SettingSingletonDetail(RetrieveUpdateDestroyAPIView): connection.on_commit(lambda: clear_setting_cache.delay(settings_change_list)) if any([setting.startswith('LOG_AGGREGATOR') for setting in settings_change_list]): # call notify to rsyslog. no data is need so payload is empty - send_pg_notify('rsyslog_configurer', "") + reconfigure_rsyslog.delay() # When TOWER_URL_BASE is deleted from the API, reset it to the hostname # used to make the request as a default. diff --git a/awx/main/management/commands/run_rsyslog_configurer.py b/awx/main/management/commands/run_rsyslog_configurer.py index 5cc214ced9..61e7aa14a6 100644 --- a/awx/main/management/commands/run_rsyslog_configurer.py +++ b/awx/main/management/commands/run_rsyslog_configurer.py @@ -1,9 +1,11 @@ import logging +import json from django.core.management.base import BaseCommand from django.conf import settings from django.core.cache import cache from awx.main.dispatch import pg_bus_conn +from awx.main.dispatch.worker.task import TaskWorker from awx.main.utils.external_logging import reconfigure_rsyslog logger = logging.getLogger('awx.main.rsyslog_configurer') @@ -31,7 +33,8 @@ class Command(BaseCommand): setting_keys = [k for k in dir(settings) if k.startswith('LOG_AGGREGATOR')] cache.delete_many(setting_keys) settings._awx_conf_memoizedcache.clear() - reconfigure_rsyslog() + body = json.loads(e.payload) + TaskWorker.run_callable(body) except Exception: # Log unanticipated exception in addition to writing to stderr to get timestamps and other metadata logger.exception('Encountered unhandled error in rsyslog_configurer main loop') diff --git a/awx/main/utils/external_logging.py b/awx/main/utils/external_logging.py index e3e0a3d1c8..635887ec14 100644 --- a/awx/main/utils/external_logging.py +++ b/awx/main/utils/external_logging.py @@ -6,6 +6,7 @@ import urllib.parse as urlparse from django.conf import settings from awx.main.utils.reload import supervisor_service_command +from awx.main.dispatch.publish import task from awx.main.dispatch import pg_bus_conn @@ -115,6 +116,7 @@ def construct_rsyslog_conf_template(settings=settings): return tmpl +@task(queue='rsyslog_configurer') def reconfigure_rsyslog(): tmpl = construct_rsyslog_conf_template() # Write config to a temp file then move it to preserve atomicity From 7cef4e6db7bac6b7442c791dbfa5fb5610a5b64c Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 6 Mar 2023 14:26:31 -0500 Subject: [PATCH 122/167] clear settings cache after changing DISABLE_LOCAL_AUTH --- awx/main/management/commands/enable_local_authentication.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/awx/main/management/commands/enable_local_authentication.py b/awx/main/management/commands/enable_local_authentication.py index a9db33709c..1811ccd898 100644 --- a/awx/main/management/commands/enable_local_authentication.py +++ b/awx/main/management/commands/enable_local_authentication.py @@ -1,5 +1,6 @@ -from django.core.management.base import BaseCommand, CommandError +from awx.main.tasks.system import clear_setting_cache from django.conf import settings +from django.core.management.base import BaseCommand, CommandError class Command(BaseCommand): @@ -31,5 +32,7 @@ class Command(BaseCommand): else: raise CommandError('Please pass --enable flag to allow local auth or --disable flag to disable local auth') + clear_setting_cache.delay(['DISABLE_LOCAL_AUTH']) + def handle(self, **options): self._enable_disable_auth(options.get('enable'), options.get('disable')) From 049fb4eff554e9e9fbb12f0622bdec62a29cdf48 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Tue, 7 Mar 2023 19:03:40 -0500 Subject: [PATCH 123/167] fix job relaunch error AttributeError: 'Settings' object has no attribute 'INSTALL_UUID' --- awx/conf/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/conf/settings.py b/awx/conf/settings.py index 27b7847ae9..cedea3a3e7 100644 --- a/awx/conf/settings.py +++ b/awx/conf/settings.py @@ -187,7 +187,7 @@ def get_settings_to_cache(registry): def _get_setting_from_db(registry, key): def wrapped(registry, key): field = registry.get_setting_field(key) - if not field.read_only: + if not field.read_only or key == 'INSTALL_UUID': return Setting.objects.filter(key=key, user__isnull=True).order_by('pk').first() with ThreadPoolExecutor(max_workers=1) as executor: From cd3f7666be13090136457b8a21ac07642ed153a4 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 22 Mar 2023 15:31:08 -0400 Subject: [PATCH 124/167] add get_task_queuename get_local_queuename will return the pod name of the instance now that web and task are in different pods when web container queue a task it will be put into a queue without as task worker to execute the task --- awx/main/analytics/analytics_tasks.py | 4 +-- awx/main/dispatch/__init__.py | 10 ++++++ awx/main/dispatch/control.py | 4 +-- .../management/commands/run_dispatcher.py | 4 +-- awx/main/models/unified_jobs.py | 4 +-- awx/main/scheduler/tasks.py | 8 ++--- awx/main/tasks/jobs.py | 12 +++---- awx/main/tasks/receptor.py | 4 +-- awx/main/tasks/system.py | 36 +++++++++---------- awx/main/wsrelay.py | 1 - 10 files changed, 48 insertions(+), 39 deletions(-) diff --git a/awx/main/analytics/analytics_tasks.py b/awx/main/analytics/analytics_tasks.py index 990cacfafb..3072577466 100644 --- a/awx/main/analytics/analytics_tasks.py +++ b/awx/main/analytics/analytics_tasks.py @@ -4,11 +4,11 @@ import logging # AWX from awx.main.analytics.subsystem_metrics import Metrics from awx.main.dispatch.publish import task -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename logger = logging.getLogger('awx.main.scheduler') -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def send_subsystem_metrics(): Metrics().send_metrics() diff --git a/awx/main/dispatch/__init__.py b/awx/main/dispatch/__init__.py index bbfd38b404..642405c2dd 100644 --- a/awx/main/dispatch/__init__.py +++ b/awx/main/dispatch/__init__.py @@ -5,6 +5,7 @@ from contextlib import contextmanager from django.conf import settings from django.db import connection as pg_connection +import os NOT_READY = ([], [], []) @@ -14,6 +15,15 @@ def get_local_queuename(): return settings.CLUSTER_HOST_ID +def get_task_queuename(): + if os.getenv('AWX_COMPONENT') == 'web': + from awx.main.models.ha import Instance + + return Instance.objects.filter(node_type__in=['control', 'hybrid']).order_by('?').first().hostname + else: + return settings.CLUSTER_HOST_ID + + class PubSub(object): def __init__(self, conn): self.conn = conn diff --git a/awx/main/dispatch/control.py b/awx/main/dispatch/control.py index d62444149b..e2b8c8f200 100644 --- a/awx/main/dispatch/control.py +++ b/awx/main/dispatch/control.py @@ -6,7 +6,7 @@ from django.conf import settings from django.db import connection import redis -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename from . import pg_bus_conn @@ -21,7 +21,7 @@ class Control(object): if service not in self.services: raise RuntimeError('{} must be in {}'.format(service, self.services)) self.service = service - self.queuename = host or get_local_queuename() + self.queuename = host or get_task_queuename() def status(self, *args, **kwargs): r = redis.Redis.from_url(settings.BROKER_URL) diff --git a/awx/main/management/commands/run_dispatcher.py b/awx/main/management/commands/run_dispatcher.py index f7079c6a3c..07cc4d87b9 100644 --- a/awx/main/management/commands/run_dispatcher.py +++ b/awx/main/management/commands/run_dispatcher.py @@ -8,7 +8,7 @@ from django.core.cache import cache as django_cache from django.core.management.base import BaseCommand from django.db import connection as django_connection -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename from awx.main.dispatch.control import Control from awx.main.dispatch.pool import AutoscalePool from awx.main.dispatch.worker import AWXConsumerPG, TaskWorker @@ -76,7 +76,7 @@ class Command(BaseCommand): consumer = None try: - queues = ['tower_broadcast_all', 'tower_settings_change', get_local_queuename()] + queues = ['tower_broadcast_all', 'tower_settings_change', 'rsyslog_configurer', get_task_queuename()] consumer = AWXConsumerPG('dispatcher', TaskWorker(), queues, AutoscalePool(min_workers=4)) consumer.run() except KeyboardInterrupt: diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 3f938f44ef..d5885a2b0b 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -32,7 +32,7 @@ from polymorphic.models import PolymorphicModel # AWX from awx.main.models.base import CommonModelNameNotUnique, PasswordFieldsModel, NotificationFieldsModel, prevent_search -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename from awx.main.dispatch.control import Control as ControlDispatcher from awx.main.registrar import activity_stream_registrar from awx.main.models.mixins import ResourceMixin, TaskManagerUnifiedJobMixin, ExecutionEnvironmentMixin @@ -1567,7 +1567,7 @@ class UnifiedJob( return r def get_queue_name(self): - return self.controller_node or self.execution_node or get_local_queuename() + return self.controller_node or self.execution_node or get_task_queuename() @property def is_container_group_task(self): diff --git a/awx/main/scheduler/tasks.py b/awx/main/scheduler/tasks.py index b762e1c429..9cdbea3a9d 100644 --- a/awx/main/scheduler/tasks.py +++ b/awx/main/scheduler/tasks.py @@ -8,7 +8,7 @@ from django.conf import settings from awx import MODE from awx.main.scheduler import TaskManager, DependencyManager, WorkflowManager from awx.main.dispatch.publish import task -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename logger = logging.getLogger('awx.main.scheduler') @@ -20,16 +20,16 @@ def run_manager(manager, prefix): manager().schedule() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def task_manager(): run_manager(TaskManager, "task") -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def dependency_manager(): run_manager(DependencyManager, "dependency") -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def workflow_manager(): run_manager(WorkflowManager, "workflow") diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index 74286faa20..c52e8c7fff 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -29,7 +29,7 @@ from gitdb.exc import BadName as BadGitName # AWX from awx.main.dispatch.publish import task -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename from awx.main.constants import ( PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV, @@ -806,7 +806,7 @@ class SourceControlMixin(BaseTask): self.release_lock(project) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) class RunJob(SourceControlMixin, BaseTask): """ Run a job using ansible-playbook. @@ -1121,7 +1121,7 @@ class RunJob(SourceControlMixin, BaseTask): update_inventory_computed_fields.delay(inventory.id) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) class RunProjectUpdate(BaseTask): model = ProjectUpdate event_model = ProjectUpdateEvent @@ -1443,7 +1443,7 @@ class RunProjectUpdate(BaseTask): return params -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) class RunInventoryUpdate(SourceControlMixin, BaseTask): model = InventoryUpdate event_model = InventoryUpdateEvent @@ -1706,7 +1706,7 @@ class RunInventoryUpdate(SourceControlMixin, BaseTask): raise PostRunError('Error occured while saving inventory data, see traceback or server logs', status='error', tb=traceback.format_exc()) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) class RunAdHocCommand(BaseTask): """ Run an ad hoc command using ansible. @@ -1859,7 +1859,7 @@ class RunAdHocCommand(BaseTask): return d -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) class RunSystemJob(BaseTask): model = SystemJob event_model = SystemJobEvent diff --git a/awx/main/tasks/receptor.py b/awx/main/tasks/receptor.py index b1d9e0cfa8..1fb8b98aa5 100644 --- a/awx/main/tasks/receptor.py +++ b/awx/main/tasks/receptor.py @@ -28,7 +28,7 @@ from awx.main.utils.common import ( from awx.main.constants import MAX_ISOLATED_PATH_COLON_DELIMITER from awx.main.tasks.signals import signal_state, signal_callback, SignalExit from awx.main.models import Instance, InstanceLink, UnifiedJob -from awx.main.dispatch import get_local_queuename +from awx.main.dispatch import get_task_queuename from awx.main.dispatch.publish import task # Receptorctl @@ -713,7 +713,7 @@ def write_receptor_config(): links.update(link_state=InstanceLink.States.ESTABLISHED) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def remove_deprovisioned_node(hostname): InstanceLink.objects.filter(source__hostname=hostname).update(link_state=InstanceLink.States.REMOVING) InstanceLink.objects.filter(target__hostname=hostname).update(link_state=InstanceLink.States.REMOVING) diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index 1a3d1fa591..6edf78ff8d 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -50,7 +50,7 @@ from awx.main.models import ( ) from awx.main.constants import ACTIVE_STATES from awx.main.dispatch.publish import task -from awx.main.dispatch import get_local_queuename, reaper +from awx.main.dispatch import get_task_queuename, reaper from awx.main.utils.common import ( get_type_for_model, ignore_inventory_computed_fields, @@ -129,7 +129,7 @@ def inform_cluster_of_shutdown(): logger.exception('Encountered problem with normal shutdown signal.') -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def apply_cluster_membership_policies(): from awx.main.signals import disable_activity_stream @@ -282,7 +282,7 @@ def profile_sql(threshold=1, minutes=1): logger.error('SQL QUERIES >={}s ENABLED FOR {} MINUTE(S)'.format(threshold, minutes)) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def send_notifications(notification_list, job_id=None): if not isinstance(notification_list, list): raise TypeError("notification_list should be of type list") @@ -313,7 +313,7 @@ def send_notifications(notification_list, job_id=None): logger.exception('Error saving notification {} result.'.format(notification.id)) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def gather_analytics(): from awx.conf.models import Setting from rest_framework.fields import DateTimeField @@ -326,7 +326,7 @@ def gather_analytics(): analytics.gather() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def purge_old_stdout_files(): nowtime = time.time() for f in os.listdir(settings.JOBOUTPUT_ROOT): @@ -374,12 +374,12 @@ def handle_removed_image(remove_images=None): _cleanup_images_and_files(remove_images=remove_images, file_pattern='') -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def cleanup_images_and_files(): _cleanup_images_and_files() -@task(queue=get_local_queuename) +@task(queue=get_task_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 @@ -398,7 +398,7 @@ def cluster_node_health_check(node): this_inst.local_health_check() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def execution_node_health_check(node): if node == '': logger.warning('Remote health check incorrectly called with blank string') @@ -492,7 +492,7 @@ def inspect_execution_nodes(instance_list): execution_node_health_check.apply_async([hostname]) -@task(queue=get_local_queuename, bind_kwargs=['dispatch_time', 'worker_tasks']) +@task(queue=get_task_queuename, bind_kwargs=['dispatch_time', 'worker_tasks']) def cluster_node_heartbeat(dispatch_time=None, worker_tasks=None): logger.debug("Cluster node heartbeat task.") nowtime = now() @@ -582,7 +582,7 @@ def cluster_node_heartbeat(dispatch_time=None, worker_tasks=None): reaper.reap_waiting(instance=this_inst, excluded_uuids=active_task_ids, ref_time=datetime.fromisoformat(dispatch_time)) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def awx_receptor_workunit_reaper(): """ When an AWX job is launched via receptor, files such as status, stdin, and stdout are created @@ -618,7 +618,7 @@ def awx_receptor_workunit_reaper(): administrative_workunit_reaper(receptor_work_list) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def awx_k8s_reaper(): if not settings.RECEPTOR_RELEASE_WORK: return @@ -638,7 +638,7 @@ def awx_k8s_reaper(): logger.exception("Failed to delete orphaned pod {} from {}".format(job.log_format, group)) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def awx_periodic_scheduler(): with advisory_lock('awx_periodic_scheduler_lock', wait=False) as acquired: if acquired is False: @@ -704,7 +704,7 @@ def schedule_manager_success_or_error(instance): ScheduleWorkflowManager().schedule() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def handle_work_success(task_actual): try: instance = UnifiedJob.get_instance_by_type(task_actual['type'], task_actual['id']) @@ -716,7 +716,7 @@ def handle_work_success(task_actual): schedule_manager_success_or_error(instance) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def handle_work_error(task_actual): try: instance = UnifiedJob.get_instance_by_type(task_actual['type'], task_actual['id']) @@ -756,7 +756,7 @@ def handle_work_error(task_actual): schedule_manager_success_or_error(instance) -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def update_inventory_computed_fields(inventory_id): """ Signal handler and wrapper around inventory.update_computed_fields to @@ -797,7 +797,7 @@ def update_smart_memberships_for_inventory(smart_inventory): return False -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def update_host_smart_inventory_memberships(): smart_inventories = Inventory.objects.filter(kind='smart', host_filter__isnull=False, pending_deletion=False) changed_inventories = set([]) @@ -813,7 +813,7 @@ def update_host_smart_inventory_memberships(): smart_inventory.update_computed_fields() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def delete_inventory(inventory_id, user_id, retries=5): # Delete inventory as user if user_id is None: @@ -878,7 +878,7 @@ def _reconstruct_relationships(copy_mapping): new_obj.save() -@task(queue=get_local_queuename) +@task(queue=get_task_queuename) def deep_copy_model_obj(model_module, model_name, obj_pk, new_obj_pk, user_pk, uuid, permission_check_func=None): sub_obj_list = cache.get(uuid) if sub_obj_list is None: diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 77b2c8a393..3260182b7c 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -201,7 +201,6 @@ class WebsocketRelayConnection: class WebSocketRelayManager(object): def __init__(self): - self.local_hostname = get_local_host() self.relay_connections = dict() # hostname -> ip From 680e2bcc0a4a0e96d4d2bc142a1da336d4843685 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Mon, 13 Mar 2023 09:45:30 -0400 Subject: [PATCH 125/167] remove out of date test code Signed-off-by: jessicamack --- awx/main/tests/functional/api/test_settings.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/awx/main/tests/functional/api/test_settings.py b/awx/main/tests/functional/api/test_settings.py index bcfa499af3..a1ae7398a5 100644 --- a/awx/main/tests/functional/api/test_settings.py +++ b/awx/main/tests/functional/api/test_settings.py @@ -279,7 +279,7 @@ def test_logging_aggregator_missing_settings(put, post, admin, key, value, error ], ) @pytest.mark.django_db -def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, username, password, mocker): +def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, username, password): _, mock_settings = _mock_logging_defaults() # type = 'splunk' # host = 'https://yoursplunk:8088/services/collector/event' @@ -292,8 +292,6 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u mock_settings['LOG_AGGREGATOR_USERNAME'] = username if password: mock_settings['LOG_AGGREGATOR_PASSWORD'] = password - # mock testing pg_notify - mocker.patch("awx.conf.views.send_pg_notify", return_value=None) url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) response = put(url, data=mock_settings, user=admin, expect=200) assert type in response.data.get('LOG_AGGREGATOR_TYPE') @@ -307,15 +305,13 @@ def test_logging_aggregator_valid_settings(put, post, admin, type, host, port, u @pytest.mark.django_db -def test_logging_aggregator_connection_test_valid(put, post, admin, mocker): +def test_logging_aggregator_connection_test_valid(put, post, admin): _, mock_settings = _mock_logging_defaults() type = 'other' host = 'https://localhost' mock_settings['LOG_AGGREGATOR_ENABLED'] = True mock_settings['LOG_AGGREGATOR_TYPE'] = type mock_settings['LOG_AGGREGATOR_HOST'] = host - # mock testing pg_notify - mocker.patch("awx.conf.views.send_pg_notify", return_value=None) # POST to save these mock settings url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'logging'}) put(url, data=mock_settings, user=admin, expect=200) From 95f1ef70a79cc20df8f118520e36776cf408c36c Mon Sep 17 00:00:00 2001 From: jessicamack Date: Mon, 27 Mar 2023 11:10:49 -0400 Subject: [PATCH 126/167] update licenses to include new requirement Signed-off-by: jessicamack --- licenses/psycopg-3.1.4.tar.gz | Bin 0 -> 469317 bytes licenses/psycopg.txt | 165 ++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 licenses/psycopg-3.1.4.tar.gz create mode 100644 licenses/psycopg.txt diff --git a/licenses/psycopg-3.1.4.tar.gz b/licenses/psycopg-3.1.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..97bc461e512ebb0725e3bea31284d247c9d0fa30 GIT binary patch literal 469317 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%0DWG;(d}a?whUTNxIpFR&ql0V3ZC0$F#Xvjx{1 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

6Jb=knV`xNzGEjrId- zjXRV`!GFosu3)R30T$c-j8x74F`+g67kF&5&uhD%(Q235YB#ObHmmhN_SG)X---U0 z=@&nt**g8-P5!5`|FQgcPyavMV}?*})i}g0Bi>q`><+W3;!#r>B>rVfty%k~-2NcG zKu?PPWMTc(0+vQ){j3&tzUH>x_g{5xi+tcU0Opa5cvFIsp2N9VkJh%w=)77Rb!Wf9 zZugUOL=Hc#@%WTDB9&@vOUq-&_{8G<<@Ra2yS>XOt7F5K8*Adgl|au~8VPh`{%XsR z6~j9Oe{^M$N)UL@V-n|t3o-cf<&HmfgS$sQcUnwCW7n*@Cm_EQ+c{4jJ(1auz$M%( z9%8^f;Og1D=bV;3itYsIff>#D)B98Vkx%ONd$y{JLc_$VR@Fk!X!ism&*K(|G12H} zB(Ja(rjJ;f1%P#9LH?U_gaUm4r;v>qatysFzL^Q~lOvd{OTG1Z_8pp>Ko|(pG@j4L zo}JV6Uhg4jy>~1U_IxG2YV=qcKA(%LbtNp&9*W8goRgr75p<MyJpEEGwbZ z$phPoEEhOY%;LUIkoCZ^1ObjRsQ+90pAf8W|LlUXtD?}HPHV)JA!u|I{;PXhU@#^%W^J+T~&2tm{s<(NQGOPUtM-`e< zJ5SBxr@?h@s|@Vtqu2kvMNbd%>7S-E8}=qf$a`a(1@F!C>| z*r(7#a}X!Vzj%kk0!inm?{||D$Zt8lX+dV=XUBUJ+XCk*?|o~|aH{mNK?3m$(6zgv z_8E%u^-+b^rHim#Vh zG)8DJf2<%sp9#5}N$j?)C(BLpzVqr*_$BF56t#dDwp+3^!FpgFnjOdu77d!?Qt!xR zI`A~xqF#W$!@xFcoYqy`5Dil52!IrJ& z@v9qoj=_>CzRu<9I3%Pyk|<>OToPjYH$(%UGi*8js13}Ph6E&C&qe{LP41iU}nq4CXcO)jyGUvOJq{&a~bY{$zC-> z!D?>>Gj3~7waF@BxOB+*3*e)5<-Un{5-x>;jxE3^Z&XS9*QH^Uh-!o74!Vjp+Q;u} zQ~l+Cd$=b3Up;)RbVjz#-ewWs`M3yH5Ur*f7G1t|&<_?jr;-=p{tQmHHDRysx@A=;tQP&%NM8cbL2&2HBZ9es@Y$prZ-}SPS17jR$a7-OLW#Ls6a4`~c&e|) zYezl2MWz8SG2f%<`wYZWb}FvWvC4u5D?p76lYwAxZb!f=wG~R;bA^S2b#aw_frZZAc zft3x7<`;kk^4%<;6CZ3Pk`JtJo0P6o9nPbs)6uOL^CDZjy+b$I`r_be>-&;vpurd9 zeb-zkEf;L1MCI8Tnp54_!HFY+H#)akCgzB7t1ajoogOSZE#zFlP-skiu8n_X6I@Lx zHq(q$N##J&AWD8PIX;m7ULkx83W6SZVSfO!$4mGJpfy~s-9=M4M2@0?SG5qEHLKRj z&poz=y$wF27fk8?kI!s(l~JH|MG%EGVo8YwcNF-35pEZ@^r9m|y`Br%;3F~;4xlD6 zmVVtxR())YazO+wW_;l|2E}=$K)EzqHq~*a>}RQiJFbFdfRkivAqd1tgnXT5t7!ro zuDvypS$CLfputEqP&@XMsyr4noh;OpU4$AM4w@;$Qd0M|JJ7I-A*Kwia7{4Z38#&c zv0Vq1$^nH5|Ji6EJ5Q*}P~@P2TQQ-hYi&oMxJyQfF6n7MwTuF5cwyw&Sy*z!M%I@5 zy?PjV4XtSmcM1-0uF zF}Dc$KIkmNA!ucxVQ=X`aNx5Xs@Q(!F8O#%ZoeVuKi~+$kqoB&j0-ZL!0_N?Pue;e zj9Os)WFy`4ZW->u01TI;oZ9lohQ6zB(vW;ZX?Ze;*Y)d!*TgNCrwxy2EUw?!4LrHV zP+KhLjp8kqb9HnZ=cw~}^1`sJ10zIs4HbmN(OQI^A+F^BohV)2Y@WOGQ&0tm?+p`I zG`fRex$S%+_1w<2Z5UaG9Cp4mY%1KT{$Un;V7;f}3uih^ z(!#gYvLk{^V%fx_{Gv5ezsqa+d;toRJ(j;9{P=w~G2v2H1l1y7<|r)U3HIBKy0{e= ze`Yzzh!&V(7 zN&M|Ck~r2A)hP^W*N0PQK!sp1Bt`*3|(jtOaK9$%os@RglaO{iJY$4w`tTlRtGSSQ z2&5-Idde8$+dVbcD#87&UhF8go8ERH#SHkq z5r8W$_rN`K9QO$Pj=2u9VyF6j+YjrQjQsYx;f*Pg&*mewzrgau zOq4pt1a@Cl>;AhTtR7W*aA8#bfhZ=}kP<4AXHk9A zZEfuBr@EG}qw%Lb7;gP1Ps;{^kYYC?tV|}Z=>g+B`c6<$xMfwo!QNEpKUXKXs^6?Vcm@Sxh1W zFntL7b~@A<(7@9S&j=2(?su=(3Be04pvdjf)}Il78XEd>zaHXtFL$S3NKk=u^=bW~ z4ybjScVkZ4MT5s%AZA)W`Y9Y;{UppAC!&uRCN|3T(Rr{>q;NO*^{CX9Bm%I;8HO zJC^R*btlZtX+56LvW!&eA*HHX-MX@r_{qP5N6G&0nIH4teek7yWq!`9sj*OZGhp*l zYqw~{Qd(}_dydqp|i`)+>)?e;}(;?U4gBCZO7daO_3a5j+ z?wy@=pZvPLdVc6TWtwp!o1drs{_EQNbtK%U{%5OTEbX_w>3`dY-8jL~hVlFLwl13Y z#Y~gjkfE3+%fMJv=xq#uScbYWy3H?gN68txYgq= zdfjV8P?cAQddrhA>%nU5=VW4=T$Z?4vCEx0p?+&n-~UgT<(COli- zcPDOYYUbmvqoE%i$7ERdcjvWYq82_;7*a<}IdMweMX^JHt60 zmJym*Mz84MuU8L#q{e*HqpZ6ABJQo50&Nd11M8Qai`}b= z2(@&N6+>$^e*wbjWNEI{Ck88=fqGr{K{4@6 zf))Mb-QRT)QLLPZsQOv}Y_YoM3Krh^LU(D*&=5XJt7_lpurh_5!dIO(6PL}t94n7W zw?vzve{5Gs6U?8yzJpu87VH6NKJEr0zvh%Rr17K3%Ck_5Zu+gVpewVgT+oIIZq?g@ z)-UzPCrTv7=kUg5T*9Gz>NS=Dn)1^f$0v;R;qP~FhP2jaA=uNSWfX^!ewPBMZ{aS{ zsX_iH`nvJPFi(qwsXh9ekUPvDqe?iUs5rpTdXHOd$EAGGArfX++@f)MApPkPI7+=^ zh*yMTK+#Bu4yN5sKH@?sgcEjTd-1)W##f*mnb}qV0{DhTQmp z+jTfPY%oF`_|apM`@~u(FA4Q-eiV%L9xegQM(Y7rn41L&6`Op6viMMkLj15yTgVS@woD=$XlG1_zooRgz7j z;aR(6&gsrj(%f5=a%qf%%I=9eJP z{Pm9w0W8AW@#6gUmYhK7%NT}ejM~=DO!&907y~R4hcuoV+n`S!a*KvZ>fo4k9}2KQ z^%uc1U@J!3q&A801Ila?GV%@BPx{7#s48cH{7V_mJ3AEQ1tdB}0W+-#i@WxVgtFSB zMU+LYPH|MJJ;?4m)!XZwQ|ZxwoW%dCZ|DEUM^D_K&{)WJ-!mtpeN7$ZElwcrx^0u% zGj&Xg&uY-ju*>?{0=X}^jHuGvPLo;GTMvWO9zz7}n>z2vXEv@RF=5_WN?!09Wk^7} zXl#jUu5Taix#Ds9q?LD4nm~L+ZOV?yfP@(`fnUa7x zXh$c7!lh)@pET^@C+iPqFX@dYg0x7u6q72y8SZn&Z9~V&LS;%|7l|a8T#W=#6$iq* z8(U!2=*Q$q%4#}WAX8>xSZE8lXFRFloi+e(!bgIUK}O(e@60fpbq(dA&=^)Qn7U?4 z^VF(CROyW0mmI!l>#IVD&Jm~mX#yKV+3z;AK>TmJ-Qm#ezYT@^Pkpa{myG-}gj1~8%Nm%IGu?&?%Q&$mC|?nQ@Q z&xLH|8}{to*uC^Q#HiKo`-SX4?g`_gNC34X%EC5J5qZ7U60b9P;k;a9Vphcp3sMn8 z5V%Q4e&sTLR-L}LVY7&fzUa$B$ywi^(r}1h;Za0ivdOC?Wm+r-mexW6H=CSEElNt_ zK2hjVl4&Qkp&>ccwL(AJR$CJo!iuRL5Kc@_JyxerSOouWb5tG*>7%AZk)$5Tzcf99 zlASJnZ_sp7dgCE4Xw!gTbcCGITU8KZ%X1!`uB^>QRfTF{GxNB{rAGeeh^E;_U&pz# zaaBb+vbn}oXSU-ao!LY|MYIMm9>*008}OXQ*E=-d8V6EEsU(vhq1~N23{wh38*(g4 zMA%|uD`N|dh+toQi42ptM~k|qqn*4yfxUcUS4e~USif0Gc`vR8B-yeA7hP`EJX^oH zU|!S`p1YRY$=1He^|2I%;h6+-9WTVK-V3?JdJ2;R5*!E#pro_!`LhE1B?1Ip z%d_{v)>HHM^M3cdaB}E~IER)yqg;BzpGM#}3!3kwqxs$?pH%q0$vj^0XC?;~8nSxG z6UoY?!ba$*@Pg-DLPo{DXc2*uMZ-Uc3`-7UnyLI=B04crI#WEyDPP)i zA-rQh=};8>%PrtL(;Qb$jUt=8t=Dr`@-kYd-)6tpcjwR8iP$!m62Cvx-R!2y%tY%m zajIKFy+Za*Bu(&kfL4F$tSW&QwOgEbaY0K0a6yR9%sR9sy%s2HnKI#*HM~CNx!2AW zb&3{$PIJ1>UQF4MW>WP?V|8ORg)b(z4X*`Crs58iu+z}A{#1(2F*UBJ9V1RmI$ZqYCSNPH;e-FyTjtui!`N3ihc?QfGyR&&!P01 z(&jufS<%YH4e8=nOt7lv_P1*s>H+&>i-y^Fw0jaCsh;B6s+{VLI%qL(8*Oads@ zVXk9@+&nTCiV>^yL^6qSIxukkN5uGN9uu%cDz7T~10 zY5kcBQB6hN**zTIZ)uIu6(R62m-`NX=rz{cFKh6ZD$?_jShSVVA3RH5pxCqAi|J#> zHB216Vnom3OT2i5a_TwPC@%7x!42X)l*MqF4sYS}>H%38ceX>qj}y<~6(P zi?|psZYLa>Wb7t()J_i!J{VU1!ypZ@vBs@@@7hT9dG?TbrY z`lssZAA-6yi-oLdv}Y?-<4Ct*y0bmT0+Hto5@9XDo<*uN>I(GZgM?YM#zZK|P=xjy zi7-^HH>eNwTPa6j>EyUY4yM#|i@a{9fxY?X<_jql#e(U@UmF=xL}Y<8=$;mKVr!}1 zaA{-d$J7Z?+D=m)))dRq15Obto-tVj$NM%kj1!i=?!8m5vUHf81@G^NLu+Z|;qNi?qhW>2Er zlRAA`tNezVJb*B_pc$R=fG@Dh%>BV96%N%{N-rJ~dTOW_Trvt{ZR1&VYsZ}PN|G_w z3t2r`#6l}^e`7t!>T;4D(l6m7^7b;g0t!mSK5gy0U|IV4Vdl2|mfE1p*c#m%Z$=SZ zN(im?WB;8MM!UDmo*{f9Plqu3%!pO8@~PG#<|J{S=kma^fNjRf`8=`^p-lz4)S~%+ z&n*{F-*CC{V}xSXGlg~4F=PoazcoxCm1F&s(9N15b_KUwUs`vrr95G=BcFF3k2XfR zPqRIbc@jMiYkmHnOHTj2DsFvR(DLxNw(G9;`m*l2MKx_vTZ(gMqvrEkp{O9>COwgh zl_B`tZdi8|kc;^iczI$KNt4k}A*97rzP?{_CRa+qIIwI5h$+sweG*f^2ND@pao_wF zb7w45%W$C}uW_n4BaZJPz9gWC2V*1e>z@sIUr`=7r~iaEQ0OQsER*pA4wNDqhGEXG)e#|dk0kfIYLi{LMrSe7a6!A`2Z_QCA@GQT6qvFI!@8bzy! zznvRBH`>Y!oHSSk38f0D_NXf46AcbMT#qqZ|96Hxr^74~8WgqWb>1`6YG!ArV05YB z%$Oz)C2~e~plOnujl#F9fD?yjx*?%BehEz7y^xyus9hfkOZZb_$#*XDHrKC>uLDdA z32Lk^&7h`1!EqKx^xs)H!&v$V{OmpgACjqw^S&#)7Pf}h{&A_1zTe{H=fT@B#E6gI ztr2J|CKqX`ZT>)KD}6@*zA3$Qje6(xoI}Yr6MY z+_Kpe!w=WT9>KdT8aIm(@$x4I0H4RM{D;VW+Mr2sk0>=FffNlqJSsfT^<2K4<&vL8 zSuMpt|E#@}L;zP}@;ZcHaIR7c41!RclFd|25MCze3~%1S>A6#o7r_N&@0D3_nVOed zYT{!sxV2fQ_^jzi+wvVHeK z)`b1XENf#sV=DRHRK4jKZW(sSVD|TxOqO3tYO}S%CY>JDX~VzqHPOqzYEdbM4!29F z321(|Vkic+M55kWkggbzkD1{PlXp$U?ivJe4-Yj~e^LspR#9oEbA0?Cm8m(}Ng_F3 zn%kb6*`FD=-laI6Qti*_j^~&-9Ak)f0f>4?Qy(40`2w3>6WtZk&(^4~y-Cnmy9SU0 z3vQ)vc8;?hA4v+IYl@NiSzD9TB10T}V$jaf5bZ^UV&BC3MGj!*)PO;=)YV9xD++Xy zSMSs;t71sU*NL$W;TsN^OZLM8ih-y2X$dt6y%6L0lu{R_yBbA$vAqURCSdB{HQwfB z3YgA(n8Q7eFQ8lY&Cu8A-_nS{;3MrgK$6LsDd#ie1Lcl)xjy2VJDV`RQ0NN;xHCA_ zly~_>2+C+T7>k_v7GTBd!0+w}O6vad0rd>%{lE+ze1_&7`MnD5r|O3 z^oA??nSF&(ukV_@FzG3J)cKiAbJbR6V*FBkV(&PW=qxmFm<4lsKf=cd7G!~c!onEy zK}vpuNV9_MUXO`z4z;0GC)2I@_K)?rA1WX+Pdf|VfwMuqvmYAm7^p*Qz{{>iA(wd` z#c8mh?15KMNj@ zW6?j`>Q+0$KRwa2-TJXG6afq#MDiW`dIt({GBk6=kkct5cJm9}d!XqIg~Q(NHzpW^ zQIbMu{KJ)S?R62i-Z7!Q2jk4FLm{I=dfs8kojjo#HQ4*q81(MTr z5xkwqAnS;uEWubFIkSL&i2aHhs#~RxE%M&N58jq%8}b@l3fyVIhF$3vd%}H)=g3P$ zjlnVROYf}2qDOu$LX`15e(6x9l&%v3EesVQEtVtLMTC9Dy4rO5jaQ||7ILk8A^mZ3 zr*lrg!2C9q3?Bz9<(Lbu>*$wbaw?1WMAP@=aei&~YGyj??CJlrA~0C){?1^T-7GfU_1U`8 zmH1<`AD94h2Zf=1;}B5JMuvZ+aOC8(1{e;%sIZhOS;?qIozR=m$Q1GPA)>*y)%s+R z16sWyoDU%gzK|`Srz21AtQeu95ru%74u0PiM^~H`+6H4%^hf2U~bW z?hCRvw)i+e?l~W$fN5Lua)@cd<2U|t9vuCg$8!KCbYly89H^uA+=JVW#7YJ*UI_3& z*|o2@36l{^WB)s?FnWQJ#x3CH>WLW~mUPrrA9D?LUt^ynb_#A|c`z zc`WRt2k9|VloG$kB(S6NXGg}p3&duLw%vCDmx zBZEI4ZbU>`4{va#KTy?ta{?3Db}}M!*x$S6JQJrs)>UlRufNxr<8n8tGdOq`Up&g4 zBKiZ~(;jhZr-+)6hm!uL-B|ctUv8^RV*~J%nNt!i8f5Ic0f~hgJ2*Es47TR9{%G++ zUHK}7wTWUqJoduvXLtT&!reUoSbJ@K>Fpv|RV!+1NZ{1=hUyu!ZnZ84KRrhJ7PAJ3Iy6j%wfcI#* zu|6ZKb?9{c6`MynH%2q^!;o+`1~xf#K`3l*LAp?$utdL)tI==lNaKn~O(b`SU^me1 zPGpBAvnaa19Lt-fLcAz&oM_&2Vv%O}fSQ?VCd1Lgvu_=$)x0GNq}2||N)9=TczGIt zO0L6AY5|l{c1HlNJ|o&`6Ln@clNMwhJwk1hd(ssah+?>zK6IcVmn*o#zXZDMf=r)C z0*vH}3PEv2y`1MCEUt|e%@Tp)Vn)1}8-Js+9686_RckbREnVY+MKFu4jX~!$5 zoHSlYWU}Xz?zH#neQ$rSqJ9eQ$(bD>aBmw?h&-a=e3Zdg+L_`XMj0ZbbaIbTgf+dI z2M%-v2%^6xBT9lb%Eyky+vK#v{L-hE!g-=38a>zxQc z6g#Z{c;FOu6y7(6hnVo)%}%c@M5X^aNL#`dBT!9W<+j*j*Y;Xtyc&GOr=;Q(&1yR7 zJ3S&a`&PT&(fQLGEhqb(s20dZ`jhWdJM+SO0S(S~mqVGVo^jTlsNI3DDl?6QX^PqZ{X8##qTg% zKES64FrhgbCbjLg?rqNM#ApY*eHLT$uNY@RYbIBRzDXUuwKD31`3u9daO3Fu8s{~u zn{69(nv?!PRN%2gK9YD7J7U7O(zey}jasK`)k6{M^Viji(x=Gm41}Y=-`o z<(^L{6~(89$Y&|^N5gh~dW=UY_MS6kJyC-q2R{>OZRFtBCdQJe2Wh}kdnzrX34yO}vRK0m%y#37!T^@}n zo>y5g6*g_NjH7nnP87%GSfRTC-#vB-z%ydjigJ*L`d?j^h@L>wm;^c|2lj!5S+9-P z2Knyw{Tf!YwKDP8L{cHUF0LK2oH1*$81VT~J1^nxjj|9sW4FObJNTCise)VU#x|=sLg40O zO?rn&nygKHJ;+dN;Wh>8oY=PIo6%2mf-k(As2A ze)q$#AuaUrDgoRNr!Y%Tua#Kq-iUP?_T)T50dHhcbgtZ?*a(@%mZU>%eJDYTx$fyL zI!|FNt#S-E5f2qN57ZaYMm^4XNS42@@7fvft|PPzH*%+VEZr}uol>JF4%$z4$pSNL5 zgB8m`lhw8XJ+-`~fR-zk3w>jsVsvAY_CPc#oOe2lfy@Q{jmhR8-zqSo`>{I!Wx8Y- zzC-hL6{?MPl3f)JetEMqHS5_7#(3t_$~}O_xVGx$ooxL)ryh1M9<+w~(z(@lJ9fN0 z*o<=psEMUuJ3qz}p&|2e?0ns9XDhv&_Y-unb8vFAuRnEd@bYYXdpliNp^^CRI$dGo zV)Ju}D@XC7%jMek-tzErZ1eJNKlONYe;Ka6czvW=XH0)WObOb`{;19+CT=fo2j+I$ z%09OX*~WO)!nwHWy>@myv~FkjE>ha^?Y=ypE{{vVK6Z0Mkl$IpAgi*Ow|q|ea6*b% zh$EJvS^wC3ba~q??0DAqW_ps}Qm8%qeLr#U^6>I<&+zy<-o6A5>cM(_ZGNFUN4g>r zF4tcD#v*yXmm8B^VD)-;c-`W6Vd>32Zso4uX7=Z6uYS`*dVX(G&nWfr!A&ey1`Ytzr?s0nEiM92ZcxL*XQl4azY(Tl3*Yj zexR!${H5#T9dM6nqA~oKI2tyB2&X?IS5QH>?6B4J5gm*b+qkI;IboJRkbf;DBE3a( zo9T?|u$7vsGITCA;4)*@M6}4;V!Eg>GQrgu9{EM_X->(IC%RXXyKbWKu&p~HPj)tg zyK=qxMc9fE0XHWab&P1L>h=(#&5!_Mjn^YwFxDHZNxa1$@Mia5d8ah3Gi=db`TV+7 zt-Nt#Mm)?gV8=;_!-@e1*1Qz_PbFeBkS3IVW11{1~i-c@e_Fb zC`b&WiNsR;?+LJ~A~KE^>W`7;jI~vl_!f;9k>@?Hk0l#(?bZlKRekB*U#yufkvZRVZZF z2%Ra4m{iuuzV02Ibt9rU9z2w>Sg|2?=u>@s;!~*-4EC2mMGYfgSGrSRLXH7_CHbU z1LcyyOizx~?;T2O;2p!3$`za`NN**PcL7&mFK5SLkl==J8g+|B)X77Bh1*KJ_4{)Z zt!_)$Si)3`cy}KeN*-Ykv2|eR5ag|VhYT0#%xRtW7y}J63iJ3D-&-<`fgT_jFN8WQ z5$Tj2Qcl>_Bde1$Uu-#XU6B35qKQq)6j#!Qsq;Yl%MxmyGb4b|{*3P+kNtQMLeGoS z%2;XufKpm`u0K*i4ID}5ZVQky7OBCF*43qK`HZN9P#Nq=>@nCWBayYo4~mql$>lY@ zu^+nb&P=hf@1WB$n1i3jgbMd3+?f^|WiBr_a%GiN=%2I6JXW1IDwrJoZcnNIC{n66?jS|(;EVN_4|89bHV+^W@+<2>(%+GlY0 zV?R?1(ch7)N6RIiT;f9Gj0&Z_d13)qCup2NlVb~?C8BzR_QqT#_wmBr1hQVx;k)8l zZ$11jJt2qQkTqT@(^V?FrlD}#^uf7-(r(ZdvulZ2k+NerkICEzRNfQsd5Rm&&@QX& zJ5-@mv{jxxcYbQmE~eQq{E~WXr80Uk@kN6sHcYu}!FK=Q^9KtLmQs04lS1Pq4B~A# zV?ZlstjM6m#tP6SYF;hyHE@p6Zj3qNH-mi!n&GwO%IwNzqxfP~=O>T|SVFf?%xvFC zeA}f!oQ|qgze92o86r|G0gZ%GospIzi_<^DtLSH<)stZvpS8{0--P!-phc*ET*#sC z_PI*0=e&I{=_`OE1UHs}s+nE-d@A9KdstTJbC;T9kn&0;*hX-cmpP&E(~6t&|pfBh3q%A2#K2!zuNn3$#Nf zX}2N=Mwu_n^-(ldH5w>NAZGBoe@OLt&FtkO%QF}DUn)w-1<@1HGtD>5@J5jyOr7MX+j-*Pm!k`u*-GF2PXYtRR%WtFY>G&HI3#I?u zMuINH)Rv}}tCU)=M{D0HY+o%>Di6V4iH<6;MbPaRW`^s9Eienz{Z6&O8P`M zgF;ch0+ykq4muc=I!Yc*+op0(?DsMnibuEQnh%-+<=l7XL^3VD}XJ{%aWB6c@^%j&>!}@#cVFwQgl}n4fmx zu{okGH8gIJQx73={O%sg6v7z)^-%+ayPUbgVI7{Vw^`tR`&5+=YW*j3-=ubaBPdODmhD=?E9Jv#ZhQ}}eU8TXK!-Xy?ig-G66#zXyHF+8eGd_Bq z#_S&&qF`6sbb-w2252h5j4Acqm`0v)vDJcO+gYy-(jATZU4+m%HUDe$VLw;f>)aQi zV=R+%7+**YBfwYHd!rPBqU6LFvFOx;x*jzvG)CN>1&4cG@q8iWja>K%0#4AYj9!2I z*)J5UR-O5=GPsz-7b z;?^3!R1MG#`Qn9E_Ta4s$)@5A9=6~d=6_InoDMcS`=mVFeetAFo}}LsXMDrYa@w~G z`4NBnpq?19uT?}jaORy}azZZEsKuW}J{3!#zvS2KW>?5BfA2QF9GS-y72!oF(5%F!?-E+LYmBSN**q16L$zGSGAPuZ zEgL#$=fFbb(Bw2lGn452g{|z~4x}eh4pd%BphS)WR9^`-sp2^~9!`mFtQ#)8rBJk= z5f<9KM`0D2W1tSX93V%TPU5-#RUgn1@siaBrE7`3oQLB-`slkWfOp?_MO(qaaW=B&%r0G_&IMmh@iWF(CH(e<0v4^z2?p#svU*a=G1fRy zeU(>^;aDS916PsjTqBq=H(K_%<%{j6HY+z#oj(KZlpTV;);uVGqwixX%#n}L8AqWt znsB+W+L&|&^AC!k8Bd8qP(H$E&N$Jt$2`gKMw)Y$al%#1Im&2|W<}2_#zV>&4}b{3 z`5?Pe-P8qjSNWPH9K3~bzMI)+Z+7dag9Hc?{&^oy{#;}o#VTLH4poI%;1hG0*P z-Gm@E#k&G`fCchIRj}YL8e&P!Faa~Bx18(R%}@j7RbS+c_ zKGyuwd&T5OXpnxzU1!uQROjeRDHz0W(-@UZe2GS<0^yU2cDv11EgycaUk*O`x&{)} zMHmk#T^VLQkHTJIaG?1_mNA@&m^qV1$*PA8nm0dVRsBcW$9zLBUgIqiKu;Lt(a-Q5dteYix^uDlZ%N>02meUlc zs|_7kq}fHpMCoi^HRu|;#U_=<%_hi<~g4q8B>ZDBW<#JpEIvZoOtwQ-o@M*wD^X0(pYQ) z>7MUmLHf}zBY0E=(r{-5BCdWeyI3du<5W{LS$f2?96i`0jywp{P0epl&_rj{jovyO z_}x3VDutQz)kO8fJCQcRt;8;KOH|WV^`b87sD<{ue!Bb5Q!cv9CbKcZh$P$<{)WD7 zNX`>o4y|XsR!2Z|OX%`^=5cPN%dSG+S7K81E76Y{+co093>Ur#Fz`*(LheSWBaopT zPR>&MxM41J&0M{jy(;e1+%y3?atqQ zf=}P0=z@$%8e z`(#{DZoytrRr;v`;+bjBP?0@bk>+8lq?1t-O+aG2PM(A#SWr>VQJm{W-^Mtr#>n8o z4eiq-7f(!l$tzCWovJo!Xp==+d-Y43c~rREcfWlEJ&^vJOYfpD=BjrL(s^~e43g&d zYjVaMW|wf&QSQHmj?G2;`FrAo*E+o3aYMV&1-PMms9koS=5WTu zou#?rqKuF)B5va}sZu;?CDT`9b%Mj)DT)4wOzulJk`+<%n!Ikg!{2py-;FZAZ?ubL zJV?EhXWYEr#7%{@&bg453*Wom`b3d@ztn79@BYCN`*Ja17MP)%lB48kwLo<}QA*Dm zN2U2D7^a*4L*UoknYvl*T6lK8H{3dlvbG4-kvDcNtK~4PL}p%J81ti}Ak8!moukn= zj6CKeghyN7L?JP0j9D>2sqShC`e~i<12ZKKOEf%hQ z3>KlJikD-qIfWTDY9S*gJJ3{-HH}fGo<>;~O$uAo;jFyN*a)7Po-(ra_=0i_E&q)9?B2JwmPwl0FB5#TM>CQ(deF$g5#7_m9Sh~31_j2Mi}bB%whFM2 ziF?*gDQZ|71KbYLEq5`4>0G$6Ynx3=1mJ#PpxprbA%<0UXsYWMozFaG`-^DLben{l ze%eI~LOvro&x85)-|Sx%SZ@A4#w&f{HJw#kmy@Xq&np$kjJ=KgBb9N_OqYkkyKZYX zEbztr#N&cNzIWU(_Ps6=%27V(I%kpN@02>u){>Y`^BAuy=UpPvHPUzY3m7Ysifjsa zl8mp~m~2!~H;#d}7|}P6zg(~IWbGz$o{>UXMq&H0tG=0`U1>Cy(#D7{=ec2&K(jF`zq zYq2}>opTW2jZHm#|B{&}66v763j5cld8QcNsFbP&+Sk~XL(SlYJ}*_ZJ{;3fJ?Ebe zsV&ChA9V{g*++{43vgS(YHQ*7WMAFuAv3gT47$*cnqY1%mS!72{*1-BbmQi1h+vUk zn#k`sas7PaC`)(BWpwSmBxn9HrZWp-K!RQprR=o?r^PEwjjho_BNhi|WQ6L&T#k}W zT>k=p!>hDD9)ua{lTiLI58~1EV|h`(lX7=DnM9)udPAPeseBDTgM9*}r-dVKpQ}gPIND32lwthe&C4n(ZkH_?QQJ#Cz=F(IdvC=R@-0`mzDL_n7GrD}Zf zl6t}j&Ry8XS8}T|$bK%%yv1~J>O5Rm&8Wj|MRE07y|r`I`ywjl(aMglNU(DfJHWlZ z8c1T5L^BF-va|w-T1EMReWoxWeGb*7+-tq`aC8j)+Kw>xtEo>CL6Y&RO9XrMYboa| zBJ-hTtr6wdK-`epA!nbNU0F;oH%DVhL%yco(&I)XqCL*`6f2j@7-dJWA61FZqg=DD zSNJ7JnY>AnzSkQ_RW8G;RQ9kDRGcW5)w;4mWTE zle{b;cVd!$EB>rU>4}q?TWgff7IqqAGN{+UT2$N1BhD5_5GZ`3_<``gJM?hE(S8ru z;YP^)BINLJM$=?T5nqh8TZ{{@!^wvr3}k@+_;+d}7$;;hG=f(W(!w~>_h@V>w$aE& zI%}AyJ?K+61n>U_C}V~v{#NK>t3b?n$@BEsaA03l|4}v;$G0+N7xwjN7OkcPTz2m_ zNtfQ9h)~bP7N)hWuMcsa#q`Xv#Tp{Q2A6%x8Zu)h@| z7GD%wA-Zo6E5-GSvjj74q)Muf&XuR|PeWB&1*Ht^Od<_i(s)?Jb~xC2lE*e1w^iS2S|E`c8^uL}1bb#fse zikPb7#xS9Y1A{Y#V(xNtp^l(#)DLX8lAl<{hvGON#_7vgPUT_kn_CYl8ISund2#(4KYdzoaMwh%%|eW9U=icNKBwhCUwPR24_@Z+Me=7)-wR-puK4J zJRJ1~5n;Yfb9o3Q6SU|6hd1_|0-w4)eI~m~P_oID2Jh`fMdcb1E4oYn;BE@jz|>kL zXJ-*!Zi&~GvbcH}iRldFbZ!Peq~%&5Oji2w2vx1-C{tV+VaBJ`?WnE|X(f6q);H1dy@aoqzZ?7>#V=tSq0UzkKWf0FOYH9tQI%e;TEi~KO zo>$v2x910@y*)}PvxbSl%mQ?l$l2X952J*59vP&31`vPf*?s6tjb{Yf78!mBD$2w- z*9k2SRPD8r2FJc(*yhAvWgG(d?2*|0Fo)uDz?D!fs?8v2!-sfPe4gds3XQq29+-8{ z?en3~Z9WyfnBzRbrHp|X9eYYWodWUFUs3zr0F?{2JMZp{~B6v99 zi*VpN^|QJ$GK$G9?ICgyW*9I){aWxN-`lzd2i^%XO;P;wV;Cko2RHDM(fvN1&Qq?wVTG znu2GGmp)GfApkf|C^fI+NzHIJIZreBQ#zQ4F&X|yU4us&j}>(iaB~G@3;7pnT+7A( zUoiiJ5M#ea{-0)Zea(~q=h36P{13PA@#KFH2a}t~03ibJcPV$kHPRH!$pWBrK;{az zF*#f+i|X4z*!F+r?oh@Z6!0sLt9CvB^Oh2y&kdHJI~mQ%R3v6NpHD#9)%!9E$dl!T zb+A-f1*8qUti^c+tghWqsv;tm-zG4=x-Zl#%6c{TZr6>B|Mru(AVrX$-xY_*XGFjO z7F!y7)_rcsat+h2>5o}ngi)TT<+`ZHm7_3jxvu5CzMT=d+&J3HO4o|gxlB-0ZqvCF zHs`RQjcY{$Ww^V(c%Zo^btC;a8uSd~2l|bPq-FZ)3N6+Mv^S#sg-K@^j7>W(?3VP@EYc8uq%Me+{%F4LqfHlY zH@Wq9Gw7IM>j7Pf)6sNLKnZkT^2#ZnpQyh*qjaZSE@V66?7tY>F$x#rpjN&ZNXQQt z++tL?kce2IiiRcPrR1y&m*#lgVQ+>IW~}Wkh#+!MF6}6geP;}51}(`AX)#}AYK$+E zJJgynSWzCYY~dYUWMCP(znC>%*m4Fnn~OG3{O5uV?)VXeSvH9~Q=LA6oy<9R!X{@G zGSAxYaz|6+#%4Mcw>2h^;>ZI6Bx+K#iJ={}U)qXAYxc20M_+2ztr{lJuD)?PbSMgS z8Tw#$-BrO;Kj9&rBV}3o;V(u~4rR*YlH#|&FtZDzw0z(%t^)ILVg6arjjOTQ3H()9 z5LVAD2|xWs;S0P5c|(;}Pkh1KEWfK%MhVzPXkN<3v7M&F8n;*w*2#JUTd6W(hpfiJ z4!&+@v}f^!sE zquvRSaiW_!tAEH!s^Kd#{i7cNeSvD$0z?e5H6C4WclOdV zmaQQc?vl14)i0B99E2cZOh+Hkn2OyLmB&a=W)^14D!jmtK8_Reazw)&?bT?TRuw6c zMIQpoWz+H4q}=JbYw{fXmY`U(tb9SGW?4M2G|K=P{fDM~^C2@1abK#QFPnUpLFbds zGW5nmiDspu6JYtZvC_RsmMT%QUHmkZ&(jk9QoIEF=76tgg~>Xx5GVUNrN zwt}YnZq$p1zUNBXk)~%>6K?7BJRDsx^Cpda@Vlqb0yG1Uo!UW~QSX^ctyLL^2vXA>FKZNVCkqNdHzONI$ZO5MwL+{r)J^9SON3A>V?8XuI%YLn&@2%)-r}%)6>Aty)&-Vj#&1+=j5mHeoJ1=kht1jru+ zInrXHMki?QZR4G`48$lG7G85#xD38C5y2H6D?gGf!M!$hT73LOS7hnH!NPDd5!isj zAap(I)dIB0{6q>r8sF!ydJj+ z$BrQEg=3INQc{%TdPm`xDSwO;4Z0MWN15jU{>5}S1{S@;{{kN;ZmFZq|D%m@=ILQV z%4_(W)}J39?za#3Uidvmx;+3U#3eeHAe#**lkf`Ud`q%n*(@j5D4^;b0}YEV)`fc; zNl^%nVbp@Aam#Qoco~w@5XCJ2H=q|fhO;*z-dT;qNt`BHgwU4nr<1933kIzVxucwE zVV>k6QRiityE-!}_4Ab$YhX4^_dL_oqU&$dB#ZR?ZxS9A1THEZwz{Xy;MKz8R<-*0 zZq{gQ__8Z>0jFxu!QJO%gfJh2pYI)PAOCuX!-P8j`q*e*2aTa#V+l-lo0$vQgU_>9 ze?JL(xbFOKA?4DmD>NnD0aWlrC+Aa2k&^Zv``U2W)->o)q~u@+o`$2~z34N7pi#lF z?q~PkyJNzI!F6)VG1k-cFNX5-hb~b5h6Z2IeWTmonuGqaKa0wLF!50q52NeIfHUR4 zX5$gce6IY5cY=5F-`D>X$$z-s4{*T)TK{4>u<4Nl=?-oXce-`fJ*f-0VKgLW1CP7s z6YH){m64c+mtx&sW?$&_Vx%PMI`2iy+Mc~E8rlUV(Q$76YK9^y91LEH_y+K3dvcZv z{aN%86>}Uuq$7&_MT#-6<=JcKpuIRgf2P?tr=^%^8gP4{PU-u^=N7_j6N(_46Bj562 z+?^!y_sWA3-vF@YaGH+8-dkjlpBgn0M^gOD|IlCj1OI>ii*=Qt{R$b3zy-CY#v0cG ze8PWw(Eyo%EXEIiCu1nnv8Uawx5ZbrvKXB>9NFb$Gh~^cQdk7rL8whaOeV|Wr0%THds z{#EIv`N``S_@re#IePWtH9T6g9ucJVTswOQr@O~LZ||R+{<^>0K0N)~?(vCg(tdgJ zkNx(^>Gr{k?c*1!4|b8G!;{lj$Ga!gA-AccSM3+ur@QUlqr;uQ!Pj50*rT;Z6HbC4 zqTpmyT8tbhOxCj`neF+2U#szo)XS(kSu`q*M&^&nT4&>M!3g@d--bX)pO-FlO& zjm=|gq6+@RwybinH`Gv~ane0EMqw^XQKjtnS=C@a{vN~r*fQI9R;fKqM%j5g>~zqC z?h~!~Xj7z8B-6WEfL4!$QfPx^Ce*Ha*JS*2PNh+Hjwo+ZD&fab2JZXle!g`=8L6#w~)bC5H*PCDtD zC$)pa)7{PB@*GBZAwo|YA+K=YC)pLnu%cWvJlqNpqFMm7rxpN_s#-^lDEJjVtFK?L zzIZ_{{~R@RIs$n=g!h9MID+U;@Ef3HfgN| zPi56$3);S<;Et zS{3Y{cbN?+D$E$Iar=3gMksgrmzeXMpdZPH=*nCwk;~9Lq`v`yq0$|swJHi&lZYe> z+)ks2WBg6WXA?LyPE39?95T6xW|42k5OQ<4Sk_ zU1uuoRdxx-U7ZS{P%T!GMQc{F7twoDx5uJdZYub$^B~Fgq#dD%;#V;Bry$OX>35c6 z0nN(yM2!D$B!b4?@GO{IAcN+e?!7i?o*#ESShF}9&qrbEWLxQDoXe87QeiEm{MzG=-HK{sAajU>j z!3NbbfRCnGB;nG_r=ly*RH5@^%DXBTVJg>sgZJ?7>+&9~J&*TntXFt)W^f;Z^X+$q zg^Ww=jhjPaxoN&9G;RYDx4#=ihOx~PJ6d8bv{NgFe2VPSYJhjY2M~yxt2~j_+y&Cy9(yFA7vk7`i-KsS zmt2nMYb^-7*%YIGQk~F%W(caIFusTg4bm(ejx7=Nk12l2Nq0q1doliCV(6Vt;OpuH zGDjrNBT<30cyhY^`pDvb%g6yYA_K_29wf`j$DVrE82db7SwhRp8uK?~vAmI=_OG#H zi8Hc0La^#ntrp0sIr)THta(9Gp+~djl*b$G^@dm0V0fq+5pb+}`1z@*lHLB7?nSRS zeJzfCW3u&)@2Tab>%!VMgZJMG>+f*>mT-Rdxs66~y_*ktH%J&{E@9A4QF<`_RSc)8 z8ixBL3!e;lf)Or#8_f%L__4~YYj{{qv5(cd0%n5AErV%4gouPrO>MGIy9fu=JuBUY z6(XRQDg&tW{w4}I>2Cv!jWX(m6FV#d!ytIjNb!ZLO(Zxvd(wWq(P-9!u?YCCzqLUq z>j0uJ+!SBzey8H57W2$Wwua*$k4;SPksS#IbwLS}62SI? z$^yOv3caf_AaxWCF#=1RWrK(hLzJ`?-qnMh;}_3Wc3B+VbV$C~m(gHQx0l9{U+Zw5 z8ek64a;;no%0~L1Jb$neOKvzkg{A23Gl;v`$M|fNI@J=8xF?r*j9G2srAyF6+l}Bd z9t=Q^4M+GG9^^V%{^6${mB)XXkkMCzu$D1&dyX0+A4FJ9qlej26St-I`F<2Z_PyhLFrJVc~ zNnY*JOmTBT^JR10gLX23vV}Y!wgn~Jz6r(;u$E-}D0D8)^!J$Q@0}ca7%&YJ;3^9) zgTC8fUNM+g5lq`?E~FQ)e=US`!jOQy)dI8-dw^P)MIefSJrr_SytHM5x01x zM3d_@+iWb*Ztlz^;xO%@tkwrcD*a)nBk2LF6;zwSC!n^y2supUewcRS_&(<|QwSlg zk2nY~S)mo0n1hTmOwUZz3uF#t^0bvLm8V(%F>-go>+KwW6ke(fXGTQVt1`OqV!X3d znk2y_SA%Ckvmlon3@(&o#_obxk_3Zraux-Zu#cAgSHLKs`roTC{PfQg7%!W0S`p@G zMY$`hR$t1`cgkpHl`heII>aPkl}-dSAQJ7*X}xG&P59jqMJtlz$kK!X0$f-H8*Xkr zujeeF;$Bh~MrQ#SnGHN)SSI3e<+A5WF~DQR+cg~vjxCuh__!7{6t}|P`9q_b^F5ms zzXZ0z26!P5bthT{hXQZYY*PP4jumgr-3u1xT4ynEF45+bFLt5B%QlJiRC=~RnS zgqPMtTehrM0tEf@(<~FU9Qw(W?F-+8;>Wc#wy#0CJMJxPZXt8qfO`KlXDsbOrQFV& zL(aW)dxx-X^TR`o9;;;J;rTtpZti*7uDN^8N{B$n%av)djYja3^}g_LudzA zM6WKTc@?AX_Tq~;#f+!uHtGa|CH%tnf6%%Us{p=x@LMN zd>|krFDp{jACnzqzkinu!R&%^^U5{PHeRU)s$8 zmX}9YU5@O`;gZ?!-wltH^RYaa%zpoa^GRvyIpHg1UzB9HAT753LUo18~ zb9a1yOqxtR?`{n4ZVaw{V?Yk=Gp`KLzujp0mhKF`fIcs(w2je&zV~*uDTcknvlyWR zI1$a~JD!mehAK1bHg=O0dls@%xP&mLMHkI_wVbpPz=8{2y4qILcDqfp1x;&dvrtXG zaU+8D3|V=@BP)}33hh2_RcOAU1^X_f;o~Sx1{d533|+zWJJ*9NVrIR$$d*&yi;B#V z{qmzteiqZz_XzCOf?&}+>z*I7OUtmc^8ha-2Pm6Jlm&7eTue(%9!kZRb@}Dt^>t6n zV<+s0k25dkG#w}+oDOaDY5TJYU=2He-v%mKK11 zlNkobCz9c-?+5p*cA=(GNYzvD2{NO>*2vPG^)Y0`@s($m`J3HswOs-+ct}|OJ z?CrbRqb%%YjvG||9$gVLs2Pl*`V~2YcR?5Ce2U>2{O?BZUT$EN3mlIB;Cdp%y0nHy z!)c9fq0MdnOEUQoP_hj=w2YH9&d?QwVOX!Y6p=I)Gy_9Wl=<3F7NtZ1g2qeH_ z_m_NYKWxcY#d}ox?btTFxJyYX#>NZul`(?8y7sd8k#in2^0ZnIf_!YUpSb-zkzE|b zssP~eDT6U-R}3ie!9EqYAr`g)A$4F?0xo=ROTvwZwOt!r!gz@wcX! zQ^knvs-EOktw@g}GQV-ubBmB;H4Fa9xl>-6i!e)hDLk1Dk}SYL={54b2}f7KC>gDy zf`I%{dP#jQTvTP=5ZiO4#XlEn8$8OZQIcV5OL44|DTe+~n!Rf(+HOXdHuL`bPSJL! zXuAzX+qb*5zabRNe&@z6OF&eo9UZ3`W`|UOI&`K92E;OJ!R2`jGFQxUJ{|-NaM?NPfnuNu;Yf6{S`SVV zk+1;znMD{d8R4lOCn6d*bY+@#YX-RVJno~5r%abCV(bckP?}FUQd$8%Il!Y)Fa$9j zYi5bnJ#!j#1YK36mkB04Lt4(ndfkjB*9_`gbsJjUVhr&yvzZpko>0cMTo+9n<(?BZ z$`Q*7jF&9|+jr;&QKKJRMgblH1rGFh$rKvg?`8LKq0pBVaVpGIh0uYeFa}t7N3KxnzGKW;LT}}94G^>L_H87xX@G1fr_~Dc4Hy{$Yy61L$BcS;l)(=Q zSs88#yn09UDLlLY-bklmCya81R=R5AfdA+aeQe?h|KoBB5LHV(y`D;>xyYS>6t9*Q z=^X2yx0_tz-2!Gnb7f))qv}k6Cp?s!mDM#R5~m2JkvfLbr=GAcBC{(6W6`sUr94{v z#B!%gVrX}|r2i0I60u-k!1~2?NrfO*Js`d%$6Z3FC7JCdYz^2uAAoCxodnP6nq~>< z?J}7TdJ6jxUEiGU)EsDd#7Bk}3$7TY@g(YLxv~<~&+0lq0&v>^NYV~85S}FtELo|F z9Yo;}W@#`8((poN*0@3;kJvbhkob(HTNeEaz)7~O#6D&V5<(%jcC}73SvN=447S`_ zI>|#`{39GwGXpay6^@dGnA4W4oxiez>fBnsd(_30duT?0z&j(ZW9O8pRP*5RliSPI z%hcX4YQw2b?wF zks@O1%5V;1R7*Zmwy3Vz+x$Wb=sX^Mp+y+X zJ|NZjKG8LJ@|d19NUJCVM|l*j{(w<3lTTiotK(9cv59UnHr36jcbAA9bxlpL;db1p zN!hAVa}|HuUI-&Kc@?oU6{JFgTwErN#`9FrtVzuK5bcqc2RT3dpN@e#r8V({6hv=- z`rp-equ?zL^MA=4A^l(6uBlekfouTtoKM?n>pSnS-bZoPeDc%%JT<`?;_gDR+*=xj z%sgcwW)UFQ`ac?LYbny**``^d-&9OkOOdhb7(_~#$b2&$UtrCJPkMC^>S>fWj01hB zCXED%sOYh%Vr4K84{DYF&mHBpT}Wu4HVzo;*|xlEk5S z*LTUZ$35dt#=mXnTu2!$e0Q5zFf4IDqS6qEixc_#LIx+9McnJ2O|-;?)=Y9Dy19z~ zS}%yru9{wC^IWO4UV&8#tWB7v%d4orj=!P3UOtaQg!1(irwa^2ig5F!(;HHosu>{_ zmlX4b-jteMT6HRc{K1Xx%s7gUccwL;U*M`qm00Mzfkp~K7W#y0k}#LoZUPw*z4a;p z2`UUkltKMxD_2Oo{9()Yk|P5N$wHL;Nk}SopYcPYhA8#a*C92vtNiV2^>}qwj}6BB zhgPh+wdkI7no1JyULt%0CwY$?P5VkSNWU2 z(N!_2xlVrpOC|*$^Jcwt%X8;N`K;uy$|TYt;~uGxS%7^w&v`4=IC(Y8h4^)ZUrPcP zWR`1|fmi6=NV@SQ#tt_8%gUtxxY-}jHT#Fluidq;l9EkIZ|*1 z7#<1EzekfK>Qw_wRZpsN&iqY3R|LdkeV08>Xo^rXPxs{9A)IVd*s<*wCPyZFuevof zwE<)EB+Oa@&xrz%uyen09~GTKqI`-{;1fp*Bry~rzLO#=|5yo{4Zxa;sJj|G#YuXG zAZG>EroQD4FwmD+kQQ2*xrZ5b3@RC@O-^Nn2qh$8OMio_An*pz-G?bwwsl&&5YKdE zo01(P@ES4h*r*i}a)~9paTLgFv1pt&Ho%%KjS5rYV#ohp69Hx} zB%V>(;-o(b+3F|h%W&v0ry%>niVOxZQ$M_Bp}xpN^C}M&P<=zUD!L1zGv&2^YZQD} zgg>O8E;c_irx*id`{%?wz5Pd1Z;m>9f8nOGV5Uqmn7 zQYVlGWxtyf2)~?ZDzuVf)cCD_^a_v5fi#!OA0$Dx(HBm;Bmlv8dD|rAip3A|VkTgr z)3%glE2({fLa|`HVjBtUnr!;4r##nFlxZWa6Rk^8UaoY?N9C#&55(7+KPt8~>cblf zCNNp@A<`Esg=v;-aH~y%w~pZG1`@yxLIq7?m@h(hT1P8=8VClDne?B)H+bo61AT#l;u4bfT=48)jEpG*4pTg2mc z#)du-N-v2AD*!Hv93Hw@PJ;w z3@0NHR%{hiSzw)+>PL=vGx%Zh7dGgaLf5coH6DkdGPHVVt(nn1MS$I7=gh9L7;_Hd z;Q-HG3-vIl{E&it_(NJP+a^}jZ~IYpHI6VwcfH-lm+iLwI{H|fH_p1kO=IKna^lAO zJvP}K{PLY|95&$Jb{<=Y{5Hy4RS~0EZi^@b+p=RSp<0mlTx31rA&ti|H+?mdeu$FXRB-VW_|sE_|@(j-;g||4}=n{ zKEC?6bQ=x$Y;3I4zwmMXU4PVQKKifb`dVwF(P}jsO?cjFJ#20KSK}*;H}{#MTnkN3 zk|di|Zr*!$aDR{w3PL+9K80uxhZ=Os^(~Z^wEFcD7AxHgc9QYcgcRwOoodi(v>N1^ zcErdMoT80osT&U|R_ zQ{|4XUPr_BOE~u1WqNTpGYXlaR89Uq;oo+}L1OfR1%acheRv3sB*PP-XE7e(m)rw- z=vIC+!fW!VXVutFW%;Vz5f(7@5T4_2D9&9FiT3O&aI^@`QNP6B)bxvF+8IPO^=v!k zCwBcQ=khZk$n1VENKC{Ge_}a7Zj6U`o5Lkv@XuNx%qfA(M*VO)kmi-5mLe*^=LE{g zw)lS1Dkg!G{6!a7k@ddbzMO>PF=DJJ3GA{}!@ukF_c8rFU`!SqA375O2P8OUJ~!0Q zg){FxG{E@~gp*_n-1I!l#_8sR2WN0loObHnWcYwFTK*HK=@cmA+LOi;K9qAn}L|m4N(MnmGy|eaUkR_qKE9Z+KxwK*RFQt17IC#DN z&%J}w$NRenKszl}=pt~8@nLZd%!vsC2;Ye&3nu+F51==jy;6#v01Cxw#7raw6#}Re zJsLW#-=;}sr0lK+tIu@HjuD2@2iGokazV#uB$(S+)1cfkKWVwFw1q;P#st>Sa@P7H zo0xC|;b~F*Z_K)(Fxx+lRC3eSnqyOR!M7o3(dTcuiIx|h)|-auML}cI?%7$9$;BK4 zo0iN#Zeo(eAUh3ei&LP^1h>98xb+3VJzgB#;|0J8_OKw(gEy~tkN0*KfZO`w6tk^c zN-x{oK*Jx-(E3#Ues;}dtytTWIF^9&m9lK(S&lc@DQfQp>18+;nl{u!M^Vqn^h}Va zs=wpxB1FB}Q~l^!18r3{J|Kb&2zoivtQ!l;Z!u0E! zEAFJ;wHnbYjz4c|#ks%Mic9OY1y+2mwaALk&7_N@=!;kU@olD%Hdb61D1J#o<^u0; zUhx}RXzr%9(4yyyEcC|uA`4A}DS3_uhM4zYB{&X21`j$>b{Rz^9s--dJBAKMOqxW$ zP1#X4fg>wk4TZ7@D&}bPfFNdrwv$Tby*jb>0#Lf`(k&eO#n}V z^^$rj+1=6MNznL+dX3zxgWXr~YTf&4`v6|;_+B0D9lV5hFTBI z3LLpukHmRl45r`>jHT$!_CXOe=xtFYe6^7D@nv+x5=y=rDe=hjLP^x-Xh9yy-WlyI zA?xe(nM?^!;Rx%sRsTd+FW82@eEBS5E5+$J%(~}n7L%Y;9SuF2q?@**Ynh(o64dk1Lug~zF6Xk2<_K1L&@p$5zxWUDrIqjgyvG6_>Atb!VwauaxPW_%;8%@75h`r ze1``JRf;d4D)2}~Kyx)|c-&BPWO$1g&J4jaCT1bs(QSLT<$F&jH>IypK4i@e?dm2} zEy~qxK`qI5G&a&qER=bEL4CmYF*Y?mJm5ZC$W3wP_zvUV_cA>5CbjbAD@S*t3*MLD zL*wZ6a{qAqc9b~c?As%$%D%<5bt^`KBMbz#70kIF#7_@n3QX>k5q$1O&kY3XzklH{ z1!$xTt$KTtondc$DkoFRT8be+zdO?u^r}0jN0@jyTY`fVh!1`T-$ zU=hO4=Er_fabrcl;Ic(lpSPlGt;JS!?i~kB$nBn942Ho*F*A1HOhX&|a8o}@>l!om zrsam5o20z)RHe5t?thc06biNAFg42Z5g+_=k#Rx`FK`!`4FbHgza%E#tZFGu3)+#uSl z_+mibpi5NoG9nXs!_vtQpy>ioO^f)K{%WnlYQ3}@QhYCe#WhcdIsA71aa>67y4gqj zomiv~(UmtQoM}UlOmdG8c3Xy&8z%eOxjtyK);UU%d6amJG^ zxz4MBY#Y7`q+1P|I8TNVgarW>3F=ow;h%z*T^OV36KtyzF1d%vNvcposQI9YRH-Ox zB104uq=K|&D+dHWwyTEIW(~pQ>xk}}!am}xkICkvT}wJDLRI;YSVgVMH(jU6>r_^G z7HgV|dwW`^1+CEES!HM40(wKZi{ZIE=q(P%$!*L6mh{_QWIy$3L$M5Ex(Xri&7kq| z6Mgw7yN}P4H2-LpFNVZ9-}+@9U;LiMY>cJ^XAF!G-i>&0Ky<5KS#`dRe=+_pC(bV@ zYJA`Lbls_)hj2?z@`CnT#;A&yY1xS|kG7Mpce0I?n?`B8spXS~KC5LDI;GVD44Ja} zSa?boIL%c$wctl+6aHF};gQ@=x~NV2GhTbA#;rH2@2+`uL3h8@p4FTR$qzj3BAS3C z24?`g6^DNm2z9rzMyXhhH(%Z*KB+mqa&ArLS;hWBf&>Ly8eauU#)46V!T3xBFAKZf zWYXi?c{EIjCn7o}i1KwbLQPTj>KYc5<14D!W;rE&i>HoHO%S5+`kem2|DXTjn1@2m zx9jiR$_CMJ0zA&eZfAcmwO9bzOBS|MwR^$o;fupfPCggQ7`h~KlEEP*?OAL55Tt|T zlA>&dBat=lBX_JW;UEN#X4#2?@g(VloxxR*jI($cry@37w;Qpm9D>+Et=zN=3yZ;^ z1Q>iFc(BgK*vFWa@gO8;Q8R6jO4>sS{WzqW0F*|6y(lfADsUKqFq^4}EDSgeDn@Ik z(=kG)$mcpf7j%f9tF%7W7>3n){#b~l9KP1Wv`v*OMmQBZ+VCkVvqFhc$v_?LGB}0l zm-=8R?LlTao0)wXUqv6s1g~YrEi(?Q9Vj5_45e7oEPyJzOyFMdHw-yK(QInLC>-U9 z!n)@~rpfRXw7-VbCL7Eq;XnWFf6I!kdG+Ig!SmaF+IY@S{@f3 zL#bl&LAQmM_j6}W5>|6k@7#9w4qh%|FgFj*kp;)YxINPMbOb{JoP(_{6?*U>838@n z3_j5ue=g_LR5`@O9m4BGRXm$OD?k($J;Murao&}L?Pbhcmg8@Yk`ab0U=Gohbv)$`S$DN^F7q3L%j_@hrDB6l5**3QVJ6eg>32J9tJ?;FOp z3XR_eEJ$0zlV($er4eQm8qzI)3{k07q`F znta<-Z<*g(FK43u;YpSFhnZGK5fi5pFT_lwz8CENHpKw25k*l98mr^5M^eWi>SJ8E zg%(bL!aR6rGKpLn$oJ?>@={q1xk%kc@5@*rih4Fo@N8kIX~aP6#TILgg{^ST_e7H% zpt~C>_oE%!AxBpLCV}O|$gWz%11Nw|>jqQ}k@{%pdsgwa4>sdOu9 zQGdeSTXhDEdN>VfCM(%}RaL4c(k;!{Fbd+VP2wShVsLo`?I1#|%j2=7*8DxE*OX9x z+R91jmoWzO<=E(ga>s_c8Su`E*9_x@N6$=L%rp8bf5ci zdY`WS0c_O$K!H1f)64V7QOHtyC@gA*Q;-7AFlzvSj5rt|lGCv)H-aXo!yrAUlLdxc zsmrAye=NG570y)HCGw!O1!j-V#3w1?k>m_5;Dx+Y3(f$}C)J8_`ZDtCT+?wy2=#f# zmBr5KwmG^+ZbcYXa1aXP0ziFHKj&&h@Uys9WVs~nP6wd~ zyRThxk6z{caFrLYE?F!d(;J_tT;cr3ctY&}rR1Sjs>szG4_1um?3G`|3D)&o6*vEu ztl$)tuB`aMvLNEZKYpdAHsE!bEykc88T@$GK{+pLJ|%;qn_E8vYJ&#AT46T zIBO15vJIxxTUXFc<%EZT&9( z<86E%tYAQjH?XvE7Dsd*?nN?V8?(L?15jY8MWR1Kv7=-{s(rJ3w;D8`JlR;qN;NZt z@~c78f#zOB7ttUYqfVTYJIw~PUJH&vvK#Tu19Is%Bak>JX`Ef*6X5kR9A`#xNU<|Y z_u^4^FzrRbQw~8{KYwODqf{*LOg}6m?kA&u49_uKFwfJ*`YN#UK**IT2j+r?SDFgfC|!G+t1jYgP{p0YgOk(BN8p#0kN58FSM}>R_IrH&2H%rb zmCN)hdep|yt9&!WZk{OLqu5Vj5hfX(GRyjWgVVw@lAVVO&dCi-%=Knx?)32dq!CWQ zD2gd+go_w(PB0&uZxEYg))YKN(FBHS3T^Bo<93S9c#pe|*lUcx{rt_|{^{O9duRWD z>>IWzc|UW&!Kj~M>XbG{OCKlc+t$Mkx@;@`sX^XgP5Q58{I}-+ukwCX( zzh?evs&6gzZB2b!SKl70ZyVwpgL|Z&KUUwK*npe%pO*TzroOF9a81=#Q?*6k9;t7S z)wd^hw_9ct46db~uc>eA>f1y0Z9{!~q`o~?-=0WtdSZ0f*X$jymp*459>l*Mw`_G2@_DFqu ztiGwa+fZ%kMb*>3q1w^i-msgHe~h`?P;G6fF=>R9qpO;+*(R6d+kwOaaQNv@W(aL+5@ zN#Ou=K#RZbPeNs|u@Fd&c(HRl16W?u!bmTU=PWSJK0uyuy_W z=*OV-@ZmejS#&qOy+rSs{89@GfPGTmz#?l2kE1c-I*ajTe<}SbCkIlgBQ!Zm5BsOl z=&g|c{$$Fx&1%h(cbkoB%`MVsWJiWU?uE?!t+R+Sl*W>=e8abDFqmFHKV z3t$lt3jo37#(zS31-M!I6Db0Q<7pNJoiL47n+=Rs8BXA|Gep}nw6W{S>vAg5vI~R+ z<19&ftI;T#o}CBbcsxly0v^j`o!+YOyxG9Iuwyg6EB2AO3(}^e?z-7pTMHfp>y0NH ze^L7r_h#h+uO3aT&)xyC`K&1NtB5mTO8XkyN2Dgx?yRE4TRaNsY6-8YWE*Gy>?KJ|v|NlV(75cTnBNMl?H(VY$xdqLi(bQ#nhX`=21i&xt| z5#DPhBrbG23X>syf&cU;s@LMh4PKy91?>qUPUT6&u^&`~Yb4V>qz)^Xi4mA2fRYp2 zgzqqevORQDacC1eL5ij%4jDO+g&u}l6{MFNekK&-0u`|X4h8!y*b*KI4|GxNoI6m& z8|C^g;jijCuvouQ7mXIkX}T+0Xi4S$U-E@|y3m8dLfr;-qRU{a!PBQSb-7YaF7;q$ zsUE@V&4JZxaw!WI76WAY6UZnluyde92wOw0-f9q25$P2B8~qY@dRTlFbpgh~2kLek zwV+k~i(76zSFY(Tx8auS`Qbgzl~eHOrvI@(L_o5W%Q)+v z)(RD;BNPMr<8`HokZ1EUWLpT1+eu{%r?9G&{slbiet6&DT7r?o*ptZ>J~&SXJ%hF* zq>7KV0jp;AhMv9CQO1@eP>e(fy3{6%@JSd`_C?^jRf`kOPMPwFSslIuULc8?*yDmh z!g!f0n!N6*Vs)yP4uTUjU}>ik%AY7+;!i)JEGtu|Fs$$j~e;=zm2>5zuWi}<$ps1wkb%yH=O^? zo8%4uJ)bO-{;alGLNqs_nat;=-4b?3_@yVH=3b-Mg8$tPn!@dV47-{8hNDRMpCY_k zshUfNHvUcZkrIT~g59(mj%lRr&J^u`+hHn$9RWckE1J@h>Cz$`EC5jX(#B`4@fAE> zAUE2qyjs$NOini$Xc_iJEBLRQZOd@oY(Iyy2269#Yty#AN!yqY-8FKQgVN6#b=vfg z8Z()%Q9(4S^4xupypXgY4Jn#g5un? zCKNYAZFdlZD50jgY}@6MwJibXKmcf7svclw@RyIvd8Zj}&sje#?@U0!3^uI-e!rZ8 zCgg^wP$#QA`_iw>8JHggb~8-7aqJn_+`hUi?h?6*ug$98sP9HRmDvFyjV2c|$`_m2 zDkEEEDlB78OA-%g9>yR~V%88FV~v*apT892GukibuvyHVJ-hdUBk2c;oj~*CC`FTF zjM{^$^Ij6A81$MFJd$mT?6?t~Of=&o@?=cwL8D36UFn`_>@+4ve z9?u2RAR!XCG0(*^x7Esq!5aBv_v2{L1MxH*Ax9O&4%-hZ*iMyY5Svq72PGxWg2fORLX{XxaG!cld~u!n(y z?Ck9ojl_VjG953_yDt&jz9@#_OulYzMdK}SuhNSI5diP+t|SYp#hjpXfQ>Vzd! z7Q8CCflq|YMU0-2DY{s-B4l@>ns$^RbIW;1HEFAhD6l`^D`#nt)I37PPlWgq0<#+B zg^^U8yVz+nghW22iOnnLKB9%76II88eHN%oajZC81P^q_2uPC z;lgZ?e2=KpO|K()dR1YaGJ13O!by)jZ4xx4ITP5Bmi;<6Xr2gcH&roxlKbir2Z-sE zF%1b!1AH$hqr3o01F;xeGgrnh>E&y#*|MgImB*1H6yl2bC#&*L!cBEgxE%3H+M<3o zY0D%&^A5mrip=i8$nt{_K-tf>0}{gmBCb;>$WN*)(c}`l#U)zacICCX7_l`~wZPyu zRo@J~_06!i9YI?s7Y=dYqC#)-N`=5ejF`Fi z@FfxxpaZL9sfmhGfRUY3I2zWNgg`PZ9$Vu#W`Lc0TAw<_@M^H(Fiaco;PE8FxZW77 z4M;&m&PF!XG2j@qN0Wwm*t$LoKbOJHV)Q9Sn__gyp~_kTg5;26O~Eob6+DyIZ52zQ z1n=r5L#TAh|N7Wyl&ef;{`Id0{BT5@3l)O_CZIlv#)GgMVa0!yYg7lmn7mA*E-Z^7`J=0CL6AU9?IG2i}&+^S(p z##h&EW48TIqk*_FvjDmmyh%|i z5)jCeuX_$V53N#!R}h|n?gi&rHcmGmJh;5PtP7)^WODYP7hOCUN8=R#tTxuy8xKnD zwt&`dqjH__m3kBoKtiJ!eUUVEk=SeCt`0&xxT@cUIZ>a&{eLx{BuKRCSuz}aSsU~A zfAi70yZ;-FM-T7z|1EspqT5|>HN8r+X!x!qLSW$`|7{rrr|CFLl0o`xYyC;RRd0X@ zTZW@XG&ZSCPBXa6@JHJXjP{eKIex40Eiw0u{>P>6V`Dy4x^4`lI4O!wy~ z*J>LGEKk}~VKPjjy9oKdx*F`rVD#)^U)?oO13XeQ<3M3?`scA;S?ZYTD=$H zD2@hE@H3u7fB!uZZ`#o?j1f$a-`6k1`@f#yi+VR1mIiSbj)FLzR|ju`{U}YLo3BV= zGYF2R9e5w?i!v8$L1q8d(f-96oF)X@YePqY3X%~1w`3TN!?UQM<5Xq`4PW*9vp74S zcCaT89GQel@1^N93Qi|TA}0$~dk|w4*1o(*E=PEhF#B^gj(HZj`w!GAJ}8yw1QYjT zwC&~*nc`yN%QsKgj7r1UsQ3UMaK5D7gHqS%}oh};vm6C&L+G$ zJlPAj(WmnQs=)8%mH>erQdDCU98ZWdA(Yo)_wYo2`Dby#xI0PGq@UrBU*b_Oxl9WS zA3)&DSm%BNk-Y~?x>gAWlmtiFT+V>BG>#9_VBDBAOiit2$=L%ts*XE>(U2_{2IL~@1+h+F9Nn)Cy?X*PrCW7M5y z90dd8rDHGyf*FqJfsbP>Jeibxn9Z*7UiL5!^`Ak01fZ;GhBw`F08+t6AP19^1W0$I zO4+9iE?038`dk;$1DRbN%_YPY8b&&vMD;WZC*AYP1kj=Ke}>in$57+_D_z-w|KHv( zzpK3cf8g&=Rs3E?+YM6qm&8TGkggdldj-B?*rhut%;(iF3*!!CxJq*gobgk?j?*F& z;>b5!!LWXYaYidmOml}idYBgx@w0-46`OeVN@>F3UtuFHLxQ4CL;c|U2rCUIU%I5@ z`eZt)yj3M@LBG7Z`U#=8$#+~D?^-HdsX@Fo<%Hxz)+1VS!tu4gJ&dq&s8sIi{%LR zeZV)SIl!JFQE?g{l!-_rLs6{8l2n&OtV?M+fHvzw8mt?z4wXHRkQ6c7n+!Ei5-?h? z#2FhGu+cjZs4-Fu6#MX}Wy~YDbo3E=mzuj%idxvmvg74IP~O> zdP?BJ?hWD&Qabhw#^5$|pQd}oMX|(|xsS^FMcFca%a`PbMkzA(L()7FCS-<4SjW{J z@(IBnCT1=djkW<^S`WuS!g>|mk!r5|fQ}zmR(bAD-jE#FQGE=OCyLNyUvwFd)>tS#Fl_$-3H?H-5%h{cWW(QLTvd-n+1yaB1*SDc}H0e z2bbYh+QxhH%l3!p3WLg}g4i03$c~7tnvf&~=h<)&T*T3( zjK{ST@bH}LcQx@jyRmuG3ycvS)ZjRX9yukFtWJL33Dn^l^T&JyJn8~PZx5$kTb=6mmk-4~_a@jr@MY`vv1ipM7D+j{$sLJiRL&g?Es zk?5$=KG64WdHL3e`&LX@YfJoF6EclLfh`*W_??5Ps$COg(E&AC*?RO=%z+l0yUN4C=w!Cmy9SdbarxUCWQO$t< z`Jcu~8cxpA&oj!bt`7S2XVl*sp%L!t>L^+5CW8U6$<^co{03>ImkbA2t0{=!Ta<;= zhWu3kqsJ_&OtylfS1ZBM$*((yN3YtayC(7>uT7yg zkGJ;@PT}l1ma|l^%NjnF2!e~gcJq8 zJZ!Ahg56eQZ5EyM?|*FQ!HwY*0;{V8-V^eE-i_f8%Q8 z%i5St|C<|+)?NFb=A(z}clJNG@$nom=(cwE&`5nKPv^h zAW2>cKa4R(-pw+pFF^x8${8*1tWf&w0Kg%>jPc@}jxkVES_brz?iBSeGFXL3^2?eS zJXzBLE9%utcxpVws#1F>PDJyswLwBoCgTL1MA8yg!GOW63g{-IUd-u@0Gx!pX2Q0C zmITlmrP3LY?ugGUSRPXybD#sBnlvTQ$knk>1VgFgI2v_S?#QAq&=!+>L2tK(4hmIX zF)T%yW=u3(hLc$zZ3tk-z5V66DEa4t10-Y7GL7wMe;&L7K-AGPULx?l@s$Y&U3UOh z#Cb)7GyE}X3ClJNdqghSNEkzz z3LM;rp1}MIl2xwr9)}mNp|cqBdncJpqI8VA6zxSwrBoIv80>b2Q3yK?pq6}fl+M(u zR72%H9G-bHt^!tB1*lywVTG|weI}JJR*Q&T>_GslGokzWfCY3Spm=|8VT&=>HI+_R zVG>S+q}_TR?6H`ug{DsPW8yrZb?7>_iB(=F zJv9ANE6jv`uOD1t_wXfmZG7cyF2WRC6)ZX7qGA$Lcvk`n!3$$j-~M#el~j~&1zE#J z94lsmV3XStQA(hZsfgSrfL2TbO{zdRbrHX&P(?V4=MiDB?nsPo)fWk%bG3$VMm$D) z3G_IJVrEK$xUeHnSQSfS@e54~slN>O1Nt~%9s|6f1ws_{`*@?muGmJba(M!x-fw+-SE?{%!Ft-B^RVbHf_HYph z3)kwwArlHRpWIW@5+N=OU=l+Ew2dX_`dfrfSHVj*`w_&-q&B1oW`1kVGGc)tjlpjN zdMN~nhv3phJ#`XgOfhvfXL7c6ItAv#9Vk%;#PpG%m-Kn_bk7r*4hM^BGG?ODuU<)Y zOb7sj801_Qb44C(oO9`TpYl~X-ce7x86aF~5JHO?%a~yottApHg#;Mb+5oza#*sCd zLq?(*R{%1I%5)G`D_KOS*N-kE;@cFnKsu+@Xb1FQZzq)FLPRh?ftf-CiH-CMv%tfc zhfp05ABF?7z{nJZFm2{;G}n+8Kp* zXPn*>*3;n;F*6yGy`Y1%3VDVK%o5NI-laAYHZCFM&Z4uWTtuIc zIEn<2PGb(Z01p|8xov5^STj*GXGqqD$>a46NOr~3kShjDJd(nRaq^K+@=`l4f;e-T zRh<(D?`{cY7>-5}B}3_QX+x^qa2FBLrYl8C3Bk7jb+u^Cs&E2TQKRkL6i6%^f2kPO)jDvO5-j90={@qI)>40$BNRlA?k zmHZSIR;@i96L{4t9buX$Bru$Q_y&}?VErTzrw3BhP-pH{qA*!ZK|S=bm=3G9nvJJA zs-l@c3Kbwer5SK|Mx(tEJEW^451A|pihPOIVp_F8)Gdbpm_vR=e?5TQi9oPDCN0;tA+Qb$O<< zdedY{jT)6}>UIwym^~Cyz%m4a4lE{(@Dm3zWqN1`N9xFJ2}l$&MbQayS#*%=G*oYFKl%ROUg*mQJDES&g!OEC$AzF(Uj>u55IE;Bj2!$rh zpnx8UuOv?jVyDg(v2Bqg*MvtZ!CZ94^dTHusaS)KDL@PWz+3ZVEJ}@8KMpkN74hGk zBsD|Y^Nxc#t2)Xe6s>ObX+~>;d;l)-_P-=EP9QI2AuRU4+J_X>Nsn3{BCYwN&TrI% z0AXo(kjF536VH+tAlikn*^wQ6r-yl z^jMNBxqky_lY(5@V}UxZh3;sSf(O6J6AH5AR@l@8w_rf!Lw z9;J3WPf*>2JukdED*zI(@@nA`3Z-U#kh8G^^NwC&U`R?<*^5dtkXnC=+7z|p7QgZX zDR(d+5Olw>7iwe`nnPYX{3OyknkY|J7V?Hgos?YmZuY_y4!>k&akvn+rSm z<6&GxM}#`bptSYnpHhh~*e$7hG-H5Rs{GB~o4EVF-3E$KuLte+rX6F* z7jU4Lbkhf6?*g}B?*Z1YqxG}slV||B)CY9ONh8$0W|8*TLS=gJUUuO9dsRgSl_i^k z5=M6%$RnSK)5z?B7+;^1EU3f7B#G$g+Qqm_C6tPhK#>|vo{ciIXLNJBDfA`dc&tiE zbKbW&rg!C1>4-t&sW*6^na*bLWEjD;k=XQ}wbI53Mk;OS7ZwAAC=JojOxRTCr@J_o z!98wmx%B~bjJpp+r+9tDdH9}q2$Qf19beTLvdRW?rA3?&zx77^MxPn<|Hg~~m$(0G zHP%~eclLj`@L6>IWm=T$xP;H+|BZ*a_+PDuYwLIX{}w(*{J%ohTI9;z^tf^pQ>;^U z;b5qx1rio?fp(Z)jk>bfHvaII9Zd&=wh8e79?UN30bN*08QM1~1ne%~Gk2{#z8vkiCP- zp79H>oN__`V=X;53MFg2c|66Mh-Sc0o zwcfh(|GAA1(sp^}#FjOO?bQ@4GNSRAsFe zJeFyV;S7{T?JP_`K%25L<0+LowO`}UQi(ln={?1#)^)U>ayOYIz-oAeZ?TIQ1;faO z2j^^=1dl3Fgapr^b5S8YU9Dhi!cE=jF$0=8BTvMPaOQ4yzasQg@&lzlsKH=?7vW;Q zz%M23aO}Y$Rf)^aYQNd27J^ZT;cu-SNuSy@Un9@rMW-Z-rLHM{3-hMFD|8eOjJYO8 z4BHN`I>QN>gOa_l*ltfL3fbd2ln@LZ??q4+Kpt;Oc*FRNFJAZ#rHl7<-3)^xt57Cd zd=RiUX?Sm=x(K9)m_z~I5tX8Pu6#*EFxk$8R|XXpxXT9WFQ&ucRjy(s--O}w&$%kS zJ;b1qUWj+Xi~qAI|3_`$b;E(p=Ksx&jmBCo{`;fmo&VQud}f{hNCV8<6t#jTtx;kl45A_buwCO~_VQQYNM>}o4t@~=YSU?SJZ5;Yah;$=?6$ zs&|;3!hE^?^Y-5U_VayRBD@G=S{704c=sP~c27=E+P`e?o$ejH!h#cVo@}GQgb8S! zq6cqYTg706ZV~wB&F%}U6#O%V)2yf2_Un^ev+ZH(7TrBQK0LNd@>+|6Z%(#f?Fv}a z6a%>!FizhbADpzGZ;L)rsON`JUH0hIo&%vP{Y$3%^aawkef2gsRqqry5D9| ztLtX*{lk+}w=f`ZR`w)RR@|1-l^BBMXoS)eg-1hJM)Z;u{q@5oI>{UICT>&|I%~Lt z-$~I^R{*Re6r=Rb@OIsJ6@C=26f`K42Z6!rHiHiD2MkZ3Ulj|#x=bczoc@FNix@6vD60{1}L{Wn!I!G3^m{C^aSv`FVFbLG=q7?}|{#unr=tEIS2`CwL>R z?So~yPu?jce7Go4ah9;1lGLyzWfr246)S)0>)12|GB}9YFSfT-GcpBMLY6aVcxJ%b zBb#S5DkF3GIO(BR6AV#U`J9|j;?V~>v0~mJj1~og5S)JVKxD|ol&VmgL!&o+>`NEJ zbL%-}yTEJ`8nDdakP%lWLUXh(8$^>e=B4zG5EuA7Xp9MCz)>S7d+v)6FY2Q!s0&NT zsm`dwb??ICb}@H~0r%w~JR{pWvKCO|L)mZw56IdY?cfaw9=%=2-fwRdbY(zyhK7-9 z$MJ_qIH2Kee9C6E9PvQGjYs5ZHW)+$Y0oOa8_-y&PlFWdlI`;(;=Hv)AjvS5>? z5xup;0QSpIKQYiY3HI$aeB;n&?e^z-{v8rXcvE(u1fLWY#c-{#ZjFzhViC7=^W*1d zx`Nn{e`RNb>`L`t;*9P;AYiWlHc>8wCFt-%uq4ecfW_0TA)#=lLBaX){hx6m-b+tN z-nFTySH}aUw_Sd3te+ukaC$vUo~#wgkklzUD!!#+_)PaN){~KsK#U)gd*ya*td|AE zi^e?hLX{PPjA8SPqO%bF`^r^sm!9fD&VwzhNV(;V6p9mM@4z02Oobx_&S_6E@hxM( zTk}U`)`jV71hcw99cXwmqvl1&+_F=Y>Vh!8DkHMk`IIW!pcB49q>8xBqo9+up~4kbv>=&TW=N60Wr`Idl(Ogu~sS+9P6?ifbdNc4`NWZ3vCf@aV| zcfUDo1@I2Tf%7IZdUL$W@r;x4 zS00b5v)#{xR}6}|wSX-+Bbn8kg)bI|VR?R!CW(JCsIi(OvKzl@Qhu*geG_zQo#&<_^3)2;ZvS)B5orp`qE>X% z65I=mDjn%222QBxb6Hha`7C57k`pmSeA3hN{BI0#2E=OsOM8J^T_}QBz8QD*Pw2J! zNsB?>{A+;G-9xEyC$NZiEA(vzI8}CutZapwSRpR9!VRq8aji?v+cTDgL9PUqX1x*o z6jUl)Ian3FuEINR9kWpUB%j(b{M(vlwWE*Y7z4CRWL=mEK<7?4oHc_$!}bVoL_>ol zni~~nCPkvl-5a4F6CS%RFq8Tawf9PE5SwBC%}K!bb?$Q1CY_zS>Zsso84JY9=2Q)} zV6{G-fxojE2^?h6bkzDo&C#RoOe(JKfvfZ@<{x z-~JV~k9E!!M!(zty?1)LdyJ~hdeeCPe0%5bhc92k^H#m#(G~NWtken>mxjXdy84)2 zGzhP#XAS!Wx{kG{W1i}U**_+4ZK^5yI7%+fO_IZwop68w$6zMU;rxqv#c=&mrz8Si zp;udee$Dll@|Wl^^~n<$-Rd@UOJYXxG~}j2D?tS||4h zQq~YE_NFy(bS-UQaM|j@TstFxcq*k)m0U?iP_Vj#DsT4UB;6+JT$k#OV`)9ROG$!p z8Lk3(O)d4%bORp9n-FGI?vyEg>O$T7)`)rcxs}hN^k2DFT!RJ7vHxm4Tyyh(1Npzp z|9vYTO7tkmHm89wZbLPX6QzAbe0{(6x}=mS$77+1B_sWqb?Awlt(7 zoYi{1KT-|Pd@f{nmM&#;cZEg+L}vG4L*u2QfSYYsIra$ce=CXm)^S?1S2sP8+phK>}669YuYP+0A- z-#fp~#|y&hHHp`@SYE!uaM1y9)4D#4N5Dw60sACO6E_tm`xb z^JxOO;2`OKu=f}Sn4Yk6gx1-%`zQiY2xpJJ*C~PaN|NiL=}@;_2^&doK>mf9)eXKtIG>v zIN~8r<^hY%@0H#wS)sv-p_{!)U3N_iGUyhRicm8 zDxZO^xzU&*rs1cppsCRz8kmzOw<)E=RhK#9X;ta>>WXRTVWO!Va^cQ1%Dm*dAoGt8afzqKKh^{8WKZhDKD<*Yiq zb8mFlF&V=TU)TtHfgFOwZ0uMcpV2>=K4Q>fPE*`bxr0aj&B5Of4u3hw_rr$=%7egz z1JtUZ!Nr)nnnN9}&ep3liIx_n#gr7>mQc<=zJ5a5VqW2LY-$X|%hsQ&-XR(*uE^$A zD7Fzu5F&rzU-;gUUy(q|$qIsopV!}j{kci@tvM{yeBmg5Ac<6+UVcawoUI?yvgiI6 zccA^)e+QkvZLTi13+5YG8>Ku()(R(RmWsq?nCXLLH5pStaJ{s`JcVR?#}XJLs?$}Z zbv2?rHi<}ty&hiBD1m(zWpL&A<7k*%XerVNPOg-k28ZfI{e)~Qa5r#zF9Vh^GNu03 z^hGaT@<@)S!4HyTY}y}hQ&{^rWwq})YG1ht7ns^wN@}*ncoP{KCxk^pinWsL0Q*GCp)D z6f=}Yo1V)HoL+?Qcy2Ik!a_^$w*AX!V_1Khk`zaT_e zfxd8==x6TD#C2{E3L=LUt1~_Q5Im2&dri&eA{sev;Opz&sizgXkA07l-3-chg2OzorA8X8oiNOxFBD()1B-$sGB05bh2sS%mBeV@ui z58b^}DgI}u6c^S1UDNcJKC|_IkD43n8~ON;8+ZO6xA8Icf2R6xQO)0sXwS2)fQ?{_ z+s}7u@EguxAXW+&*m?0H+2KLF`v?B01-rv>cBM3nQEI3IyAiS~isiUyP|3YaMxEY| z)67>*TP>g9acI;Pp{Tj+C6IAo{wkzp)Gvt;$D<5R6oa@UUx_Efa1?@AxLnZ68!(P0 zv%ee|;ek_AUWTGH1!R)NPegR4$xY-^aCEIAYUVYxo{qB96BmtjA%?Z)4TU|N5rWWg zXQp0?Sjry#jDBR*?#E}-N#u?0=K?7V=|?dJz6^wAD4q)k$l63_s3HWO`N-7_%i(cR z{_d3F_y}7(1~=#v%9fVR0*$H_DqKy(`!pxFYP_}Sj zyW)wSWyccqT~1OL=VaPhTY6LFqqO0h_GAikIq||jrEfVUAJ-;j?q*OXYWbEl6VV8B zo?-0qcNqGf-sC4u#(+dR=xyxnJ7X-auYlnMAW+AS{YZNze|n^#KBk2wAAE`pyhZlM z`$A80KakO=WSAL5pG!)4)&ZQy9JUnV5KdMqxsd_x1sREFm`8GSl~FcQQea~iVAR5- z8W1LPqtcuu))F8^)0+i2`TtKuF zI|#j3!IUFMoQIPhuwg`F=IlsE zjFgG)B|_2FnyK8CV*U)1d$e@r76Z{F_ATjRO8IMRRDT$8JiB}f3-R_&Q$jOTH z5Pd`?&%`?{QyUm;VdJDQB}FH-O&e_&Q$N<5pi?e{2WPSP|MA#JDm3&=24SS<)gE+`!3 z?seKj*-j)wRxtM-@b`qJmR`g}-`J4ySx+5i z!XOQMPEbSa1N%u{hM0iduI0yhi<}$NATEocF0IZFlNqKn{>$%!H?QA0-Z{S84bI^n z@LhqpG`R0bXT)2~I}N3W7Si4*ih8M3YcFUIJwrS)i&_3pUfU3_d4rH9{M(+d0Sugz zBz%)DX^er1TWBfMkOnOWu8`}t|eMyHlocJ5bdH~PRPuoMckL9)$iX<>#X9gnF55(C}x=G;60Wp$Ii6N z*`g9Dbj9L6{P9H=HnVG!LSl-h}1@_dk1xhp+NRA^3D%9kg zVwCl9l@nA#pipI8?c&bPBB^_dQ?1a@w@-8`&BR4&UaE<$K<(;ezSKpvb;FGFGnd}u zjp_)m%8Dqx-*xcTTxfN)H*=fT96kVNVm$AsB;&cF-8DRL+ctw07!!VoJp3u3#C;yy zB-y^=B786By?FMVqMus#iFlSS+LBgE0tbw$a%cQ@Z4cQ6B35iuvImvhL8eh)>jjmg zLC4Gm-lxn|3^0cB4wF8fi+Bwo>awc!JerETX033MRy@imR3u>VsxN(5WG|aVHDoRa zdH9D>p?Q;G(qut$g+-kTg3P|Gmotp8Yk{b^MS57{fHFJOc#%<&pPSc zPa!JfP!3nA({p36ws|1A(cZLgJ}SdV(I1Mbi+YyO0YYhn>XvYFl~;gqx(~%@b+yY- zncNm2-JUN)Nbv6|sp);jzauzth7`NiM-^FQ*T>>7vh($r>H3h&HOMVC#`T)OdR_We z?h8JLsLN++YN@-SL$o+lqXp@W0za9XPw;m7pCVrB^GRx~HLTPM_GJav>HVLnC-0TA z(7JsgNr4ZkMvN%ldWIHDNY%Xdee-4tgX;!|9&M?iB^5eR4Nn{rwOYcT*NTsHERVqy z1GQwIoA(GoLF+{s9Jnz^y`BI%cco#UxHPG7-v62JGv5c{8S1Pk1UZdICfFc@&q^oi zhEvCwOk5gW8o5RgCR$a%NQ@dXS}7B8EFWP2eJ-fLX)@_{drX;Zkss9>b(%?>S)V0jxkNpoqIx=D^C_6=MChz6O0$avbm8{&*ARb z+~K)HWH_~488lqjsu-3OwQ9bQXC4^d>ZkZ~IbYs88TN$W$C?SLP0MW61MKFc^KYPC z;=TfTq`2~{V^ZJ=lUXU&ICqJ8yr>gC8CXbU6DQub3bChK)pGH2!T5o2lI8IGnmQq= z5VdvOM3YWKmo)R3i6`k@_eQUb3kNC(CF75&OmdFatbgztquk&HBU6x*Q;kmh_FaS1h-Vxo+} zhz442wfq)TS+b4Ei4Q_-;ADxGbq0WlC&9myPECXhi7{!LUP&RjN{uUL21$L=Y&g2Q z46iUh5ODnI**VTU26yOE zSN2Z6!y0b@(ttV2ZbTd@%jj*SRboWpEI8V*ZxE-Mqp|VPQgJiU9Yo>8b4w!|wcy#x zFAa?FM?$jHx0l*-u#YJ`4Yt&Y{P140BUvT2^FY>@{7M zDmxQH@(hW|m4-|U=L1l{H^uDKY^JC^gZTH`&3834l9aU^-h?_vDZb3)P1u`XsGyHA z#b=|C=&DjwNUCck2_TH@;Jq_uH;VJ;ZZ>wJTJGvveZxB-#Mz1_(KA#1$rOTCuYHcY z(v{1IB5QSyc0xR|P$;*9^PWuiY^z6mMJ z<_4Em64+Z4z`Nk5z$=UiaM;bP9;a4 zrj-}K<)^GtZKS;MNag(l;iBXz!eI1=RB~pIT&+4^{7P$>i)#yi1#bb%G?@s9X`EcP zeGtmd2~3-cyKfwI@`fWtj_Afkq@vPe30583)IWf$_g8iD&X>{`K{SVYejHXvZ?Abi zTO^w0&oU^wkuc9?K3b#Y4`Y6c#?n#PJ+~Zf<39TVVDxmU>a=vshE=Cl9>(c7VJpR$ z#a?wCKhwH!=IZfOe}Ux6)&vA54_P?#qf>KCyRjdc1vbQpnXtb!jVF`Euiwox_6z=>Oi~!AX1n@Z_|>I>ljkWpP7>o4qqh zK3Japn|$HPcQxJ~EEY|QhU9f<=B}G@6P$}7opO*}VrJ|g^?ipl(10q@$jXT+y=rh@ zqt%OaJ$RqXYxsVar-8pqMwjKB2ptD}-3-c(PgA+zs&X9cwqF)R@lt!TrHr?hBMPqF5Fc~s#x9P>9~2&p?0}n^(^kn{{wPfv=QI03gQr;Rui{~J6x0W(hx_=zNr@p zdpiI#nU2^M$GM0#sy`<;!Nfcbt^9^*OKF;EY60;g5M(j(Pdtj#b9~2fKTOMceGp@J z1yRR~(9)HRRB6(eLmm{#l!GEwv6dhO)*cL#q3KVdP4!@=>qbuCy0c=GJGP0bW19w} zCt{BJ8rSxS@3|#(6hW|uQh|r^Su~kUfi`vqHcR)?d78bg;5W2(U(6~Hy|umkf)66r z8|1DjUg;uM(59;yi{LqRSo$b0Zz#*-9cMMV2~3MEY&?3gGCq|VeHU91WFB+)UQv*=Mb2zx-ZN7=jxnW1ezrMd z0&(fQZ=#R&HaiEm+wcviv)wK#>YHc)UqGP0eR2}K-L9+L?ku}wAMq^^ zA+%Y$EYA+I@?hd*#?rb0d$m+0{!;HI<11&;`OVw1!-GjHho>33J5h)HT3`^6#hp{U zCL}%qlFx~%9ItxaTs8XPdJXI4pC!4?p7Pn2gu02GB(DMQZ@vR$exs{Pq3dcWA;^@y9ea|2KL3d3SbnJ0^6$r;s;*Z~$O^BLzi z^HPAmX>W|SuXHiVef>l|_>3kjYC@FMkhk(=a6(LGMwA&ATAWP&s*RAHmGzsLqO4zRLoGOn*MwO_{dlJ=ByEGDBE=7;rkz|F*|FJ3 zsMnk28)#V!G4ntxp;TY6BEc2CwFO)e=&BFzk!Iob1sp^aJPPSG9oMYjO!*rnVfI7E z?$C(mz&@3^BS`hV(Pfj!k60<>p$$U)Drek6BRR0Ge9)Cj?y$7wbjiN0!H<_3=aMZI z6H%WS;D`YIGPzKi_F%9omY#nz_!NEo?40gVbQV&Jo11-<)Ao4U^@|?Xsnfs`sV5c( zQFeD`ZE=B2GDj8cpZY~ay_sqn3w&WzOZlWfpDh99 z5&t@>VsD({yy!kVM)5skMr720T(p4A8G8IhR@+(M8Tw>lP_lqNIq&GOLmnJ?V|;Wq z3@IQ?8gwGcDNI3dd*;=+Tmu$Pqjs1DPc0#6=}R2XhFC<_uxahCD^34I{#JF3!9za`qv`}oTD3EKYH3ECF# z2>DTNS%uZMLS(F^xYg*&$j;Rdu538*){eoYPudQ_ta2U35x+W#{ef&gOd^ZgDS62+ zEK$8OJK1HGV})YOeJ5=x#)?q(_+h_kZU6{Rqx4q0<-G7F9j1Zl8e5WEgtB}H$TUEc zWHmriC4Yf8=5$$&8167HE#)!FEdXj>!mo81A^R|HBHG?Fgd3y5vzmDr*fG~&x9KhHSBEsPh!LZ$Kt9HaDAvQ5W#;I5a8QgPIqL#F+ zj3y2jStm*SiRHdQCrn96_(z{*p-8lgMt@mR>}rowv_<7BwKNRdz1s%eom zRK);3a)_ptkvNP2sZP=;LI}?!(r_zdx<;0d9gbSwFo{tWWMu-J;>(+!?5ZTc}Lm|r}SGiQ2v>NppN|p*I_mqXN3@jCh_Qvp~I5tM%xm4p^ zp>0;D=Ws5}r(IH0I)YWX5=!_u_7KM3nS=qF9Vi}p7!3b3&5{Qbpxm}WacO7I?~`8-NW%Oe3+ zX-o!k2Gq|?7b#q2%~|*QZ!f<$h5zQdvkmINI972zurzdp>wsWvu(uFxjq#S=6;C)IV=4c80rX#=)hxDgoyNdIF{ zh+(ku8q(;*@;OwyzmMgUG{W9pOD~{cCJYnh#*-hOHWi*i`t`F#agh{he8X0U zxJb!V@Dmn~(Bjy-mQ$FSH$`ZflW^2fxO;9c31^yv8E|ApZN+4)E#jBTS3)Yq>eMJZ zVYAv4Dj_}d{O_ca@B)~O?~4@{up9Z`3GvXZz)YyW^wI3>`yyf18HG_??&jnpt|g|5aW#t0|--1asX)(?w|=UOHS zMnh9!(IX9b7g{?TJqZ;8z}`S#bTX)c0MeFYNT^_7f@=29tPN^7G~ezVBa8@c1wJd7 zM!XmlCpY65phtZ2C<#NOQN<(w_lF(``4#Yk2CDhk$kYo)nl`z@eYwR;X`Q|D?RGn- z$cksXL7WT1tQ?}6iwK+StNz;tEnZ=4tgjb?({HQY-x#Zz}gNgT-gulwDZUD4y!=ARdf|NV22r5(xKDS!2B|{{lS%RWi;i10? z^AKPdK{JYng3~0+V7!`7RPAXrnNQprRBBB#bP%Ij4@9KBl>^KV1vKSNW0t0r6e7X& zhS^V4ov=#|QgKy*a#>6h&zZKq7B0U)dQk*#($`K^Xg4>U^Hu#UlmE3(%<%GAV5{@L z9_$_*JTmjY?sgCM@AJRj!AH&i8f-WLEVUQKWu@zbhq(FOs@GK}nahEy*mH zuBx017Be5VHkR*|;4;`i(pMwr{at2$rLJ!?{p$(&c(R#SpB+9|&j@P(icY&cEv)hK z%gGJv92itKp4ZJ1>ugTh2&bI!b(yTOD>wN?XOR_jt6eXJEW_Yd6UfQ|)k+_$@65V6 zWO2KlYAJt>dNO;g97}l?S*^r^Y_fW{w~aUm`V?(1fxTVQ?aw5eLh$tzG8sn4FYl)kM5@+}Tv#NUfA) zQ){Kk*3kM!u8%#7F{f<7HZK|BV=b~#W$FC zQCS%KvJgLCO7cZz`i=w}#p*1dh|vZ9LpL5NqQf5|^U2I6o*>HFM%_qqMV;5M7v5APoCDzl%{S-ucQ zogoFZ2CS9ZoIAWW1XrE`DzJ2Fzk;Z^68yQg`U3f%I`u#o81 zve>E9uFPepoDelK+LbP@Zlw1oOEAa4ruPfe%oXt7P_nt&@>H!HU<%&cX98O@6PR+{ z(r~Otp8X58a+Nv1^2&PtsO1uOm5wGK(RGmwLujbiOv<%H-mUxOR%<4=D$<&WUIl4c zl;+Ah23E*+wNzrH`ud;y^hl1zgw^90nI1`HI+jk7q%b0Drb^Q85Njn$Dicqa&X!aF zu_9TL2Bu|GCTSNet0zplmQj|hL^lRC`J$2}6*{snGgXp<5mdT#CQQQh{8G{-(ddg? z%!>eZ!418_*OJ31HioIxtjfAnK*_qcln>HNy#67YQCwG+=t12<52=0prx1|p-f=Dp zjbY?e%EfY8#yZKA3c=l0sJdcd+SIWh*a?yxCOJx$B!%EC%9W(|^LtB~WZzJmv)X9- zr28aDda~h~jNR`o6_UamS0zNMF@GNHmy%3KIjufdN+D$kfA+*eDpz=)UPyMeIA_n2 zd4-D2eD~Rf%F_y!i3BCdg{%ZZiYcCvMreVB;a#T_GU|Mm971JDd_>Y6UJFjWV`vc8 zOPu4*kwds|RlKvjHay!uWp*2d*A)b8V-{T1XVM=sQ;iECE*3@Q(G3gq`=m9tO^AvG zLbPxvtx=DV!F}qQKYQvLg}B`(u(?lQ<1&_&)b>7&jpI|Hr^{cjl*Xopnn3I1KABAp zx!TEW6fFNEr?jb78OTy)iEU~k;(dCX`}8&@M^T;RrltkpMl;>$_HOt2ZfyL!&v&yp z-%W)fp9=^zRJH~i?#h6(!gje&gL9t-=T_3-)ZhvJOv!Kxdz1T=I7Lfed`cXRQ>jRd zvjXM4&yMp&XUAFoKKaj%_sMjAC&_e#CBpACrHn_ZfZeekuPrd3{{IOn-{xK8lypZKU|Q&+W59?iNkg zqvzr&mg~+k@{rm0eLkMM%*UhNC75|JoRsR;Qu7qCha9PSHZaWF%+li;!tXv+&jw&F zFBs$BYwjNB!pa0bE+&5MEIu2C`kx}L&jw(2XBmE!#aSZHkGiCKwx4_rWn7$cx@*Mi z(YRN6Vv3ccGn-41TU!!LX7MY1klW zy0SHGf&jDIqXC%Wwd(x15`7h(by^HOdOikdq-N^sc>vlW$`Je9KQ+NH@#dqn{U-YS7|L$(5*R|Hab8x@@ckw~W{De>H zV5|ymu~(d(6eA>lI>E(-*PX5>^cTXYCay~;DCb~VOXk*_69SuiJ$oh z7N%dj41*%Q82*^e)5{iri)W=N*ks};JE7Xk0EGIJ`D|RB-%Dzy3Lc5{d_`?>%Hz<* z>CY#$FpqGgu)=gzcz3AsC*k{CXdo5qp;%bHjG6*tf&3r^5&|@ilkgP7ASTf;Ec}Pn zdkBK$(GfRBztrBw*)8<;U0G-0ZFE*PwTs)B+V^Fh-Nw|u*QaK1=7~eCP_9*bF4F}` zKM5I^p+%Yuz5oh&-{IzGR#U3kQb*Vjx}H~3X^A9SdLfb3te`J%oQch3f*^wq$-CO) zpI@K+gR^n;PoDpL{OXqzD13mP;l(0w2oPQajRmi>0|{t23k_(;*rb4$D&w$a0(DY& z0OSXgY(No^e)|h9$ZvGA$qKu)=7KnLF! z7u~lFpMc!Eq0e}X;u?0jIq0y6L=;$`u`E$(@g4kZj)znqHZShti&7-JN!%?uP1Eh~vlC?|qgE zfnyA~yii!%fSgLZU)6EKejs8t$vCFrhgmqllw>mGCp@1|vuLbR(HsJm=%EFi7pfV} zyzckNC{(6Dt;`#_kVhyqWq(>uLAjo-;uj1^{h7Fi8rI@p9`8`s65`f4h?=nx?)iv6 zFCU=<&b#L(T#r8kH?f*subv-SFdo(8I}f&sCVDc&4v%1GMP= zZ|}gq|Jgg(y}$ptgAcMCVxie=KrA%yL*sC{I|i9?PP9P5VSw(TjDn$cN0bRDnnJnD zESsf=4Fn)w9%7?!PhP$Dp1geKy*YmJ>@RpW z-o$fnaEU?E54ZY#(H(gk`H055ZD^?DLshazktH7hSMb{~9;6R}ET`-~2P_{kufq_| zjwIyVsuBX?+K35y5{@wr-|&w{A1n4hu)OnGdoa3Kw~qz;zjv^2-v4(W?eF&P_x~My zPA6d&41+8<+Y;8~5+f*j$1qF>NyMC>8t0MiW040EG+=9wQr zdmV4~o(0ngHk9{YL6QXj`d2L8^f6x;HZ$b+?JM#AKQ8b^dk{~y#?c_0k{j$#FMsh~ zgy_TL{S;0?Mjm^w=jZU=dm+kP?Rt$DKfQi&wF{j0EQ$Y#;rn2qsdq#S&|l+8IK%s9 z_rR&l(|D-9zW@PievTuNMde>A{X9+QD4hj^cXWlhxZ1-AtFSrTv-o-ng8fh(&&@1i zDDv}0G=$fKYL`jsm5nv9-@eFO^J@%#d4iCM3pnk8DcsQr!dk8Pi$1MFkM+>SU zkme`zVMGyxptxuRTBR})pz!9^+vnbs8I0x%s=)8%RskD(#n#erJiNV0vv7i~{2UBk zy)C}{cX`2Rki=;`%J9eEqv%=I4PhYP6o>_aD)8V&`}|O!YEv0pQnoKq|Thk zySp{EW8wL~n#q^;S#bV$d%Jtq`M=k@xBt3}&x5}_oTtgd^Jw}ooL&iZ-6g*Nb)04w zN%;0}FEA1!(+FS{W~e!)lb?6#633Jsld!=yNs-;$8chY0&JXfBl|MDzq3{+R;n zvBlXCw&5U)lN&Vnk{Ej^mC$rig04!aGo@yODVcM4<9I+GJJ4JsY+tmCsC?p}^>D$P zMe4~d3JrGzBZVECUABYs6#q8lZx{$NP>nv3pMJmD+yYU>Q5t>euZN9h6JzCIqpXa9 zH-k%Pq=AosT_H^_yS%?VmMH|1bReO%uOE$riQ9?Fe<`M2S>EzR|gourcxn!IYxv0^Q67 zD2%EtGVY3)H1f@nH$j(>`K-~!3o}}`hIn}-{%+97`TkS-si6N^{GlC9qxJh(r2pw0 z^ep<{>pr@t|99{?9gTx`;p4NdN$_C@y+L-y;q(GX&yn}|@fO?3!S}!KcXnIeaj&y` zzbpSxA7lUDh|{l~#gp--`dFm@>GUlA@1Wbc*Z9@u+5T6JARXYPbhu&9>F$%gAaAD_h3cu-VdiYfX`M>-JlGJJ3#0nyYQ#18NFVq5d^6dDBUw+DA zG(fXt3>%-!r)OJfJWmE;F@HmSB<@Z9(wiHChuLt54E5Po_+c=f55qnVQUNjWdnf;R zecXTg*W;)E`TXTihoY11U)%VKGuc=?| zt3Qdz0ISbJNm{>Ae}09bx&8GUB3Qtvwm4<)d`c>U{xBTntzf)wbm=r-j!2DRy+!wx z;`QgIN%x<-`{?ICVb;S<_kri(qeuHo_^{Or4Yj!dp{n;9Fig3kMiEQw#Kg$N2Ojj~emY>$m@S`s(#h z{gdOjC;ew{UqWNkEANV;b8d-x9O05?CzY5jjwAvD{_QvBM}Pb6@Q_XO{@t5JvwWC4 zVa}7BV!1P46be6(M$#O>k$)Md*%9g%$N0?~o+Bf8B)J)ELpH%ZZvpUdY=S4<(&4&8 z3R3~rd4@?AF2evrBO#}gVt&Gi4S(gWEruEmGP1K^9#$C5QJ9pO>J&T0*JBQ3G-K1~ z^BV;sx%;VdtARY1gp@J|{^>v){s`Ox?w1!aAa1AZBU*zYWjF&5c+>d@Z)ZoUn|Irf z+xsoi_0B=N)9&G~oo>6^X?Ni3cz$tlv(ssJfuxDXej$_jogL0+IlkEe)_-`^+v^_e ze|vDyk;TT*`Ru(HTm=!?P#=2TT@+8Xx7P`VDNBsFV~5^g3zzGM8#HtY=3@?k!YhZE zHqVXr0mAPAx_W&MM#CX$Wn~U!SbTHR%+k37= z&?4Yt^w(iDq7*Ti6*Fxv+F+FMV1Tl-G#rb)Hwn>>CQ2v2QC1j%NWbNK@cGZLU;LJD zKov>U5=VT$AXd-270fwpx7%kMSWzA-&ZFJ-`u#)QYRR^5cu2NI!7O?>d*8myCgTUQ z_d5*79lh<8aOEvUTpkqFkof#eWD99Q$bN{ZV8#a&$+qV>Dxt5Ftp;qm2Cd(d4x4 zJ;@6H6TpP)gmdcL4P{W*SGLpr_VF&6ui~EA_0o3{EGc~Lc01k&kwFtqjYp5$y>99? zI)|O^VfS%U);GuP?Myr$uQL!n{+-Oi>pp(;D4#-4nZm)h7%oAqe#_f?tj-9C+}9JAD_QCZoNHucKqher{D6h2NaVXQ%VIhbdA}P z`-5t>y}w_El8gbKWNAEG@WgX8qi~uM zN3lo;3!53XgwE*jq5Ml4j^^W>v=(GlkYK?hrJf8OA;`5j045mJG9Tp@?dI7y8ek@# zpQ7xq^K;=4!xr)w{XJ)giZjGG%U~kZn&6CRU>Kr`_=i!9vOX`|>z}?Zs5FPJpy<~D z5-6e|L&|l6%otBEooWFYHMT0h7M5`}1nYjk z3d@<-JLv5{I;4LAdSv)FNQUPOVmWur&?AO3Jb##fKfLPo(8`u6-41pFC)^a-{GA;D zN;p93vGoMww+P0fz(AXu7x8#=c1aGnE{lz&j(8@}U2=qSn&i6$FE%`98ZL-C2Dkj& zV%Hb*amoMELv<6jKloXA|7+`i4)*TtfA8euT7O~WllH~Aur3}fy8k=aJ23q}I=$Wd z`@g&RI6^fQQJE;DQp@{giaH-Q%aSsxC_8(vJ#Gi*1NrLNd;(%s%X<-{#-imtL9BX; z#+x6q7BEXcl76D){V+!c3Qj_b!{0F6W`~EOA@9ih`Q~kw@UI4?&%t6%;eJc09ER;7 zyl(g~3?I3B?;OA4FTK?Jd7On>v28B5E#g#;<3llU>h}c3%s(3)N4Mj+jb_`8^P8kG$SKMJx)@e3f8f$Fv=c(?g1BL=kMUsG1{3 zfw+uCY=))p59s0t{w?|-7>Ynj=l?v!lbVwt;Q6T-fw2#C1Il<`d%b2moT9Q%O@PF3 zUfk4GFrMd`t*Cn_U3fHx>44#MoPvme&ZbsgBUr(&(rw@S3JbSGEEo2f#b{9LcrCbkWv`%6y=S-T4+!PPIhR9i_h7W6E9O3JbSn*Nx!9xkA7;Jm1pN|fJ zNHp}6cPf$9Q}u~ol=aWf&dfk%x5%!#&VP(CNIIgs;r||W9@+Lk`+N8N-(7s9ZS_rR z#)x!q1{gjjH`$gFEdTAJ-W{YrO!=l*Y_wrx^g;e=na^hL?Ps`s?Wdyv1Xo7`N&LZ4 z+AujOUZ8xdKP3-Ps>3EIO~HeR3E?h?EQa^>POmI;-4cOC0H9OuWr)+b z43Z(b8>wv#r|KYbOE!2cZXHoN&+*&-wgbN3asR8%z^~iOo4y=qg}i$X0x+H21dpF2A6RJ z5I;Kgg(d{;_kiGPcy{EY7EzD|4=c++@sx3o;?D4n5)}noRXNgW zyfcW$sMOwx->Hc;NI7)mry1Hvp)Hd+8a>bmCNY=_Rjg=`?!`XP@eXL;Aw?aA76z=} zhl8Bex4av7#-r)zXiB$cMd+Po{b`UH)ea)3GEB61yb6*d|K%?~t0C**L_b2F%L07I z0(d+|Z^jVQUI472om?5r*>nbg`NyPww-< z1woXNXkjsPr(y@lpCezzl0)w!{`use>0=W&C8R!Vh#z8X54>k#hU#Tb&tj7h!ob)r_JWBCvvbzMxnj7Jj(DHyEF6aBY9ob7HB|^<-+rP0ZI*D!q68f z=QQz=TR?lv#@}W7^ViDoF%<~Z<+;h0{(@sw0&(+gBg$gc4L64281sK^>yx^AC>!3U z>j{jrq;T|2wPBgjk(>XKR;K_8h4@k@j4`&FQse(ras#v$O!N@D+v=V&fLdp732Iz` zRUDrDyoeXYzuV%{LCC*)grZy-VQkwi*(or2?cA;cOI%0O-JY+uz@dTw5*%WvkB#*) zO~~M;A>RtG>$h|z87CA0@CB56&Baiv-eU7o+yH%H_MD37gCG=&;DaurfYK9%b)#QQ z$3-T1Ng;lQ!&1BD0@i}=_>inO#4bw7^L*zz4BqYVe#5jb5hWm%ODuAexORet3yk~> z$!XjdCrv+ow_w%vV=iC*Vp_Nk;zs@$9%8hC_RCjv-SM{n^woKX1p`+Owwj~nA^-T~`HSOc3ObMSZiw0mn)uz3G87|_osBweN)0${ zjQkU#m@;(OM@Q4r)v#7`KZ-+@OHq?Wd9$V3fL8HZBt9GWf${^Jchis$_=HBqXwhEF z(@tuDoogQz4297YU@eDr^VPFV=n#g=Y=~n`>7Ki?17|11yh81J|I9zar$qmQNdC$Dal5D1I1DAEp#`<{@6x_b=wrFnstxLAD)oBSJOskEnYxgKcb~ml^rW zwEqPX8(O&HIn+VNv@JUX2fW$?r0(SH;WV}p!?)S!c#G7<)WWxqyIV8TDB(V zLIeChfFAb6?;R=OP`z$Z5YG84e7M{06wjoQ4!`Jj%+U<0+ae&d6q4!=J+Sn@8 z7BnK92)pX?#IPxS{G{97QNkv`oBc;^D7r;1dt7q&kuidJkjf#von1!L58OV&bTm(B zo*3_~-R-t}yIUz0*+CaQ^6txD!|e9dx6tkmj_48>7E3`3J@>SPn-v#AfPU^h@n`xt z>3=dj-=q@|DfyT4|Jm>D?ce+V+`*@G{WoX?wBY=At^cFly}kSM{|-K->o0WBc+0vj z1}s?r{rv;e{-^us(S7{aJNeKpA7H?ZR6GsCaE8CFdp^z1hpa{Ag`qGPYk5!MX%P&{ zs6xeLox=R*1bCzrHBw=sm*=~B3;=nf-aqn1xn6X}k*e}YQB)O!BO#BHMd)xr<=gE7 zt7TcTx*$bs*dGd$CHiq5O~r%q%2aSH44m>>{6OA};^j`EC?K~Bgx=QHmgb5v3zA@h zy5xU_AiqyCAisWLCe7;K`e)&~jk^75%i{{Uj_e5t>^J}7;W?kp7hxA*=)+%oCBzx{XE@aUxWY54@*&Rz+dSiJwnTPJAR#Db z&1CW)z2mzzT(g#F4)yTl?;^*gH#eWYo5t5<(az$E%%?~O(9-6En-a;4fxQ*A4r;j6)Y)go?W#=QG9Xq_QKJp5->4NZ6%X~m%y9{As@U7c9)6CDX#Zj0I zfU6E0WPR39$_lNe+O0oGLcCofX^gPypJ_ZLqZ|*voi~NDNFOU2cPDrUBYYpQs3%N$ zXqc(jFvi`afq(qu+at~gBS1jCv(bTQ+i#lF`uM3OFS=N3oF)A+5CySO`?v4b(G3HJdGjQaTWAPw?c%MZ8G6I$|=yP zk7M)Cn4tCHtyLqPpNo-jQXl2{Uxwvdp^ zGUBRU_{(0xwquepWXBbmo`eUKQW9)FEE=+fwis>NR7>{HX~vZmM46_zPeBS=(t~&@ za*-3MKk^U@iZb+6ApT7hf}BdpJ{aU?&)5rpbH7(cuRSnI7h@LR^!I$6$vhxZ3(Gf} z_)58j(W?Z*VI$M99*5Dt7{}+qxIf4~05ZY}pe=UGn_Vc|Aa5}VF91%kQ3S@ThhK5t zHT;Wnd2d#$YF;hB$7636jU8wU-wzxvMJ~kOikU=l(3q5gNi%gQ30w0_%@)u=A+;P;#)O7l;Q!SYJ+J>OXX+O)vQ;qV0}~sS_=~d%KsVc!<18EG#v`_RBbX%QpAn zkn&75^}A#OF!tPSd2qZW(GU$1&)?4jv@%dem(2$Kb2w|JpJ|Lm|NbbB?Xe{x#nStX zqmv_OntBAZEG`Cnp2Y9MsY1uqT~j98J4PmvQ6>v8$EHh{h=SuhB0@tPnc{aJSZSgW zrx+tZd3q+LPI-pXz{W8;w%3@XIXi_ThT$}eMmK$ILzuiz(U+;^87MAasL0*&@WyWtPbN{u z>{1D~FITyzqy8Fes-7@G?}lTTJlmqR*h(ZFic!4Xk0N57gU% zv0J4cunrHyu~M9l41@^^I8UKLvdduVbyKUBKyg?k?>p@1JFlme8KKeA*a3^I{m(eU z)R&)|_4*<{b@~53**&Z#1uWwK5BB!0{C~aP{r%5fd>s70bO75d_fP524G};q49GT_ z1^LwqtEl^&VYy0FI5lO3mL@%j*`T>`k)v6YBLZ8Ha16Gs7hkHhB2*Y-utf_ck29x$ zb+x{lIG{-sj%FR>)5U}hjO|wB24m1J>EUw?ojWTNDjWm1MT;+F=+zR3F%w(vPGQ=4>8JHkUxS&0*G_Yu8DFg=LHO_Q*bF}w-FJ=Ig;fh6%8uZb46BB`*MgZwc4ox zbxU*!T(XO`hw@SjY3WiG4Vgt<|2oSrKef<6->f-Q%4HiprFeyqQw(@LQAat$8**5m zUzBk!$0h}ul|>VMfi42H9KgH3Tjc*1^Z#gPy`Bl!BKyCCj%okj1EJtP|I=N3R#n1Z zh0|f2ICSu|uLx(j2ss)m20*@MzY!+DQpkLCm96PTz3;sq!Pz__i0SrW$Mt;0W=iCz z>CYnge-ie4y~@6n;$$`N?&SNU@?L5;|GoEl?cEpc|Jlv@2Ef((zk9I%$dv!Pk1!_O z{r+-rNJ0-((VSiW&$q7Kpc+{U=P)=12_nJKfk`e`DGLnR!kGISgjvNi- zA<%rNf)X_R+4GylV{Wu~vxW&P+nSApk?%PL1rwnvP8*7W9rUFD+i$i!`SyqBFQ2^m zNAaHF?>EmdQjelQnceiGX`g#Yr8%tD?}FQfCO~mOj>m=43~kRsfGAu8oi%~{}sh!V%?jD(jo_V8N6N4 zH6W}YShIE+>(tKBj+DdG^b0R|dVf;9dP{HG&tD$DdGqRx3&229Hx1L3faIQh9**x$ zu}~u;6y9D0!aDNLgCQOw6wL#3O(Ow(@VL9b|E=#J19yV5f18KN%~KMG!{O2h%f%!$ zTLyW}wb>MkR`?+h3B&jorWZmE@X0K@(Wvfcr?#$8mFt4)@@Q8=%SwjTm|BhB@u>{@ZMqkOWIqCF{0SGzR%a4gUh6mvuvnG z@9iHnn`DC=p$)Ql-ho|>ws+!Bb1{(-_WyNhO&@^PIK?_=F2@AR7eID1jwVrtq{Uo> zLLqkAIm4B}y2~ua`51)LJ6;RqmmADmw}W&LMg4J@k)dwQ6`?7JX6es2p8xCA-}GuV z@_uf2u}ZlRoXek@75QQay*R8lOzJn!S>yfz8bcw+G&VzDlW3I3Og{27iNjXQVsl4c zhEaPP)=T`Lz}bkJl$)!#bd6dlnl(8`SEOugphad2O*7>0DXcks!-&LZC5S?#6#oDD zIJMPKsE^^rNO1q+k%@p^4EL1fVksZDJmG`YTo(KO0E@^B?0PE*i!<&zPf&Q#!`-u| zAEt{}xPdjfQuDTGhp~DM^et;)#nawd4Y{cpVaba27Ov>2=u>(RwLJOYI!?wzzj@|T zS@$sxu{^zm_~H_x^uzb&a|l(WEBr9H%M+NRLmtb3#|?iv2bOGl5no({(Y+;s~#-7@eu8Cn)Ss&`bxNj6ZmoWQ}VTpF7t zQH~1dNmEw9@8w%CZw6gii|yFOD|TeVnLU<(NWJMC69kN5owLj09f*95ubW%i=DkSb z`HaXh%&+C`Zb@g^#akJTo;liR%M;MCwl4`Vi>&GF*WW^sb#}v&en1skPbr22^S)1vx`% zKOJ0#lb|t$WlN8G9km2`CQ9D5C!OJOsF*XZVe$C&tU|Q%hQA;Vk!s8no0ZfY>S=(( zB%T2!m>AT^U04`YaB-_VK1Rj=`*Hj2-(HB-`S=Ol=Jm7i6CN-GST{e*oe{n0V(32)hwqp6v<2t39X>&ncRT)N1IZS~VX5V*IwPB>wB?6552#_BNNGg!dT>?J_ z<0k-u-^H}ta4Yx+uHj@KtbSaKpjODj114Q1Xak+5g6=7#$0~+{y@+8CUI$ZhL;n}- zXsp}P2VY`E!)2J5NrhJ4oanB&X%n<>%8`F%_sX%btL{YFnfXtv6>3QaaRuVsxEN3v zhxq)TP$+FQ4F%~`C>y4yUGcYf29xwfc@L=+#eSs%J5>Ht3xD?bXZP%rG+Qv(NFKC^ ze{LhQTf&qG{v~)IEWZC=$MT;)3-13P?H%-N|KHtv`=7h`+}8bn_0@ho>ww?o{r`d+ zf8I?lV*ycgk!?UrlAx8{AU@Zfz2*9#-`ocaukIZN<7_cmQ|?r3c{imXlD4D^Z}S~y z>WlR{su*LK0M}RcRD-=xuGccqUkct!D%oAjv#g+Rtw*W2zqq7kkX|9Y2MeY5k|jWW z!RDd9E*Pr-W8FZ1HmqLNVxVLx?sN;3*$*tUa&@c-mRiY;A^Q@_<+8;fn}VQJwfx!7 zfeH(QH2}Dxje!e@rlrAJi2XS%4i;~PS~uC|4zR5c$|+dQYwd>1H)o+OLgk{dMZ)J< zvs<-HxTRIKtQ78KQ5W!4y5+(>b5&x~@I@RrQa^kCl}a|*ufT$xHaSKet^QH}(43@cW_hK*WV z)M6WMKBqux*R4yE_hz|`hP!-)rG~ww^S18L zP-8XH@JF%UaN)IL!=Xpj_#%uriV>Tp94klrFn83F)*Ut;FSPL}t8#DYVL{44>3(z;3pcVxfnEM@T=bsw|$ZQEhwQcl=30A|&PTn0{F2JJ|p z35Qw4gr*EmbDqTeL(eBvI|aNt^Whc!Y8Y0%dh|0Zir89ltmVhHwJ#V%oD69#`Xdk` zV|b{et$l1eBb~`JQg9e}ngc$D!2}jB{4fI~K%FTdLIG(i|4~9#yQwrk@7uF^)^Ls{ zB-z_D^a3Tp)Yfxwc=qDh*({F^1;t``VpzFmfb|smu()3ML108xyluu5ZoY`Kt;p@R z*sd{SS~|1>=4L`Pktn7qj6{hx=FuK;>o!$e-6FsvtK#1yL({-ubAVGvT}=js63n?H zfMx$`0VL{e%*d1CI=7)S%0zPtU(PDZvD)O+r(|G0aY`S381o@h8XxBeKZG{ylkFG` zv;`0bC>N1&1vJ-}A;zo0R9YN95J&Q*O*cxFWMM8f<9pl{W)x90Ho@(fo{3pfDeo`; zKW`fgY|9mYFQeDnE3Wk=qAhYO46OGQWKrF8L=kW!frOF<7a_-5d-C$>@eA*7zZ}1L ze*D(!`Wg>xLO7o;Z-e{L=zp?L9sYk^3-HDKzit1$dvG8B?JhnJ{$Iv_FJb5Dv5Zkl zQb4MU0k_ES*A5u3+ENn^=c$3^!LcR3;eE6e4>n>_y$aWCYF`W9*;Kp+)!efhbs6

Si52T34(t;HK;8TE9Tnng{M?uuHk-+MKtug+=Ume;OkQzih5t4su22Tvpe3 zbTv@4#5s)@FTF#%HI}?I@;Y;>dZ=dn(FY7@FniT(dEIvB%VpMGpj(w?|55>=vGL_L z0~=xHOL3(&XKH9V6zxN*X?)m>a z_>}l;T1>(1q;&-{{4Sd5`8CVayJAkbx+z{4ly#+f#UwYt9?dSybeX_y&jw;BALuBg zCQ1_$Ey016Fkgityhs`Z-L2cSa51T^pa!F7Zu6<{k>!#nTD5cZ&(-Rc_ zQIpYvk+;vzl)8#xQJrp8y#i{X+QVp&ky>Gy@jQb{r)ie7P+hjla7t3U-7!!~Mq$CI z(7k+_8QCH%$6M0ir{k%cOeYTOb&UjS)?0{f`qiZ$<6FWFkoo+ zmXe)DeEv`P`w`0teVa<7nAfAyS}TI%t5ekM(D#3J=0yESMLy-0#A@5F5qxf%uYO$T z|L{DRMZM1YiGReW`uu+cugvqmd(hpxKmYII^WZNJ=V|irJeocXr&q`aT!Ikyz#EN& zcj4nhj&<_@FBuNKcr@DD-rn|JQz7r!58jj4&%Iu|;|-JODoi}QkQqm);PU3vh%Z~b zbRK14n;GSk%P95Ic$8gJ;+oWZJwG2u1MgWp38JYNOo!eixbe=Rei{zxRw15eUJ{~5 zGSP+DV*WPvLT?SX7cOJ+83aRROkc`F=h$i7Q3(Cz3a;$Ly)AGA!Z~`;`zlT zY-Vo~LFq6UTyAmZc&LdcCe&{_C$my-98E*MAK88~4aVNn97x-E>kwsa&wDb)R6fAK zqb4*%Ai;l9H;oVg`3ry&z`K|_AKw6kuP@_qn8p(Y+HIi}+}ZJ-2UG8dXz&gV`C!$y zw)*{KkoKctzwZG#+y3|G!$Ysw>a8oU+wOKTt=j&>PWNG_=XH9Ad)>oM*ZWsEh5x+c z4>RxIx1k-8gbf77BrV2%Uka&NPF0F?8GD7}nl-ghbe z{15(fP7mADF#CQx*C61e)L2w%j_UL#ExDg;d3f$@VX`DSFdi4q>|2=D!_I-%**)Cd zKZMzO??#V4OrY!ubOaa|zXSB6#S%!q+wP!q>tH+|!qNidVl;72GHwx-ER-~_YU{J^#B!Tu!Ku-k#LBiOoo z@SoDyli`rJIgUr62=R;)aeCp0ES&Q0V_o`CB=QwkM!2V;9i#{0hZ$yr#jB$rgAIQ^ z$BDu~a61)@g~#^V7O=k+V+A;OcfC&cuzPU0d!UT<=V%Ip%&x=W9YgkQ7LH(-{5TGQ zL?vc>k7av%FnzDnIqdEp_V$(bp7JWSaKJM(_MBh9Pnr=r82#MddD8Y?gp>1maskD6 z2v~uzxtt~8DEiRCoy~q=bl08E0wA7f=1!wX(R0uX#@E43N(A64j)vjT9O)xD(%!?~ zf!71%hW{QZBmE)4IU^x?_Ur|#b1uU%j(IenGF{DQk%aH(xS%kDXTeo8^xn+V%kvwv z&jY2;E@DP!54u(Qg#A7mF`WMzPLt@Jcl<6K1Bp9?m-qpk3mJL(bSYsyodWKlG422G zF5~!}g`E4v2)d8FUhlB;_;61h!E^L5#CsfVWstyQ=o@2bI5JG z9MB*zj=_8k+#tZO3&XkyrxbTi6deTP@hpi4+z3s?9P^$s=6%Ac108BrI7MgN`~p@8 ziJgsOEyQuyIhWzJchdI$6Xu6LT0e$E9AylI(fcV0FXAMMsjX+hGz!P?I79s`Vdzt! zaBxC~bgNEJ@Td*&FdNXTctoV~DQsZEUBXDhnW#8%nHvDoeol)D#o##iCIGq!Rs`@5 z2th=l1E>pt4;&~VADciB19*9ZJ;7uEQ$Vc0FK!r`KmrLTfC>+ih{y)j#laMm#Jh~b zBuECA=>C`_KqbaER4fh0qxLMG&5^*8!yu(!hKGIm6feor82yC;YX+G3Jc;lGpgP0h zxXZ^h6KdGZ@hrGNx=g+O*ONC-|N7(&?&JAn%AFCf62RFq%r21>MuSWE0p~s(eBo$5 zh7%p#+zXs@3JxCg~pe9KLx|l_y)rv zX0$zI_jy%hsIz1~K>MX3A}|rJ7;kgcf$&L^Z)3!w!ls8<4jg%L7~w!8!OIgrgq=V8 zVFxDC_MXFjEUKeL%pjxf8)UpK`;}xijwQ2^Zc`P!1-c0(x@W}WDU~(&00%lB4|Nbx zm6qK8*ajfXFEcd13X*5>^|a+`i#;6BNiRq)M1vao84uWDY0n zg7~+SXR&~ixofgbafbNu0BC~{~6v~$H`D>4=IM)5Ig5GyNGg>fEAIiZD`^7h@d|W z*`tV2>IUeMsDkZL8zN909bV9m=3Vqv%3^ebyr8b|2n`Z+wQg>EUui>-ZS-7ipa2e> zYRy(Y$e}2%NMazR<$HE{?$oM5RbcCc3G%pDjea1=UgGdz5z{P2qKQ0PI7F()Yj_pr zk&k!2r%Fg1B}%?Ufm;#{q;C@Pl1V`11I%XzJ8khP_JP7(AXA736}J>1iqg%gI2#db z#p%mC0X3E40q_Ie25yBGpXJI97KgjMwar-+#Vx96q_X$or8R)>>+ zFM>0&l9@^N#wRcshrx82DUhk1oB|!b_B`-|#7~GE9-@586=*N>VJnVT-iAXr6ab+y zQ~>e1`Q1Zt_M7Ihxm|#679c-}%zzenkTZ_ZCT`_ldk!1dQWIR&)&T0do$P5S>b<)9 z5oV{#`n8YIuH4<<1Mf+i0+|)GV;BwbpbI|$O>cXzh-G4~i}-6|Lt!OLnv!fXtnv9g z)xfWQ2nloOMZl$ut>i>7!Eu~wevJ828Q5yUQsf>`At0+-%JOlskw{U5e6U9qWEm-L1uykO_lojCO*PnuBw53^K!bAxuGx zo~Hsav=_1k*}VX`eC%ulje?N(w?V|l8^>6nA)9DzL(%P3!TpTEIgG;;F&k!%%4gZO z1z&cJOaqYIZdM11+KK@f^_8nJ(rI4><7miMMece1G6jN{Hne__{&ZU1RHM=XLmrv5-#w@4K4l4TU^~v*BFQ2^dj{p1Q_~l#puDm>vH+v{}Z%_tPNj{%G;^OoAGDhBgp0Xq+ zlznWjz&8P?<@7|b7Nr?zS4d^Wkx|W(4wEbWs4qnlWL^cK#m=Fk{8^4zSceZFQNzF! zS9zV}$%^{Z>J~IYCL7QmR@XPFlWf9#zIYx5)luhBJgoriQ;ukWHA+t6Q-) zzHG*NQ6lJ=f)mNhOUX?R2KFgO;F%!%iEf!KzLDa~rkshx%fuVLfKjVE<@WjlFx$|@ ze4NGB?*5+IpPXyLGhb|;KT+{amYMBmg{vdTi$Z((Xm*Rn<{#@Z`h8(uzC&zAS0%WjqC3?BBX-qSo)WiK{pHPLlD z=Scm1?wj*p5!&!Zf%gO6TPE90-}}lT2U4e&qFwzo?O9k(w50AQ5Q}kOXI9gCLplOw1ZEx1uv-=81eI!=NyV-KBWg1k6OW|i!eh&tTfE3c6#qtcRHF+u;~Pv;lVM3 zRZ-BJD*N5B+o$mkoB1fA6ud@w(O$T@m*x-Ip6QFEu5xg#oeBbyTVxefb*F35)B>PY zv~}UmF7@rbGxoufebf|psHp~6bsgcr%fN+Eoad8s02asbL9;KM7Bc(r#04$JWCxJp zOcF53A-WVm*IBu?v-BsvZIx}}LB z?Fj4O+oe@(A~|X+}%(uA{Ucb zytlJxLX0=I?1*WvhRd{tgvzdq$)c6da6SNm4mnPN0Ac3n&)pb{5$+rZj!vQ}U)3o+ zIjh!$4S{DA#|}QL)&LwBuJ^vI=uS^RvmyaM4-CU4NdY;F5Ri1CO&fU#qTJTG&;Y0{ zVdI6SS6PTRoGHn^r7~HA7Lhu&P1VJgv}wx@aN8PTdwZ!d7K*sikzun72S#S)Aihn# z7%lgUmY%2SJomFhCo1#}+WEUx z!)}x@tY!+8gQFhTqadw3+$?(ux}ay11`GUlPAU1>uA1rpYC81?HvMh*Pvdw7ph*3e zP0iJd_v+zGON>oT;IMn=Gaw6+jg9|243oN3__&Rww-1Y%d|G27!tP~LGx_SP^sbj8 zx82#?92&G9wP&*Iij-QVG`61$R;HNa_8LTF6S_lSs>+#CH~)wUvU)8k#^jDuQZ6H% z;V8T&X-%0P0ulQfbaDfz)&1Pcrm^rxIn}9!*Mi?a#K8ss(zTD1 zypG(Lp0Y7p%2Uz8C!>Mok6tm?whB47@UoF(IEPFPF>AG>crz2Ke=KiwMvkL-L-SeY zn8wd!LsN1daGROa5(hSZHnm74hxVrCq#oeq5zZH@bo0rryT0a;pLfs4{x8#a)A)Mo zKK8Y;6-R&1r8O0BV$&~Oe?ZrEl)=l;Hv&i<%EaQlAvog=k+=<#6)Tt?{A}tbvyvmp zfmOnl*z>A$!s;64MM~j%j7(nAWM-UGC>R=f?rrM~KrwC?>bQB2;z+I2*phm)JU;lw zc?j)&t`(F0EmZEDhd_HwOBnkSU?>WiOo5E#7dr#R4F zya|V7E2}&zU&ZbJhED;8Ggap;L-!b`DY|sOVdw@FI)2{3p=3f4e==OV00 z?&Cmfq``(9f=m3%WjrAjO!%p$Az!6}Y}n$3BhNUFEY1C8#lmQ%3hqf@lpL3f_qZJe zMg=8jhI#=h7l9u2X3$4Qq2#O6OB_OL&lu(6W1k@Zew@Qzi4;{Spf#YB64pGH-H(gSQWx&ZBGlNr1p0FwsO}Zgbw5MzwiG?9XiHI*eXBRF zy1ataa)G#F)Rs}|OLR{dqf1ddv7?jG1Tq*x!@9g)NYna%PAO+yK-!k)foD68E!5@K z6$@=>-PWmGavQT?=is(i51MBE?Cp z-EA!~?`7`XtQPB^zv^~!9P^4Y#X;Zi_~>Q15$;gCl9xhLql3B@DDatu$QPE%w|}LmJ}U@ zs+-+EP@07wrOkf+!;%)DRF1{52*b+F`4?f_WSRP-UxXYs{2B0yM~G7*2z8*uaTX^b z=d_>b;uZ0cl6+>@sxue{YmO3101|Hfe^}V?qQpczbeWT(542wp5O(xbN0)zR=J#cs zJuhNY5hvQ%{wwETL9R;)T%}l-JODy=B-6^#0|FaQxR|b-C&&?cNy;3oKN9$WtI4j@ zUpJL0l$JH7s+S9=N_;GBxNf3sEwdJz*<9)8BMz~QBEfvdF_pt%u28@>-i8^)qTdYA zHFE%pHEx62ic~44a_iomIBw0GQ*`Wf<|HiFNuVoz~l`259kB&Tx{FYV44kV5^#)7$@ zjw()hr6uf=%2Rsh#RK4W%lj71QqDQDVDPqIN?QaOTpCHEZML8jeJ6>h0a)vo?{|F( zmt<6P<+>f!5O%&d!GJOplyHYK2qG1i5!X|3;~%AYbXe_*{5Dx$g;&!yaz35y3UR%- zl9`C0z#_QW2BT_dNpWtMpdn`J-Fc1Peyi!?87((SN5n5L%`g%qhILyd>UvqiAREDc zpgcmHnu^RxCQ2w5rG6eJ?|d9zdrFpoTY+QIZ=>7kbQYEAK^f;&S2d_{6WtQHZ9u;X zgK?2zP=_tWNaTppAu`~hVs2f*0f;Enf{V~IcZe{c+vX@=-ipz#1^CJ{Sd(F^OpIRs z^5TWtf#H^n&sQ-$uNT5CsTICWhDe~}Ya6F8?C}d_F^8R{Q)^|y_{?EzHtZTv+^G=k ztX`|zYxVYv&W1fl$sYmIC(+rA~4e$f+X)whb&p@QK0Mz|o z6qi?09FYl#bBAHzfiRqKma#~SXKO(-g%fGmZMNuduW3Tz1V?BQaqSk~A)hocGGx8<)VnR!+^d*4q z2iSCpWrTQcOkb2b-^P4P6kS&JiY+T_(QS?ZXLeS`hbe8gwz;awjBSe)Wc;?83$tea z{NCLOZKYzB;fT(8KXz1m_p~$4`)2-Xg|2|7^2J!4-XSdyL?>!{Z=%L6k*Ux5y z_UvZ;K7h;Y931S?U-%e*yPe(6!M}C)c6$e%9@2bx-aUBq2+FVD_2Lh#LXbe0NgQWY z$Qv?YgJ&(gNs8Au zT(Wys%&kuO-kAact^5P;B)RcYOiUSm$P&QQH1}xHXQ2Z^hjj;C!{y@>d_rCTH_HZ`*ZMhDsn_5}8gWcJu`;zsLn&(ZW^9_z$dokwY(27Ce zZ0`uq^FEvYTF~PlbA4eChlFGnBvo3IO@VU(&IttmMq@2=V^3klYMT(p>uRpK{9fk=j;Wo2&!S+W}d%*{qcU z%{pZCkG9Y)Ph07=U<^O*;e0D_7PM6W*$LPOWK=`mZ-NMs;d_KG)+eu@YJ4U&K(CeR z=JcG&({7R2tg{kIGOLwgoYUQUP%a46pAF7(=1V~Ob8At4zaN+W55)ieAQ_%-MEUn` zi}Zh;gZ-|p|J!@Cf3N?$gO5WK_e!MK%++?Y8&cY_)~-Fzkm!h4|HV0ypI(N8cl=%; zR2vaUmU;@`pB53KS(Nf@N@^k^7nKu4R0UNWCPOy5Pb+)9W@ zEA*TV@czkr8V}wjaWJ@i_Cui|^u0#dzG!>f-yeCsZoAj+cD7sI_IF+nzT!7(5r1ws z#dw?ex9?OyeTXS_Epb4AF>wwaF^r z=!gg47lc?bNuzQY`>*MJr)nLg>0F#)#FLE6y}Ra;JKjg12j_n(=sn&%!r7Czh>k^a zBoxRLV+VSEJRRRCs#XfZL}ajP{%es0$}{R5CH8%aZYkX_%EoAvoQ6 z9mGOO+%zGg7Lsd5bL2-Y&!=g~nW_O6MTb8I@U&F`fRF1LI`kiDyBUL1Vu}aoxS5w} zUteOTfFleZtLz1OKS?j(1(mu$6HORMe-fr?a1kO}H6=a~ywZz91yH#`A-9x6E?=0u zA%XR>E&f?F#bX%xAK}ZVL+>NM|K!VdsUvs?8{mQW3lOp>yYVos3FnNzzKjN!l$?%J z33Gk{P93k@Y5-wOX(ga9owT*Z3%S8c#($X8*wZvi&R`pS@4=Tt1&-nlqI8Z1en2@5 zffS@L%x>q&7^>TzX#QoE&CW)C0G(A{~9+`PQnp)#5`pTBsyIuxVl-I{+p;NMv)V zylRqmwk6Z^Wd&aw6`Fpanqv?V?OtPS*ivElA@ss|%XLRdtrWGiv8IExACE@bAQ!a< zoY{03Btzm6;snKnK5P>N+!3@z9Xx9+d`osKFx){j3C8%cxA(1lIl#+Qe7M)$-QCY00u=(D0T%UN@CsPx zqI@(=;8FMSy0?ESZJbF|Vjb}F;t%>?HUU0`D&h&A2fB#$M9gXIo^H@G& z&4|o3ga-;%+Up&3^%BHLUB+W<^Up!d)?k+IseNvixX-Z9*RIWegu5i6bb(@$oSpcYAXAr{P7AfvoGvh8d=h9_8;bZc*OoZf}2I z&TJZE0!nuGgjYpuL3oozBVLOAo-B?jps!=tEC8tFhEN|%^!B@Q{bm<^7z6Agn08+v zw1LdzR3^YB8-|?(0=ZCeiRH`R!JNWmCq>)Yyue;}uUiy=_W!j)!&7WoeOLN9r|p|N$bRJGK>QlV7jURuu)Ggva~6KcKuDL; zzIZYTroizgE?Xa4!@yXmX%J-L*?Z^X^!->@IG_@H7G(J-fWry(60`U1{xCeB=WV?H z3H6}Q@R3uy!2&XzpxH$drjq_3)A1JAiSru|B)&<1KI=;}qDGUWh_VxDG+|$fVLF9J zA2Rfvh*EEkN#=kUi{=jTY}itza78?TS7*Au1kV1LGm4XdCOswjN4t1i=nQstu;LDk zLeV6^p&48S$&vr;?Mvmc2J-d!{ zfx<6DB9A#XWW$pAv@p10&NK<%&!dEcy%Z)`y1d|fr#JDO#4-?GV~-eC0INABV5_e@ znA2IisNYmIE|oBvz2C`_U=X@s^zr1)lc&c&K7VoCdVBKh_|2P74v^`=e+el5PvJC7 z*g2WCSkwi=B5x6$sJYR$zsz6>k(FWamB107ru{6LhmJ9_^luFEMSLN40yHuJLAC8Q z-q5;)X%6J)Kfiu~qSGZ{MAOhC3C!e#eEmz{b;Cs0=HU)Fk{T~SC^01!HFKFB%L-3K zOGj`jqW@}_6~tTSYDaOg0j;zoMvcXxktZ`uzon!ig4MAt&2i0`g=w{^4MUsog$MAzG_ZC5gNB&!?>g5#Tqu!Q8$TL&9 zIv(?u>Q8`s9^HT_Fi9KquUHxiC;-1v%|XwL;o>V&l8IMsLBz=UR0kmHbwtUAKZ|A| zsxr|mEXaR2+<&Q2!0$E>I-*x5$2xvVA}PCrErE+(Qyp9Ush zQ*yIbyU<^u3~Fe#Qw_7+ifyUW{6v!IuBuI_KzxqHV8h8Rhg+gyae?|0g zd3xiKjZ|CAh;$0@>bHV^{Z^c84blA0H3%2Yw$?5aLeXb?4T7lR8wn!BU(o^t6ctEo ziK;e(Hm`gJ@xya4iDAGXxWWNFud^m_5eLAlE!1SCO`63s}zZ=*9n~74esL` z&;NDmEHxU>(@SZ3!ys=n{FO2Sd7CyXDQZxN3M}6rjf0D{0fOTR{%pVf<@M_~$8X>E z(V6V+$&;U7zxDo~m%n~<{1d(X`PH-IrpggYj-bL|8})bgfQ)6a3}M88f&HOLx=z4g zp2e_(j!r-%U=qlcSQIv>pr9)YC=tsZO_M#BEufs;M?cYiA92NJu|Xj%WfZ{2fP@Z- z1CI|R0&3^fn9xMDDM-Up8f;@6UWMZ$`R4h{A78aR&Z~Fif7K8dam`d|Aw=6gSpnwy zf}Q~%D^|_yF{C&OFR-76+K&+2-nWG`b)+j8oF^-$gG`@|&DE^G3uFsf)HcOQbHJ9HhE>&2pf%9S2iA*yW(h?Hw)J z!>JpOPLcMs*!JM8;$#GIQpF@6=wR3SN z7h4;|Da`av70S6tZulW02lV2V_?o6tp8KaI+3tPQBlrU^91(oWXSvWyN6c z1V_2g+rw04J#2&xzEF(iK@+rtJ3?HyJSI^=l`q9i;VB+RVs457p#YhtGcUAOb*&I( z1@6Z6Ryxd%)4H<>YEQ@5ek;z2TdAB_X_4h;mtGBwbI_ipp+N~`krfX@t~?Pv3<%GgO)t6Fs>M^Yn6gYB@568uEodaqD*lX4e__-38SR1 zzZN#DiehpyBzu`7PwhZ#y236FX;=A!ehBOu>i>?LLut8o9F<~ECEI*1*9QTkA!`Iq@ zBUbyZDg0jKF(Q;TMC5KBqNW^efDXOrVj3smDgM}j0h~!(dqUfwB~Cp|lSmghc+Ynk z4+)!cWDqY6_Z&>~!9FpkhlMTgFdSRY#CS37kY;RcGfTuI9lCT8`GqqrIcpML29wax z96a!Tr2A$?B%}zz(nBa5w!If3Es}_R2~P{RAXPr|_1ggAO7dK!QuvbkdeqkA==FOQ z{USxTw4Pn~I!e|svnJdjBT@Hte4_wVOS84MLg#8$$Hwf5je-Ko9xyD$>1vD2-&?B5 zxUt9Bia>hM=!OL9*}hdeKg}Lr{UHqVSDcme0Ac&MhB((y^VHe#< zqg#gcWhgJ;E(5l{%>uGIzX`Lp_vAc{lXD(rI1X;)5am`b1~mxS#5iO>y5O85J1BQ@ z9-ORE5{}`JfO!X3aWtfX;yj1(HJl`{U=wQYay}gDnpm?gR~}5Qqx+aCn1tN)_yTnkZt(Z1~p_o`Kc+V zJclkFL9X>t+f~?oLnkIQ5N*d9mI?!Fzrk+J8Y7>N5yyodVVB%Mhu%kM19fzt+p6vU zQ}Uu#&ZS|+K%Fqq{AsjqK- zq+6&;tJPzu z^aUpmQpkrs-2lR=xNAP1UI4zLH50u6j>mk?FHlO<-}Lwe#UV55>?;a{KKhmP`$a%M zaUh$~Llr%iqW#NX^KB(w9}1Ka@m=*&0tjgSb+)Cy>ZiaJPXd#j;div66|eea-sdiW zfgs4@?Bgf>4aWv&IggYO&oLM~#SLuuhzk8ol_38EnBf@+em6Pnc*Lf>Eo26DQl{Z1 zX1pSjK}&I=wj~C`KTs)=3DY`bL@n{dT*m^=qP>OSESdcX)oP-s2?J>i zYCsj3vhlG0F#>kWObS(`1mRIP&&v9x5mo}7N*wA8DAs%z-ZTc|^pKj+9az;*p<{0M z`)uyv2oRFvWXd-k^pKp0^BW8vX|shLAHn}i)|HA?&X$4P2WUFxZLOPOxny<4rM8s8 z;HK2#rtqW2bUq%ZM{2fYPZ0f(R{qPXlUXA0*1Q zI1s)rlu#xG^)=$ozoMCnH7zlhqUKp8dNbq=NYz~qD~P(BX{M+s3y8FZK|o{M-=@%$ z9PKjCIbKW8DsADqYP5&VizCQLB&SaL@T3}QA3q_?#M~MNL8XQe0h+3wUA^2i znsnAJLv~Cf28cYdViB8Tq`qxO`&|w;ndbVCu_hpSEzYHX5;+T&Zap6-lPaN~HbnfP?^_TYYSSZt6SOsRU z6e{NwN%vQd*CqI352zGELc0jSAyEka!Z`@^^8Ch&h6Q}Mv6cxMIdDUsl*1oI(_vrW z0IGz?;Y5)a^dRL=xd~6Sfuaz)Y*8DmpB60y8PHo=L@j!`Wx`$9DOITQ@k95#1sT-! z^Us97&k=Gs&v8@|C=v5H%|euS84H0Y=2i0oc9?9zxtT@de2SE_I*H+%shHLB269k2 zL1N339P!Cm5JsCViiq#QjTMrFEHnN{amxWKtoBc067*_Nqa@{_GyHSucqO(l#Us4` zCkDcX4qHah?K%r)T&$R%gihxfaRctg@dHN_Cvoz=2jRF=-kfZ5C;<5Oag0wRsG6kO2)zVep2M$h8HFzYys&Sd-8Vn$Wu@tmfxIO$QZqiW(< zElBqRr*tK7O7{a~|I_jSiOyKEI6Kp2o$E_w}{7_eE>WW3VEQj!d<2nU1R6*|!9Yyty-H zud-92`61D>^`PY`RZqAaSA* za$w1qbOO1%*IHGOl?|D6XizZC>tLFxB8q4h-oiVl-py4_fbv2*?vWAXwe7|yKgc^o z)46^+P9!Fy&WHTJQO}qMc+876iUBG!bm?PB{zB#N+c2a3c2*39)ikMFA0<>y>8V0| z6p{6cYH5iM0B&f{3;+{V+aR;2CZ}SUMUsiKrA#9Lk!|!a3}=15(Za&k9!4wKbGoDA zwu)P?Capj*Gl!iCkdy8n-UU}IkB+`q=;Y1=QFM)D7Ul)xF#riSEka2J5m1n2HB2B?owTv&vdobiO@bNcXlC1~U`jkD>nDj=;GFVUc`de78B1!|T z$k(~CDn-K~<85dZ$OST($YXG4qa0I;k&EDt9B>E7+dP3Xi3BgZ6>F3D4VUpZ=nupK zjvy%;l?Pi+4ch8j7h@0UhP1e!;Gs8s29HljWpNx>h!B))8?gzZ$>gOV(X+s0aXUBD z7-`dIK7aUODdCrBp`+oxb8PMOHnsa#1m`ScMS=qq=EW$}hWg##vn_v6~cNx%pRN=MS&&&JJI4D-XnZmTE_NO4A{7BhM%E&X&$Y zC6lzZQs&tEu z&SDU)FaU-GvC6-Y0lf~rNpx|E+rsRP~A4R$Y;RUUT+W6X?Em4-9E@M_*u`eHZ$BZ>u1 z%QK8dqc9;qM6pn$$(c`+a2%m3>(CnjEekNDSr8?u(pEs;BO+};(GKeS;B<%*u}08Z zN2w(P@1M^v(zXb(7$+AG$whN-e|PVZNk%D`2GY_Uo{xc-!ur*XmYUY%$m_Jf{nknJ zWh1Jlt1rxK`zf2hi0gOQkBT^%Mi*q<$o2ehb`*YPI-eA;PW?{%U+C`V^FQsOulQ`S zcFzBoPhMto!+~Ntj4q-~$Kr0w>veQqg!_YkbF_j6p|1`mixq9Oysp*jaKpV?ybw>> zX9f(DKs1yVJ55{t#ytZqZ5gg{Y7DNK4*OF-{06%Tcc`;7t*AB$m;qaxa0{GX#n-pG zL@LfXt=H>x*BYC-R(b@X`4n)Cg9q@CDH^I{ zDxZ8?%f(}`Sb}3fW+yxFz&m;M?A0Mk9NQTS!x`nk2~s@2uj%4u8VctqVQmzmMiI@5 zoJNthtfO}CX7wC(M&mfhv~4tu=V+irQ4ib%|2r4KhbdlyD1*BndYJ-!6ZcU$KMv9i zfYo(M@F1*}M%k8W(Du$Z+s#j%_D6-jdEb5K?e8`}h04R7-EOC~+xga%J;e-oYStSf zREs<7^~}y5wRRtyUDc3;B=6p7cUs;K{mT&WcK|?sGykdo0$SuZo0iyNuV79HTV61m zCGiIlu^IXwt4VGIR9pm-{BS7Yl9S%?YvvltryGq#|0r7vQ+M9xNj%4R6Aq2KPEf^` zZ}jNAj(CMBisj47h1#{5#F}5Fu_{~ULlW~!sH^#p|>J| zOp4Ac0Q^Aa+5#aL?_yai-R-f?4PA@#F||F?Qv)lI>%P04_MXw4uvy#Q>9+Se-*!3& zz0O|eVE5b3x8XP4Zg2bWkY@VWs79Zi?>)0xmui(N1FEh(dU!AywCYFfd#_rUMX|Dw zXvN-8>6$}S#$9B!?dB&G^`F|dz2jIeM_lcOJNqVYO}#x{Z6ez<&4MrYA9 ztL#akXiVt7?I3?Bz8Q@@pJu(qJ3`+D5 ztmxI){N0|#pzEV5n$)&_-BC)_dC`k&+%LoII!@lzRBahE#nSC5w_vw@u=GM4EVB^Z z1LsN{EWZ-n-s9?}I9O*XaGbT);$Z2uIHlM}vnn?kbqQ8Ap>y#9E_EbWUV8z>7;& zeU)8CX)XmU5&|>yajrK67HGp zXoTHLLvdPn8SOYHsJs7arYkO+9#Oo~I8US)kv|2l3wt7AhNkaD1!=8qIE)eS#My_F zS#~3^Bu~D18Q!4N+k6}(fG(7$6Vp8AEjTV}y26ywa8J&Y9@&N=A{rfR1?NBtHp_|Y8e#L zzTxZ*S5bJq&Q+&4If{j*eKoj&eAOu4ZXE?vE-YqCr@ zq@;&q!tq;mA_bWpxSSVbe}f}7kZ=~^Lt1^})+OdmSt}k%Z(O?)j9uF1C*N55(tanAsUm)A1(hBF0iY%74=(ZKIs&3H zjr-@wMdpuOx|?+dAVz@AICVIiY5TF&wov43pm}i>Y4z|7#GMT^FAOoP=1-*I@CN#5 zDApdiF;QuU*}pd4C0#bz@@~oTxiU{ebPo83Xd%C$$k1<;jlz|!ah7g^N((ThkCF{h zCbf$`-J4^rJ|9>1S+!|a?^bT0s-8nvH6;FQ{Kd!^NsILrt{XYue*}Q_9h&^K*AlB!QWF%n6EdXFhqX zKM^q1A37jiRe-UgC~;PzNstOFF$s%qzp+q7Kjhn;p5vTH?>*aofx^m&z;eQ&XoM+6 zN6`n=GbwU9{=`7SB#6_}s5-(1W?@G0nFAGLVfG=Psx{!*c#H<)imx`w@VQn@GYHgG z+=aD*Heam_DUF!NLe`rDB3cDPC77NPP4DFRzfbbQC4rU%|3(84c_bDpQD_}f%@dU( zSCT)J!MGRg;9D$!Zm3m6U9)p?LxSkfgn`)3huz=`zk#@1sNCZf2uVk^^%!l+8DzZTC(hY2~Y zo5BDW5jdq;Rfsp;vueGe)&`(lUd=t&2j25cm=F!{${*7U5XLPzHLct47xgLtk%V|@ zA2tjyJP@(Lh29@GI1>Th=TaF*alAw@E{fDT6*R=58$9$tNY40rfvzGrHvtnMk@|Rc z(~qWoCLuzxN4Y-~|3)!WbK6&Lbq<`lV4MOFkDJ zb(L04rJX3E2U0;b>olskMDlD=vY588&?(`9qV~?`f z7*W*T#yUKl%H0PZ+H?R{hrKN0pn@L`PxYZc%o-mYT$&&|AKF1G9c&r`?eKeho^foB z584{$fjPFEeX$7X3iP0ae1-Q7F|dT;izd4A0Rb5vBm%YuUnG{P=uB5o;fL%RCt|DE;Cc&&R zxWo&yD~E!t)S2~x_mqNY6+WjoVft_ySL&m*9Jm&5S?=)4Dg(tbaiI$-2Bz~S6o@Cf zn#3fPw@M3|Vq)FbaJOVRM#G$usE<^C{ayp4;XG! zofw>^GE^jR2zJ({ zMANHyd=-j3h|>$DrNTKY5BS4wT5Y9Jg~gSb1Ei@`)9u7^xr%2jjnX)Tov3Vy`wl(2 z3KzEsr^HZWWu1tgMzPDJ;?6ic%vP7boRdFFO@mrI0`0cWnu0*{BC;7&t_W-ZIZ^MM%?RMdd^^$6}nRs@-iqEbE*U z2DCWTQvUqZdOY0IV#mo@=r8E0jKC^<2 z%HU}4?l%vu89OWErzR+z^=}70pK5GJv3-SCBl_}kk_?Qf%gK8=vQ%+~*zM@n-Z`!} ztpvc(8GJ)KQ+?^Iur|8=U%?`{c0HVV^DNY30PJ*o#N{AU$?VQIYES{4k5C0(883sH zJQ9DKMPjUct8)JwPK?rPsgVmQ>bxw$0i!67Si=Y##Uo0?a9Xg>f{mqm3W=fMVE=`_ z(i{`arvOqD3^7M>mxgf$+yy3-#1j}_N)-e)FBw{DwLOdBq#0#0YD-4(?2d}$a&7)5 z;$Stf0ko~<(#+Zbpg>>08^gmeRG2(RZ@!>^$`G)qt{k}xQVL^5<7iP^#&IM^C<9)p zB`ff9(Zpa0WGaGiDo+4;f@9s!kv6j||KsFlcC(@Mj|=iYc6K{^kF5NU`}_O%`5*7# zBhvXLp-ga?&d+B_JP3jM07sq9tVD=Je)tEbGap44^Mtb1!#A;!_y-0vjiwPrT^ub`i_g3UKH~~_*rs9T1@kPXq!+<>d{ek=`yNLAq!j1# zR7Q#yNeP>xuckSJ@mM5ehiw{-Za^NGqz(F4%!bZI_>D&+J=f$j8n-Xs$rOl=XoU-5o6GNdDDH>F;-yaS)l{wnu>DX{lz~-T(NVMJ%9`=-=9NV<+ai7SDu?j$_ zbG)oi$MJRT=CQCNg*Y6(@hm*@VWmXoW8#{ji$*q?^=CnL*&hXiEKY7DVqm)N{xG84 zQ$~^YXp4U9jJ;5#D7_Nj^pER!aK1(p3Yo+pF+Fyd46XK3fmd^!!4=$tsxWIpY~ zx{sn<5W=s@X(~U1$q@0E0x0@+dAkg)0Pb~*Ne;edWSr_b_Vef(0pfS8pGEy zJc#GnY@YEGE|ShC6Z2l3+u?1tgM&W8p9rZPfX~s#9L}GtYA^x85;R?Nl;>s+2`A?? zYXj^Wq6!KSLrmTck6%B3eN4Y$?D+fb$+K6#oEXjw0`9z2lFOnW2HZ!;sK`Zs==ref za3<*sKvoH(X&W$c+VHP^${#+mInPo1I*Bms9Czfj$0v?Z!wNY4NBLPT$B&{UT2BPy zP+GVl9E`yOp!36B#LeZ1$7C3fiyQ+es2O5lP0W(_|G>e`&uuv%@!Ma&5rfF1@-|Ml zfA!Crjnn_TefCZB*KYf3zXc_K?fE=Jt(78;p8qukh|*b-V%Ie86MFw)KV|&i?ER*= zzlHqYqi(Nj@qgV%d-wd`9ef0H7pFP@cawh|aQG@mLhk1o+J?o6%*y=|PKqIggBPXY zEJgw<%b!T4>yPlz;wY&~d!9w8O_Axr!@)aX8qa6%Wo((PtvoolEBW^9{gw#D{hS^s z(YR;tg*AbxA<$Vtj@;P441*zOs4f^ode=$7W+yT( zH(ARadLLm+_EF>?_xqm|##z<_hIz=P1i%_iS25IjV@?~{Ao|1(C5(%f&uTIHsPe{S zoiJQ(otekgg#c=$Ax9H_n1O7L{6ZlYAYaUfejXd2DydQcNA};wFnOKrmbd+#_ig)N zyF>zj*6A!Ye`gw`Ftxh)wMaOMri_LllK3hbhC{-I;?7Pq-EY7@$`*J>cMk7p4)4ebG;KqPC_(G* zkq5FQx(%e*MZRS*gl9LvmI|-yVizoX|U6rw5M=$pPDHc~_io?W)aEz2o*> zZ5!r9Z9_es70xGH0_QA2E}9lk>S5nsQG#U`iIsX+E@LN&(XoTtCd4ha4ZxBylr?kUDC9aF}BT10%o6Qj-wQ zF7Uyj=L1-R^FjOdPx#w+s%P;H#;*Mk4*I^aaNLeaG^*?kyE-QvtgPSWUyHVwl3C6+ z(;yhUh%Xx4mH`}iQGf@i!!*kJeVJ>*4H7dbP(ET~uzV#gxve9e(Q2H}F$6V`5jF2T zx6m$@DX-rqp+8o`tBb-ZCP>E${n0qMNb$I$nYG{k^7{3gI|Rc})I zuwBJe9aaspao}*~DFuyu-+l^D-qM5itN(O(c8WT1X4CkaZb-BTe$87H`h{!;%KmFnrfgpg0V&JmgGXC;`^d$XOL)vw03NIIfa3?Bl~IOdHsU zfttL@sFpH#y&7WoxY}=q+|$5 z$|6=Io%_G4DcXx^6a%sK7kM8?`8Oc$s1Iux&UN?^wq+O)k-z3;9ffhMN0d*hyg}kb zLe@9a;Q%m)vLxfM*(ng#8!wH=5wObB*bCD^Ff+VSxS?}kR#MpQmo257_kIrTr>;m( zPuMGN5>o`6>rli8q9DSQ(HWUBTJgjk;|Z!Aor*8OB%aY7yI2^qVp3C9;m4pyyds6n zCRRURheNao*ebw&h;{>860*fx(WfxWBTPKI*A)G}KBfAfB>u3e3&4f?pS=T1|MO_? zUjK6!A4~s(W(m12C?32EGx=*AUtHiVb=gHBiG}GU>T#qrND1vMeUJRfsJG?Pr{E!v z_KusptShVtMPM=XQXNoi=wU?C9Q-#42Cv?dhs57O(u}Xkf(^;_)8}eSXv-8%1^b7g z+(t3w{=oZ4@e+>`iepCCZ+NRU#16KHVKD0BB)66J$m4Op^OZ~_Mac!*-v35}3%oYO zXWO(Vw@JrB7oEjzq0*8TRgT?qku8Cv3|RgdyXW$J+A2flQ{(P?Of<>!^I_My>#Vv= zq>ijx*v;J|Q~TycGKF@&jjLprI7odphUwIybK!AhF}1g|gLQYHBynVjBU0gl`8i(a z?I`lsj9&xS9M2kMBghx4Y!tZ1rt`@;z=7TO#a{RD8jZZRNhqAA*Cap4QBheg+2%hD z@$1Qt{pT-_Pw4hdL58$_4%?{F@cow8QRRx5A~L0DmWeGO4mFx;q{6h#+el@)1q7gO z&d?By@(I#kdW4xkWw>;VQ63FKRj=aB=E)311d;Lb3A(Q1s-V~)gT+TzkqAYYgrv1V z`(j201pY&M*3P>wlkh}@^kN|hv(aQw2%u!wEx+`$xR37|N;Oq~_7kj;3}GK6!KB#w zmoQyy5o;q@8$Leqo49)mB@DlL{nKAxy*=>_=}B}c8lpcaQR83fGKN1i70yFnB&+ks zF>E2~(%Gt5ab_w~OT*Vx+_Mp_Zk*p{fMpljTSL5risW)x@C(v9npVG<2bV?lXhAsjgYVMh&4@8_O z74)Ho;r+wB1o<>Hm}D0R6*d(PeV6G$Fv?PKEKDZR6tgV4-r^!O7Oh{5%%ZDtZR`IBox+^M zvp4`vDrZ{y^aInV6{7_-^AJyPy6AAM#DTaTGruUX7ZIEJNPAjDCuK54#Qca)9&gpa~tH_ zG_Kfv!)Qnm!-@APgc=keqQc-CKQ0u?EBN>3LtpNvRR1HdcQ>E`TA=^g@9plH`kzO= zz1@5L&mDY7`GVn>q~--3OYpaC_w5oiFUIkCFz$1TgCy0g4B!k&_;#5~d9sv<{1mW! zehFk1J(ey)Qgcjln**0#NH!tp{CqOQ_KxyVH)Mf!U%YIpCHv<$eGG0@RY8>DdUz{e z+Jku6%vIwl-HW7IQARk#De`-9c3M4SFZ|8@UKzdiz$jgeS$xyqv!TOa90rMC0!S_< zvW~A5a~8cyFdQ~Am&V~gRQ1jv8J_p)dfD&o%wTa*o}NsiOqhpfvq2-h8Ynlz@C0uz zmFMztn@we~it-Fc-Y2!uhhUJU$}4uJ8wt8T@Ei0#U7yI1Qd}qV}o7F=d)cD*!H+4hjXCe0hTCqL$MI9E2?Ss6 zVEy+U`k%c=kM7t14nCW6?k{XHJRcF~kom7990wxzD9K8UZ-iRX&BI^bC;x%>L|Da8 zL!xVPVbQ$a1t+NXma9A}eEN9{6qYX2co;^*C2U-v`tL*QUAq5iC8p$Jvn~~=-v9gX z%Jl#2bsp{B+yC9g$FS{VktdquOg~*Fwb&|>_GtmRaba&53tN!cQg_9ncUOuint)g^VEH2Z!E|dz~)+LZ?Tvu74NJqEV%3VSDyI zA9A6mVP6C3gGxwG#3I**kAs_jVG+{u!f6U5k!}|eU~Z>Wt&NwkiJs;yyoNW`<*~$5 zG(-ZR;&%-58qX1War|>Iy?KMNozUp7)ZeuT6UDht!%;9FXQ^TgMmM1Lz^DWQduFLC zXBh3VpGN-*$x{O(J?6hUcHxW%jc<1yud#MC98>KshX{2S8b>3FM~ejy$_h^BlRnKYXL zr_b@>izSc|TCj_T+^I!>l=D*cAS2XXxOQfTN8EwAcnpJfQJM`A$RkTT>%}rExq;cg zOf;*`m9uEpMKUgZ^wBRa0{lY?z5Hq2!J79ATc!6jsCEsfLvI!heFc%CEbUKYB2E1u z>jPs|d+U^Lm)etnv2>+_9_bXtAp7vb2+UsIq$8OURPTv)dle0@1Z=Z8x~Rac<~W%a zb!~17R5q_gmdSRF-QC1JprknBnX&8?_epyK)D;i1d{ksNLzZ}AF)iO=^H5aXi(6i& z-D{Rn809!K&2h?bNuljWT@whjqHNDZ_AZN2v$DCosXc9-2qFy5)z-?OS~g7hxNlk` zX*!oL9~gx!z&$EXTb?2t*q2iI<<@}xfC_WEWfr8jU_q8_TiP}4Tkih635Ze^5TwT0 zEVa49#&%u}bbWIJ3kkVE3)Gt79a%@c&`<pkMe}D4k<@1+6wMaM)lOsPDBw=6ZH@+qNyPSsP;9q;k)u8S8 z5ky%W6h}lwRenK0LENCKZ~W&kPu@Iv`IfX{dNEj^c5YHqb0Lx#*rU5$h82kC-=CcP z-j)f6ywnmcmH=QkhAMkXzm3C~yx(1?J(DouNE9 zx`|U%9o9U{jXh?<7)CK&VBV!+LShLTD?x0Yi^b4&8Y{=faW4n+L~m6^9nD;Ua)bH5 zoILegIw8hcJ4WD=13M&M1uYY%gfX+_a{jFp@X;3h9%GCTqu zZduN2s!w%oVPj^*9kmv{v(yghi5;@a`tg`49=YNzm5UwD(RDQmGs@H4($}ta7}q2) zw|h7{iG~hXDuNeBx3jZLxqwxc?QXZ-Eu#KLp`szP3rYV{AgS_p(@alogugu|$cgUj zF+lgb;ZMICmgX&OH6!29HT)~QDwh_9MNm9UHiWOXciWxz@heW<#MlaWG#5A()KH10JycN>i)6W=X!L9MHrU6RHStQ4+Y*{~{6$T}ED z9~0X(H?)gq7k#Ot>oslMU98T}y7rJ@&*I&s#QO$pY$&z^!zYb;kw=A!iC9#0&wNVR zu11{c3X?`EStD1xzL=T5vm_0jx`;x{Biw65t)`U%?7)b6$<8;1t-MV~DvGL`onpt} zu+TyUGaIVLE&@&h3IQ5g%i^$Vq`k*~_VRxY=pQamw*4}bn@sIS^;=3?wyTTCc`ML3 zAiwwqXM;mjVe^7iBUO}G4oxA> z;r2DxwuaNuH@vbR<0rhrW8F9v@WWe1NhK_<^^MzphhIA7hsbw^lB&UW^-bp#*;kgO z+^!67Zba;x+zVdWDx#{4@&>!)OyLG)-b1hqs)$2{7VhCryX)A+d$+oa)qTJ#KuEu5zU1|5TH={w6;u0ni_Y| zrWnZ)g*_=MX=U&Y8#9QtY*v?_QQk$A?$So{6eKO~x6h^hGamMB9)#-M*zyNr9WvlP zA@Q^HDM@>w;-t*6m`Q}fjX21I>oldx8rjee)Ua7aM9Lbxog-Q!Om^vlR4q@AdVJ!r zhSj=fTVAOn*mmLf-et!IXs6aG`yXynG!#lu=acwHjaZ z1<=7jIGn%aVCnM-`d@{OQ0Ec)N zM@l~ii8YCaD+*h=i6o-XJ~=ki<*FkS`JHZ-`%~%uR9fp)+Fi(_u6-&k-l?o(B@beb z3%0E7qO}5>v0YRPE^U_4vpQO2%vfmtxtT6^Vpzn24ZGMn=v&{d8y?FzO2kyEXY1X$PG+scC5y6(bs^g!V635QKM?sw{% zJJoSJBQfMP$7e+b-*jiO_xN>?ZDt1_zj^cO&1c-f)c=Nda9JsgfTnJ61i@9v#_{)? z`_?!2XFeB2@+Hd2)i@_)px8gi%Y4nej0oQn_5pmDs|Y0WZU^L&EEXYzH?h~AJUw~- zU&rfhHTNBO$yU?!Y(96tV5g}Set7cCRl2*z$%;{k^JCTCe=fJ3TiT4XKkaTrAfUHp z&fU1q8L?+Z(KJdg4HZS4L>EeJD;7N-)H$PxE57BdDP>LhJ1=DMeUR*GW9(&Th=h(i4>e3UlyqGJkZ3=hV zlI2bTzzQ>HJA?7R*px&IzCTDX=d6EkCu(Bt%s1+B0w5F^HIn4*VE6H48 zmu;RXxlA}7d)FP#@NwNGn=m!kj=oVTL}x9d*mCcduHo4d_JrvV4(IOyCUcr%t~wYL z#vn%+ghTJTaN#tJru^%!YH5AlYb?scxV5r6li!G*@X6d$IX_lzBTyzmdI{3Q;eqb*`pesWgDFBO9 zldY_0cO!0yvtC6vJtUVR9vI;`H|}Or<-X~N-=Zm^kGW!v;*Bw5F95BW_`#Hw>ueaA z@~gzQtEcWpOuy3ytQbdwD62(XT9mx)=*M83hHipb;AIIt#N~%QbmWVZg|fljgqfO; z+7g8}OkueX%047ur*19Rfw4Sc+8BM|Q!|=k@<12WT@K_j0~XJ#6zB$$46HCB>)?no z;x8NOcAyg-EWj$qvn5!Og=ki+g@T-4Ds-xFQguh7sniEjt=Ux0VM7vC*~XIE0aNbH zx7i?=VpHdM&pNkunOND|j?a~Zbt7~+7NdrnN`;&zx~?0;>sG9&)WB{k@_kkvqaq3^ z!qhVEBErgD&g=+Hsf@KU%yagQUPLpGzgf(~k>f)8A3uc{Ogv&D@CS3xwUtfZA?b7OzOT+7mh z%(Rk8+wN*6ZH}yX)v&H_r+R0rvU?Y+qN3$`EA{BlyHb_K)>^6ERY~NW@-;2CRIYDo zjCS=KGBaLeabGj;XHIO(Jj`@rd#7l z69xMdbl8HI-|jC&S>38?s53X-^1 zViwPqUWv!0C5t&25UQsmF`6xNvdahJ_OLVPgK`HXVo17-2=uUu_+*)AptXWPF5JYc z?UZ7K8f3~*O|2mCxxl!3)y5oZprlf-qizGW9&ZM3x6`@pBmy<#|M!FRW;$3g3qW=J z|AWrnBQyU;uh-q}+{gdFgOALsipv|tTZ_^GD0u*WcQO8rD)PIVKT$|Jz@ugWICC5Xb8jQfw1Sipcr zReFJXVENr;8ZaQR;d}#SkgBV&G)7nK)Ox80sQaSp^85pJ7uOs>Nh$)Rxy>XbFyLUN zC8#_8B{CGOHV5LwSIARfOt3OrLG7JbvHO;qTmAF}3maZNiNPA{Q8Sf+z1fVL$hA&} zjpa5lhI#iH4(j6H!r1x&j@?dqu#xtSw)Y$h?9PO++9EHX6hRxH`>Mbg?*_C*7+;ZfsLH?KoZyNf{Ttkv9@&4XYz%8o(3O+niuN?8E`)||g9Tf-MI{~82* zaQhh?Y7mh{q{~>ObvN`7?cgMLe449fOtQHMe6qEc~yR@}hJX*n4`F#22nB ziQj7)j8)F@%8VE#dx`R5NRXNNF&taWPKhB7^RhG;&NjN$frS@r)Dmy!`%D%q9czw! z7E2#*^>@1ayek%c=`#;M_p!v+h$X)KFt6g$` z=-eMVUr0I%(^k4XDaG;<#BG|WmTbD^O;heRV})rGe7AWkHmGX;Y&k4SZ;CB~y4fTa zuIZpHqU-K?Rgt?S3Z@jbzl>n|)#~_#s`w=k$90%~wuBdQ5!~@~m$?P_VzOXZ#OO|Q zVfyWMQ72eNi;(_0E>{e^78J4|F@?9n?+XK}wjzo`95ufNdz7Mt6azt5x> z#wPvDsW0v~u6yHdaNianUMsx@_wz+3*|_H*HbSbt@GKdoqePx71NMiR2B6A=QiGEt zU50Sp(^6&(S!C90s>uMVl4#V-Sus?_a)AMNmp7y6-vqRoH6x&3M%s+kyjL|cn76xr zA`SNjQXs4A;mT(0Os%oZOuNoQZDBQc!VNL0O{Lus&DqH}T>GpnD@EOX=5Rt^XcePG ziKyBQtE8!@X_Mm)-BOvdq7oq0Gq<^$h1n~XXsZH-TC*jytuO}cuED#lncHFsb6GK0 zmnPJi=R&Yoo6B~gK&(3F#S#W%x0drU zSXDSImq>%*X8AyB&Uy=TVHo?lDkDba8m^rd!x4jGnH(5( zvT7_v*VTcnlqh3KT6ZfXiGcw;9@MdU9lXAIcl)1OEOiJ(_BH4E8DGWW#urI{%#`L)ymLOLo!+? zS%;kXXH3~)K&B#bhh^1gvW|DHEOlDwEgLXvncN%+Zs|@~It@hmM!It_ z-$|kl8{1Y{fJcAG1^5#3Z#Ze5nT4a;0DD;r>gtRfD_Bq0&&#ni^{jSzb0z9n7olAk zd7o>;)q1U58>=73X5NhwXU99wzOjrF#%O%S92`y>pL3$a_$3yQj zxC*`VFyz!EGt5#lqI(febP{?(-=FiFTlwjsq|p?GWz3ky{>l@MRHK2}qewHN;D=?&xxr*3 z{mb&;Ba*5nZ7Lm>553zHHRAddQ z2~vj#Y?;ZHd4aj)`YXE&8YkId1H*NYr2i8p@w4bE!Xw&sCA3tCmO3u)^3(Mm*36^X zD_wOPi^O%s@+oVfxxqY1Q2ZQ4<1yN$teC1r-uPhC!Ei{y5YVS%#57aYwqbNGdBep1 z_~dP`NUcyGjl$LXLi;7&pulS*Lc32r$3E4Wu9^Gu#|W_LO4Sk!jj?*3ZsmSG)@*LsF} z1Tu7th9Ss48H%1;#%ft)>ZGOrOV08XuQ6i!Zr68&m{@5JyQfY_kvMROmT39;YjpiUS=DA{W8a*q`GFgZI z2$Qk!#tPuF(X2|JYsspJ>)`e?2vzR>atc#`e?$9mxl;l^pCxV3-6agFT$mMztrBJa z_q%X)f}YpT`BR$hXT_teBE!!{a{FvxSV}&h`bba_vw!s*Kb@t3*;9e3;E=^A2jT)QpJ=aunsLNJONhO<5ax5tF$V2lTf7;o$l&jyT`T_v26osN0u_;FU^awMBLZ)p!@sDg0bptPD$1a zwuWeAL2?0mg<;+D=+dhZwW{-9LeJkvUX1#uNo6(+cODEg{{==Ks@iaNG7Nhsl_tihZn*2%%X_!FmrMMn z*UYNnLaje!YK?_SHP%U|vD7W?(g!AOi2BjYO-+J>Qv4Z1n%6z(YXmZ1_K?3b!tkY} z-dK=yW9f7o>!c7^wB1%qv0-j9z2BwsY?NimSc^S%q}Hg$+S|^tu~EF257x=UVN}2! zA}$+wi?H{s8tVHRK#Z0^cXBehl6Txu+K$`YZTE-U{o%H#XpO_|bEf#HliXuH3&Bk$ z^H};8_-+$;+)3(=wUz{DF5TMjyMn`Y=$1|pKU=y5XMoA&Frk*=XLW^@vy`aLD%9K^ zWhrqaAz3D{{jFRw+-6>h&$&}pk9Vx^v0I9C{5#x1D`4y$ree7DBn+RO?0=!@1#TUa z|MEF7`HRV3@LBQ}Y#P_|cWVdb|I)+p-=9lg;%@%J1N=Ke`;*vg2KO)XHqhiIM__+5 zsDG69gE1VEVsBN2@E5Hv8Bt&9fCqnv@%%ZbfI0%jS>A}~Pd|)+{%evw+2s1M{GD4- z7r^bAIV1NkH>IwrK&V^M9ld{Jar+$+`<0u4F)r$LkW6!DKiF#cd-49!G~Wuq7AQ_i z4S@v8D|gNbjPpo_#Q+*Gl3}u8+}_N@czka~RS>gjc^D$RaV@C_E6}dlhJi}7$5EOs zuxdwerCB`NAe~X1_^BAH|BO;+-Z$ocE+Ak8jB~2=YV7gKv<-D|*(N|%pzno=8&*r% zQ0@s zHJ7y>B6t!}zRQ>k_0BCbEP{>U*4ip-h?6=(t6TL#UI}zyLD7KZCda9bv1)w6Lx1Bd z9He)@$Quo;QMshc$n%S1ZB(v~=Ev#CCsIj<){~%hJWy!G@;al^)m$g1NLecik$pQmE#j-EoEg0DK5^quI-~`U$6a%d8i9oBn_;wxQh9;BhN=ua}BJhQC*{N?kL=TBbrpB=w=@(;3cX?N<@r8@op{ru$Q_zkacw{#y= zw9~>XOJx+k!ly3ZlsYJCNvewkCioX+T<`1y+2N|il3*`iJED9nKI?PZLI*(~GLWJO#Wm0zvirUv#Z`?cr*`aUW;E?y}9whBKW!69Ww*dwmj zJm(|+!v+2TWWgnxNK#>kAk3_!Btn9)u@|A}Y00w+37AeQq4}o3DfFVEDqbMAl4KAnf&gWX4+wziiG)YII?7wqQTEq~ShsOfRs+pKJRId_*>80n!d z+vzRXR@H&Ts&a|#SH+gjuSx{0RIa1uXln=WEGn;Z?owC!D0UsZyy@|$XGhqp-U9P! z1Sj33KTpHu&33Fjk^{_Ef(NxoTS8u-2D`5u(~s97k&Y~X`Y=u-&bQh;<4|fQ2f(H5 z-~$|)2;a4@&?+cxGz-_u-q{M;;UXumVk(dZ6A-Yq#IkZqz&IeG;LBDnh=6dc(o2=WARoJ*U>axmYpfytQdS;f-Bv3acRoQW1n>uci2H4$2$tsm#7W zsy&x%ukC;PwU)ca>SfQ-i|v@K_tLBGrDykYAeYf`(=V%?_HsvO`WGd5OMqV{HOs<$ zEVZ&{m*UqtIkT6}mYt9LpAqmIIUPx+L$-gj$JdrccQJuDxw?Nth;K?yosKRq^&VkP zIT%j^TW{iz-ea}E?mnY~IA1f{P8VA{u z`N0)pplO3@<=I{~eTdA%y(w3wC6>x!E}ZEbmhdxP9Es1>gIIeRuF!TXKvW=uW55P^ zAX?Or6Uopb$XB{OwNatOo1mi%Rc11;SF^itlD)NONh|?^>wj>AigLw(1zv9ocxYB! zG$%TdH;|{uIZ+F2t7i#X&Q)aTo1L;u^S6B?(Oc_AqDr$;kl2-T%3FNKI=Qwh8#8ik zmzAxVQ-0a&l-<>?Q&R9{qV&>PyH~zaUF}-Td@b+N7$? z^tFhoELEMIza!*c;#T)Qi@l@uT3PIuJMhiS^`AdyeLbUgquCX+ z)!%KN`c-bK7e|g=J1@QaV7;Tf^aqRb(sz3u$DI=0fD|AxnfIkn(M4eTzLfoNKnRPM zkp~Mh73W%kowMj&SY|%_zjA6@{i&Cg*MO&*@ZX3MSt&xT1f zya*ruHF_5$(bLxt&&Tok!(n*!P_#3Q2lEM_VEXXy;TUR$J16nZ$z{0nzvt77aoC;= zYhinL-?ouj#%U$jc6S!0WwY`;<^o5zQ@U|#oPE}Tx8J$#6VD!=>l)`fINLNQ&5h8Ph=uz)eL|{Ds2EBFX&lAs%r$(av4lP6jzJB%>am# zzw&c2D?m8b0*P{A(x#tEXQ(N9p(%=<9slslPg*aPWkfT-2V@YDqNB8X8F|@j(z1O~Ofh6*}kYf@;15QZZb;chhhn@W=Pr zyyFd>(_Y}oI{k}q>W$`8zR{-Ufbg8(&}DWo!Rs+E#uQ3WUMRJ&t(+dnW~gT4Yh*E7 z-q&Aq-s}Yy*2$Gn)nNmaw$`j)RCm|`FkL}ybcd$u?RbscURt$crYR>^MR)_*A08i8 zf^$j9sI=4g&8pJ!ECbco1xGW{vZ8vCegtd8QBnNj$+0RN99BSKj@<8X`Vb7Kpyt(ynU+70bduO-ZZSOrqDw#gSP5+RCQjiFm-b@GW z+0Dv*bl`Jvut$I4qyO!8b|3BU{abf$w|CI#0r%2{=e=&{(f+@6HaO4H&m7Mn=rW1p ztg76i_vYk&Cm&(MPHP;+TjHlUI=0C09qEF!b;s}G>CKGx2S0x@1>PSoky{=ayl=^t zm`f{uGP-T47WM7fd)bVo_0LLJN0f}f31!nrFXQ=m2xsb5=$(f^!|{G+2BaH9d7~XtFn9+ts0^BsYiU^GA>9Md z9NAO4M^v~~0c^a2rLUgCpis6t*xK+A5rfi3T3qV##%5 z_io4g8pIKIA$c)~1rN#!Dh@MFroPUNbg#IG?iBXvdw3yjfL1opm-QFiPS=EcwOdf$ zW}VfM-`yb1OUdtmiN*IKb_+-J&f8k!mcLWL)^*`;z!$ImYhU^=zRNF#dEI+`V|WD* z#{poK9mWA+f4;$va_+i&PvVXA(sbZTyHA7QK!@eha!GCU#Z>CU!7ityI_nCbFE-zq(b4{8=?J zOB=V_7~dE*<$0&rwnef$aqm~o+^>myI+Il4p=uyXUatmv_Ljh!tyRb3Mkt{PXv;es z+v7|GL&?v8qHoK*eOdO6Mo{iL<2Y_d(FOWT7APA{Bf1spnCE9v*f=_K=SQlVKjwzM z(XamV>Chl6l3BZ_f{vx6PU)*AhDc-kFo+wx{)?yn$|R%PDrR| z9z$LQ7=98uHJ$LdjIXN!;tuZB;Kra~CB|1%m`M8oKqPkA%`80hqKj#qV62N__~C3_ zvEs|0UENi#kDe(6vCx5^d##t>|U1Kd_dxxsBf_^)XZesH`ybO34<3#_3 z3Tilax4-Egb~@WO9`G>Bcm^JH{#?vq(_Di((0Mjk3x8;cNA&Mzw4ZX_RNJunQ17Ww zw@}eyK8wz}D<5YZPPFvElH;p9oAdyq9AVV|<>aZ~T45^nlM%YM&|Ms4&Q0KgAQkk2 z@%T%@(dvU%Em}|EeXITVs{1eetco<2%JWShz)ND`Z6C;P9Q?e8@jaq$7*Xr+5u5Zr zHc;8j{7}5E8AEh)P_If!UFW)Fxp<@NnvS5DyXUXFZBIIUikz1=We2iDpe?H0_KoE?ePQ>W%SIE^jh+F9odSLyBqOL ztPKDo3a^gH@}k1)s&pIJSAWq68nhqdCy#ezzHq53Gq*d|NgV$iOmE%@e-h8m#;#{w zS3;xPdDe|=BV=GK!Z@ip(Tfb|#U{}+hMdFD)W9Yy9X@DVBCI@ZFO!lTMd79-;MD9W z_;GBsPJ0&@ylLJp$RJ9VF}|~nZgp7E1>3bGOUR!2(#o)ITc2@ebjQ^Y(N zF=ofgYwGb#@V>LHEJU-qe3_S%?rL`XN1S?Lvg%P+f76%W`>%NZ;it|SSmKxIAOfz_ zl3LJ+gLYts%_>q+*5K_N!5aCoOBV!bJ)+Z7!}(iRpUa%qt8IUIx>?zDjqTsd4`bTD z0y^fQ3sdmE^Fm|*z9X-vRd34CeWx$tV^wUZD2LuEN2dh5Y+~I_wd>kc26jeEx;UdL zve;tZBco)Gjnt7Vqo0X!`YtJgh3OcnD}Nm5S*(lU^@BK@za&hW&L@-&yK$0jp23?M_e!^hMl?%D0W>ZkEV5IRWO4H_VDs#8mnO~uK}uPId+E!Pd~nbT^SA6 z61H;Na7tc**f%A!Z8kX0lXy_k&$Z3&&#wEk%R0Mu&6gJIy7t*scUQ97P6>~{Ve8k; z*&LVbz2z^rdse55Op#sstW}M?r=+4R^3C6l!gQ@wLr~;5Br`{<93WG>csTheezBKljgA+D~lRE#mTDf9NKmxI?jX6)2N>{xP5uBJ&i=8*8- zwsR@AeXT*~Z5Vl)IWENPki2Dq>+a-+BAOBz{o`-CiXir{llUSDCdj`zjrJYe^*YEl zvl)-yym|HJkFpt8Ky8};hETh#6fE+MjrlnItB@^w|FBq3Z)X=d^7b3&1P-qu2;kRD z058HR32%K^mk727$V}Z1@ON44rP&ZT!%blOlcy)o|LgekAp2iF2eNC57@w!V0N2$D zM(!C|y1O>f$GinO#kY6BZDfABz3pHi3{H}wTFV2?pyuk1;Kba9D91f;ZneCPqL&BW z&%wKp{K|9A4B?p<&}zyJDu3stT<$?wvgP@*tl!cmq9#bVKkt4oBw%-i^G>Z{CfHd( z5NeQ*UWMTykpl7>0XbjwHO@28mif78!l02hHkb~jYlQl|J!FPhuPHOh5)R9N1Imlj z!{R=f6p!M$)2}p>eQc@NwvkM?wZ>5NZ$esNJi?m%nFIPY7^f|7qiP0?Z04QF%~UL1 z3CSo8-CwbDT^fk8>0c-D^kRLFZZYldI=*tEjh=m66vs~2!G6MWA7IPA+# z>+eTxUN#nM-qs845tR4|RXa#cV!xbsTRoEq9!3d>Bp_D>Q8g@Vom?KMQ-N!N^24Ru ztAMQ5Y{~R1th2g}I-quI9m6i0nQ*L~@z}fW0Ou2A&?*_`1j=1Wr7C8j<(!zSOJhP7 z#NC#QOAC9#)&d8pL=1yrVj?nxP&o9i3$Gl*OvS(M+SZiUy~c(Nco0c&Wbm9< z@S%-FVr{#c9Zl9VTkpAB@8RLCMuJn@G(ykm6V>$PqER~Hp(V+RfI!Srg8;W;hUL8Q z$Uu_LdfI+At#x|#uErpZeZZMEdLXc~og{4p4(p_@A6vz1(r4S{QM8)$_ETlmNq z@s4n0-c1N{#EO((9St_taKyoMopP%ZzgwYU%r}}5Fr65<9EgK41tjoz(th;{I`M5_ z1$kK?-K=Bq_qJ4aFd7%=fQyf3ON&bjG1pu{1?zu55L}GxtC9HVAD z412d&NMJ2Cey3=?>J_~b(83vg*GWw_I&d9x7Y=y8B=GMhF(F9r9vPMwGM5R+Qi%X7 z3d(h3v{bI8!(WxkFRw0IQaq|8Oe<)2N|(GOyLEov4uUCC-E+Juo|hcAf>^I)IHpE^ zq=uF7kA<^@NETjL@nJYkbj8>wUkv(pm;T+OfA>4ZzX$a1qt02gNFRC*qIx}hF(dTXZTKnOw%^feM;0eCb{$qcXeE#`X-DZc zje~p3P|0tp2}F$rwuOpOp|N{_9QH5qhGZy$-jOM+;>+KWbi6;s-H;l~!&hDNsam_J z+%2nY?FS$x)2`eLvQemAOtFnm=(X$OtSE<(^q{2QQs!2NXxxf(Vz;^a{bx_#&s9mA zwVk~0NS3b0f`%4W+pJ3%ciKf5CS6^s5{N))k1K2mf29trj$Qj zg4tU?bZebZMx{H&H5Wbqju{ki^R%pMAi8;_Ebfu<@>)NYVF$LEsBjit_-)@rYw5PB zDjwuJ;%kS^w>$fiGX&~{P4nBx`^HlWM`u<(@0J>6bjR!J*}d@{x2fFH6NgZ2Gi;H{ zV5?l%;u83MDWA~U2g=1&3lzj&zIKE*smnX$_Oy(2h2YJ+pP7o*NziUt za$6v!8I$~u8Kot-jeao7!i2=$zT98R#(aPYr;?ij3(>!fs(69ekE-Wcz$Y$UmCfcE zCo++NMIRtZ!j9koABJu3ZHQ?l(s}4T*nQM#YlNUcQ>Taf0+Nsi8rZ<5*3?k$y;`~@9Hk=Y8o9sr&Q{i{gK$}6K~8&Vv6l{PW8Pj)8y$KhFi-0P_o%2WxdVPlam^g?&+U8Tgp zXhndn)81R$PS2Ka1S0Oa^cos@v0rNmv=;QdSK71fYOeQeC79QH?k(#1Kr@^)lqzY< z8|Z;mM6;*8+_jzlMg54S9$6-ZRL#6m1zlJ(Ay+PCDS2E zm}LWQ%ksMbu^kF+@D1%DQ}pa~bYZji2-85r&>Gl96Mys`s|9xVf!)O9o#MT>dvLn} z2h_B0>lxlMpk-U->dA^@5JqU+IG72FH5v3L}vTKkB*cV ze-U5z&dBZGx*n*VyNGgrZ_p`iwbiwlsPaprCD)|NgQZ4q0%c^>OWW52F^EjJ0g2>s zZc%B@d`0V|cd6U18`Vl2Jv!E~&BX0>93vM`ySMhdiN!$x{ts?Y(SRAy!8>jNA%~G7 z&5u}#4QFF3N3v4LF2{te?7l=!KP%q&VPv!ZBn*%hw$u3C<-JsIQ}$OWh@w$=hznSYlffOEVssvX&C z+0axdhpwbGFAGamE4JGT`DJr@S{sU9cPDBSI8oe&b{jdyz`ts^inZhtmUrYXw4c;DSLsnE(N zv}&kmt-Nb(X7Oz4wRv1xvY3?xv-(aMM&o5cT=U_$Be*&#g|y))64$v5IP9CGMMi|Z z`qEIv4MyFl!prQeV$2G}+(#*+rdmPZe}SR(s$p=$@=E)U)or8J^O zG50%59hv3UH}+N7cW^{n;`1;(pI=ab+;Pmxo*Xe8$RPAN`Cq#2O&|7l8EskZ19O!M zA=ol6=vhOmf&^D{8B9T9SBt*Q06dew@^i7n0O?r6B+7+Jn|>;tp%&_eri6NS{KGFl zX}wgI5zPd{q3m1Ka(YLt;ORhKD-?;|z!q!$ikng@V>zmbp(f!Zz6zbAb-^VEBC4Ko z-K%$C8V&>o_&yukyrDzd3p`n;e-Tc-(R|7#0@NIkkMkR{4hSZA3+Tm|6%5J?troUr z>}uH<)o*+qBo}GR`}*s5*Z6ILC4F+Gxrt#jlr-CHrD()uYT=*`sQ&H{5WF3)k=w_s zR`djn2Rabc?(MaBE4I z0Q?SH2vLY%5~%^1 zv>l=WN`r0?#exX7q~&#+W}!X1(5_WzS6tm1k9&6AUS1a+H>|(}rFjIzi_^}Txby0k zyk)aohn1iR2Cv7XkrlhLS!bu+%4U1gH*Dd8_Zj7@)*UT?c^@=@)&LuIM38EE!vIcy z!B22W-4g4Mj4)!p|BRzN>Vk2sFESCO9<3|XyTQ2L?OIidUjjE1=$@wriR1skb%*tCj5U7OQJ^JZ*xGvr>4%6v2kW+xd1-Urn zD-~*}*>xNW+Q^D_xvA7{YjX(P)w5WN1ePmf@rLEU8uCB;h_9gqSRnsD+THJ&@_)D2 zd2}!T-@!-7*+N&eRYx7LKo4Mw`l^KA?hoS0EXZUXMT=fvCqR0&FGMjQ;MVf$Y75Nk z98+hYPp(vPVBM#zB@ME^uoe?-7OjvB&7zuoXuhmaE6AdM3gvWUKi`IQ(>qG9h1Ly2MTt9^Tamh7r8 zSF>SYT@C%lJ?5>d11TmsjnPm|iS25Hnbyt#EWF^nbJbi?J5p&J=Qzx0bTu?3x3)jN zY{khRCfW}F#BosC64*TfGjL)S@hbx-S2(4yC9?bDvOM@AW@GVr<`F4(+ zlRq;0DuNafPK<$5g#UjSlfOF7uW_oa{Tc9$)`K(4!2{L&jbuzo1h2>17_Z0r_@FI7 zym^RV86XPKyu9Edh^G4N5~HRV2mF)HCm|fCv$^WTqc$$#e)8(st3zhD$+JaXNhIMo z!W)T}huMRIXq+O}WJz!Z1=4sDGK0&Fh&k$zls(`*Y_YPM9<6Lm7t90WB5{c*?Vr!n z8`Ev0bfJv3(EyS!IfE<$E@gwgrq2D5Us4RAKtZ`U$PSnO;4Ix;+;7+F zH;&8Na`xQy-Sn0(`Y;q9JU5B&i%6uq4bEdEg-C|a=b1N8!~94Y1%qe|R6k5b1PW?y z8VV1=&rK@z{o^{w?(xLL6J_1BG|8*QIkhq1Tnja*U}c0pYkdr&iLotpY^-R;&S0K9 za_6<|)~!nlCvsHa#%|sKR4!K3fOaVnd;9$5PcM%9M9a)N(+p$yJD0h7+4RA5KhI!# z&cXC*4@M{N?vZp#$QeaFOBbMyER|!>zjqH0qiN=SW8qZv;RGeCeCNL9jl3_4Ch9UOof3 zwx}Fkwe|Cxo|2jKSck=6PjR_%%=;@X`e#_f<>9?CyjcLf64dEuH?y!}b5>0#-+UcAJiC+O{6~=JBU1XOH#GP|Mk)YYi zANAy;FKOQ*$YHWAobef5#s?D&qC5$*^yn0T*!_IOd)H*T^kQ96?2%uZh|C%PQosY} z;XK1=kpx_9kaQU&RdGT`ldR>%^GrquJ@t zYzYwKgrJfjZ%1}<`$)!@(M z&IXrqOz!tGa=#VaeH@+7-Z%X3flhbS16A&6Wb-jpATJd@F;{>KC}-&`PO}Rj^zX-q z4TG1y^6{>+aQTQAuZK3JB^RU&>gPqEk7YO*6jjtKRco2feN2NPJ3CUM z#Y#hT^*!03r&-bnIX%xhOi%UsKfBq40oVfjpKfn&&$9p7-Rs<+|99|N?flmqB1;52 z#2%FVIN=X#3h<2a#kWScLxOw@PI2*N`!XDlO2CdW3=1#$8NG?ah)1#&P2T@xdT#19`5G9_wsLn{j6KO-9LEj9qbnx$#1>K-UvSYk9@oD zJ$iI7@*efD^4``Ky?4zjK|?5DqloyR0t{q2K!D5eL&NvkA0CRdQy`uhdQWj4*7%yp zkqsYF(EoM%>l6^-%;=7R&&}H7&~*K?IWU8;g#BquL`l~GtR+ig)7T`n4|MoC$Ydsi zjmxbied+T=+4dHviB>GPK0nckdW_CgRjsHhA|293&Xu^v?#?YOOeN1b5g3nJ2K-|? z#%vf({UtOXum911{*s|#Wn5C`N94mwC-l#vbgyGrJz))LG^D+t%0zQMM&8#z`n+$v ze}4Kk`$+$6|MxaLY!q*rpSDyTR>5ZxRIUo3=(r{K75->~Xfr^=1V2azQRFu*<^tOJ zUV1q?+vN2ut5IpAwHbw2wUSTh>@XV^9t2Ga>np!f9>d1h;-R>BBDgdeX#@r>sm05+ z;x&|J&YPT0y_=lwx8GJ5>`CK@&Vm+q)fOFl6CHc+_h;Gu1UY;-zVQMKw0a&Uzh={T z7XI<~=8sQKp1kNEzj^cOjamhSG94ZylGNY4`JR=#Q{Rerx(iFT0yKo6z26We8{&&U zu+IJIJj;OIW9Wft6#JiHmlz}XLu?Y#%-#+&j!hRh(YY-?)$XRsa)IvD@%9~{`Xl{l zpB(@9Ny{sK|M2|flQ;i3YdRT@80ou_&S-$$+(i>y5s+UF0?^uS<#X%E{>Yyy{co5Kf*HEq-Rk{sx7U5N zYu*2L54!jI-#hrMrvIhqZ8(xY^iktmg!4n~?;!2RqfynNN_4?TV#u){{1!bq&B>}X z$lKobn=SPzDQNi>>xzx{qd4A1OFt@sKk%2M(67JBQr_`4{iY{*$+Om$a+=dd2>Wm- z0c$bNDQ7VODIcT*zJ)s$J4ds{!K3^L%e0O5iX%nPc`A8CEm!g;0BU4R{CJ8fMHJvS zeE3JVp49v7ckyPqkYNUCxjEGc_)tn+H64P`hqq98*u(7lDU4%!ks_<|5t=AF0hT(w zY5+2wg@cHUJ3qoI`-g-mfGTWOO21)MaY?uRPdP_0P-LZ+*X=#FfRaLu9F3 zGaB!Q8S*1MF3N~T?>*=i#`aaZ?R#HQCk{#G2+g-)ilPb8ojSI;7U1H}G!L#Kl_0MT74uS%7v`viadtrAqH7Vz4>&Ogu`fn z`h^?s`ZAo7sTqdl3x{4n#%LvbPyTZ4#l@RZlGqx1vF_{>*>Zc|`lq^Y9OSb}{^Y194M>5#D#)2mJ= z|Ic?2Yx0fLP8*3AL|qbS;e$^)UU91fq@~mQfW&1`5V!)d7f^SDu5s_y;iQnLTSG#% zYa0b!OqE8i#ns#XL9=Y$`EyaPV%j!Vn~s|(cS=V_0KI6HBk$-AgI2)hjW`3+L1KeR zJ>zT96XQrk_!-G@EHD+vqj~fZa^~2$(mA)<-kDDq?w;x37I%-)KXm5UKD=a`-#=A+XDSR?EAa0|L*SE@gH|P`}g|)JNP{K%foq^JUox455wsd?(WNYy1QcV zN0r#)i8PI;;X?C(lbcy(Jc0&?VmI2Z#p3ZX2t<0@`+xt>+otP+8V8pYL^eza%ZJAU zGoj}SIkfoHUl?-eHUbLW9-x+*o*ROkaba0FKIZr~MUcW<3B=?cup^vJorQ1ZFnLTc zdF*41#qOg{M~Q56TgzV(aR7U-Y^J-Q8Ghf}-DE(MazK?M(R4l@ue2G_qNPPqE5x^5 z{w6rch*csS)Bm>C2zsft2n$V(MV!qtAT1XRAFmYE0Y}Cg=8+--v|cjB%&UZ~35Wx8+(Av*UHuwH&(d0^iv|>29JAhg3U~%`y%f^qFwL`(xz&0}$+})wnQjy+n<@8!D zWY?cAT9-Dbs&HL@$Y5OeakzfhpDO+DBuei<|J&Ky@9o?A-`>6c_bxtb>v>fIRYNJu zF%N1|L({Krl3wstm$O&3Rq6-t$)Jk*oLX=+kzisEqG}?5$dN*RiOe>j&a)`En8s-q z4SvK&?Vpd|zJ2o3asTz3=RZGr^ABwVq9LGA4~1QI1CcqhsZf~GDw=naLi_uUM9GLKj@NEuG*D=#_%iz>C$B>XC$QMg~~o? zZREBYt6Ox8;rN<mC$`zeAmXHAz4WyImT-( zj7Fp35-qem3F;%?1?ZKAr8X*dO^tyT7=*dDM3!aYM5iH7DM8X!+R;eaTCMLUEQwVK zgX!9SpKGwz5T)W+SpXrUU~&`+_*b!c7mZxHqb~2i$`!EtJfxAJrLTX22A*WuGvHhS z0fK3tFM2xiKh(RBDAcN|)}PKNYAwEJsZkHa)xNj@5H+F8eXZ(QPQfJ*qw_hMw9tgA zf=BOenJ;xoK+M)%Na_rDZtgO@yi7h1yGs^NMW=SmYVo>T{kkXeu~%I$^>(Xnja-*c z{GQwH?U$azH3XpY<@wx9-4dTF{$DCa)|CLN`TxCccfV)x{|EcK_x%4Id<0V;r;_y_ zkm_3g5_!<&&+9OFmxQCOO=k_&ODTCnb63-OhJ2|gcQNP>;xYH9$LfSf!}G>4m4^*J zV>aXUPlU{(5EjX;b2WNOrL@!KDLfIU3#w(9dvJKy>w{oMwy|g&GHU6Om^rZ1+ z@nQ6cv0s09KRkI>sd_yRhA?l`FQNp|^7eXXP1n$&98pOwzohAoJw}=^3cmtXjV1*_czZ^N}I)Y%%;_5QzNma0OXGWylFv?TT5)9tzz9apoDa- zjzivT_$YAts8bEnc#1(Ts0z6O1=AaEcuvtT%z(=|j#A{`0#7Mw@30RK(A_62VjYKh ztm9C~#5j2+(yxZX6hZ@Qd@@?qf*E7%=2GH76?q)zzE@Zbr$^H5ILg8a2aCclIH+K<;tK14M^I$ zUJJ(dPRH?eF+0Jati}OcLpjkv8yhLKEcSSZ;ka-fEBFz8HrEZO#S~AnKg$YNM{-}& zS3~jjl8ks>uZ3Zag&!>jK&I;L*MH-ix&I0ijJD5j+d*~(pC6n3SmBa;wHUWRB zEn~bUe5Ry|V6y7z$s%MpdLvncB*8|y2!3oNjCl6s3V@_66WR^*tUksY(>$a)(a^bFEqsY@aXY?2mayC!Cb!&MF0AhT* z{I1W@1ZM*}`W8M`1X-ntm#_M7j^Dn1_44hpmLBU|-+1!ajB`1WkClQ%mmhdm+A3jy zbB?93#O*BS@LZh`o>2Ofam4ogW)h)c{yYQa!M`F zcyW7kq}EF_dO4?wc2=on<4`e@mvQ!XK0~q;4i^ulz;dWyT!o9gc}s0wcM3g$q150J zHGE5Z09!7F@16?Z%yjyL2TRWu>Xc2EnmfW)Z)d95aQTigr`n&!@yyBP;kF5;H;tv| z?c&|Uq>UT@ED5G*K%sZ~%x_fjn|5h&lAaVV1e5ao*^6Tr6H4a6?g1{*_{)|guW7rIRRsiar5)8(90~*@Gmd_ z^X03*ztoRbx_=52i5H~9shceH$?MlIpZt7``9kHTAze}X>M6C{{a${S8sl9fcARbHYa@9FwmSy{>+nI*Zl{#cy9bT!3(Mo!7 z%zuly0B>i=rj}kAFdZ`bK>1mLr~F%;gDCO6r;WD=$5^g4`Y6gOsv{*2K(4hudG+ko zp$Bl8+<52l2QLEbr%8L}WMN47Hoc7J<6#?UaE8_3yt<0gmS`;nS`}v7sh5V7${@h& zf*?g!$&254oZ)d0PoQ}WloyYn#Wu5%$&GdKsX+ztOo31MVGzy=;}&zU%ECZnHErwl zZk-01rKDvOCisqi)fUe!`}+z$<6N;Jcg-hX`l#EP{x20ks;1Evmzw7nSj9i)o!V32wYJi^gLrthOoIyNcl11?|I}NfRQmC}UXHeag^=*TPlDKU-xlecgG z{_4#$+FZrmS6&22HFd31Qr+d6h_{3LtZ!5NYpEI6=IOGJu!T=H;hv9>_I1IpeFG(eVZlWC`{CW zJ5IM^;J3t*C>^N$6Z{`mW*lOUr#?<+gE_}st?O5?RXTy{MigT*L`1_Enx7eYsJL8H zDbQZ{%(V`#a_c8eldV}Z>yMH!Ty1((b1fUdaxjUu%Y|Ur7SZTN6@mFl6}Lqt(7#+U z?oj|G*{pE{1b>R|=Q^$!?pc$y>$kk^?sjD%XaoxNsta*TyW27V|Fl?}VoI9g zu$_cszOl-k$hFt#^&Jfr%O92R(MpCNvLxVUq?EpF_j%NY^}6q^*!_lPzw5iM|6M3m zinGJm#Mc1^AHD=;Vr*W{m1`A129q2%S;2BUE>}1!Ov5nt{{7!c1Iq%Ks4GGlieKCR z(*s!i`@ehRV0tk}K7KZyU8L{FD+gd$5+phxKn@`bIN=|`gB~vg7&_N&rTJ(uo-r2gYr%0o9Lbe#c057A&e5 zhp1Z^18PO1hM(S~?b$fU&^-~Y+qcKjbpBymyN62xSQy}?yL&}`&B+YpmrM%7R0M5y z<#X?$=hH*K;DNYMI|fqH@UQ(QDzrxS1tFGdjDYb2h{g>i*7=H;$4c9{C3rTYad45U zX;CfY)i`3M#C*ylTvW9us#0l0UNL>lol733M#zD@M_f~`5di(RMXU7XynIh}$(Fk+K zc9kV}wUe*^Ddzs=EWi!_SG-9>DHtE-tEpj!BVn+>1=*x(41DVUh!={z1N`@IDA&Q4 zZLegC+e!%0Q~w95iBV(yH}Ul|ihV?6o|@=Va01_Z2_LV+fA+kcuGew2((U5EXb}E} zWN;s<|Nq(h*Y&oMV__Kme(Nd_IDSMnGG8PH+p}M-dy1Kd!eU$VqWg#G6_$1zBm@;*Ze|47)J}d8?F{yx7-LaY zR_~s@J^E?q-QSL&>>tg0Rp#x+QutrLQpGRKntr7<-SDtGOSEI>yZ6Q2v8_>^}F~@jP;h5#dwzH@x*#I-+=mb zrIq3u%zssl1^iEQ&cpRfEVwN}^HaF4f=d%ovV)f-Ad!()KSemnQVfGYE;LcFgEepE!zM|R>N6*b#Qnf)NKYP)v*5sgV1(wO( zO1b-vbn*3L`}pI((3ni?Mu4fv|FgTd`&5hnGUyHV`d{O}+`-2h^@Rs-afW}a$N@U0 z2bE4hH*QBF(D3-DHz)rZ{^RH4xBt?Teu@)5DJ9|-8)eAxj_e)3rQ}#hq=;oP#zT^j z3AFMc6_WRo;?|y1SFvA)fCb7}+%g_3=n-Dd;{pOisUglp!*V@V2US*!jK=Dd@7yq~ zV;!N>X24uONVFq_WD|R#HJebp=2=`hm*0E?6iCJa0EyhR%e8)dIic{;H!Hf;gKPJ2 zA%ikCAYfLP;$ZI$=c!k=W@u>`qt#6|%?!<0JBGcPFW_OtP^&@@DpxLb2U-I7D7Yw! zMSk$@x93DKT#krbbouQ#9ly`gXnZjlmEXTj@_ZTR-+tGB`u&~^WvOhhaRv15_@Bpb zUl1nv>h-Iaub&;geDOcW&r97|nl)*J)??H|8Jrz`?w0=X^4-bN$uVnVZ}7CIW*M-} zT(ju7m2+FWIoD0867dT3ax`t|UR%ByDwc~`Tr&Ck8J)}+^T8kcZ3w9a!tPwe4&aeX z&Fl}XZ*+(B={EoaP&6ZHafF}z_*s*Q7@qtdx?SS%3-|U>8k}i7!W{t?)i;qRnr13wj=_k zPliO^fXFi|=2)0y=_0^}Fc8&sl0!f&GSS7L%$P7HK!7PF7Ap|*$}IFX1lvV_``{pp&&M;;`@um9mciS_Kz~SMpit~I1X&1GPKad! zLG&@QC87w52U;37J*c=zWwepLyOG_xjR1M|r2AQG0hXk%lKADZSt7Hl{q?HS$dDC6 zGu_Awg9VS}oEC~9b*FD4$3we`L~i*%f3`BU8W6WONt~JN3DLZt^Mu{8f2_$ zgfM`Wj$y}KzVMR8V7@+rNW9h(1F6K5O01O~sz`%~RjZNKC^_dCyhX}F_$c5e8t^5> z)OYrm0~yCY{7C&M2r8L#Z6s|++hnIA|DpTLt)Ru4cr4m*F3}2<=`dIhxbvEMbKNPv zD7En;i=&v&oRY@;K9Q8k0CGU8C#X%tJ^4(fDO)5VK~x*GX{;&6Zez zP>q{t5uMhivt@oUWX`9iACxPa5V#$KAKoHM;by@e%SUo(l;ZE#n_&!^N1yUwgg^ec zRcrbTpFB&FTAIVS&$Aadu&L<;m*BU27>=Vk3=pO};9vykU|EwUYNGmbIV%!T*&8+K z9`VRC(V~2PcskfWQyQ^RZ~gWMjoW8eHB?PQ1(j)%#N>}^r5lmV?o`c zS$$pOzLWt4XR#np&Iv{3;6wp|BWNR*DV2dzeF-125y6P%`k0G=4ZLz}a$(2#q$18S zzIpNH_~naN$HRC3diBhP{5&RLObqM~>SBN3$Nu0Ru+N6{V9_sl5)C@=`qjz|et(vAh~41NY8Mz1?n_To=nM zrc;30eg*6Jhy}q7c`I7`G+>Z&ne<82`y90L0CY5EfFSh(;|6XR%YJN4TkpN3E-WqA zq&I<=XjBHzff+h3NH9X5EKysw$l{MlN&rJlthzFfet7-%1=M3B_p-EI3c9apP^B_8plKHygmr6U}8c|#%+2o7n zF%B8}4kvI!L-9#I_pQHM_v6+7epo;ED}4O=-`?O!zi;G!?e+G)>VNOxQ|5nNEpw|i zKkN7+9>1r$Ut4@p9tl-T+#wz-EB<5fm*D%}zGlwxG5D`wfQW{5ev>YPD2s#hG^JU+ zBAO~ji50m_W)r<@&H+AjhiZZ0kjCb-y&zKmQw+=MaGnOnrRAC0e)H~M&tAXz>+t0G z-O2EmqgN-xmoI*J^N-;VKfieSe7mh^U!ysN)<6`zA*d?bJ`KI?hSU)KJS`}KjiKoJ zT+6(*NbL^xY#f4C8Sjgq-jLnhGGIzMYmAt-tPj~rQ?-UlLr5M3Cl_%Z)7algV;3>` zXB3a4C3`GilS$n&ZsS8{>4a&~YcLHrmp8geE|qWF ziXOpE?J8et(iP#RC9A`u+!bR(zZw!lP<=@qw+!`%A{VbYoVqtGV7MAzkIUiukx?Q< z0xvAmG)QL?;Y3Lq?Bap+-UJET{!fEihd4?GkE${{=0(@*xw%oAC}4ZJxV-Tx;!ULG0xDCcs|A$ z=!+;za&pv7r>J@jKIYwkni2=k<8g8skwgC^S`>Jdx&=+5RG5(l$sZ;Z!Y_2ip)V(_ zB74i)sUvmfA7)!y^Km)@GoXHNYo4W7@O2*%zeO#eVf$yioQMHG;2si26!V^-$csrl#~71YYZ?}xlFy+O zKuZ3Ic*E3f3h``~JX4;O@0kx8#n2LC(?N8BWtOKI$6P{%064?bDbV-SW!8n~a0!qy znF`QH)oR5A!Wgqj{zU(FQElI*k+YzVx(~yU{w)m&=tbMA5nfWUdzB>x2JtoVk8{B2 zv?ZvSAX|Le?ciHNkv%&S&x{rsLNJx2Knc}aOGsH0_3 z|NcLCGT1fj|N8yGSNp%a_>j%|jdCo7x!&43xgf_=h&_-_mJmRX9+Wvj931d(lOf|S zZ_>Ot&tkF@QBD>WTX{A{g8G)UyPU=Ow`wEW&+Zs(@1?ULZ@SecC*xlTU>Kb=n8wBU zf@yK#LOfJMhm<2lPqf3(^Ec_hsclOP?-_#j*%S%jq;mt@U&{n{`nHV$w>Konz((@f(h% zNy>k+;H6a1A^n4VMGzx2Y4i!<>d|?e(NcKhnx>_?jkI4RM0TQg2RD$mmcKfh6WCuA zG_71Gc)g&;Zk^yA*b)%&t`nSq{k1*T2OgoHr92-=Cn&!=^nsv1!OV8n_juWr<4Ib1 z-;G9NUWQX63wEfMD>LMYF1aQF%*mH?$bP1^z4*Y(QYo+#XrAS2@gd5)MJbmOJZ){U zw?i5ZI4Fb8p2x*YeAbde1Ph?N#kuuEdyCLWejq5N`-<#M`63#F{t_KfgO{{A4c0`r zDMDhuWI&D?Zk+TLO;JKR%jr5H)Xr8)7f2E-g0wp%Ybz;+!&V;8raX+?0VvGKOt6?x zJofQ{0G>iFNls9^J7nvI-|A>@6%;_)UH%&2AkTQTZVIOa1AU;0d&yGgdo6wP02Tli)A*a6@?2eCXoXnim=QX1b1zNluH{28AZBG z;vb3*Oy^+=Rw0YZ{5U874?D*Da_G)r5KSuSp%v7+?GkWd@T&!&F6Xf<3rTwjUDI%$ zMk;hd87x*Uq;x+FF!*g*o}lt7RFTj6rqMz57Nn@S5|K~h8KZFv8PRMt7?6jqf>3Ht zPlO^4>QIL$DklI61 zyg<6ie1LC!r{W3LJ3BkmtD-@kttL51ot+Vy z1(fQQ=+Ue}HO1Nd08VM72-8=b9RK$TE$N&>r}>jYn<9vnj1&YNWm?>drro9cNJ;3pA0I)o|0wc`>iw-9CgsB(&@l2eqvPqib#S%*sHDAJvs332!xIkhbpd}v{f$l9EuXz4J2#Z2?NfgtXKTYkUxn>%X7%AOhyq% z@_mUPhw<(foyTIi7;+fpi1jU&@0`deKOFz{#j61GcSBn7*RPZ)hmvVC2A6;P`b}_h z^ux>J;Kh%@@qfQ~ck(Wf&fGYIN&~9qP}X9HRm#Bd+1ulzljGp$S1(`x^{>azS;u;J ztGQlZ=@duvwN(|ePBt+u7SVx2nX5DCEgyEy=Z1vU@ z8AffQgS<~>SJI$)-lY$cXbjj(3b5cjl=7W|PD6Tx&(K;ZILVgk`9NV_D#$F(L2x<^ zKgq>P=K%sQdDjpA>%W301L?7<_~tXr;b*#>mRo9I*%~P^GC;Ju94ls~A%Qc{fYs_r z?}8nO_$195!3P@7aHJj>hTxM2@8m(dCbZ zKrZoy*N~wT^+8xHcM5?>HP%_12_@LGYfTnfq>sz4~*3rVZ)k>ShO3Qq!-a3zrg&whWTCpY5vREc!$1<|B ziS^%t)!!}~bglnrB?dsD#)Td^`G8T#!w%$uti=^<4Si(}50W`Ve(peL@-BIVjdo;K z;W9i%GY}jRHwih)&X=%S-ryS^`T&1)qse3#vG*luhC6dfS2>CE;xI&$O6lokTtpwE z>@a-$`j>Y~>1jlyl*4{+*z5Jm=dgqifnA9w7x8RC+Ff3b2)rrPn1O#gGh$_Ob{%MU z79YY+Ko|32m=}ag3=6_?$V1u*_*>1=s~ybzEL-;wUKcj#2e}Aom7)ZH4Xb+=Y_&;O zKwuJDZCz-Xgsx=jYzHk6#G?h6xuG#R5FQ|_U5Q)*0L?Va$APxZG$n2Tsw!#{eDe0_ z*>OOP9z1Q$;6h<%hcI-}9{G;-f)*GRXBk-5G16&sWz_jB9f5m5cFuA%lP_Q@MEk%$ z&`Zws)T*Hs>_IP;#O%+HfB5;Y3{KU`%3GEjqmWmUVYS*98SvkzMT=0D8jMtYF zFKZAqYe8i!)xf+fvN*crPn&^Z)K##u_@Jo0@tMhJ*_`2Frp2f`V1e>RF%dt=@fbH} zT+3~vMY`0qZJJs`cC+QY<>K`nd;PEee|PbD^oMVkdG_rnnSUG4 zKL(WLp#A#WUIfBII!hj8)b1(T#=3^Su#0~zvXql9TBaK5j+%7;x3jgU2m=i5K(mi{&e5=jFyG-CVj2>jz!HW7t*%J#1RJJ&bcK+-Lxr(ZyGfRLA60c)knzH5&SeL5u&`VJ5z*wckLi)D~HY#Kt@ zgWyw()ZQVZXb0bbTW9ZcaGA$EM+Pk$!V&jl+)2nWqf?|sH0!X7vXC1pja3?%ZhyKw z4PpLqO@(Kq3;rPb7$q~bJv;lnE!F6Js$YUOYQAK#RP!N+PbovNdI?w+XklOI8TL#b z@vn2{ISWH;bFB^~@7AId6iCo?UdTjCi?>aEWtUD68*AEPnsf?{(GQ11A}|k!UacXKj8H#HmB69U_em2=#CVu_Hsh11h=_>jQy?m8 zQ6^tmG|v0g%4SkKxm*BVK%u{02Bp%uge#|8VT{bKk@lGjbrzTgH8kL)`YixOTH9fQ zjSW|gH1k}BxQyP@HOqFuMgVbv+X9X1Gc&$OlW|PgcZf<@&>g>c_2X;!`^(YWS1(@S zBbubTtpiODD}=T{!5kIADeL2a@JM)eCScZ2L^h2wTVK5RQ796W}73XYzWLPQdXg_7bYjNx!X9y!AdyiDYP+TDcmZF);p-RA)rwfK8)X@h8CYFFlz@nQ{{cg3(I>u~$5aM`&6X=#xVd%* z;bCl1@*C=xNT9BYn9iXCF@cJK>N!MM?<@^1<@t+{X2$f^p#ip>waz+QQV_@q8F0%z z8lEu%MRYN%OgNh$vOsD>(U<;I8dKsz()V4_BWAXcB0)p^CDJ8s2?#K1OjwYqKOE`< zluc6P_90EUNMNSkm{<#P+BroVPk35)`nhMHWx`>Gt+O-=xAE(?{(4(_zrAggfCCb| z#S3fs1#bD|1& z8Y-sYCv2!Y98xAd9DeSKM<15ajLLGK!%gE$S%u?lGHQho%{K%(j&iW#;Fb-n`CyXH zw~HW}P9ZxA)Ce_RH>5R&G#o$DZh&an9>wLtc z{55JqR4;gSVSx)Uiz77wokiT^L1}PCOG8azc*kd_=NU+dCTk;gn zz_6BCVFFL5U8|qbdi{**_ET(NJX;!-$d?I>QWzc7VjBh#2pXtgoma*A-_nqv*w;zc zbaiIA3L|2It?jz8yWSu}nP_xO)*O|I}#ffVQ%~*g_ud;w}*Pg#Sfwyj_Ko;_$DD6#(`%mdc{E?)2#8C4z5Ms z1m6UMws3~us>|La5KIxzPSp(KXKiUJPJ3r~$ir9ky-sToo+C@a?P12}L7oVTkx3fo zAnqmei#SVI+9s+pqd=0gU4cXhS^~5yp(!WISr7vr#@7*;0t!{jjXnu0pr=v_6WDRn ztqobV+9r)BKW z8R~r2n^UScT5C>E2s2^oC*Pz}Xj>uUJ#xLuiDk!o#<(^+vD=?6lFmi+nYDg;R-=7m zUTqwY4fy^zo-r|u<(1D{(j2Hv4}fP(4;2q~u7}~Tm}UaGACDik9wqoVphgOn9I%nj z5wPf1K~W838FZiO5kcd)N1pd(1yZRdG>WrPiyhZriR&Hh)l{9-n2=J-Js_`w3R6{4 zoOXG>pbf8jiZQIw&5*Qa$%(`D%+SnWAK%a_Tvx*>r&3qL3i1Z^ zX%PAvTCN7MmMzU3gxa`&*0&!~fP6!N^-z$)iE{HO*|3rd+O4mos#H#C!&hdZR4p~D z59d+Q#%N9T6gv*kOeTkD=+v&YsX8~lI?5`wSF~l?T&Mcs38%ENM#(pGMTJhHYSu$7FLEohosK-J8 zx{WqZ;P2E|fv9Ni^Cehoa;i3ZCRX--D7)nB$` z;=NW&)s*E$p&+j6Aq^@Z88jGFWm}wVDvqmYO_YxQ%@3!oaQhQBAgM0|!Hx;Vc1RD9 z^Gm^PJM0K_l5X30jCA%KPA`jLx-8^#sV-ZWLcwrO9|EPO@_i=VoVE9(C8zO zs%c7u7MRVAIwQJT09h5)Gm&x$7@iBG0*v>y_|W1lV6h1eAFmj=kb!hqePyL2c{0xn zNW$2fV344e&vHy%u~5M2-Trz{GMg&=-8{v@v z?MxEL@d)X3sO^6%kK^Fq1koeb){GEO#u9^A1=`1-D6+aZ`=2}d18E6$f_|^QNlCwF zGp{moPy?`dA4S3DM9ajkqM)IllAPdWe4)pk-6URWF-ObFoTqrL zNlumV#I-X2Nm$tQMqHU^F%`W7sDloR5#ttQ01^C6FE7E+yocWYRLOo}cv(1Iojd3S<6Q}1d5aN6&6f&uw&w|7QBKq80WDHb65 zHGmlO^!dnV>6P|`aNK0t8VYBnoTjZ3Jos6_yo;cYEF!0iBDo|aHW3$UtLj*RR%q6dRFzYH~%kVDA4ykxX!y=UASJZb%jy}%TMO9%0sFa6xlm`NU?lXQ? zE}t+13QMSU0y=~Ng3QBZ?2szhO8lSB;gE*f2Xzih*;h;=Q)!&blSda(EEBFg})U%8;{s_@>jWr6Lslz1Ya`2ibTs9)?TMS!Ssfvw~M0bRLNQ+A;Rk6ZI z&5q=_Sw+hTO`n59Dr*(gRgR6%`)ag_`m5XufzpIn?bt+1b>VE+ZLXYkNIU>-iJ9m5 zq~yuQtOufs#WWP7t_`Yg{YyFRf_h5Z-bti zRJo2NF5p44!Cl!=Kn&ZdkouoEOP?nn6IcYgLds``O$FkFN=CXtXT?k~(><%%o;DL` zv{iE^l(JPbQOi6K-sl#A>)h0fv2ScTwl9)qrYMQ!md2Ewbm>+RZR;rTPj#z7{Vqh- z6J+E>nqG3zIKtp#q$yp&k8jGGck)ttOh%dJ@h~R`+smj$md`9d9Q4{!2~;#?WHPf! z-rDEKvNC~%^%{p-DJ?U{VGA3E#E!$fxRi*_EJROyS~2XL4J(;XhV+O6_RvI#yp-3D zrC|(0O)Il{&^SY2mkm@3TxP;VX-I>Kg#i=96U}CFqQdi(ba55U@jUWdvcT9{dZ#7K z^f@I+hWwUjLJFRR-YBJ;2z3!*ffh^sV7{DAlj}0#5f7n9H7Hy!iaK~2NQGA5v2f7X zmke-0L@^%Qw+w+qAvuY;e%jnAP`g^j5)flFZ9$-nlk?|xX4A@vq{v3dH-Iq8$4SBi zcC&&dh%$;KRjh(05U~zzSmbXjY*~0Dq?s}yjIsGAgjspICj=D9ApBo-JCwyDXBKD0My_67da06ZV!8JyJU_b9pl)5Dll%xJa`bR*rDjAzrAk zLP?H4J9x`7#4QyAE8|bV6(sH*qpU57#H1C%dE+e}0nxB|W2Qo^Z{XitgN5tz8NOC{ zco{_yhXUsn^P<((igYP$lm7cYPcIbs`--WVgfh}0OlfzL5DAccTN4nN)Tj!YPhk`u z1pUuCE;vjLaDoKM>m4d1xeX}MUPzsH)dhn=?euo&1ZwR=+sJCUL>R|BSX3?Y5-nY< zq*!sFhl|aAr(Ng#*zZ_N(G1b^=_)3sGje#VvOSQRMqLnT9_vlSgwtk> z`DLYCXKs$O7Z8M%%uihF;5|(t7SmSUzNN7;OG9`u6!=|v?D$F~2V>BEL$Bw~<9VFn zu@m#iLkOyVuN@i-1gp2j8E;s|@ZQ(ZAej%}1=i*6d>F*D@IyhNq|O&(KmZ4ATt$Ps zLmlhZk32ZxKV;mY1_Ck1RsDB?I;QuK&EV&{t(>7eGSx*Mtl7APsh1P|GkLGhR9!(* za$3BLRhFfPx`Mb#JcDQWy%f7ttX{R+{O(jn$Kssj%dG)VP1%Jv>6>GYNKsa?`GefR zEQdt{l7{w_y5)FX&^t)GqFFGudUyQt_}K|59a>sf>_XJKty-0s4|Eja1KLb!(!$?|+?TwrHBQ?G z9`Hz(`#En&G;^?sg3Do*V9*uaE^GZca1s!t<^-<>B3O{WyXv4wlSwX?sy=CDoWHa3LNCkNW*VdDOPE^wIKsNQ$AQscxW3cpivQ zvYDD(Tro^FV#4@1seHV%yz0?RvX%mTv=Ekj{lQzo@gw$BbRWJfmq=9Enb-lNV%?xkJ3u4O-^ zcia33$VaOmXzY{lDlOjeRH>F(@WgSbP(O8;heBVV(ZYL8_nnP_+7!M{pbXB5UZ9d; z`Z3P3WKuza2DTbPLgR8&2*G`sfa*|bQ%S}rMsVdjGNolP{VvqB@~v)u0jMGs|Nh%O#-mkQBvR26vjx-DxFwFiM z7d+i%KaPzx!=AYrw}1w03HW!g&taQSG7aMEBro!S_w(m+0P-%yU)S+4q84OBINX>&~W64*(;;5p2=yD9P(91a!L_%C&Vn*J((ttO@&jl|p^d&7W#~26BF>?3Fdm5zVp9vJ*Y{>8t^-=b!g$f&KOF~x9h^SJbT`TJj ze04qQF?A}2lO!KU+2l){k{YPrh;nCDBoiJaU3xtDMZFmcSM>afbJ~kn?~dP|tbKmh zCWfCgm=La93e{OvHQ{A7L~ktENv$p`7bC+b5X?ogCbfhUvhfmOPTg*=sGBGlB-2A- zYlrHIb_N|w#CvtiTBDm=YFcL-&Bjw#A%;Ir?aObT=F9N~m6+Yjjs?J;MhO`HK+y4Y zKD*(b>%kR~xii$Ip^7V+2a9A8L&jL}6^rF|##xkK;Gs;(%i9fpxk$zr!Bx7PO~5f4 zQoTcJ@tAf8lq|IZm81M-J`TprKCal#A;onbce~x-T^w@*8_8sJh&8&4o37LnRR^{d zWkXxi3YM_Lb)b$LHIB2q7RZsc>7_tL+#E<}>p6WQ$zeC03NE?2Q@64yEN8RfG|BP} zMYn(s=+QF@M#(wqA4lw)C76Y}qnK{)*p$P+-3W7_>@bp^>2$Xf?42pQv}Kaa=tiBu zxd(VAPrTUhh{UKcmX9(fIxabqwJg3@1;nwPllo2@7@M7d#?P8Jx;Ln3b#G8*Z=j5u zY+c22F^hAqrTU8Pq)RsNolMUKIb_PiKY}#JfqB%~RxNyq#O+!XP-c{+@8fy-b}7@TSss#6`2i$0sr?X{I4eo$@ zX*~+kIdxShg6$+?J~i^BHEx?Ll`Zu0Vm^tlJruIjxAayQqLunHoBzJ?fWKdTzO!Z{rbm|6CgZX|$OjNE44Q{xCk+o(SOJT`5i>_$*!gP>lu8Kk;> z#7LVzzkJC$aa5zD#hIt+&3Mv#&)LnSA)lX`RFrFomA)&@>}|oG?KnkqGqjO`xji#O z+&bahCKa}6^*V^c;Bx>>Ig4CqVIS zKr0ft##`0WSI}=;Gs`I}1Mcl7vOZEBUQ?50UYnWb!HLHwtv*;4AW?<8 zyhxFrV0{isrB{9Whw`;3Y8RK@UTBaM8aF{O#uloWy&-NF7aW;*1rRdlRIpA4*NDfh zIh*o1OnL9KVj=~tL(CqEMK-@>i*@8F7#v!<3aXo`dU3aB+o#3F=eD9SXZ>PR%(ZuM zBXI!ot4mHzX!o4APH7rOGXg6;`a)qiT`-l#X)6i-MAl2YRLf9@&3>Rt z-2#H0M>N@(WK0k5Ps&%!sQ$&Pleb5&-f1D#ea6v)Pn#fA)0asGXQ4+^O4Mo1IOqGI46)SSB z9YKD*T1G;u@Rg$#Sj)7@@=kDxCeCzlZlH3P)c zB2iW0N=6kZaG@6%^!mM>-e9Ny9iNT}w(%<+2Jzb@UaFBJr}q*QNWi=03WKncj5w5X z>X8mx!m3X}PJaHw(VG{+1)0_xr5G-UP7pzZ@qBrSG@~L-2bzCiTL`EV0_3WlB>7?% z-3)WWnb6cPn@2PHON5OG@^J(K$>9npeQ)cfOBzWEX)+N_W`sn(T2B)UaLYqEj>%A@ z7+&ys6#RmjBBu$BVtN@Y7hATbx(qB;n1c`7p%iTMlr3rtfD+IyEt1fDTjEN|Ie=JC z#w_iCQA@?Ek(W2`as=ox|_@hJVpu_)^M+yBfQ*2pxUB`5*WY zKo)&{3;?HC2?NQL$8531zH{IQCjN;isD>N&SKHeZPObbtpC#jXU2ZRqAt>4hQv4E8 zR9(ZTy@SCSb$X462r}4Z+`}*B!zZMvmIVenl(|886H=}Nkz;?0<*io1vWRg>V{GgH zwmVwskDynNvc?r!aJ{A$-y1lpu)Nl02YW_Q&a-NR!zzHhg;D-HL9b?cyn3NkcD+>~ zLXj1q@3f+pct*5#YY%$bTeUVF+Y@(n#UMah1O=GKNTkoxc>8H<1uvaxX_Y*i9UOdu zZa&KkB%QItm}94dV335@%nZSWJX1H9GE|hMq}XNfi>-vh_aKZue6bZYxD?_><1;i8 z*nfy9DNUVa-x9?rPQaXue!~o2c}ptV;cx!-;;(-@es?l_^Y-=0>u0ZDmVGVfMl%q- zF>kTQ2A!PZtxRh|4`LGx(Ove4oY+!CbaQ6m&eDN-o+1fT^EGXmL1Kw?#yqZFl%Qv1 zU~_B_7OWsz9N)A;x-CCHZd&(18rMY1a%~6nQSf34wsRNJ$C#yOz`QPaQ%q!Bxcq{E zqNKCb~ku24<7ZO4uYhhmV3d!mo$k?G#)3DcwTgC z;Ee6TdqBA0k12B*SZY#y0|{l^Btbv_^y~8|i8%;)OaubZ3MdlUU{{+O46Z&;i(y24 zSE{JSU>|n(xKO)d2IzL+G8z`Naj_{u%>CuA&9NBhP{zJfUUhHE=g>qHb32r`G0o*p zOn!5>yA5HQc^cjhqDwbMSqIeMLLsz;qYHrnVmnJUC0=;?;`z(tGtYau*nff{kKj1&(5D)Atd zc=5Kt@cV74fD#v;+sLW*CtMo?3RtzLlEGf3+548n7o4FWMU+R%RAjYmiwFo~82oHD zipKA$L%4dHrPoZg!(s|R13fUA#DuEj*}Dr{8NR(dpE2~ynCZOYgZinpZA|awa%#8g#e2UA3{SL_XA^k#mrciJ<3ZK#-QvSp<1$JDZ8v`EEzv~4b zxE86k0nmY`xCugv%U973G9`OME`vq=LsJmIw|RM$VZ_MOZeMm~27nAf{4}a!)BIin z#KiM4hE_;N|0adtqDSH8bC&uHG?nx(+~-Y0Ry+U>8BY#^Pgr0F%Y&~kl*6C>v(Mg$ z1lU=#>t1&3gFCu*C(xf-?{0Yzi`J=n-_pZdm45rIBem40S3*7IO32SvUzT8iMoe@+)VTla(n&wUB4eJ=aV>_ zlSA#r7R5L0M{pY;?M}GllGKtkg!*E`rWFAbZ$;8h6-is8C40ybRCT2g!MdcsvVD;~ zL+N9zq|GpzWMwHhS5Z>bQHZt5lI1?5r5B-NYnESRRpRC1w|8H77#d zDNJlwy^TaB+RRXOtw~cBglLB4QbLmw_FGDI;6|vD+@v-f1{SP|PS(H*J(4xgHDM04 zUcwU_^)$rE`g5cBiB)14wRH~-#nM%%HZDtAl)FZ4nIfeUxuAOda&T*=O}T5-@)RmM zVp$>;MK+SQCv?{eG)|ptvj@stwRW#s4l9hU7S68BgB5IH; zA7xllu4rJYiC3B|k@3=-dc{4W%_U&5^zm@guvma=l#E52C>~B5QnIW_QtPBkny$sopf{Pe#n($!`WCsj-I_S8+*E8)^IT-f^SsoW-^$th zn(xJh|K|B#95W_oeTiHV-fHoc`_2ARPu}LEmNS*eq-vysk&fGUn8KtkAD0i!&H`$B z8255(kmRJAMJdTn?2}-mj8VkN2aEUW3^MnD;#?b@c z%w~4Q+sO{IR%fesP_BoyQ^r)&_kHD!k+a3b^GUE=K++g?e6i+@k@K|tExn3Ag5P7F zUZTM#=`SL!EC@P^8-kScM99~#f9eMBu%RHo03*?|t%y`6Txc9&2mxrN8@vGj{rP*Em?ojo zZD+}7@nOTsXFLl}q@Zb{XdXA?O6_MWn!DA z77&iqHk+I=Bf(7_`P-7_rg61_t=cA1-cam+A&GCCH-631-{@BIMQvhhVyh*x&t$S2 zUWsp;hjtdLVO(YO#JPO8sbtZy42b5^xy4cW2O@y>X4YxchCjcKM;TG(*{RVR-rrcc zlE;xkL8>nYk00Ic%s7=-7-oJPPd81o{+3K znnQY8IV5}b8842ppgp0FNeCY!?iEIENtjfGy%C)5t+e_lEv!&y;DD#R$jkyXgbKZRo>4E3QU7hpMfmDb8tviG}jsffx=4_vb841{SuXg|OfStz6p4L23 zf&JGX`e*Ifz!dsTL}|Co_FRF4^%2YAgjFB@4a5_sz;7_1u#9^+)|at`Tar(v9z@9a;P5Sc-0^?YIhllvtgxF^F(~X9{;zu+uQ#d|Mw0)kPYty zW}R@YXa;I3MP-I9{}R-Tii`meupajisD%_^{}cuEYd% zPw-odtN!G{dbzo%a_tGZZ}glNDd98 zkN*mK-S0rG6rKdsrUQ>rC9xV}i$0sMo5{RQjq?BOA|Aizsr@DidKhFeji`VQ6O@Vu zkNUk`R^VR(q3(g;ZB(Ppx#NheB9+4w>Gy}BW1T4ekqaYy* z@hZCM2EUM+5u|x6V9qf+VF}Xc24TF4&@(0PYVrZDz3xBYUxGf!Rd}f)HEbMWJsVIA?5Dh*&?hsWyq zn2KvuBx%c*KjxXhOX&g}E4dms5xt%&+t`A*!67J-qXS!DeH6R{>`?k*5HJ{J+zBOK zxllBb2PXobCZ(&Wja|xTHIht z_NQNMTM^#}=%^?iNa;$XFx;Fyexvp zlyK;jGJ`hVfRRoxlOlwVatyid7E34ycg(`GR%n?neccH_Gk>^!c|(71x3>zhc64~P zPQhvoho?5o3Y0Cg2ixtkVZICm22e<8Q7R0+4MN`5P1x?H0G=z4d49homaB;#q{S%Ra$f3Bn z$m0e1K}v(#tR>d~_Zr3!(j}lcUvzO}fV*B`qvh=$k)jy6fSU=axC3dz={%ox;6j#2 zEQh52yOZaye?Ea@^T$K-AH5RnPGSrL!_^caS$(r;tXVW63_vp-_zKsR$$}hu^TjMF z-~dPH4z2eq83mbVpdoiY;es5ZLn(6*K7qTU#*6Amo@kB(KWNhjp*)Ju0p4OS({1B_P%?9TgR3^31mo?})tA2Fu{=NzBLA9&Ol;hIz2pH@m(ytaV)!iU0A|q82!Z8v7*h4(2kXpq_5`FC?safk+QngVa<)?%y$l;7r&wmB|ZjTGQc>#IU z;jjqXg_vf3S#27BS_CFZ3&<{>`UVNEKk3{Q==VAIc;g7+5*0foD;22Bw!DJ;^65gN z0y1I|ZeYkH2HnI@)f*&}cn;eG9)Xrw?9>3^*5na1RE{^WElC5k7K=0GkaNx?LBXqQ z!XCXPR95XHV;rU=0x9QbClMQcI7pfA$*&h+8Ap~~G}CWxWHh=N8zDMbMdqYr{t>i0 zP-wT;-76OpnVZ>68$%(hu#6IlP^Zqn5M>%1&ei9HqLV2-Nx&h3$o&O`ti&DuDw*#N z2UxshqzJ7N6?%nXOZ(slXhBEkB9(#a#_u{WFWN`H6 zd)iT4Q9q+@=@_O%%zur7l#Dg)v9T;)B)9`1tMH z*Kg^G94um_HkexYAo%pj*9SrG=TJKK*>}WE!TbE>@uq;S=h$LNj|K`Iqz&740Su2W z^(D(;@qC8V#)Bw!6?3nJ|;vC#9&MD^+hsD zKs);}i2_ztV(WQ)K8;BKLo(U$w$%KtV!zPqc{rt%cvR+&+UP|>&@`QG2{>DXsY#05 zex)WC3Mm^guO=MA&Ve#y^El>hOoU6awGGilXE=np-yRMxqhvlDZr4{OBVUCv5Do`y zRJz?*kf%ctgKk0SVZrQJVWiZxZ6LW;Naed=G0_65O_#-?bf_i}%f;}jsilkf8SHs- zG0rKXt+%9^vQyV)an=xf3${T>H z{#p3d9Hh>tj{V1a*`F)zKlYyP8Tp_4`(N!p?&RaQ;!q7Yct&EceFiJk#YbKBBp(Q4G?o*|cMm)-kMdZS+&Qqb|9j*p@v#&hOAaarf>8`jz_8fdL_y{t{K zxPO$UHF8}ud**PR+vXA^+nqC|iMf4cTiJ|qoot~S_oeju%?-@vEZ5T#f1|n;WyG~C z%1hMLPfw)War1KYGCH!|Mwg)4@1=2uYuru4$9q3r!V5Rmk%B7`020NWQ}yP#6HI4m zRGdkXA+1YPTG}OzbtLScHC)LJZqC16h}$m2B}PM zz8Rxu4WhCI;kZNEDm`*nxgUp5c}M=0_8uJVId1y(XubOFe#ODSyySOCTZRau-1#e{ zRL1}ya#;X~mbg$>E#;~v0hI*}%K%BC(&G5I``dq?hvA(Y0a#aM;jjr%4&C-c-4|>i zptE}2Ou&8@-=xPK9r{N{Z#CKx#^Cxo0oKy_9O;e{DFi(*}kj8gg<_;0~^ zcc}iN!w~8(#h#!eTRIxr0_&z`ESb6j5iifAMm{noBP!dX=4E5vsY~mk`d(cstTMTc z-LJ!E{cCG=t?Ap?EscWTx^H|4o^4egiYM(HY_5E@WXpMruCMY2u#Rz0Q!5`e zF%T826gwT$49D6EU2POcw`4|O*||s;C-mm@_<8}RHqw?w9_A?A0n~;GLV4j@!raYa zf2RWiF5Hb}D|F^&Qr1#YD|L*sne!c&@gOANjjb6X8U$gZ5 zT=E#Zilg^gJhffr9nEh#)FB&RLQ28$4Cqqa0*Xhq?)JD|%z4KL!Pj`$VO!Pfzl;7PF;s^U z4)8-FeB!*?0fslhPdD$13?jsk@)BDtkI$}giHgwTy^L@aO~k+$=&K!DjIo825qdq+ z{C<;>8Hv_;Jz_w~wh(y=;%GVqy5ssst3J8@NPt|4$Z#04u83rbyIklS;zgPlhaui` z!dD0?OCUNFuyq1$0Ef)DHJ(KaGOHCz>aP9%~6lvW`Az#VK6JFNc8x6cn;u${F z7bI(!%sTjdUvc{s8m1am#jHdZt|HI;TbStH)>{ZiLJ^jix4K9dt+#QWF0*m`3pLJZ z3m_Ue{5a2qc2H=P;9G%4HUGDPM)OJ_@7FH6GsJ18EG=#J%aNdxMMjOU6Nu@=TJYtkG@6r>BD4A;jUL)Uvn15=I)&62 z%p^`)pscp(>@RTb;WYMG!^&===f{MR@@%Mk<(*)&-M29@tOB_ji(kbu|LBerWxh5t zIGT0Pm;#}~syhkw^IKWwtikA4m^;0?lm_f~H>1|cG~`sv6nI&@DB!q6XdrWOn36f3 z#s#54nt9UtXvBQ~wcs9by}6jB!b<~xpe4{O{us|%Ou5kg<>>9J7q9->L2W~v9rE-6 zVcRKs)}mGCWNTJC_{fV#1K9?BR!EST2}jSt44+flxkav2%c`)Ls{!nI7=n4g@-p2m z&HAFg){J||(=N`+JcWAN)F|65>|cxkLbjRlEv`C~ia}GL+x{3=kkmsaCQFPmHk&{! z!`4X6z+y@G(eEjVSFCJ9ur=N`E<}!YxdK1Sd2cFgU1*0u^Y-HC*~yE49)FR9s5mLRqIhy1S6{N60HAUip|1d_81AnP62GFOX`^jW@ytFGy4?d{ zR~K;>2WTU#S+hV&X}Ekw&>_QNuT9fc^+Si+W}SnyFyMFcVM1VpcfjPU+!!5NkgFIp zXXd64%d1{11riKR$=djH37t%I?5%dOdK~~qjAk+&s(auKl4%A5i09xGAR4-E2j#d( zsia82;DSAjCv5|C8~Ip{%`yRs-fr505O)M6TCLB1OtUySpZ`6+`Dc>OaORv-wo&4h zw3Dm3W=ot%IaYk-MSfo72xIe*xX~PM%W`@PH)I=591Z&mRV!!52V^8_MyBn2fUu#|R}`b#Nd zsl9rw1ydOYZnJErTxP~-!mti143}wiNY9cyo$sU{<7^f!&RiYb#L-1nC)766Heah+ zk2oA3eRC#D4R%-vM*`$3?D%2Lv?TO-7|5F}Ju#CCyj%sl#m-1MeB?Q_F;KAO13-0Pz&Zp;?0-o zoCuDK2y@m_Vx+-g)p_JLTo(*=ekfxLHzBtn-pUUdzfs<^%U=qh zczTn>Gv@m)jRTbOm>yS)hDBBa_zln>VMl?ul)G))(>D|m-+V(+Vyt4>rn4mvrOj8d zQUVcb+rkb39WkO=6Vjg(j*C)Km0Ncb~BaN|)QBL+!G;kCUv4&@dGtt`%E zA_e4^)<$IcLgrX{?jog?^PeTa5do=PQDERN5Mm6bEQPd|5IZIG7gr)Gm6%e-&mP|l zIol^(Y|@rTVrUUXj!i;KLop>q$^!0ipj;7OWzw9a!5{yKx><%?+62qV%YJSDIUwNv z@sGhQnx8L8XTf5&IL|-KR9Y>GgHS>!HxMfKhBC=O$ycvWUOYPv&+1%G4w#B{)yv6J z0OnVd8VTvQlg{q?t97RnkZ~I-rag-<$@$Yy!}c;RD)ml0i!8=xp8c#j^^V!v-5`08 zorN(cPAL|){7+D)*_GXHY`XcXBSX%O%3FEJqO{2SC1Zr20}D@_E0P|m!nwiR#=XkE z9NbGPz_`u)fc9OsTO&hF9bRF?@^Qx`nq!P3okDQ9l8pgKkoe39UsFF8%)GC^r152B z&S?q%q`)+gU@8xF`G99o=O9|woppxXh#AyDj1|6tg0q3ffYf9;)+9L%kUD6FRH^Jm zlwSx^UUh})IF%F#9IbY-%?zc-vaX-@d!1m=J2Ny`y0!|7nWfU~GAfKv((r0=&f@V- zX`vRi8t56<3kGbhh$f&PvE0=WIVbe{gwKu0mqGt?C9Du?xNqKL7)rSTDL1ITOU7b0 zWP>Lh5zSV`c_*OtExO7TCZJz)0{ZI3xbXRNr38UE+8(8=0+Cd_D>V)3-qOEOYuC&c z=2Y)WO&+Qai{{xt>t6G3teUIsXd8^!RqT4xu2lu=Q@Cinc;8@6gVtqr5-p2hOIX%&Eo+*3Qk@> ze|->KMmM84m?qaj8E}zE>gPm=&j?dZr@^*-`>-91;#qptm9`pbf)6$FB7p2Vr}kqs zi+N~3Bmh!anpH)54G6b|LXf>3>V+Mv)};(QUu2fsrtlQ5W6p$E2bM6~QEL2f^jxnX z^)pS#9+WeW1TBbw1YactK>E41mts{fvB14wgP4tD|- zl0yNlX;SQ;Z)FBFrfkO1q)h=|03@}Q2IN&3XXL0~P+My5vUjs8_}|pu>9u8rtVE%RdV}P<1{0I$w^_-xS%+SUpOsxmwwm@nBqLR+6XU6?m#s&^PthWHb5oFAiCe>v{qaqj z7a-U1N8pbKT8-j*h=38YP4hefxM+zj@`ipJUPcg3>J#m^3t)E1mI{H-x-8#rD;$D8 zAqd+Cqy$#O9zIF|-!-&veO7xo4auCH@iVmkYC6StEFSt+3H2ene$WV~BRv!o#2(VU z3g5N#NdZs)?0tS%!-AO5%~=VELbIo4N7CxG01BUE;v#JL*uf$j1c6J6V+` z0x~#iFl|3RQ+I)Lc4;FOz{R0jD2-|K^$tI}=;Eco2jA;i1+p0x1w{XNoVPo+hZ1p| zD#5gdpC~MZaeRhLqmcDHbd_QLR&9qc%lZbPkhSE+a;Xr5Bdg4x+D+!BTp~(-CfiIU zmy204PL!#VZF*#52t{3|S@j^tLf!>j3-QDDD1qtRG3Omxu@pHL=j1{4q^~*go11(q z0U%qNN@&u9$Rd5k#QQ(CTCLmc-~!K#ehK3nrtSmasRh0W(j_ZnHv!pl8>@_e6y zCiV7)Y!IvNSnZ;j)yDi_#vNZ5aRyNY9aHVNyiuq?cC@)`5@;ghRpA9xYtm7cVpBSO zfijFE`SjpSDs(!4m*RT~@0MU<_);)2iG5M-cBqfEK6|U~qMD~|fS;|&%PQt3FKAjL zX@1z&00So5TRxc*NPC@N-@iDmw?TrYwc|yA@JXr!^S%A-)_r&U_Qlc57yong!^`7t zxogYn5xp%*G2&@Vxd5a<(MSEL%s3S zoa_QxicFtaAUiO%yu6u=!qQ%gw;;?UMWvQe>vIRosOPkGdhC0rrN~*qBD)uq(lfYl-<`B-8E@{2OQaPtl^K zyb*bYNG-yb&cUi9W3f#k=x0ZdeoADDuwADLFJ6T0I@g?RM2Do&>Pu{TqfE_)Lf!$y$ivRs&cW+?i|K05mzQ+H)gU<%z zf74XH5d65;>%%V|S#qV= zs1^4LYYHZ|?N??i(mm+bj1Mm52q{^<9d3*jE+AVg zJh5w()|lZAXq4FOc9b>>&hCQg_G7eL=b&DsbO&yDymT2Y_Yg4Mh0+HTH(f^`VqZ1{_CNc8Ory+O3;>S|dzr^f zT+dr!8BE$-TXNuaU*3D2TU7HAd(3Ogw$m&Mdou~4!31r3SPcStYbo_Cf!f!YTw(d) zo8E>YjosAH9Ca&Gh2Dr6NccaBR?e(@rxXa@%#dwe&Yq08N;*i3FtV=HIIa;SUZP?_ z#99!6HHf(e6CYS-GyNL>{jTD_JBY>;1zwjH?oUbwA9~yC@%1EO}9vOZu z1*AJde4R5(y*Tm4Ix2-gzDwB1t|IWMwN8^D&DI7iQJR%<_TX!ggW}|neb(-(qoK;X zpCzE@I>4#%nyv6{Hhlbs^$IrB)C?wXB}o=i-lYlo{f3seW70ML+YK~-7X;7Lxith( zyDY4SpVz2KJqUeeaSd3UJtX}@V{&Fx`rG4dia&)$Xhx*^dnGt|X(@-(O-`jOnyeC5 zd;^qzXZv#H`CXd08hmQQSg0aK8r=RXMcx%ft`MWq0<{rqc`fjykoRBEg0aM_zpVvh zI}6D@x+2$GCi|!;vSdUCZNK=cjNq&nGp7wS7ZT7$Fe9S{|MK(R3*RwQ(-yLIyrFGj zxF*Qg4hGGyY>S1>cM^@?04b_g0QjTmTPM@5i*V#$%=kffbFR1_4gOBRZN74Gk z;zn*V%)e_Jy|rln)mEgxrK#MA<_LI*IRcn|+@B=C zSI9-M1_6j=wtmt8Y^q&j4j)G5fJz+KNF89|!g2xudE41k1_71l*aFl$OH}0$sCC$C z!d#4`0+uolEVY2bcsH6`z@Rtl+*Kjyi%v1%NAAiC*UTuOtxJweix}v+DEH?VaBJ#r zCCh*p&_>Ay+<==Y2fTI!mdpe0wnhE{`_%9(1Z&QaI~&33)72y=fnhCCW+t$zvencC zbzN#}XDFZzR^=)1>d|i{U4h3H#gVkYHGN9z0?9g5-kw%YU?4hekj6l&<4a~x15{s1 z1JO%^#0FBG2bA8xM+$n912KZesSfHmkAshp<+4)Gdq9gA@=|sF16I-Kmt`Js-jm9S z5R?s6%7n0C8y%%zr+1~o*=&%z!_gl>gSKe&S{!<*T+J}_)}FN_3H4n~OyOv3$(10r z*Q&6*TPbyd7yT8%8a9U4T9)?@GpB;S(5;yjoK$QrZV>akW(gLII*rKN4w5y^f{WHS zk!_(#pj2%R+#$}H=F$`6TrOb`a_$ftOI^pkhd1Yt>fzXJa*if{Hi>_}%0xgkO9*B; zTx2QPBZ?c_lr%BY$zAit0x{loFl~b!c;mRsP+P)kdvqpJSu9#3z&347BlIaKemNBZ z-ad!zmKJck2GOrc_?sjCaseQ3(}UAHmjHb3F9N*NaQWfUE{(ALWe~2hKY0Si*Cg@^ zLT?l`Uirm?JGX2kdh1c;YfZg1w!Cdit>GZz3zxl)X;T9#xos4gD}_Pp8+%=nT|Hj? zgTs@EUEdT{wam9{w77nx`*o4nDBgW7jDp5RK4v_Su=mXoRoUhG;z;dS_^KeWN$y;0 zPIh8Na+sR>RDQ` zN7mm=40DY#?D5A{eT>p}X_v^R+A#1FQOg_B67cD&d=R!P6vGS#GtYKDUSwyidH8f~oinW~p91 zm8@pv{x#ECc(h^|97MCD(=tXew}l3$M2po38L(tC0`}RESru!6(Lb-q45?vSFgHjS z{}+Dt?jEFV$RP#Iqlx`}M_7N@A8-7B3=_0^+<*S@$N%5m@AaQ*@&Efz_n+*3jsJfK z9~Q)&UFfo3JUTo3If;rGgeR{`Ir6Ka9U3Gj@y>-U&*M^8%b%yp0+B z9S5h@8OHN*Iw8P`tN@Gi!QzHI9yu|Df3kZ!UF3# z@M6<2kKS$g!rM@^jXBgZG3Myk?a{VUWy;@uVl?}i(TC-Qrz>8jvYx7RQL>A{itOWN z6YB1OTo8c21DF3F)C^G2pvCNte`5U!N2^fr?-PQcdQ!EnKDK^oK0H_XdR}XAn72Bs zK{w5rgM}|paU6#1SZV=VH|l%x;?Vj+Tcc2hyM-#{lsSem#Mwa}kF&V=zwzh);;x#z zhu20g(@>C+MxoVnhPgL%#JDewJ^I_~sckSp9=4Djf1hlr$|8L_JV^niUl|%A$wTxX}WZi`0t`-H&mW1|yAXB(A}`wV z3V{=;5^`D8it+BDgc9!U-gknJaB*j_S7@}G6fx;bU+mN1eej1vc?U6e1&MGmLF{|v z(jS#_COeR7zQ;950HZnd6f_XfJmV+7l;M-#`ec`o^Iqgaw~rPgaK8V181jx?lRShQ zvT~r(HG-s*wT|2XSuTS~O2TLX)-v>llWi`{I*}KZ6~B{s2Ec@G{(AK0&8wrIz!4P) zo9wWMc-N@WzHz1S%{T5q<$P8QkofF)XxR#FPTuO!GFMxaVm1J*8>CZn9MZ)D1;8Ze z|Ma;&v`n^G8}~53CV<;z2iu_oP|3Ll0z%c?acE(*Izd8t{r55$wRL-`Y~hEa=Q@p< zk*sP$XI3ox!CX@fVfD4g0%(O6A!Cs&;#tCM-phTRJ*_h&k+*BY zLzB=%d3}GVYPeBh2?{H=N|9_&7s<4i;H)G-zH{`cpaCds^JJhHTl>IvBuQ1K)Z`in+wcf&uB*RjT z6*0dqerB(^TPl?Vc-%=;d8^HglBuRGQ)=*7U} zHoj)ojH-0vt;g$hl^9LF25$f4Yw6DwnT7?`2o}jiCoVbiSiPy1BXra$q|=_Q{;eU& z2q#iXdTeRhN3E^pxDZPjeBHN?m*55W?c4NHxT3>HV>Y~s!G=|iGAX*nZ>nKYI-NqF zhor^svKZ5!EmDx*_qRZ4hyMBfw!w~AZD3yXYqv;?Xhs+bfo+mgr}5n(_ANH{sME^DvA#!++B^y{qgndACBJk zw#^;E5xJ_@lmO^{0rSoZ0McuA);Bh31}{Br>A}ysc825y&)IV$3^qbxe|_)0$FViL1-{| zAe)04H!7ro4&0!_s3-AQzFbk*Yb#t9)9*l=@bk%!_?P_N`A#-25XE+CmK)Y77ca;E zh7pIyKR+A(?>F#`JQ|W`wxT384lf4|e;m&@BPhy<=} z#M22hw0am3n(XG(lz*C>x3)E^+U{U*qbaJFz_6FRIP)kGOlj93Qy@FIkgG+X2)|A1 z@FkLyVkg#sw#<4p2+dA7ycJMu4nIa&rE1ehOm@}ZvzIT9U!5GkdiMG`L_@>|suX{o zWSKxdABohK(p$_o^uqt$KVG`;3OHaYF~i4ue?qH~O<^&M zh%^@N(5TPlgCTpcT!43gv0CJ&8m$;fIM?u`c$NtQS?!1@t)BV`FQ(UgeVjvq;p*J*g*?7vF-sAbD;N+b{n6N>-S|-88mm;-j>aLY|r$1 z%J6B0{@`i1NB-BB>eVV1@XOiqomLZiw_DWNI-r*Mok17>R{@QqumqD@Vv~^B@&wc< zy=mBP8H`VaDgW*DyA#Q4LXzmha>F(Vbbaunf8`>ekLf*D3x~6>f?a(9H+g(a4$fTV5 zX>wgGvsfCj40y}5(ZScyEP!3wXNQ>if_s|S#9-lvD*2vDZ~5vbZ`HN>S&myN00dJ` zGA_Kggt=?o!r1=m zEd8JM@%Vo)ZZ_ci4IjV%_mllT`L6kYKY2Rnef9sogAem(J|A;8?i{@(rC-aj@C(0) z@{3tAqCU}yaIyXYSl5f!oq&2;zIaUwWMn^ra?E4;B2C6|2cKfxD%MItcDgj33D4{C z&3G2C;$yz}V11l_m|35rWkZgpAgVL?;sY=8Bj#Ap-OCp@{QWcXy%W3y`@UZ?7)U4h z$1+~V6MXbMOFqJ*ACp;3U#l%)ycppie`D(mqDl+IKz=~e-5rZ`FY+SI;?m`v1)!mi zZ58Ir%Q#EMyvB=pvBzEAmqk*}Mhx+n&&Pxt%s|7swM8ccL{Bg$vn!hcN3cWX(Itl6 zr?;UHA*HoP)^?9<-@V?T#|?$Siwa)s^{9wUo?oTeY!Z?Uo;AU;ydMT3&-acE9ULTZ zV8PbdcWN5EeQ*E)bL579e)*ET#fG=rA#WIy-NSZ$2#1GRpGdq}63yh4_aGH0VuwQPAsc^?CvD7Uds&xGR3|;kWO{!CquO+usw<_Mdzg zJlTIT4xWskOt-cm4u@!VkAC}pOv+5jhyKIg?gvkwKA8qj2T&QP2HxAo1mVPC(os?w z0jYF>!Y<G+GZau`J#Wq1tu4jgES2=qO;Q`!F$1T7W>0(DZ%_k0{EunmZ7_?sfVWGo-r~J^~`b^-3 zDVdp6`smroi+>(l>;eTSP zFT0QZhUT_BkLO@X8H15=Lgu$mU|L*!ZcAtndB50{1=+YnFb*onFRjy%?8kedX_q2q z1G8C>ZH1;8N(lM&J9LXlFz+RXPVM*FXLmJQ##(b1g)!1B)4^#71el`(c{0gEc?vOF zDGpO!pPhhLUv&;cHj4`9~^eKFXciOUn*WoNsJ2tlXfs-1U zGCYLzWk{2D*vQEZtU(*BtyQVvv_m3)Av$MC!b^3I1T#jd=|fb8wDb9)y*AhY+GxqC@Pg%BR^#AOr{E<6-b@ zm9Xw|Ry3ryIU@pn%qd2 z1e#p)p3C9qzJbX36GaIN86qPceMGV4nH$8X=heruq61j`8%Y%5rXM#}U-1mk695WfJg zqe1v`x49kb5IV^PI;xe zZlf6ebKr!@js0kt1%b@ z0}$HnPi-n;J^?RVNaRWm?o0ryJ$tBpJ@)0#i-ZoKA$BHH&}#6yWt6IiOR(LDdar z2XM{C9^o_#pKyL-w{h}l3E1wCI%+bxd^y6P!8}1&<<+P4-qT`nL+6s))x0aR=a>u% z@bp8J$MhE^8Rg!yvZ)p%B!U+QL2^D%v-otL?qon(YC>7kJzWEYeTf0~mN)cimlqtaD!tG<;SSs@+5k2PT>G^p)Pf~rMXm9UynSer=axR=Od^SzyNq!O6lCv9Tzw@af zELJW9#l*!oBaYh?Dfi#T@421$gZS_d2Zw!XPyc{0>83;$@vt_}urdRVw;yf*i%!HT zqtg^(-_GrZS36+A((ko{>(*RBXes^KF$+fyJo?aRg!*gvZ0^jx2^|H~8EsgSxuweo z(;||AuVUGD?4UO@=4{Z5T6*Vayo3)}{I`;}mR2NTK8AQEOr(>hW=2a%ML&0ti6`GK z<9TuB*mH1UmKVKuqcz+B9SzH?y)S~I46}-&o3xb#IBH2yHpk1X%`3on_pFL$z&er5FcSJx11NPZ`xZ5VVq~_a)E?F#@7jUw}h#0C7HlgYbT)pGVEB1f*G+%BrydO zrbF(W$gT7m&a+o?dj@llM1?rd4og?R7WCfU+=Pp%7DFTKJ$~QnDW-w=ocfV4et1k?mFUo?%f_zPO>C$2wuz2ybseaiMv@{KW{q>Vl`7}BET#CSE zoC0ribY_~{->hwWBb(m9#1APE`pj=soR*1{^%rA{l>ovy`Vg5sgbq~Iz zE@jg4kyi|JC8M4_m6v_M_=ZI)bD~GVTf!D6gc=rfbHI5ZSOqpWigNsp&+v?OMGk@# zsu*%MJST$jPt7Xwkxpa zM8-qIhD5Qtk<9K^tw9gOpgSzb!{P2Gh68u5Y%p9e=$E)jDerg&wiEs4I0LFuJ>Bnn zEEj)>CLn`>ob{uu+^B-Ll}xG(IO?Nw1(fdejdg=QMYYxFHHGEf&X$++VLz->abQ;54ej%)$U-D|j4dF&P{g_~jx%A`Gqw9kuA~1{na?Zo4*? zrp5r!x+IBIP-wNCOBi)V;eBi90LL_UW(_@^bL+&KxrMJl(Y zg5!%c&EsJ{zKAcQ)|~9ls<`^;GhI;RuUJcPKD0-WFd8&NN+{s)fE9#F+tl5GV+QV5FvEMU zrNiPMS`gV8ma~@bvyqyRu*T`? zL)jJ=xw{WnxCZ@GkR99|InM$Dh+L$Szg75{p&j@qo~c7YKILvuI=a z=-0io@!narf6=XqY)vh)`B=qNYg8lo(`*}AWuvOK1?f-jZ3nXAsI(wc1dNJ)Y{r2~ zA!G8X%;BIFxEEkTza+>T#Q@mzw4fPm0Oa421*n{JT{^NuPs^}d9Ok4en){FEu;FDo zp`j?**@E5)!WVkdHIEs%vZ8U8<}Nk~Z7R%hRi0PP-})W@`+;;ZqcH}?c3w>4d6AH1 zpHc2J%(Jm%-GrS~^FLcL>#2bj*3aMEd(&>eKs<&28XmkRU|fRHTF=o@0Sz23;vl|W5WwR}Kx6&Ta`0j@;)bca?yH7?k?=A%P_+hC?N7`kc}um>me4gPvlc@?HP?frKTf zjJpV16zYpPTQ2xleU($sZ}_9WpuLh;^o#nk1O!qXh##f6uS^3}G14^)h|QeM7SDzR ztS*ZfY=9KU2E&~JI_I0Q)-SUk9*Z@PQc;N@uoH(YFZTEr8c8De3BDDnW@>QaXsFRi3RzV_5|99IuC=J%@nu98-?ix(3gRjjk!BkXG6l3ucY}w+eDb?9D z_{pSWiTEKYA47GLBm-g3G?noZpzxt|j-W9WwzPukYc&=)j2i6jDEE*Dd`X7OG9!Uy z-eCVp^BG%jid5!~)ok2d?pHO6REk}8my1cH8g{{l5$|R9BEFs^=MZ1`Yr?oM{o~F5 zMsskkodvEU|J&2Or+qE|+o0Fq9emCIb_bt|{BK_~z9|{sj$l22ePu-vo(>LwC<)^5 ziDb!O%M4c|?OWaCakrNlE`pngj*%damJ}RB%t>iF(NS~wbSx=-;KVaeKSUL+(TL3* z?GoRxdT_NO&X66|mrP4?NAs6iaxQm_7e)@e&Q`-*1X>zrWWpjt zGp4V^U7NU-363iAkKO7NuabexMFlhu86yKnBC=I+e}DPN^hsJRE!o|!(^V6bX){}< zCsWq8BR^U5sr_B0Dbu*MJy}`HT5A2IW%s%bm=v;+CBHd#tIaA-Dr(}XK2#*Im1i^; zQ)({#hMCPaFgY5=^$ceW`L~(kOq)gLG*)IhYlPH>3D0QTTG}&)99!PAW&<#ogERYC z!!d3o37TtH7QuEJtNm6$9~^1RxB|GX2%&&yt?H2XB{3j*ft?jUN?CjWSJ9KN15Xd!w$ART0i#;*mJyDvA@ww zZ`K|*pYP4u&243UbJOf-vH{=1Hd2>8G#-7YjM3RyM|X*OWI!V!38Vfx8z|N?aQu@7Gq4MjlUY%?Ha5P zuE0mH2-~tyRA3v(c;}M>Z(a0QCGFRy#T7*NEoZ^Ir31V(8{Sv7inHW>Ov}xE9;#|B zpu3uz+svVNOS9?CrB`c48wP)?R`0BuQ?L4#&CCb4c{>XyR+S8UcZFGH_$#H|E9I;Q zf%Pg{RCZ48+E9MK|A2XC`TsUD=_};{Y;H@v)8Gg{p2xkT5v+A_-7XV#ra&|cn?PS7L>(bgSi6I_kL94Q7J^u#PfWoojf zRa=oZ>ey2WFH|M@AU@qt20|yje9c2B%6`p5=rTZ)vl04?&+d8M*fSJ1Sw{8J6xxNV zdrDSl<7zx*q0G}ZnMf{@Vl8iH6#*m}_DlBiub|MH|zR1o3Lp}2{$Rj2-Q2|M1w4cwZMO|zTZ%B@(#0%_A3 z7FR+w=2^6@JDP2=o|2@IS@ykUU9?zx8zYxfFy7VJYa5~4GBV2jJ1*e7Bd%{%zNtyB zO4jJWM|I9dZDexhM#amc9Edv1K+k4SJ>=h69!I~Uc|FK~r|BFu;*yg(-j6?Bxeqta z(Div}6&oyq>6;P)m{6o2At|QH zVdbqRth6!R-*MVXf4o);Aa|d<(mcx6X>^l0EUQg$_0PR!vh*K5S4_7?8~q(5UAy(2 z-gz<7V4wcFKi|&&T(u+qep6uH^PXnKRO3XL6;`yCqAMlEv>rH&!qW$v8uNFuA&G?@;DyRkf(j1h8$fXo~XH94bSYbs6m%eC`pmQB~lrs*zhJ?hBCxh~{xGi#O* z)X1;tF1-0Ho7x7rsa%^{v-gm3v%C;)ly|da-)m&wEc>pRgVX3$&&0{Jc}~KxZW+F< zf|prwhp5ccS+cywxgsswVvUTEwpw5FMw)pe9TU?ukDt>k=4%eguQ?G!siPov$w#($Z^0sJvk3N)MpR>h6i zQdQZP?>lkdhCc56kGR;@&ix3Viu{j*-F-d(WB=*kY424NQN?6CbNR@IJG!Bv$3LY)2p8%v`n$2LNwAJPLt~)m&4fueN zV-ql&Eu~_viuEP}Ali)4KP!cgEygo^_%FbAl?>Ui6t#_Ydzz-(T>7rjw=`B94;}JQ zpl0Q<<13!7MKiRpMx$wm#st#LDniRREVYdL8X9!r?3S@Ecjv<(>YW}63MJQAF$M&1 z&~8gM`gegk)~z3Tpu>2`xI-Na&7;%1JJhjDfGyc#47OhxRmN49%@W#)H5->Ob>*dD zBo!d)OclhxVa2;xg&XVXhyzb?@(jNl_XP~TEBTC7g0nbhc>rp_Q*%G%P5S1TBT|%= zK%zmHF5^6p&YN&lXiurDo+)k6J4m~tSx~aRJAQfm?1YpKEv+j$Hnnc6R_o8+9v__? z2Pa2AygUvoSAi!ozXBGfSEz}xaynS`Auu79G$L;}D|52o^0?4X`PoOP=-QP<_5yQ~ zb~PlDhLT*Y09|B37C<9ggrwoH(>~M7$qqq%C-haV6Uh-{vB1B(mR=la@UTHk4Rd1h zm~dXuMbwxSC(0k^m>;x*U#Ph<{{|O%eaO`bxI-w;smKc|?s6}5c%;{_(hb!_!I zL62o-?uYft_gQ%WuwIQpiO?Dtci(g3mWLOeaJd=4KYxbHO=FHQoGx=Iqk=izE$cH} zb9YsSS4OIX$H$}+3s86b)0>lj4gc};@!Nl`$w%x`93LT^9U*GRT;AGkp~&gkX?3Bp2#cM_N=KZmenWzMs?$Zcc7vP=9tPhcXBaXM;g zLY5Lqb?&q-Ap~p-t8nYSK<%?X6l! zD~BvgfMPTRQ9QKV^@Ua8TON@BPcwFUGIwNeZ@*fmw?dluYt7OvHEM#G80ZaNjbq#|$T zC72SC3FB5_jsZdh`r$Oma=sd9#kG{1^nexxqvRZQha>i_9aiw&sWS7TDKYJzC~!18 z7!jDY2MQmSv@xf;tLTp#(+Ny8f=-!~B)xCkO*^Bfl087H($UOV&_p5I36|_OFGRR4ka}~X;W2k_1 z$JUij1eTuM)(W+dqs%>F)uT9Tc!4kKRhv{apGelSN*`{?PpQ#wT4A78z*X7rRdhlt zW%K+1&3RABT%B1wddC)vA*HcW!kg#ZgI6g~>Y|bgW3PP!Dnsn%H~98j z_}M`%WaFv26_!cHdP60{N%jl`6n8TLY38`Gq2}kEV1Tpjytl!i{uv(Yuw7%~X>L^I zu8+q5u`LSp8pNoN<=dr9r&6L$KQ`1>oJ+$O>d}f7*+rD~0dWm74NiDX;~k_|qkz|M<}&=xU98XEwsQOS4Lq;6C+$8;$aGM$lRb?tuH^JPOizP+Y{p z2$G!;XhsTI(+tXP^HVkmI!v1_s+kFZ_3=m2=pP5H z4@WIJSd=cn(t|!1kR zuA-Sb4oW(PsXA4r4jc>+#-LQz)JHy@{90q$B^`~zJ#}1pL5>-hwT#7S3=Zj-TOMe- ztQj$PBG3Slng_i>f2Rlk-#$117un!Xkc!!%7XWQ65%m&TLpR_Wxso^l8h&WTq#laI zhoG|bsFR|LF7*Hg&0yJPNm7kByY03GIm7%zEm4CZ2+v?DFVc_$A7}K|)iDRb?htcI zn%w2gI6ml+NWU@o~eo=%LxjM zLMH0zL~ExT8JFs8*l@o{MD2#uQe$X?PTx8-F>QvaGn%C3?~_F-B+lf!1nZhmAj^3m#MT%7BLZ7Vw{P-R$(;mpcE;dYL1&ySaND&l$tcLFNAV2a__H zv_`Wj6xX+R46=hr1u6@O(%d5i$$Xl2i!7Sw5e>>OxuwASlkydFPkHg``0d-*Z=HiB z!i73qXeL?~={O|=09FBa>cxJrmy$GEgO>Tne74DnN28Df5@6*93gRkl|K& zy4&sVkwauWPA(%<;nAbgB2n!|w$X-Yn`)Dwz=d95(ChbhdV`(*cl=Nqfzs+qhe11S zN@!#E&$%aU9?%S@7^R%bkg+AK`V_Rn&wn_2^CGw)USmdzN5V4+&!?SLhOw3v;UL|LIrId5QGS9XnkXFW`taGlk1^rfx1} zTuMtxvCH5WTM32lk%BmITS0?MC1tqsGI$q;CjAc)C8epe>|3H3#R+&Q&~M$z@^X>4 zq@o@E=5H_l`nThEC&M>yU!S~w_WEVn*K%$&GfSgM-eQjpIyuGLgBB#ThYSZGc1k@W zC$o*B8B_vvJ79VV3)(Q_lOX0H z7_KYxq033sdFvH|O~Wu2CZd=gK;Fi*C=O!sn@4ik5T;r1irYbS85u*?A2l$a3DwBN zA!ZdQq~z1Q+$r3FoO#|;MnXz}&55%VVV6|JV`-{}=?ejaD!+Y@oc#Re%VUn zTw6f^*`nB&ns?*VI*?|$yr!3h;wt9%E5p0jVDX__qd3qhu1avx=>#DLydZxGGZ)#E z&wMRNSNYhExWb3(+^PV+s~7xAgg!`rhP3R+?Z^g2z5uvNKy4)rnaK7?DoBrQ*~#|X zQUN778TUj{Z4|f`2y7Kp07}NLXMhwjZJkLUDKnFAg&w}jeI8cB3eP@Iffe3v8q354sZ;bb6TkT-yFCsmK^oC-FOcU)%Ip#=4xFrIMqyXnjf_$a{Rjw%17S77`j01cR zHeuA0SK~0u<>GW2e!}PTsw_a1# zpX@a?b>rbMelPiYHvOr{|1-o4No!^S^5_5A-+j8ftL6V0^!A?izvlnBgO8d2hi2nh zC;!jwr1Ghic}F5$UPk4#Z$O_b`x~i9V*u zB>3^Wem_{wCvi3>a@@rhMK(zKpm~$zeq44*s$|imF2IlzC^8PCmR*9CqMMpCQJ!`f zY}u04X^Dcc-G-Thn!^>CS$W*RN!fWU_!2vB1H4tH61siR=^@yJIdWxBM z&CE_tE@cp9Lk+=gY+4Gt^kjRovO0P5tIYXSrv>L;Z_oc!fi^R{kq3j`JWyUu<6Y%N za;ygCbGJ4L)z1#~5V7HNm%B|e@#Ku!9GdPkca(-_C4*FCHMz5GqfPTCHKJW9EfN$I zc6pT?XXELmtjJ ze9t+Sd_qaxTuYud>gHUkGf^V*(ic2oH6~_*s;Bi3UuI+aqL{+^Yr?oq*mPDV=VX0Z zxtVJ0Cp<&bW_HEf$<(w~XRCKmu7|bLH&xU37nZ}xLs=pMU=xMk3b~x@lXg29oqSBV z%evw(8D#oO5pLBHWPYqSg#P=*mnlejNQyT_Ho~TVuyOAxbj+AQ28P&Mjz*cP& z`J*WIzmP0a&fB|YxukTXbG9a3m>J~@k zABX_jo2IH!8~$Wfo+Epiw5mpLEYPNfD|zhJ6{PwSTKUoKPBT@h=tnibl5EP;P1BT9 zwq=L3*d+0krx7FlR9SZQBvdw(Q44=-Dk}GU(}YwFCVj<}R8=kvWl}22Rceq${WMkj zWuum?N*;alY*kK7Z6IBh-#%6c_*RovRSi?hT2*b;yD}PlhFWYj)iaA;QxT-)v#P(z zNLj6n)&@S7VrIBnwf?@dzCY)cv%&9N4QlzXR%oE+ke*f!$)3u|i(@Qk&yHmh!ixPg z&6H(9u`7L4Z5Y?++tpP?1}!H#n�mI(BE%stx1neK*XkWi}w?*Rq--Xj!(J9wBXc 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
<)JKd%MQ$ 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

-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

4FUEY<2LHg-<{->_Jv;nq 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 + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file From 24cbf39a933474d920c2ae805ccf5dddd3b54998 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Mon, 27 Mar 2023 11:15:13 -0400 Subject: [PATCH 127/167] fix heartbeet ascii lint issue Signed-off-by: jessicamack --- awx/main/management/commands/run_heartbeet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/management/commands/run_heartbeet.py b/awx/main/management/commands/run_heartbeet.py index 199412dfab..ce9e531074 100644 --- a/awx/main/management/commands/run_heartbeet.py +++ b/awx/main/management/commands/run_heartbeet.py @@ -15,7 +15,7 @@ class Command(BaseCommand): help = 'Launch the web server beacon (heartbeet)' def print_banner(self): - heartbeet = """ + heartbeet = r""" ********** ********** ************* ************* ***************************** From 57d009199dc864d25d5896e3597ca8f3525ead86 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Mon, 27 Mar 2023 11:20:20 -0400 Subject: [PATCH 128/167] removed unused imports. fix exception message Signed-off-by: jessicamack --- awx/main/tasks/system.py | 1 - awx/main/wsrelay.py | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index 6edf78ff8d..a83dad5ccc 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -61,7 +61,6 @@ from awx.main.utils.common import ( from awx.main.utils.reload import stop_local_services from awx.main.utils.pglock import advisory_lock -from awx.main.utils.external_logging import send_pg_notify from awx.main.tasks.receptor import get_receptor_ctl, worker_info, worker_cleanup, administrative_workunit_reaper, write_receptor_config from awx.main.consumers import emit_channel_notification from awx.main import analytics diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 3260182b7c..6baa2954b2 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -4,10 +4,8 @@ import asyncio import aiohttp from aiohttp import client_exceptions -from asgiref.sync import sync_to_async from channels.layers import get_channel_layer -from channels.db import database_sync_to_async from django.conf import settings from django.apps import apps @@ -240,7 +238,7 @@ class WebSocketRelayManager(object): except Exception as e: # This catch-all is the same as the one above. asyncio will eat the exception # but we want to know about it. - logger.exception(f"pg_consumer exception") + logger.exception(f"pg_consumer exception: {e}") async def run(self): event_loop = asyncio.get_running_loop() From 8c5e2237f48e10c9f9d52a4be81af23d3af5031f Mon Sep 17 00:00:00 2001 From: jessicamack Date: Mon, 27 Mar 2023 11:38:01 -0400 Subject: [PATCH 129/167] import typing to fix lint issue Signed-off-by: jessicamack --- awx/main/wsrelay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/main/wsrelay.py b/awx/main/wsrelay.py index 6baa2954b2..93e7527dfa 100644 --- a/awx/main/wsrelay.py +++ b/awx/main/wsrelay.py @@ -1,6 +1,7 @@ import json import logging import asyncio +from typing import Dict import aiohttp from aiohttp import client_exceptions From 25303ee6258860d2be75ccad329b4e97b5973193 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 27 Mar 2023 14:41:48 -0400 Subject: [PATCH 130/167] Only select task instance that are ready and enabled When select a queue for task instance to run task only select task instance that are ready and enabled --- awx/main/dispatch/__init__.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/awx/main/dispatch/__init__.py b/awx/main/dispatch/__init__.py index 642405c2dd..009438307a 100644 --- a/awx/main/dispatch/__init__.py +++ b/awx/main/dispatch/__init__.py @@ -19,7 +19,18 @@ def get_task_queuename(): if os.getenv('AWX_COMPONENT') == 'web': from awx.main.models.ha import Instance - return Instance.objects.filter(node_type__in=['control', 'hybrid']).order_by('?').first().hostname + return ( + Instance.objects.filter( + node_type__in=[Instance.Types.CONTROL, Instance.Types.HYBRID], + node_state=Instance.States.READY, + enabled=True, + ) + .only('hostname') + .order_by('?') + .first() + .hostname + ) + else: return settings.CLUSTER_HOST_ID From 968267287b9898f6ff5b50e6ecf6c82fc2b39a2d Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 27 Mar 2023 16:23:33 -0400 Subject: [PATCH 131/167] Catch SynchronousOnlyOperation and get setting async If trying to get setting from async context (in daphne) catch SynchronousOnlyOperation error and retry in a thread --- awx/conf/settings.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/awx/conf/settings.py b/awx/conf/settings.py index cedea3a3e7..8e063ec862 100644 --- a/awx/conf/settings.py +++ b/awx/conf/settings.py @@ -11,7 +11,7 @@ from concurrent.futures import ThreadPoolExecutor from django.conf import LazySettings from django.conf import settings, UserSettingsHolder from django.core.cache import cache as django_cache -from django.core.exceptions import ImproperlyConfigured +from django.core.exceptions import ImproperlyConfigured, SynchronousOnlyOperation from django.db import transaction, connection from django.db.utils import Error as DBError, ProgrammingError from django.utils.functional import cached_property @@ -183,16 +183,20 @@ def get_settings_to_cache(registry): return dict([(key, SETTING_CACHE_NOTSET) for key in get_writeable_settings(registry)]) -# HACK: runs in thread in order to work in an asyncio context +# Will first attempt to get the setting from the database in synchronous mode. +# If call from async context, it will attempt to get the setting from the database in a thread. def _get_setting_from_db(registry, key): - def wrapped(registry, key): + def get_settings_from_db_sync(registry, key): field = registry.get_setting_field(key) if not field.read_only or key == 'INSTALL_UUID': return Setting.objects.filter(key=key, user__isnull=True).order_by('pk').first() - with ThreadPoolExecutor(max_workers=1) as executor: - future = executor.submit(wrapped, registry, key) - return future.result() + try: + return get_settings_from_db_sync(registry, key) + except SynchronousOnlyOperation: + with ThreadPoolExecutor(max_workers=1) as executor: + future = executor.submit(get_settings_from_db_sync, registry, key) + return future.result() def get_cache_value(value): From 4b0acaf7a1279e1d2a33b379cafb9969bbec7a15 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Mon, 27 Mar 2023 17:16:29 -0400 Subject: [PATCH 132/167] Add back missing rsyslog.conf file --- tools/ansible/roles/dockerfile/templates/Dockerfile.j2 | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index a74129905b..e7218ce80b 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -194,6 +194,7 @@ ENV _CONTAINERS_USERNS_CONFIGURED="" RUN mkdir -p /etc/containers/registries.conf.d/ && echo "unqualified-search-registries = []" >> /etc/containers/registries.conf.d/force-fully-qualified-images.conf && chmod 644 /etc/containers/registries.conf.d/force-fully-qualified-images.conf {% endif %} +ADD tools/ansible/roles/dockerfile/files/rsyslog.conf /var/lib/awx/rsyslog/rsyslog.conf ADD tools/ansible/roles/dockerfile/files/wait-for-migrations /usr/local/bin/wait-for-migrations ADD tools/ansible/roles/dockerfile/files/stop-supervisor /usr/local/bin/stop-supervisor From a1e39f71fcaca8461a1fe10c16f84b67badc2a71 Mon Sep 17 00:00:00 2001 From: Lila Date: Tue, 28 Mar 2023 16:42:07 -0400 Subject: [PATCH 133/167] Removed errant comments. --- .../roles/dockerfile/templates/supervisor_rsyslog.conf.j2 | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 index 8f689e91a0..2f2842f01e 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 @@ -1,6 +1,3 @@ -; needs to launch rsyslog -; needs to launch rsyslog-configurer - [supervisord] nodaemon = True umask = 022 From 626746970900407b620acfacb3dd6d85981fa63d Mon Sep 17 00:00:00 2001 From: thedoubl3j Date: Wed, 29 Mar 2023 11:51:01 -0400 Subject: [PATCH 134/167] remove rsyslog_configurer from dispatcher as it is already being handled, add rsyslog_configurer to tower_processes --- awx/main/management/commands/run_dispatcher.py | 2 +- tools/docker-compose/supervisor.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/main/management/commands/run_dispatcher.py b/awx/main/management/commands/run_dispatcher.py index 07cc4d87b9..934836e9d6 100644 --- a/awx/main/management/commands/run_dispatcher.py +++ b/awx/main/management/commands/run_dispatcher.py @@ -76,7 +76,7 @@ class Command(BaseCommand): consumer = None try: - queues = ['tower_broadcast_all', 'tower_settings_change', 'rsyslog_configurer', get_task_queuename()] + queues = ['tower_broadcast_all', 'tower_settings_change', get_task_queuename()] consumer = AWXConsumerPG('dispatcher', TaskWorker(), queues, AutoscalePool(min_workers=4)) consumer.run() except KeyboardInterrupt: diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index a843edf342..768715c62f 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -101,7 +101,7 @@ stdout_events_enabled = true stderr_events_enabled = true [group:tower-processes] -programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsrelay,awx-rsyslogd,awx-heartbeet +programs=awx-dispatcher,awx-receiver,awx-uwsgi,awx-daphne,awx-nginx,awx-wsrelay,awx-rsyslogd,awx-heartbeet, awx-rsyslog-configurer priority=5 [program:awx-autoreload] From c8c8ed1775560f78beb6dab2e57031247cb0d341 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 29 Mar 2023 16:57:04 -0400 Subject: [PATCH 135/167] Raise ValueError when no ready and enabled task instance --- awx/main/dispatch/__init__.py | 38 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/awx/main/dispatch/__init__.py b/awx/main/dispatch/__init__.py index 009438307a..2029f540c2 100644 --- a/awx/main/dispatch/__init__.py +++ b/awx/main/dispatch/__init__.py @@ -1,3 +1,4 @@ +import os import psycopg2 import select @@ -5,8 +6,6 @@ from contextlib import contextmanager from django.conf import settings from django.db import connection as pg_connection -import os - NOT_READY = ([], [], []) @@ -16,24 +15,27 @@ def get_local_queuename(): def get_task_queuename(): - if os.getenv('AWX_COMPONENT') == 'web': - from awx.main.models.ha import Instance - - return ( - Instance.objects.filter( - node_type__in=[Instance.Types.CONTROL, Instance.Types.HYBRID], - node_state=Instance.States.READY, - enabled=True, - ) - .only('hostname') - .order_by('?') - .first() - .hostname - ) - - else: + if os.getenv('AWX_COMPONENT') != 'web': return settings.CLUSTER_HOST_ID + from awx.main.models.ha import Instance + + random_task_instance = ( + Instance.objects.filter( + node_type__in=(Instance.Types.CONTROL, Instance.Types.HYBRID), + node_state=Instance.States.READY, + enabled=True, + ) + .only('hostname') + .order_by('?') + .first() + ) + + if random_task_instance is None: + raise ValueError('No task instances are READY and Enabled.') + + return random_task_instance.hostname + class PubSub(object): def __init__(self, conn): From ac2f2039f5082ef095cbfd4242282cc9f98621c3 Mon Sep 17 00:00:00 2001 From: Lila Date: Wed, 29 Mar 2023 15:05:58 -0400 Subject: [PATCH 136/167] Fix cache-clear for kube dev env Missing conditional for when running in kube development environment --- tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 index c622d15645..1ae7dbeec5 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 @@ -75,7 +75,13 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:awx-cache-clear] +{% if kube_dev | bool %} +command = make cache_clear +directory = /awx_devel +{% else %} command = awx-manage run_cache_clear +directory = /var/lib/awx +{% endif %} autorestart = true startsecs = 30 stopasgroup=true From 13b9a6c5e30b33dabb602ba575f1f24b869b7b32 Mon Sep 17 00:00:00 2001 From: jessicamack Date: Wed, 29 Mar 2023 16:20:54 -0400 Subject: [PATCH 137/167] Remove unused import Signed-off-by: jessicamack --- awx/main/utils/external_logging.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/awx/main/utils/external_logging.py b/awx/main/utils/external_logging.py index 635887ec14..75cc9d4971 100644 --- a/awx/main/utils/external_logging.py +++ b/awx/main/utils/external_logging.py @@ -7,7 +7,6 @@ from django.conf import settings from awx.main.utils.reload import supervisor_service_command from awx.main.dispatch.publish import task -from awx.main.dispatch import pg_bus_conn def construct_rsyslog_conf_template(settings=settings): @@ -127,8 +126,3 @@ def reconfigure_rsyslog(): f.write(tmpl + '\n') shutil.move(path, '/var/lib/awx/rsyslog/rsyslog.conf') supervisor_service_command(command='restart', service='awx-rsyslogd') - - -def send_pg_notify(channel: str, payload: str) -> None: - with pg_bus_conn() as conn: - conn.notify(channel, payload) From 0cc02d311f196bb6f01ebe19382ed99e300d7644 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 29 Mar 2023 19:14:12 -0400 Subject: [PATCH 138/167] Rename supervisor.conf.j2 to be descriptive supervisor.conf.j2 file is the template for supervisor.conf file for the web container rename to supervisor_web.conf make it more clear that it is use for the web container --- tools/ansible/roles/dockerfile/tasks/main.yml | 2 +- tools/ansible/roles/dockerfile/templates/Dockerfile.j2 | 2 +- .../templates/{supervisor.conf.j2 => supervisor_web.conf.j2} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename tools/ansible/roles/dockerfile/templates/{supervisor.conf.j2 => supervisor_web.conf.j2} (100%) diff --git a/tools/ansible/roles/dockerfile/tasks/main.yml b/tools/ansible/roles/dockerfile/tasks/main.yml index 7a3953e7ed..3b4b215b5c 100644 --- a/tools/ansible/roles/dockerfile/tasks/main.yml +++ b/tools/ansible/roles/dockerfile/tasks/main.yml @@ -9,7 +9,7 @@ src: "{{ item }}.j2" dest: "{{ dockerfile_dest }}/{{ template_dest }}/{{ item }}" with_items: - - "supervisor.conf" + - "supervisor_web.conf" - "supervisor_task.conf" - "supervisor_rsyslog.conf" diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index e7218ce80b..e63b2baa65 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -213,7 +213,7 @@ ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/ ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh -ADD {{ template_dest }}/supervisor.conf /etc/supervisord.conf +ADD {{ template_dest }}/supervisor_web.conf /etc/supervisord_web.conf ADD {{ template_dest }}/supervisor_task.conf /etc/supervisord_task.conf ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisor_rsyslog.conf {% endif %} diff --git a/tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 similarity index 100% rename from tools/ansible/roles/dockerfile/templates/supervisor.conf.j2 rename to tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 From 6c0c1f68532eb876459c1cd693a9811ebe6bb5de Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 29 Mar 2023 19:41:35 -0400 Subject: [PATCH 139/167] Rename launch script for launch awx web launch_awx.sh that this PR rename is also now only use for launching awx web container renaming to reflect it's purpose also remove the no longer needed creation of rsyslog conf as rsyslog is no longer in the web container Update Dockerfile.j2 --- .../roles/dockerfile/files/launch_awx.sh | 27 ------------------- .../roles/dockerfile/files/launch_awx_web.sh | 20 ++++++++++++++ .../roles/dockerfile/templates/Dockerfile.j2 | 3 +-- 3 files changed, 21 insertions(+), 29 deletions(-) delete mode 100755 tools/ansible/roles/dockerfile/files/launch_awx.sh create mode 100755 tools/ansible/roles/dockerfile/files/launch_awx_web.sh diff --git a/tools/ansible/roles/dockerfile/files/launch_awx.sh b/tools/ansible/roles/dockerfile/files/launch_awx.sh deleted file mode 100755 index edababb445..0000000000 --- a/tools/ansible/roles/dockerfile/files/launch_awx.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -if [ `id -u` -ge 500 ]; then - echo "awx:x:`id -u`:`id -g`:,,,:/var/lib/awx:/bin/bash" >> /tmp/passwd - cat /tmp/passwd > /etc/passwd - rm /tmp/passwd -fi - -if [ -n "${AWX_KUBE_DEVEL}" ]; then - pushd /awx_devel - make awx-link - popd - - export SDB_NOTIFY_HOST=$MY_POD_IP -fi - -set -e - -wait-for-migrations - -# This file will be re-written when the dispatcher calls reconfigure_rsyslog(), -# but it needs to exist when supervisor initially starts rsyslog to prevent the -# container from crashing. This was the most minimal config I could get working. -cat << EOF > /var/lib/awx/rsyslog/rsyslog.conf -action(type="omfile" file="/dev/null") -EOF - -exec supervisord -c /etc/supervisord.conf diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_web.sh b/tools/ansible/roles/dockerfile/files/launch_awx_web.sh new file mode 100755 index 0000000000..d12750eead --- /dev/null +++ b/tools/ansible/roles/dockerfile/files/launch_awx_web.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +if [ `id -u` -ge 500 ]; then + echo "awx:x:`id -u`:`id -g`:,,,:/var/lib/awx:/bin/bash" >> /tmp/passwd + cat /tmp/passwd > /etc/passwd + rm /tmp/passwd +fi + +if [ -n "${AWX_KUBE_DEVEL}" ]; then + pushd /awx_devel + make awx-link + popd + + export SDB_NOTIFY_HOST=$MY_POD_IP +fi + +set -e + +wait-for-migrations + +exec supervisord -c /etc/supervisord_web.conf diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index e63b2baa65..999ce24056 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -210,7 +210,7 @@ ADD tools/scripts/config-watcher /usr/bin/config-watcher ADD tools/docker-compose/containers.conf /etc/containers/containers.conf ADD tools/docker-compose/podman-containers.conf /var/lib/awx/.config/containers/containers.conf {% else %} -ADD tools/ansible/roles/dockerfile/files/launch_awx.sh /usr/bin/launch_awx.sh +ADD tools/ansible/roles/dockerfile/files/launch_awx_web.sh /usr/bin/launch_awx_web.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_task.sh ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh ADD {{ template_dest }}/supervisor_web.conf /etc/supervisord_web.conf @@ -297,7 +297,6 @@ USER 1000 EXPOSE 8052 ENTRYPOINT ["dumb-init", "--"] -CMD /usr/bin/launch_awx.sh VOLUME /var/lib/nginx VOLUME /var/lib/awx/.local/share/containers {% endif %} From bc55bcf3a2aa3547cfa11aa6e3097b47b8abd0b0 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 29 Mar 2023 20:05:30 -0400 Subject: [PATCH 140/167] Rename SUPERVISOR_CONFIG_PATH previously this is used so that task running in the task container can reach into the web container to restart rsyslog now that the web container and task container are split there's no longer a way to do that so i renamed this env var to reference where it will now do which is pointing to the supervisor conf file of the current running container --- awx/main/constants.py | 2 +- awx/main/utils/reload.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/main/constants.py b/awx/main/constants.py index 32d8a2184c..66666f875f 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -65,7 +65,7 @@ ENV_BLOCKLIST = frozenset( 'INVENTORY_HOSTVARS', 'AWX_HOST', 'PROJECT_REVISION', - 'SUPERVISOR_WEB_CONFIG_PATH', + 'SUPERVISOR_CONFIG_PATH', ) ) diff --git a/awx/main/utils/reload.py b/awx/main/utils/reload.py index a7c2a1ed99..29d0784f12 100644 --- a/awx/main/utils/reload.py +++ b/awx/main/utils/reload.py @@ -17,7 +17,7 @@ def supervisor_service_command(command, service='*', communicate=True): """ args = ['supervisorctl'] - supervisor_config_path = os.getenv('SUPERVISOR_WEB_CONFIG_PATH', None) + supervisor_config_path = os.getenv('SUPERVISOR_CONFIG_PATH', None) if supervisor_config_path: args.extend(['-c', supervisor_config_path]) From 598f9e2a5538acce99587551b9adf2440fb9ca2d Mon Sep 17 00:00:00 2001 From: Oleksii Baranov Date: Wed, 29 Mar 2023 19:22:49 +0200 Subject: [PATCH 141/167] Add host_metrics page to the awxkit --- awxkit/awxkit/api/pages/__init__.py | 1 + awxkit/awxkit/api/pages/host_metrics.py | 18 ++++++++++++++++++ awxkit/awxkit/api/resources.py | 2 ++ 3 files changed, 21 insertions(+) create mode 100644 awxkit/awxkit/api/pages/host_metrics.py diff --git a/awxkit/awxkit/api/pages/__init__.py b/awxkit/awxkit/api/pages/__init__.py index f5587fc211..7fbdbcdb0d 100644 --- a/awxkit/awxkit/api/pages/__init__.py +++ b/awxkit/awxkit/api/pages/__init__.py @@ -42,3 +42,4 @@ from .credential_input_sources import * # NOQA from .metrics import * # NOQA from .subscriptions import * # NOQA from .workflow_approval_templates import * # NOQA +from .host_metrics import * # NOQA diff --git a/awxkit/awxkit/api/pages/host_metrics.py b/awxkit/awxkit/api/pages/host_metrics.py new file mode 100644 index 0000000000..8ff8d9c39b --- /dev/null +++ b/awxkit/awxkit/api/pages/host_metrics.py @@ -0,0 +1,18 @@ +from awxkit.api.resources import resources +from . import base +from . import page + + +class HostMetric(base.Base): + def get(self, **query_parameters): + request = self.connection.get(self.endpoint, query_parameters, headers={'Accept': 'application/json'}) + return self.page_identity(request) + + +class HostMetrics(page.PageList, HostMetric): + pass + + +page.register_page([resources.host_metric], HostMetric) + +page.register_page([resources.host_metrics], HostMetrics) diff --git a/awxkit/awxkit/api/resources.py b/awxkit/awxkit/api/resources.py index 813f4104ee..d453ff4f75 100644 --- a/awxkit/awxkit/api/resources.py +++ b/awxkit/awxkit/api/resources.py @@ -44,6 +44,8 @@ class Resources(object): _groups = 'groups/' _host = r'hosts/\d+/' _host_groups = r'hosts/\d+/groups/' + _host_metrics = 'host_metrics/' + _host_metric = r'host_metrics/\d+/' _host_insights = r'hosts/\d+/insights/' _host_related_ad_hoc_commands = r'hosts/\d+/ad_hoc_commands/' _host_related_fact_version = r'hosts/\d+/fact_versions/\d+/' From 17f5c4b8e6677a20f91732356809944e1337a7e5 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 29 Mar 2023 19:06:48 -0400 Subject: [PATCH 142/167] Modify dev make target name to clarify intention these make targets are for starting the different daemons within the kube/docker development environment updating the name to make it better reflect their intention also added comments above the make target to describe what they do note: these comments show up when run `make help` --- Makefile | 53 ++++++++++--------- .../templates/supervisor_rsyslog.conf.j2 | 2 +- .../templates/supervisor_task.conf.j2 | 2 +- .../templates/supervisor_web.conf.j2 | 2 +- tools/docker-compose/supervisor.conf | 8 +-- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 97071b8f0b..2a7d9b9e03 100644 --- a/Makefile +++ b/Makefile @@ -70,12 +70,6 @@ I18N_FLAG_FILE = .i18n_built VERSION PYTHON_VERSION docker-compose-sources \ .git/hooks/pre-commit github_ci_setup github_ci_runner -cache-clear: - @if [ "$(VENV_BASE)" ]; then \ - . $(VENV_BASE)/awx/bin/activate; \ - fi; \ - $(PYTHON) manage.py run_cache_clear - clean-tmp: rm -rf tmp/ @@ -223,18 +217,6 @@ daphne: fi; \ daphne -b 127.0.0.1 -p 8051 awx.asgi:channel_layer -wsrelay: - @if [ "$(VENV_BASE)" ]; then \ - . $(VENV_BASE)/awx/bin/activate; \ - fi; \ - $(PYTHON) manage.py run_wsrelay - -heartbeet: - @if [ "$(VENV_BASE)" ]; then \ - . $(VENV_BASE)/awx/bin/activate; \ - fi; \ - $(PYTHON) manage.py run_heartbeet - ## Run to start the background task dispatcher for development. dispatcher: @if [ "$(VENV_BASE)" ]; then \ @@ -242,7 +224,6 @@ dispatcher: fi; \ $(PYTHON) manage.py run_dispatcher - ## Run to start the zeromq callback receiver receiver: @if [ "$(VENV_BASE)" ]; then \ @@ -250,12 +231,6 @@ receiver: fi; \ $(PYTHON) manage.py run_callback_receiver -rsyslog-configurer: - @if [ "$(VENV_BASE)" ]; then \ - . $(VENV_BASE)/awx/bin/activate; \ - fi; \ - $(PYTHON) manage.py run_rsyslog_configurer - nginx: nginx -g "daemon off;" @@ -265,6 +240,34 @@ jupyter: fi; \ $(MANAGEMENT_COMMAND) shell_plus --notebook +## Start the rsyslog configurer process in background in development environment. +run-rsyslog-configurer: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_rsyslog_configurer + +## Start cache_clear process in background in development environment. +run-cache-clear: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_cache_clear + +## Start the wsrelay process in background in development environment. +run-wsrelay: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_wsrelay + +## Start the heartbeat process in background in development environment. +run-heartbeet: + @if [ "$(VENV_BASE)" ]; then \ + . $(VENV_BASE)/awx/bin/activate; \ + fi; \ + $(PYTHON) manage.py run_heartbeet + reports: mkdir -p $@ diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 index 2f2842f01e..f225b935c5 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_rsyslog.conf.j2 @@ -18,7 +18,7 @@ stderr_logfile_maxbytes=0 [program:awx-rsyslog-configurer] {% if kube_dev | bool %} -command = make rsyslog-configurer +command = make run-rsyslog-configurer directory = /awx_devel {% else %} command = awx-manage run_rsyslog_configurer diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 index 8c3a46342e..6826611e8b 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 @@ -24,7 +24,7 @@ stderr_logfile_maxbytes=0 [program:wsrelay] {% if kube_dev | bool %} -command = make wsrelay +command = make run-wsrelay directory = /awx_devel {% else %} command = awx-manage run_wsrelay diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 index 1ae7dbeec5..75b536cd3f 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 @@ -59,7 +59,7 @@ stderr_logfile_maxbytes=0 [program:heartbeet] {% if kube_dev | bool %} -command = make heartbeet +command = make run-heartbeet directory = /awx_devel {% else %} command = awx-manage run_heartbeet diff --git a/tools/docker-compose/supervisor.conf b/tools/docker-compose/supervisor.conf index 768715c62f..e8bb858910 100644 --- a/tools/docker-compose/supervisor.conf +++ b/tools/docker-compose/supervisor.conf @@ -20,7 +20,7 @@ stdout_events_enabled = true stderr_events_enabled = true [program:awx-wsrelay] -command = make wsrelay +command = make run-wsrelay autorestart = true autorestart = true stopasgroup=true @@ -29,7 +29,7 @@ stdout_events_enabled = true stderr_events_enabled = true [program:awx-heartbeet] -command = make heartbeet +command = make run-heartbeet autorestart = true autorestart = true stopasgroup=true @@ -38,7 +38,7 @@ stdout_events_enabled = true stderr_events_enabled = true [program:awx-rsyslog-configurer] -command = make rsyslog-configurer +command = make run-rsyslog-configurer autorestart = true stopasgroup=true killasgroup=true @@ -48,7 +48,7 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:awx-cache-clear] -command = make cache-clear +command = make run-cache-clear autorestart = true stopasgroup=true killasgroup=true From 4f99a170bef0000cb15feaa84eed29e513f9b6e2 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Wed, 29 Mar 2023 16:54:37 -0500 Subject: [PATCH 143/167] Nix websocket docs for now Signed-off-by: Rick Elrod --- docs/websockets.md | 71 +--------------------------------------------- 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/docs/websockets.md b/docs/websockets.md index 84e1226594..90381f0b12 100644 --- a/docs/websockets.md +++ b/docs/websockets.md @@ -6,73 +6,4 @@ Our channels/websocket implementation handles the communication between AWX API AWX enlists the help of the `django-channels` library to create our communications layer. `django-channels` provides us with per-client messaging integration in our application by implementing the Asynchronous Server Gateway Interface (ASGI). -To communicate between our different services we use websockets. Every AWX node is fully connected via a special websocket endpoint that forwards any local websocket data to all other nodes. Local websockets are backed by Redis, the channels2 default service. - -Inside AWX we use the `emit_channel_notification` function which places messages onto the queue. The messages are given an explicit event group and event type which we later use in our wire protocol to control message delivery to the client. - -### Relay Backplane - -Previously, AWX leveraged RabbitMQ to deliver Ansible events that emanated from one AWX node to all other AWX nodes so that any client listening and subscribed to the Websockets could get events from any running playbook. We are since moved off of RabbitMQ and onto a per-node local Redis instance. To maintain the requirement that any Websocket connection can receive events from any playbook running on any AWX node we still need to deliver every event to every AWX node. AWX does this via a fully connected Websocket backplane. - -#### Relay Backplane Token - -AWX node(s) connect to every other node via the Websocket backplane. The backplane websockets initiate from the `wsrelay` process and connect to other nodes via the same nginx process that serves webpage websocket connections and marshalls incoming web/API requests. If you have configured AWX to run with an ssl terminated connection in front of nginx then you likely will have nginx configured to handle http traffic and thus the websocket connection will flow unencrypted over http. If you have nginx configured with ssl enabled, then the websocket traffic will flow encrypted. - -Authentication is accomplished via a shared secret that is generated and set at playbook install time. The shared secret is used to derive a payload that is exchanged via the http(s) header `secret`. The shared secret payload consists of a a `secret`, containing the shared secret, and a `nonce` which is used to mitigate replay attack windows. - -Note that the nonce timestamp is considered valid if it is within `300` second threshold. This is to allow for machine clock skews. -``` -{ - "secret": settings.BROADCAST_WEBSOCKET_SECRET, - "nonce": time.now() -} -``` - -The payload is encrypted using `HMAC-SHA256` with `settings.BROADCAST_WEBSOCKET_SECRET` as the key. The final payload that is sent, including the http header, is of the form: `secret: nonce_plaintext:HMAC_SHA256({"secret": settings.BROADCAST_WEBSOCKET_SECRET, "nonce": nonce_plaintext})`. - -Upon receiving the payload, AWX decrypts the `secret` header using the known shared secret and ensures the `secret` value of the decrypted payload matches the known shared secret, `settings.BROADCAST_WEBSOCKET_SECRET`. If it does not match, the connection is closed. If it does match, the `nonce` is compared to the current time. If the nonce is off by more than `300` seconds, the connection is closed. If both tests pass, the connection is accepted. - -## Protocol - -You can connect to the AWX channels implementation using any standard websocket library by pointing it to `/websocket/`. You must -provide a valid Auth Token in the request URL. - -Once you've connected, you are not subscribed to any event groups. You subscribe by sending a `json` request that looks like the following: - - 'groups': { - 'jobs': ['status_changed', 'summary'], - 'schedules': ['changed'], - 'ad_hoc_command_events': [ids...], - 'job_events': [ids...], - 'workflow_events': [ids...], - 'project_update_events': [ids...], - 'inventory_update_events': [ids...], - 'system_job_events': [ids...], - 'control': ['limit_reached_'], - } - -These map to the event group and event type that the user is interested in. Sending in a new groups dictionary will clear all previously-subscribed groups before subscribing to the newly requested ones. This is intentional, and makes the single page navigation much easier since users only need to care about current subscriptions. - -## Deployment - -This section will specifically discuss deployment in the context of websockets and the path those requests take through the system. - -**Note:** The deployment of AWX changes slightly with the introduction of `django-channels` and websockets. There are some minor differences between production and development deployments that will be pointed out in this document, but the actual services that run the code and handle the requests are identical between the two environments. - -### Services -| Name | Details | -|:-----------:|:-----------------------------------------------------------------------------------------------------------:| -| `nginx` | listens on ports 80/443, handles HTTPS proxying, serves static assets, routes requests for `daphne` and `uwsgi` | -| `uwsgi` | listens on port 8050, handles API requests | -| `daphne` | listens on port 8051, handles websocket requests | -| `wsrelay` | no listening port, forwards all group messages to all cluster nodes | -| `supervisord` | (production-only) handles the process management of all the services except `nginx` | - -When a request comes in to `nginx` and has the `Upgrade` header and is for the path `/websocket`, then `nginx` knows that it should be routing that request to our `daphne` service. - -`daphne` handles websocket connections proxied by nginx. - -`wsrelay` fully connects all cluster nodes via the `/websocket/broadcast/` endpoint to every other cluster nodes. Sends a copy of all group websocket messages to all other cluster nodes (i.e. job event type messages). - -### Development - - `nginx` listens on 8013/8043 instead of 80/443 +**TODO: The information previously contained within this document has become outdated. This document will be rewritten in the near future.** From 7bb0d32be17b36a00674a55dd239eaa8baeaf591 Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Thu, 30 Mar 2023 13:46:15 -0400 Subject: [PATCH 144/167] Fix docker-clean file, accounting for slashes --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d81266352f..9afc7c7440 100644 --- a/Makefile +++ b/Makefile @@ -561,7 +561,7 @@ 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);) - -$(foreach image_id,$(shell docker images --filter=reference='*awx_devel*' -aq),docker rmi --force $(image_id);) + -$(foreach image_id,$(shell docker images --filter=reference='*/*/*awx_devel*' --filter=reference='*/*awx_devel*' --filter=reference='*awx_devel*' -aq),docker rmi --force $(image_id);) docker-clean-volumes: docker-compose-clean docker-compose-container-group-clean docker volume rm -f tools_awx_db tools_grafana_storage tools_prometheus_storage $(docker volume ls --filter name=tools_redis_socket_ -q) @@ -680,4 +680,3 @@ help/generate: ## Display help for ui-next targets help/ui-next: @make -s help MAKEFILE_LIST="awx/ui_next/Makefile" - From 479d0c2b12c0766a53ad28bea10cd904e6b3c504 Mon Sep 17 00:00:00 2001 From: Lorenzo Tanganelli <35271287+tanganellilore@users.noreply.github.com> Date: Tue, 4 Apr 2023 16:09:48 +0200 Subject: [PATCH 145/167] add instance_groups on cli and awx.awx.role (#13784) --- awx_collection/plugins/modules/role.py | 6 ++++++ awxkit/awxkit/cli/custom.py | 1 + 2 files changed, 7 insertions(+) diff --git a/awx_collection/plugins/modules/role.py b/awx_collection/plugins/modules/role.py index 51ed564397..bc7f9ea803 100644 --- a/awx_collection/plugins/modules/role.py +++ b/awx_collection/plugins/modules/role.py @@ -116,6 +116,11 @@ options: - Project the role acts on. type: list elements: str + instance_groups: + description: + - Instance Group the role acts on. + type: list + elements: str state: description: - Desired state. @@ -193,6 +198,7 @@ def main(): lookup_organization=dict(), project=dict(), projects=dict(type='list', elements='str'), + instance_groups=dict(type='list', elements='str'), state=dict(choices=['present', 'absent'], default='present'), ) diff --git a/awxkit/awxkit/cli/custom.py b/awxkit/awxkit/cli/custom.py index a2764b15ba..c4a13cebfc 100644 --- a/awxkit/awxkit/cli/custom.py +++ b/awxkit/awxkit/cli/custom.py @@ -396,6 +396,7 @@ class RoleMixin(object): ['credentials', 'credential'], ['job_templates', 'job_template'], ['workflow_job_templates', 'workflow_job_template'], + ['instance_groups', 'instance_group'], ] roles = {} # this is calculated once From 1e690fcd7f2854dda493722f0084a4f22758823b Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Tue, 4 Apr 2023 10:26:52 -0500 Subject: [PATCH 146/167] Only use constr. inv URL when req comes from it (#13797) When the API request is for /inventories/id use that as the URL in the API response. When the request is for /constructed_inventories/id use that. Signed-off-by: Rick Elrod --- awx/main/models/inventory.py | 11 +++++++++-- .../tests/functional/api/test_inventory.py | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index a4ddaabafd..fe1b09e23d 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -17,6 +17,7 @@ from django.db import models, connection from django.utils.translation import gettext_lazy as _ from django.db import transaction from django.core.exceptions import ValidationError +from django.urls import resolve from django.utils.timezone import now from django.db.models import Q @@ -206,8 +207,14 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): ) def get_absolute_url(self, request=None): - if self.kind == 'constructed': - return reverse('api:constructed_inventory_detail', kwargs={'pk': self.pk}, request=request) + if request is not None: + # circular import + from awx.api.urls.inventory import constructed_inventory_urls + + route = resolve(request.path_info) + if any(route.url_name == url.name for url in constructed_inventory_urls): + return reverse('api:constructed_inventory_detail', kwargs={'pk': self.pk}, request=request) + return reverse('api:inventory_detail', kwargs={'pk': self.pk}, request=request) variables_dict = VarsDictProperty('variables') diff --git a/awx/main/tests/functional/api/test_inventory.py b/awx/main/tests/functional/api/test_inventory.py index ab84ff236d..71a48383c4 100644 --- a/awx/main/tests/functional/api/test_inventory.py +++ b/awx/main/tests/functional/api/test_inventory.py @@ -680,3 +680,22 @@ class TestConstructedInventory: inv_src = constructed_inventory.inventory_sources.first() assert inv_src.update_cache_timeout == 55 assert inv_src.limit == 'foobar' + + def test_get_absolute_url_for_constructed_inventory(self, constructed_inventory, admin_user, get): + """ + If we are using the normal inventory API endpoint to look at a + constructed inventory, then we should get a normal inventory API route + back. If we are accessing it via the special constructed inventory + endpoint, then we should get that back. + """ + + url_const = reverse('api:constructed_inventory_detail', kwargs={'pk': constructed_inventory.pk}) + url_inv = reverse('api:inventory_detail', kwargs={'pk': constructed_inventory.pk}) + + const_r = get(url=url_const, user=admin_user, expect=200) + inv_r = get(url=url_inv, user=admin_user, expect=200) + assert const_r.data['url'] == url_const + assert inv_r.data['url'] == url_inv + assert inv_r.data['url'] != const_r.data['url'] + assert inv_r.data['related']['constructed_url'] == url_const + assert const_r.data['related']['constructed_url'] == url_const From b5c052b2e6736df239add34f3a758fe8c0f4606e Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Wed, 5 Apr 2023 09:30:44 -0400 Subject: [PATCH 147/167] Adding import of centos repo key for dnf --- tools/ansible/roles/dockerfile/templates/Dockerfile.j2 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index 999ce24056..3c24dd30cb 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -15,6 +15,9 @@ ENV AWX_LOGGING_MODE stdout USER root +# Import the gpg key for DNF to work +RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + # Install build dependencies RUN dnf -y update && dnf install -y 'dnf-command(config-manager)' && \ dnf config-manager --set-enabled crb && \ @@ -99,6 +102,9 @@ ENV AWX_LOGGING_MODE stdout USER root +# Import the gpg key for DNF to work +RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + # Install runtime requirements RUN dnf -y update && dnf install -y 'dnf-command(config-manager)' && \ dnf config-manager --set-enabled crb && \ From f62bf6a4c37ef30ede0b2effd4223c43ad313caa Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Tue, 4 Apr 2023 09:59:16 -0400 Subject: [PATCH 148/167] Fix supervisor conf file inconsistancy --- tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh | 2 +- tools/ansible/roles/dockerfile/templates/Dockerfile.j2 | 2 +- .../roles/dockerfile/templates/supervisor_task.conf.j2 | 6 +++--- .../roles/dockerfile/templates/supervisor_web.conf.j2 | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh b/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh index 53ef60f544..9494210250 100755 --- a/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh +++ b/tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh @@ -24,5 +24,5 @@ cat << EOF > /var/lib/awx/rsyslog/rsyslog.conf action(type="omfile" file="/dev/null") EOF -exec supervisord -c /etc/supervisor_rsyslog.conf +exec supervisord -c /etc/supervisord_rsyslog.conf diff --git a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 index 3c24dd30cb..3ff4222ebe 100644 --- a/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 +++ b/tools/ansible/roles/dockerfile/templates/Dockerfile.j2 @@ -221,7 +221,7 @@ ADD tools/ansible/roles/dockerfile/files/launch_awx_task.sh /usr/bin/launch_awx_ ADD tools/ansible/roles/dockerfile/files/launch_awx_rsyslog.sh /usr/bin/launch_awx_rsyslog.sh ADD {{ template_dest }}/supervisor_web.conf /etc/supervisord_web.conf ADD {{ template_dest }}/supervisor_task.conf /etc/supervisord_task.conf -ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisor_rsyslog.conf +ADD {{ template_dest }}/supervisor_rsyslog.conf /etc/supervisord_rsyslog.conf {% endif %} {% if (build_dev|bool) or (kube_dev|bool) %} ADD tools/docker-compose/awx.egg-link /tmp/awx.egg-link diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 index 6826611e8b..9d14a45621 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_task.conf.j2 @@ -3,7 +3,7 @@ nodaemon = True umask = 022 logfile = /dev/stdout logfile_maxbytes = 0 -pidfile = /var/run/supervisor/supervisor.pid +pidfile = /var/run/supervisor/supervisor.task.pid [program:dispatcher] {% if kube_dev | bool %} @@ -70,10 +70,10 @@ stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [unix_http_server] -file=/var/run/supervisor/supervisor.sock +file=/var/run/supervisor/supervisor.task.sock [supervisorctl] -serverurl=unix:///var/run/supervisor/supervisor.sock ; use a unix:// URL for a unix socket +serverurl=unix:///var/run/supervisor/supervisor.task.sock ; use a unix:// URL for a unix socket [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface diff --git a/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 b/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 index 75b536cd3f..a752862537 100644 --- a/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 +++ b/tools/ansible/roles/dockerfile/templates/supervisor_web.conf.j2 @@ -29,8 +29,8 @@ environment = DEV_RELOAD_COMMAND='supervisorctl -c /etc/supervisord_task.conf restart all; supervisorctl restart tower-processes:daphne' {% else %} command = /var/lib/awx/venv/awx/bin/uwsgi /etc/tower/uwsgi.ini -{% endif %} directory = /var/lib/awx +{% endif %} autorestart = true startsecs = 30 stopasgroup=true @@ -76,7 +76,7 @@ stderr_logfile_maxbytes=0 [program:awx-cache-clear] {% if kube_dev | bool %} -command = make cache_clear +command = make run-cache-clear directory = /awx_devel {% else %} command = awx-manage run_cache_clear From 454f31f6a4669167e0277d372ccc87ff16388d76 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 5 Apr 2023 10:38:35 -0400 Subject: [PATCH 149/167] Add log handler and file for heartbeet --- awx/settings/defaults.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 61fb2df764..593e6ae002 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -871,6 +871,7 @@ LOGGING = { 'awx.main.consumers': {'handlers': ['console', 'file', 'tower_warnings'], 'level': 'INFO'}, 'awx.main.rsyslog_configurer': {'handlers': ['rsyslog_configurer']}, 'awx.main.cache_clear': {'handlers': ['cache_clear']}, + 'awx.main.heartbeet': {'handlers': ['heartbeet']}, 'awx.main.wsrelay': {'handlers': ['wsrelay']}, 'awx.main.commands.inventory_import': {'handlers': ['inventory_import'], 'propagate': False}, 'awx.main.tasks': {'handlers': ['task_system', 'external_logger'], 'propagate': False}, @@ -904,6 +905,7 @@ handler_config = { 'job_lifecycle': {'filename': 'job_lifecycle.log', 'formatter': 'job_lifecycle'}, 'rsyslog_configurer': {'filename': 'rsyslog_configurer.log'}, 'cache_clear': {'filename': 'cache_clear.log'}, + 'heartbeet': {'filename': 'heartbeet.log'}, } # If running on a VM, we log to files. When running in a container, we log to stdout. From 0e68caf0f7a3aafe7324e9795b6412564395751c Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Wed, 5 Apr 2023 12:03:15 -0400 Subject: [PATCH 150/167] Do not add closing color tags if --no-color was specified --- awx/main/management/commands/list_instances.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/awx/main/management/commands/list_instances.py b/awx/main/management/commands/list_instances.py index 7d93f5baa9..a434e2299e 100644 --- a/awx/main/management/commands/list_instances.py +++ b/awx/main/management/commands/list_instances.py @@ -44,16 +44,18 @@ class Command(BaseCommand): for x in ig.instances.all(): color = '\033[92m' + end_color = '\033[0m' if x.capacity == 0 and x.node_type != 'hop': color = '\033[91m' if not x.enabled: color = '\033[90m[DISABLED] ' if no_color: color = '' + end_color = '' capacity = f' capacity={x.capacity}' if x.node_type != 'hop' else '' version = f" version={x.version or '?'}" if x.node_type != 'hop' else '' heartbeat = f' heartbeat="{x.last_seen:%Y-%m-%d %H:%M:%S}"' if x.capacity or x.node_type == 'hop' else '' - print(f'\t{color}{x.hostname}{capacity} node_type={x.node_type}{version}{heartbeat}\033[0m') + print(f'\t{color}{x.hostname}{capacity} node_type={x.node_type}{version}{heartbeat}{end_color}') print() From 98e37383c2c9a1c505379c32b07d5928596c9830 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Thu, 6 Apr 2023 22:14:51 -0400 Subject: [PATCH 151/167] Temporary workaround for make requirements_awx failure --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 9afc7c7440..fffa237d3d 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) MANAGEMENT_COMMAND ?= awx-manage VERSION := $(shell $(PYTHON) tools/scripts/scm_version.py) +# temparary workaround for pip resolver issues +PIP_OPTIONS="--use-deprecated=legacy-resolver" + # ansible-test requires semver compatable version, so we allow overrides to hack it COLLECTION_VERSION ?= $(shell $(PYTHON) tools/scripts/scm_version.py | cut -d . -f 1-3) # args for the ansible-test sanity command From 14e613bc922e634564097cd6ffced13375f3fc96 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Thu, 6 Apr 2023 23:20:58 -0400 Subject: [PATCH 152/167] Fix failed license check psycopg2 also start with psycopg Co-Authored-By: Gabriel Muniz --- awx/main/tests/functional/test_licenses.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/awx/main/tests/functional/test_licenses.py b/awx/main/tests/functional/test_licenses.py index 4b8ee7a918..9961c7ca96 100644 --- a/awx/main/tests/functional/test_licenses.py +++ b/awx/main/tests/functional/test_licenses.py @@ -26,12 +26,12 @@ def test_python_and_js_licenses(): return (is_gpl, is_lgpl) def find_embedded_source_version(path, name): - for entry in os.listdir(path): - # Check variations of '-' and '_' in filenames due to python - for fname in [name, name.replace('-', '_')]: - if entry.startswith(fname) and entry.endswith('.tar.gz'): - v = entry.split(name + '-')[1].split('.tar.gz')[0] - return v + files = os.listdir(path) + tgz_files = [f for f in files if f.endswith('.tar.gz')] + for tgz in tgz_files: + pkg_name = tgz.split('-')[0].split('_')[0] + if pkg_name == name: + return tgz.split('-')[1].split('.tar.gz')[0] return None list = {} From 1191458d80b6e22f5950136ffd239bd66592d543 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 20 Feb 2023 14:09:28 +0100 Subject: [PATCH 153/167] Analytics API: Basics --- awx/api/urls/analytics.py | 32 +++++++ awx/api/urls/urls.py | 3 +- awx/api/views/analytics.py | 173 +++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 awx/api/urls/analytics.py create mode 100644 awx/api/views/analytics.py diff --git a/awx/api/urls/analytics.py b/awx/api/urls/analytics.py new file mode 100644 index 0000000000..17078c32c3 --- /dev/null +++ b/awx/api/urls/analytics.py @@ -0,0 +1,32 @@ +# Copyright (c) 2017 Ansible, Inc. +# All Rights Reserved. + +from django.urls import re_path + +import awx.api.views.analytics as analytics + + +urls = [ + re_path(r'^$', analytics.AnalyticsRootView.as_view(), name='analytics_root_view'), + re_path(r'^test/$', analytics.AnalyticsTestList.as_view(), name='analytics_test_list'), + re_path(r'^authorized/$', analytics.AnalyticsAuthorizedView.as_view(), name='analytics_authorized'), + re_path(r'^reports/$', analytics.AnalyticsReportsList.as_view(), name='analytics_reports_list'), + re_path(r'^report/(?P[\w-]+)/$', analytics.AnalyticsReportDetail.as_view(), name='analytics_report_detail'), + re_path(r'^report_options/$', analytics.AnalyticsReportOptionsList.as_view(), name='analytics_report_options_list'), + re_path(r'^adoption_rate/$', analytics.AnalyticsAdoptionRateList.as_view(), name='analytics_adoption_rate'), + re_path(r'^adoption_rate_options/$', analytics.AnalyticsAdoptionRateList.as_view(), name='analytics_adoption_rate_options'), + re_path(r'^event_explorer/$', analytics.AnalyticsEventExplorerList.as_view(), name='analytics_event_explorer'), + re_path(r'^event_explorer_options/$', analytics.AnalyticsEventExplorerList.as_view(), name='analytics_event_explorer_options'), + re_path(r'^host_explorer/$', analytics.AnalyticsHostExplorerList.as_view(), name='analytics_host_explorer'), + re_path(r'^host_explorer_options/$', analytics.AnalyticsHostExplorerList.as_view(), name='analytics_host_explorer_options'), + re_path(r'^job_explorer/$', analytics.AnalyticsJobExplorerList.as_view(), name='analytics_job_explorer'), + re_path(r'^job_explorer_options/$', analytics.AnalyticsJobExplorerList.as_view(), name='analytics_job_explorer_options'), + re_path(r'^probe_templates/$', analytics.AnalyticsProbeTemplatesList.as_view(), name='analytics_probe_templates_explorer'), + re_path(r'^probe_templates_options/$', analytics.AnalyticsProbeTemplatesList.as_view(), name='analytics_probe_templates_options'), + re_path(r'^probe_template_for_hosts/$', analytics.AnalyticsProbeTemplateForHostsList.as_view(), name='analytics_probe_template_for_hosts_explorer'), + re_path(r'^probe_template_for_hosts_options/$', analytics.AnalyticsProbeTemplateForHostsList.as_view(), name='analytics_probe_template_for_hosts_options'), + re_path(r'^roi_templates/$', analytics.AnalyticsRoiTemplatesList.as_view(), name='analytics_roi_templates_explorer'), + re_path(r'^roi_templates_options/$', analytics.AnalyticsRoiTemplatesList.as_view(), name='analytics_roi_templates_options'), +] + +__all__ = ['urls'] diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index bb27710dcc..673a1b11cd 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -82,7 +82,7 @@ from .oauth2 import urls as oauth2_urls from .oauth2_root import urls as oauth2_root_urls from .workflow_approval_template import urls as workflow_approval_template_urls from .workflow_approval import urls as workflow_approval_urls - +from .analytics import urls as analytics_urls v2_urls = [ re_path(r'^$', ApiV2RootView.as_view(), name='api_v2_root_view'), @@ -147,6 +147,7 @@ v2_urls = [ re_path(r'^unified_job_templates/$', UnifiedJobTemplateList.as_view(), name='unified_job_template_list'), re_path(r'^unified_jobs/$', UnifiedJobList.as_view(), name='unified_job_list'), re_path(r'^activity_stream/', include(activity_stream_urls)), + re_path(r'^analytics/', include(analytics_urls)), re_path(r'^workflow_approval_templates/', include(workflow_approval_template_urls)), re_path(r'^workflow_approvals/', include(workflow_approval_urls)), re_path(r'^bulk/$', BulkView.as_view(), name='bulk'), diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py new file mode 100644 index 0000000000..ded72f7018 --- /dev/null +++ b/awx/api/views/analytics.py @@ -0,0 +1,173 @@ +import requests +import logging + +from django.utils.translation import gettext_lazy as _ + +from awx.api.generics import APIView, Response +from awx.api.permissions import IsSystemAdminOrAuditor +from awx.api.versioning import reverse +from rest_framework.permissions import AllowAny +from rest_framework import status + +from collections import OrderedDict + +# docker-docker API request requires: +# ``` +# docker network connect koku_default tools_awx_1 +# ``` +AUTOMATION_ANALYTICS_API_URL = "http://automation-analytics-backend_fastapi_1:8080/api/tower-analytics/v1" +# AUTOMATION_ANALYTICS_API_URL = "http://localhost:8004/api/tower-analytics/v1" + +logger = logging.getLogger('awx.api.views') + + +class GetNotAllowedMixin(object): + def get(self, request, format=None): + return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) + + +class AnalyticsRootView(APIView): + permission_classes = (AllowAny,) + name = _('Automation Analytics') + swagger_topic = 'Automation Analytics' + + def get(self, request, format=None): + data = OrderedDict() + data['reports'] = reverse('analytics_reports_list') + return Response(data) + + +class AnalyticsTestList(APIView): + name = _("Testing") + permission_classes = (IsSystemAdminOrAuditor,) + swagger_topic = "AA" + + def get(self, request, format=None): + logger.info(f"TEST: {type(request.headers)}") + new_headers = request.headers.copy() + + data = { + 'get': { + 'method': request.method, + 'content-type': request.content_type, + 'data': request.data, + 'query_params': request.query_params, + 'headers': new_headers, + 'path': request.path, + } + } + return Response(data) + + def post(self, request, format=None): + return self.get(request, format) + + +class AnalyticsGenericView(APIView): + """ + Example: + headers = { + 'Content-Type': 'application/json', + } + + params = { + 'limit': '20', + 'offset': '0', + 'sort_by': 'name:asc', + } + + json_data = { + 'limit': '20', + 'offset': '0', + 'sort_options': 'name', + 'sort_order': 'asc', + 'tags': [], + 'slug': [], + 'name': [], + 'description': '', + } + + response = requests.post(f'{AUTOMATION_ANALYTICS_API_URL}/reports/', params=params, + headers=headers, json=json_data) + + return Response(response.json(), status=response.status_code) + """ + + permission_classes = (IsSystemAdminOrAuditor,) + + def _remove_api_path_prefix(self, request_path): + parts = request_path.split('analytics/') + return parts[len(parts) - 1] + + def _forward_get(self, request, format=None): + headers = {'Content-Type': 'application/json'} + analytics_path = self._remove_api_path_prefix(request.path) + response = requests.get(f'{AUTOMATION_ANALYTICS_API_URL}/{analytics_path}', params=request.query_params, headers=headers) + return Response(response.json(), status=response.status_code) + + def _forward_post(self, request, format=None): + analytics_path = self._remove_api_path_prefix(request.path) + response = requests.post(f'{AUTOMATION_ANALYTICS_API_URL}/{analytics_path}', params=request.query_params, headers=request.headers, json=request.data) + return Response(response.json(), status=response.status_code) + + +class AnalyticsGenericListView(AnalyticsGenericView): + def get(self, request, format=None): + return self._forward_get(request, format) + + def post(self, request, format=None): + return self._forward_post(request, format) + + +class AnalyticsGenericDetailView(AnalyticsGenericView): + def get(self, request, slug, format=None): + return self._forward_get(request, format) + + def post(self, request, slug, format=None): + return self._forward_post(request, format) + + +class AnalyticsAuthorizedView(AnalyticsGenericListView): + name = _("Authorized") + + +class AnalyticsReportsList(AnalyticsGenericListView): + name = _("Reports") + swagger_topic = "Automation Analytics" + + +class AnalyticsReportDetail(AnalyticsGenericDetailView): + name = _("Report") + + +class AnalyticsReportOptionsList(AnalyticsGenericListView): + name = _("Report Options") + + +class AnalyticsAdoptionRateList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("Adoption Rate") + + +class AnalyticsEventExplorerList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("Event Explorer") + + +class AnalyticsHostExplorerList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("Host Explorer") + + +class AnalyticsJobExplorerList(GetNotAllowedMixin, AnalyticsGenericListView): + """TODO: Allow Http GET?""" + + name = _("Job Explorer") + + +class AnalyticsProbeTemplatesList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("Probe Templates") + + +class AnalyticsProbeTemplateForHostsList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("Probe Template For Hosts") + + +class AnalyticsRoiTemplatesList(GetNotAllowedMixin, AnalyticsGenericListView): + name = _("ROI Templates") From 0a40b758c32e0f4b7d4ce0b8579b71a938146dee Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 6 Mar 2023 15:51:09 +0100 Subject: [PATCH 154/167] Analytics API: Paths, headers and Error handling --- awx/api/urls/analytics.py | 1 - awx/api/urls/urls.py | 3 +- awx/api/views/analytics.py | 209 ++++++++++++++++++++++++++++--------- awx/main/analytics/core.py | 4 +- awx/settings/defaults.py | 1 + 5 files changed, 162 insertions(+), 56 deletions(-) diff --git a/awx/api/urls/analytics.py b/awx/api/urls/analytics.py index 17078c32c3..c8601c881d 100644 --- a/awx/api/urls/analytics.py +++ b/awx/api/urls/analytics.py @@ -8,7 +8,6 @@ import awx.api.views.analytics as analytics urls = [ re_path(r'^$', analytics.AnalyticsRootView.as_view(), name='analytics_root_view'), - re_path(r'^test/$', analytics.AnalyticsTestList.as_view(), name='analytics_test_list'), re_path(r'^authorized/$', analytics.AnalyticsAuthorizedView.as_view(), name='analytics_authorized'), re_path(r'^reports/$', analytics.AnalyticsReportsList.as_view(), name='analytics_reports_list'), re_path(r'^report/(?P[\w-]+)/$', analytics.AnalyticsReportDetail.as_view(), name='analytics_report_detail'), diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index 673a1b11cd..94198f3766 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -42,6 +42,7 @@ from awx.api.views.bulk import ( from awx.api.views.mesh_visualizer import MeshVisualizer from awx.api.views.metrics import MetricsView +from awx.api.views.analytics import AWX_ANALYTICS_API_PREFIX from .organization import urls as organization_urls from .user import urls as user_urls @@ -147,7 +148,7 @@ v2_urls = [ re_path(r'^unified_job_templates/$', UnifiedJobTemplateList.as_view(), name='unified_job_template_list'), re_path(r'^unified_jobs/$', UnifiedJobList.as_view(), name='unified_job_list'), re_path(r'^activity_stream/', include(activity_stream_urls)), - re_path(r'^analytics/', include(analytics_urls)), + re_path(rf'^{AWX_ANALYTICS_API_PREFIX}/', include(analytics_urls)), re_path(r'^workflow_approval_templates/', include(workflow_approval_template_urls)), re_path(r'^workflow_approvals/', include(workflow_approval_urls)), re_path(r'^bulk/$', BulkView.as_view(), name='bulk'), diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py index ded72f7018..d59e202377 100644 --- a/awx/api/views/analytics.py +++ b/awx/api/views/analytics.py @@ -1,24 +1,42 @@ import requests import logging +import urllib.parse as urlparse +from django.conf import settings from django.utils.translation import gettext_lazy as _ +from django.utils import translation from awx.api.generics import APIView, Response from awx.api.permissions import IsSystemAdminOrAuditor from awx.api.versioning import reverse +from awx.main.utils import get_awx_version from rest_framework.permissions import AllowAny from rest_framework import status from collections import OrderedDict -# docker-docker API request requires: -# ``` -# docker network connect koku_default tools_awx_1 -# ``` -AUTOMATION_ANALYTICS_API_URL = "http://automation-analytics-backend_fastapi_1:8080/api/tower-analytics/v1" -# AUTOMATION_ANALYTICS_API_URL = "http://localhost:8004/api/tower-analytics/v1" +AUTOMATION_ANALYTICS_API_URL_PATH = "/api/tower-analytics/v1" +AWX_ANALYTICS_API_PREFIX = 'analytics' -logger = logging.getLogger('awx.api.views') +CERT_PATH = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" + +ERROR_UPLOAD_NOT_ENABLED = "analytics-upload-not-enabled" +ERROR_MISSING_URL = "missing-url" +ERROR_MISSING_USER = "missing-user" +ERROR_MISSING_PASSWORD = "missing-password" +ERROR_NO_DATA_OR_ENTITLEMENT = "no-data-or-entitlement" +ERROR_NOT_FOUND = "not-found" +ERROR_UNAUTHORIZED = "unauthorized" +ERROR_UNKNOWN = "unknown" +ERROR_UNSUPPORTED_METHOD = "unsupported-method" + +logger = logging.getLogger('awx.api.views.analytics') + + +class MissingSettings(Exception): + """Settings are not correct Exception""" + + pass class GetNotAllowedMixin(object): @@ -37,31 +55,6 @@ class AnalyticsRootView(APIView): return Response(data) -class AnalyticsTestList(APIView): - name = _("Testing") - permission_classes = (IsSystemAdminOrAuditor,) - swagger_topic = "AA" - - def get(self, request, format=None): - logger.info(f"TEST: {type(request.headers)}") - new_headers = request.headers.copy() - - data = { - 'get': { - 'method': request.method, - 'content-type': request.content_type, - 'data': request.data, - 'query_params': request.query_params, - 'headers': new_headers, - 'path': request.path, - } - } - return Response(data) - - def post(self, request, format=None): - return self.get(request, format) - - class AnalyticsGenericView(APIView): """ Example: @@ -94,43 +87,159 @@ class AnalyticsGenericView(APIView): permission_classes = (IsSystemAdminOrAuditor,) - def _remove_api_path_prefix(self, request_path): - parts = request_path.split('analytics/') - return parts[len(parts) - 1] + @staticmethod + def _request_headers(request): + headers = {} + for header in ['Content-Type', 'Content-Length', 'Accept-Encoding', 'User-Agent', 'Accept']: + if request.headers.get(header, None): + headers[header] = request.headers.get(header) + headers['X-Rh-Analytics-Source'] = 'controller' + headers['X-Rh-Analytics-Source-Version'] = get_awx_version() + headers['Accept-Language'] = translation.get_language() - def _forward_get(self, request, format=None): - headers = {'Content-Type': 'application/json'} - analytics_path = self._remove_api_path_prefix(request.path) - response = requests.get(f'{AUTOMATION_ANALYTICS_API_URL}/{analytics_path}', params=request.query_params, headers=headers) - return Response(response.json(), status=response.status_code) + return headers - def _forward_post(self, request, format=None): - analytics_path = self._remove_api_path_prefix(request.path) - response = requests.post(f'{AUTOMATION_ANALYTICS_API_URL}/{analytics_path}', params=request.query_params, headers=request.headers, json=request.data) - return Response(response.json(), status=response.status_code) + @staticmethod + def _get_analytics_path(request_path): + parts = request_path.split(f'{AWX_ANALYTICS_API_PREFIX}/') + path_specific = parts[-1] + return f"{AUTOMATION_ANALYTICS_API_URL_PATH}/{path_specific}" + + def _get_analytics_url(self, request_path): + analytics_path = self._get_analytics_path(request_path) + url = getattr(settings, 'AUTOMATION_ANALYTICS_URL', None) + if not url: + raise MissingSettings(ERROR_MISSING_URL) + url_parts = urlparse.urlsplit(url) + analytics_url = urlparse.urlunsplit([url_parts.scheme, url_parts.netloc, analytics_path, url_parts.query, url_parts.fragment]) + return analytics_url + + @staticmethod + def _check_upload_enabled(): + state = getattr(settings, 'INSIGHTS_TRACKING_STATE', False) + if not state: + raise MissingSettings(ERROR_UPLOAD_NOT_ENABLED) + return True + + @staticmethod + def _get_rh_user(): + user = getattr(settings, 'REDHAT_USERNAME', None) + if not user: + raise MissingSettings(ERROR_MISSING_USER) + return user + + @staticmethod + def _get_rh_password(): + password = getattr(settings, 'REDHAT_PASSWORD', None) + if not password: + raise MissingSettings(ERROR_MISSING_PASSWORD) + return password + + @staticmethod + def _error_response(keyword, message=None, remote=True, remote_status_code=None, status_code=status.HTTP_403_FORBIDDEN): + text = {"error": {"remote": remote, "remote_status": remote_status_code, "keyword": keyword}} + if message: + text["error"]["message"] = message + return Response(text, status=status_code) + + def _error_response_404(self, response): + try: + json_response = response.json() + # Subscription/entitlement problem or missing tenant data in AA db => HTTP 403 + message = json_response.get('error', None) + if message: + return self._error_response(ERROR_NO_DATA_OR_ENTITLEMENT, message, remote=True, remote_status_code=response.status_code) + + # Standard 404 problem => HTTP 404 + message = json_response.get('detail', None) or response.text + except requests.exceptions.JSONDecodeError: + # Unexpected text => still HTTP 404 + message = response.text + + return self._error_response(ERROR_NOT_FOUND, message, remote=True, remote_status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND) + + @staticmethod + def _forward_response(response): + try: + content_type = response.headers.get('content-type', '') + if content_type.find('application/json') != -1: + return Response(response.json(), status=response.status_code) + except Exception as e: + logger.error(f"Analytics API: Response error: {e}") + + return Response(response.content, status=response.status_code) + + def _send_to_analytics(self, request, method): + try: + headers = self._request_headers(request) + + self._check_upload_enabled() + url = self._get_analytics_url(request.path) + rh_user = self._get_rh_user() + rh_password = self._get_rh_password() + + if method not in ["GET", "POST"]: + return self._error_response(ERROR_UNSUPPORTED_METHOD, method, remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + response = requests.request( + method, + url, + auth=(rh_user, rh_password), + verify=settings.INSIGHTS_CERT_PATH, + params=request.query_params, + headers=headers, + json=request.data, + timeout=(31, 31), + ) + # + # Missing or wrong user/pass + # + if response.status_code == status.HTTP_401_UNAUTHORIZED: + text = (response.text or '').rstrip("\n") + return self._error_response(ERROR_UNAUTHORIZED, text, remote=True, remote_status_code=response.status_code) + # + # Not found, No entitlement or No data in Analytics + # + elif response.status_code == status.HTTP_404_NOT_FOUND: + return self._error_response_404(response) + # + # Success or not a 401/404 errors are just forwarded + # + else: + return self._forward_response(response) + + except MissingSettings as e: + logger.warning(f"Analytics API: Setting missing: {e.args[0]}") + return self._error_response(e.args[0], remote=False) + except requests.exceptions.RequestException as e: + logger.error(f"Analytics API: Request error: {e}") + return self._error_response(ERROR_UNKNOWN, str(e), remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + logger.error(f"Analytics API: Error: {e}") + return self._error_response(ERROR_UNKNOWN, str(e), remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) class AnalyticsGenericListView(AnalyticsGenericView): def get(self, request, format=None): - return self._forward_get(request, format) + return self._send_to_analytics(request, method="GET") def post(self, request, format=None): - return self._forward_post(request, format) + return self._send_to_analytics(request, method="POST") class AnalyticsGenericDetailView(AnalyticsGenericView): def get(self, request, slug, format=None): - return self._forward_get(request, format) + return self._send_to_analytics(request, method="GET") def post(self, request, slug, format=None): - return self._forward_post(request, format) + return self._send_to_analytics(request, method="POST") class AnalyticsAuthorizedView(AnalyticsGenericListView): name = _("Authorized") -class AnalyticsReportsList(AnalyticsGenericListView): +class AnalyticsReportsList(GetNotAllowedMixin, AnalyticsGenericListView): name = _("Reports") swagger_topic = "Automation Analytics" @@ -156,8 +265,6 @@ class AnalyticsHostExplorerList(GetNotAllowedMixin, AnalyticsGenericListView): class AnalyticsJobExplorerList(GetNotAllowedMixin, AnalyticsGenericListView): - """TODO: Allow Http GET?""" - name = _("Job Explorer") diff --git a/awx/main/analytics/core.py b/awx/main/analytics/core.py index 77f6108205..90bfa198eb 100644 --- a/awx/main/analytics/core.py +++ b/awx/main/analytics/core.py @@ -359,9 +359,7 @@ def ship(path): s.headers = get_awx_http_client_headers() s.headers.pop('Content-Type') with set_environ(**settings.AWX_TASK_ENV): - response = s.post( - url, files=files, verify="/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", auth=(rh_user, rh_password), headers=s.headers, timeout=(31, 31) - ) + response = s.post(url, files=files, verify=settings.INSIGHTS_CERT_PATH, auth=(rh_user, rh_password), headers=s.headers, timeout=(31, 31)) # Accept 2XX status_codes if response.status_code >= 300: logger.error('Upload failed with status {}, {}'.format(response.status_code, response.text)) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 593e6ae002..1f7a7c5346 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -792,6 +792,7 @@ INSIGHTS_URL_BASE = "https://example.org" INSIGHTS_AGENT_MIME = 'application/example' # See https://github.com/ansible/awx-facts-playbooks INSIGHTS_SYSTEM_ID_FILE = '/etc/redhat-access-insights/machine-id' +INSIGHTS_CERT_PATH = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" TOWER_SETTINGS_MANIFEST = {} From 0fea29ad4d65700c0c79ef73193a9f7b6369e644 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Tue, 4 Apr 2023 15:13:14 +0200 Subject: [PATCH 155/167] Analytics API: OPTIONS proxy and response links update --- awx/api/views/analytics.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py index d59e202377..3971d36c86 100644 --- a/awx/api/views/analytics.py +++ b/awx/api/views/analytics.py @@ -159,11 +159,22 @@ class AnalyticsGenericView(APIView): return self._error_response(ERROR_NOT_FOUND, message, remote=True, remote_status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND) @staticmethod - def _forward_response(response): + def _update_response_links(json_response): + if not json_response.get('links', None): + return + + for key, value in json_response['links'].items(): + if value: + json_response['links'][key] = value.replace(AUTOMATION_ANALYTICS_API_URL_PATH, f"/api/v2/{AWX_ANALYTICS_API_PREFIX}") + + def _forward_response(self, response): try: content_type = response.headers.get('content-type', '') if content_type.find('application/json') != -1: - return Response(response.json(), status=response.status_code) + json_response = response.json() + self._update_response_links(json_response) + + return Response(json_response, status=response.status_code) except Exception as e: logger.error(f"Analytics API: Response error: {e}") @@ -178,7 +189,7 @@ class AnalyticsGenericView(APIView): rh_user = self._get_rh_user() rh_password = self._get_rh_password() - if method not in ["GET", "POST"]: + if method not in ["GET", "POST", "OPTIONS"]: return self._error_response(ERROR_UNSUPPORTED_METHOD, method, remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) else: response = requests.request( @@ -226,6 +237,9 @@ class AnalyticsGenericListView(AnalyticsGenericView): def post(self, request, format=None): return self._send_to_analytics(request, method="POST") + def options(self, request, format=None): + return self._send_to_analytics(request, method="OPTIONS") + class AnalyticsGenericDetailView(AnalyticsGenericView): def get(self, request, slug, format=None): @@ -234,6 +248,9 @@ class AnalyticsGenericDetailView(AnalyticsGenericView): def post(self, request, slug, format=None): return self._send_to_analytics(request, method="POST") + def options(self, request, slug, format=None): + return self._send_to_analytics(request, method="OPTIONS") + class AnalyticsAuthorizedView(AnalyticsGenericListView): name = _("Authorized") From 51e19d9d0b3fe4ea1eeef9142a1c6cfeab0aacc5 Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Thu, 30 Mar 2023 15:02:40 -0400 Subject: [PATCH 156/167] Adding all endpoints to /api/v2/analytics/ --- awx/api/views/analytics.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py index 3971d36c86..ac87a373e5 100644 --- a/awx/api/views/analytics.py +++ b/awx/api/views/analytics.py @@ -51,7 +51,23 @@ class AnalyticsRootView(APIView): def get(self, request, format=None): data = OrderedDict() - data['reports'] = reverse('analytics_reports_list') + data['authorized'] = reverse('api:analytics_authorized') + data['reports'] = reverse('api:analytics_reports_list') + data['report_options'] = reverse('api:analytics_report_options_list') + data['adoption_rate'] = reverse('api:analytics_adoption_rate') + data['adoption_rate_options'] = reverse('api:analytics_adoption_rate_options') + data['event_explorer'] = reverse('api:analytics_event_explorer') + data['event_explorer_options'] = reverse('api:analytics_event_explorer_options') + data['host_explorer'] = reverse('api:analytics_host_explorer') + data['host_explorer_options'] = reverse('api:analytics_host_explorer_options') + data['job_explorer'] = reverse('api:analytics_job_explorer') + data['job_explorer_options'] = reverse('api:analytics_job_explorer_options') + data['probe_templates'] = reverse('api:analytics_probe_templates_explorer') + data['probe_templates_options'] = reverse('api:analytics_probe_templates_options') + data['probe_template_for_hosts'] = reverse('api:analytics_probe_template_for_hosts_explorer') + data['probe_template_for_hosts_options'] = reverse('api:analytics_probe_template_for_hosts_options') + data['roi_templates'] = reverse('api:analytics_roi_templates_explorer') + data['roi_templates_options'] = reverse('api:analytics_roi_templates_options') return Response(data) From e60869e65330c20d43ccbe99e2fe5b53ef1571cd Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Thu, 30 Mar 2023 16:54:28 -0400 Subject: [PATCH 157/167] Consoldating similar methods --- awx/api/views/analytics.py | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py index ac87a373e5..7f1075df44 100644 --- a/awx/api/views/analytics.py +++ b/awx/api/views/analytics.py @@ -131,25 +131,11 @@ class AnalyticsGenericView(APIView): return analytics_url @staticmethod - def _check_upload_enabled(): - state = getattr(settings, 'INSIGHTS_TRACKING_STATE', False) - if not state: - raise MissingSettings(ERROR_UPLOAD_NOT_ENABLED) - return True - - @staticmethod - def _get_rh_user(): - user = getattr(settings, 'REDHAT_USERNAME', None) - if not user: - raise MissingSettings(ERROR_MISSING_USER) - return user - - @staticmethod - def _get_rh_password(): - password = getattr(settings, 'REDHAT_PASSWORD', None) - if not password: - raise MissingSettings(ERROR_MISSING_PASSWORD) - return password + def _get_setting(setting_name, default, error_message): + setting = getattr(settings, setting_name, default) + if not setting: + raise MissingSettings(error_message) + return setting @staticmethod def _error_response(keyword, message=None, remote=True, remote_status_code=None, status_code=status.HTTP_403_FORBIDDEN): @@ -200,10 +186,10 @@ class AnalyticsGenericView(APIView): try: headers = self._request_headers(request) - self._check_upload_enabled() + self._get_setting('INSIGHTS_TRACKING_STATE', False, ERROR_UPLOAD_NOT_ENABLED) url = self._get_analytics_url(request.path) - rh_user = self._get_rh_user() - rh_password = self._get_rh_password() + rh_user = self._get_setting('REDHAT_USERNAME', None, ERROR_MISSING_USER) + rh_password = self._get_setting('REDHAT_PASSWORD', None, ERROR_MISSING_PASSWORD) if method not in ["GET", "POST", "OPTIONS"]: return self._error_response(ERROR_UNSUPPORTED_METHOD, method, remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) From 9f27436c752fc412e0e75d80fb0dda8c184f9c88 Mon Sep 17 00:00:00 2001 From: John Westcott IV Date: Thu, 30 Mar 2023 17:13:21 -0400 Subject: [PATCH 158/167] Adding basic unit/funcational tests --- .../tests/functional/api/test_analytics.py | 86 +++++++++++++++++++ awx/main/tests/unit/api/test_views.py | 1 + 2 files changed, 87 insertions(+) create mode 100644 awx/main/tests/functional/api/test_analytics.py diff --git a/awx/main/tests/functional/api/test_analytics.py b/awx/main/tests/functional/api/test_analytics.py new file mode 100644 index 0000000000..0c11a1a3ff --- /dev/null +++ b/awx/main/tests/functional/api/test_analytics.py @@ -0,0 +1,86 @@ +import pytest +import requests +from awx.api.views.analytics import AnalyticsGenericView, MissingSettings, AUTOMATION_ANALYTICS_API_URL_PATH +from django.test.utils import override_settings + +from awx.main.utils import get_awx_version +from django.utils import translation + + +class TestAnalyticsGenericView: + @pytest.mark.parametrize( + "existing_headers,expected_headers", + [ + ({}, {}), + ({'Hey': 'There'}, {}), # We don't forward just any headers + ({'Content-Type': 'text/html', 'Content-Length': '12'}, {'Content-Type': 'text/html', 'Content-Length': '12'}), + # Requests will auto-add the following headers (so we don't need to test them): 'Accept-Encoding', 'User-Agent', 'Accept' + ], + ) + def test__request_headers(self, existing_headers, expected_headers): + expected_headers['X-Rh-Analytics-Source'] = 'controller' + expected_headers['X-Rh-Analytics-Source-Version'] = get_awx_version() + expected_headers['Accept-Language'] = translation.get_language() + + request = requests.session() + request.headers.update(existing_headers) + assert set(expected_headers.items()).issubset(set(AnalyticsGenericView._request_headers(request).items())) + + @pytest.mark.parametrize( + "path,expected_path", + [ + ('A/B', f'{AUTOMATION_ANALYTICS_API_URL_PATH}/A/B'), + ('B', f'{AUTOMATION_ANALYTICS_API_URL_PATH}/B'), + ('/a/b/c/analytics/reports/my_slug', f'{AUTOMATION_ANALYTICS_API_URL_PATH}/reports/my_slug'), + ('/a/b/c/analytics/', f'{AUTOMATION_ANALYTICS_API_URL_PATH}/'), + ('/a/b/c/analytics', f'{AUTOMATION_ANALYTICS_API_URL_PATH}//a/b/c/analytics'), # Because there is no ending / on analytics we get a weird condition + ('/a/b/c/analytics/', f'{AUTOMATION_ANALYTICS_API_URL_PATH}/'), + ], + ) + @pytest.mark.django_db + def test__get_analytics_path(self, path, expected_path): + assert AnalyticsGenericView._get_analytics_path(path) == expected_path + + @pytest.mark.django_db + def test__get_analytics_url_no_url(self): + with override_settings(AUTOMATION_ANALYTICS_URL=None): + with pytest.raises(MissingSettings): + agw = AnalyticsGenericView() + agw._get_analytics_url('A') + + @pytest.mark.parametrize( + "request_path,ending_url", + [ + ('A', 'A'), + ('A/B', 'A/B'), + ('A/B/analytics/', ''), # we split on analytics but because there is nothing after + ('A/B/analytics/report', 'report'), + ('A/B/analytics/report/slug', 'report/slug'), + ], + ) + @pytest.mark.django_db + def test__get_analytics_url(self, request_path, ending_url): + base_url = 'http://testing' + with override_settings(AUTOMATION_ANALYTICS_URL=base_url): + agw = AnalyticsGenericView() + assert agw._get_analytics_url(request_path) == f'{base_url}{AUTOMATION_ANALYTICS_API_URL_PATH}/{ending_url}' + + @pytest.mark.parametrize( + "setting_name,setting_value,raises", + [ + ('INSIGHTS_TRACKING_STATE', None, True), + ('INSIGHTS_TRACKING_STATE', False, True), + ('INSIGHTS_TRACKING_STATE', True, False), + ('INSIGHTS_TRACKING_STATE', 'Steve', False), + ('INSIGHTS_TRACKING_STATE', 1, False), + ('INSIGHTS_TRACKING_STATE', '', True), + ], + ) + @pytest.mark.django_db + def test__get_setting(self, setting_name, setting_value, raises): + with override_settings(**{setting_name: setting_value}): + if raises: + with pytest.raises(MissingSettings): + AnalyticsGenericView._get_setting(setting_name, False, None) + else: + assert AnalyticsGenericView._get_setting(setting_name, False, None) == setting_value diff --git a/awx/main/tests/unit/api/test_views.py b/awx/main/tests/unit/api/test_views.py index 950ae57af4..edb60351d0 100644 --- a/awx/main/tests/unit/api/test_views.py +++ b/awx/main/tests/unit/api/test_views.py @@ -50,6 +50,7 @@ class TestApiRootView: 'activity_stream', 'workflow_job_templates', 'workflow_jobs', + 'analytics', ] view = ApiVersionRootView() ret = view.get(mocker.MagicMock()) From dc0958150a6341c561b56a22a6488e92f30aec7e Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Tue, 4 Apr 2023 15:51:45 +0200 Subject: [PATCH 159/167] Adding analytics to root API page --- awx/api/views/analytics.py | 2 -- awx/api/views/root.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/awx/api/views/analytics.py b/awx/api/views/analytics.py index 7f1075df44..e7c50ad5b9 100644 --- a/awx/api/views/analytics.py +++ b/awx/api/views/analytics.py @@ -18,8 +18,6 @@ from collections import OrderedDict AUTOMATION_ANALYTICS_API_URL_PATH = "/api/tower-analytics/v1" AWX_ANALYTICS_API_PREFIX = 'analytics' -CERT_PATH = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" - ERROR_UPLOAD_NOT_ENABLED = "analytics-upload-not-enabled" ERROR_MISSING_URL = "missing-url" ERROR_MISSING_USER = "missing-user" diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 7f33fac4af..4f65b01a15 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -126,6 +126,7 @@ class ApiVersionRootView(APIView): data['workflow_job_nodes'] = reverse('api:workflow_job_node_list', request=request) data['mesh_visualizer'] = reverse('api:mesh_visualizer_view', request=request) data['bulk'] = reverse('api:bulk', request=request) + data['analytics'] = reverse('api:analytics_root_view', request=request) return Response(data) From 44db4587be0eead95355e244574818dddf35c8b7 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Mon, 3 Apr 2023 17:26:37 +0200 Subject: [PATCH 160/167] Analytics upload: HostMetrics hybrid sync --- awx/main/analytics/collectors.py | 76 ++++++++++++++++++++++++++++++-- awx/main/analytics/core.py | 22 +++++++-- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/awx/main/analytics/collectors.py b/awx/main/analytics/collectors.py index e7655997d2..1bc4c9044f 100644 --- a/awx/main/analytics/collectors.py +++ b/awx/main/analytics/collectors.py @@ -6,7 +6,7 @@ import platform import distro from django.db import connection -from django.db.models import Count +from django.db.models import Count, Min from django.conf import settings from django.contrib.sessions.models import Session from django.utils.timezone import now, timedelta @@ -35,7 +35,7 @@ data _since_ the last report date - i.e., new data in the last 24 hours) """ -def trivial_slicing(key, since, until, last_gather): +def trivial_slicing(key, since, until, last_gather, **kwargs): if since is not None: return [(since, until)] @@ -48,7 +48,7 @@ def trivial_slicing(key, since, until, last_gather): return [(last_entry, until)] -def four_hour_slicing(key, since, until, last_gather): +def four_hour_slicing(key, since, until, last_gather, **kwargs): if since is not None: last_entry = since else: @@ -69,6 +69,54 @@ def four_hour_slicing(key, since, until, last_gather): start = end +def host_metric_slicing(key, since, until, last_gather, **kwargs): + """ + Slicing doesn't start 4 weeks ago, but sends whole table monthly or first time + """ + from awx.main.models.inventory import HostMetric + + if since is not None: + return [(since, until)] + + from awx.conf.models import Setting + + # Check if full sync should be done + full_sync_enabled = kwargs.get('full_sync_enabled', False) + last_entry = None + if not full_sync_enabled: + # + # If not, try incremental sync first + # + last_entries = Setting.objects.filter(key='AUTOMATION_ANALYTICS_LAST_ENTRIES').first() + last_entries = json.loads((last_entries.value if last_entries is not None else '') or '{}', object_hook=datetime_hook) + last_entry = last_entries.get(key) + if not last_entry: + # + # If not done before, switch to full sync + # + full_sync_enabled = True + + if full_sync_enabled: + # + # Find the lowest date for full sync + # + min_dates = HostMetric.objects.aggregate(min_last_automation=Min('last_automation'), min_last_deleted=Min('last_deleted')) + if min_dates['min_last_automation'] and min_dates['min_last_deleted']: + last_entry = min(min_dates['min_last_automation'], min_dates['min_last_deleted']) + elif min_dates['min_last_automation'] or min_dates['min_last_deleted']: + last_entry = min_dates['min_last_automation'] or min_dates['min_last_deleted'] + + if not last_entry: + # empty table + return [] + + start, end = last_entry, None + while start < until: + end = min(start + timedelta(days=30), until) + yield (start, end) + start = end + + def _identify_lower(key, since, until, last_gather): from awx.conf.models import Setting @@ -537,3 +585,25 @@ def workflow_job_template_node_table(since, full_path, **kwargs): ) always_nodes ON main_workflowjobtemplatenode.id = always_nodes.from_workflowjobtemplatenode_id ORDER BY main_workflowjobtemplatenode.id ASC) TO STDOUT WITH CSV HEADER''' return _copy_table(table='workflow_job_template_node', query=workflow_job_template_node_query, path=full_path) + + +@register( + 'host_metric_table', '1.0', format='csv', description=_('Host Metric data, incremental/full sync'), expensive=host_metric_slicing, full_sync_interval=30 +) +def host_metric_table(since, full_path, until, **kwargs): + host_metric_query = '''COPY (SELECT main_hostmetric.id, + main_hostmetric.hostname, + main_hostmetric.first_automation, + main_hostmetric.last_automation, + main_hostmetric.last_deleted, + main_hostmetric.deleted, + main_hostmetric.automated_counter, + main_hostmetric.deleted_counter, + main_hostmetric.used_in_inventories + FROM main_hostmetric + WHERE (main_hostmetric.last_automation > '{}' AND main_hostmetric.last_automation <= '{}') OR + (main_hostmetric.last_deleted > '{}' AND main_hostmetric.last_deleted <= '{}') + ORDER BY main_hostmetric.id ASC) TO STDOUT WITH CSV HEADER'''.format( + since.isoformat(), until.isoformat(), since.isoformat(), until.isoformat() + ) + return _copy_table(table='host_metric', query=host_metric_query, path=full_path) diff --git a/awx/main/analytics/core.py b/awx/main/analytics/core.py index 77f6108205..9cbc873b2b 100644 --- a/awx/main/analytics/core.py +++ b/awx/main/analytics/core.py @@ -52,7 +52,7 @@ def all_collectors(): } -def register(key, version, description=None, format='json', expensive=None): +def register(key, version, description=None, format='json', expensive=None, full_sync_interval=None): """ A decorator used to register a function as a metric collector. @@ -71,6 +71,7 @@ def register(key, version, description=None, format='json', expensive=None): f.__awx_analytics_description__ = description f.__awx_analytics_type__ = format f.__awx_expensive__ = expensive + f.__awx_full_sync_interval__ = full_sync_interval return f return decorate @@ -259,10 +260,19 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti # These slicer functions may return a generator. The `since` parameter is # allowed to be None, and will fall back to LAST_ENTRIES[key] or to # LAST_GATHER (truncated appropriately to match the 4-week limit). + # + # Or it can force full table sync if interval is given + kwargs = dict() + full_sync_enabled = False + if func.__awx_full_sync_interval__: + last_full_sync = last_entries.get(f"{key}_full") + full_sync_enabled = not last_full_sync or last_full_sync < now() - timedelta(days=func.__awx_full_sync_interval__) + + kwargs['full_sync_enabled'] = full_sync_enabled if func.__awx_expensive__: - slices = func.__awx_expensive__(key, since, until, last_gather) + slices = func.__awx_expensive__(key, since, until, last_gather, **kwargs) else: - slices = collectors.trivial_slicing(key, since, until, last_gather) + slices = collectors.trivial_slicing(key, since, until, last_gather, **kwargs) for start, end in slices: files = func(start, full_path=gather_dir, until=end) @@ -301,6 +311,12 @@ def gather(dest=None, module=None, subset=None, since=None, until=None, collecti succeeded = False logger.exception("Could not generate metric {}".format(filename)) + # update full sync timestamp if successfully shipped + if full_sync_enabled and collection_type != 'dry-run' and succeeded: + with disable_activity_stream(): + last_entries[f"{key}_full"] = now() + settings.AUTOMATION_ANALYTICS_LAST_ENTRIES = json.dumps(last_entries, cls=DjangoJSONEncoder) + if collection_type != 'dry-run': if succeeded: for fpath in tarfiles: From fff6fa7d7a7e61aa7d1a60757002bb5a7a1cb982 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Thu, 23 Mar 2023 14:16:20 +0100 Subject: [PATCH 161/167] Additional Licensing values --- awx/main/utils/licensing.py | 6 +++++- .../SubscriptionDetail/SubscriptionDetail.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/awx/main/utils/licensing.py b/awx/main/utils/licensing.py index b3ea7723e5..c692e3131a 100644 --- a/awx/main/utils/licensing.py +++ b/awx/main/utils/licensing.py @@ -388,9 +388,13 @@ class Licenser(object): if subscription_model == SUBSCRIPTION_USAGE_MODEL_UNIQUE_HOSTS: automated_instances = HostMetric.active_objects.count() first_host = HostMetric.active_objects.only('first_automation').order_by('first_automation').first() + attrs['deleted_instances'] = HostMetric.objects.filter(deleted=True).count() + attrs['reactivated_instances'] = HostMetric.active_objects.filter(deleted_counter__gte=1).count() else: - automated_instances = HostMetric.objects.count() + automated_instances = 0 first_host = HostMetric.objects.only('first_automation').order_by('first_automation').first() + attrs['deleted_instances'] = 0 + attrs['reactivated_instances'] = 0 if first_host: automated_since = int(first_host.first_automation.timestamp()) diff --git a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js index a9349e3345..bbb4935c6f 100644 --- a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js +++ b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js @@ -112,6 +112,16 @@ function SubscriptionDetail() { label={t`Hosts remaining`} value={license_info.free_instances} /> + + {license_info.instance_count < 9999999 && ( Date: Mon, 27 Mar 2023 12:06:22 +0200 Subject: [PATCH 162/167] HostMetric Cleanup task --- awx/main/conf.py | 9 ++++++++ .../commands/cleanup_host_metrics.py | 22 +++++++++++++++++++ awx/main/models/inventory.py | 12 ++++++++++ awx/main/tasks/system.py | 15 +++++++++++++ awx/settings/defaults.py | 8 +++++++ 5 files changed, 66 insertions(+) create mode 100644 awx/main/management/commands/cleanup_host_metrics.py diff --git a/awx/main/conf.py b/awx/main/conf.py index 33b3b4714d..c9515e845e 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -822,6 +822,15 @@ register( category_slug='system', ) +register( + 'CLEANUP_HOST_METRICS_LAST_TS', + field_class=fields.DateTimeField, + label=_('Last cleanup date for HostMetrics'), + allow_null=True, + category=_('System'), + category_slug='system', +) + def logging_validate(serializer, attrs): if not serializer.instance or not hasattr(serializer.instance, 'LOG_AGGREGATOR_HOST') or not hasattr(serializer.instance, 'LOG_AGGREGATOR_TYPE'): diff --git a/awx/main/management/commands/cleanup_host_metrics.py b/awx/main/management/commands/cleanup_host_metrics.py new file mode 100644 index 0000000000..788ffcba94 --- /dev/null +++ b/awx/main/management/commands/cleanup_host_metrics.py @@ -0,0 +1,22 @@ +from awx.main.models import HostMetric +from django.core.management.base import BaseCommand +from django.conf import settings + + +class Command(BaseCommand): + """ + Run soft-deleting of HostMetrics + """ + + help = 'Run soft-deleting of HostMetrics' + + def add_arguments(self, parser): + parser.add_argument('--months-ago', type=int, dest='months-ago', action='store', help='Threshold in months for soft-deleting') + + def handle(self, *args, **options): + months_ago = options.get('months-ago') or None + + if not months_ago: + months_ago = getattr(settings, 'CLEANUP_HOST_METRICS_THRESHOLD', 12) + + HostMetric.cleanup_task(months_ago) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index fe1b09e23d..626775a9d6 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -9,6 +9,8 @@ import re import copy import os.path from urllib.parse import urljoin + +import dateutil.relativedelta import yaml # Django @@ -888,6 +890,16 @@ class HostMetric(models.Model): self.deleted = False self.save(update_fields=['deleted']) + @classmethod + def cleanup_task(cls, months_ago): + last_automation_before = now() - dateutil.relativedelta.relativedelta(months=months_ago) + + logger.info(f'Cleanup [HostMetric]: soft-deleting records last automated before {last_automation_before}') + HostMetric.objects.filter(last_automation__lt=last_automation_before).update( + deleted=True, deleted_counter=models.F('deleted_counter') + 1, last_deleted=now() + ) + settings.CLEANUP_HOST_METRICS_LAST_TS = now() + class HostMetricSummaryMonthly(models.Model): """ diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index a83dad5ccc..36fc266803 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -47,6 +47,7 @@ from awx.main.models import ( Inventory, SmartInventoryMembership, Job, + HostMetric, ) from awx.main.constants import ACTIVE_STATES from awx.main.dispatch.publish import task @@ -378,6 +379,20 @@ def cleanup_images_and_files(): _cleanup_images_and_files() +@task(queue=get_task_queuename) +def cleanup_host_metrics(): + from awx.conf.models import Setting + from rest_framework.fields import DateTimeField + + last_cleanup = Setting.objects.filter(key='CLEANUP_HOST_METRICS_LAST_TS').first() + last_time = DateTimeField().to_internal_value(last_cleanup.value) if last_cleanup and last_cleanup.value else None + + cleanup_interval_secs = getattr(settings, 'CLEANUP_HOST_METRICS_INTERVAL', 30) * 86400 + if not last_time or ((now() - last_time).total_seconds() > cleanup_interval_secs): + months_ago = getattr(settings, 'CLEANUP_HOST_METRICS_THRESHOLD', 12) + HostMetric.cleanup_task(months_ago) + + @task(queue=get_task_queuename) def cluster_node_health_check(node): """ diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 593e6ae002..82d0e7b343 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -475,6 +475,7 @@ CELERYBEAT_SCHEDULE = { 'receptor_reaper': {'task': 'awx.main.tasks.system.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.system.cleanup_images_and_files', 'schedule': timedelta(hours=3)}, + 'cleanup_host_metrics': {'task': 'awx.main.tasks.system.cleanup_host_metrics', 'schedule': timedelta(days=1)}, } # Django Caching Configuration @@ -1052,3 +1053,10 @@ UI_NEXT = True # - '': No model - Subscription not counted from Host Metrics # - 'unique_managed_hosts': Compliant = automated - deleted hosts (using /api/v2/host_metrics/) SUBSCRIPTION_USAGE_MODEL = '' + +# Host metrics cleanup - last time of the cleanup run (soft-deleting records) +CLEANUP_HOST_METRICS_LAST_TS = None +# Host metrics cleanup - minimal interval between two cleanups in days +CLEANUP_HOST_METRICS_INTERVAL = 30 # days +# Host metrics cleanup - soft-delete HostMetric records with last_automation < [threshold] (in months) +CLEANUP_HOST_METRICS_THRESHOLD = 12 # months From 64923e12fcc6a898b3352dc593d72e626e4f147a Mon Sep 17 00:00:00 2001 From: Salma Kochay Date: Wed, 29 Mar 2023 13:42:25 -0400 Subject: [PATCH 163/167] show/hide host metric subscription details --- .../SubscriptionDetail/SubscriptionDetail.js | 92 ++++++++++--------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js index bbb4935c6f..70356a030a 100644 --- a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js +++ b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js @@ -24,7 +24,7 @@ const HelperText = styled(PFHelperText)` `; function SubscriptionDetail() { - const { me = {}, license_info, version } = useConfig(); + const { me = {}, license_info, version, systemConfig } = useConfig(); const baseURL = '/settings/subscription'; const tabsArray = [ { @@ -56,35 +56,37 @@ function SubscriptionDetail() { - - - - {t`The number of hosts you have automated against is below your subscription count.`} - - - ) : ( - <> - - - {t`You have automated against more hosts than your subscription allows.`} - - - ) - } - /> + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + + + + {t`The number of hosts you have automated against is below your subscription count.`} + + + ) : ( + <> + + + {t`You have automated against more hosts than your subscription allows.`} + + + ) + } + /> + )} {typeof automatedInstancesCount !== 'undefined' && automatedInstancesCount !== null && ( - - - + )} + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + + )} + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + + /> + )} {license_info.instance_count < 9999999 && ( Date: Mon, 3 Apr 2023 13:27:14 -0400 Subject: [PATCH 164/167] UI test fixes for hiding subscription details --- .../SubscriptionDetail/SubscriptionDetail.js | 12 ++++++++---- .../SubscriptionDetail/SubscriptionDetail.test.js | 3 +++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js index 70356a030a..6f16cbbb4d 100644 --- a/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js +++ b/awx/ui/src/screens/Setting/Subscription/SubscriptionDetail/SubscriptionDetail.js @@ -56,7 +56,8 @@ function SubscriptionDetail() { - {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === + 'unique_managed_hosts' && ( - {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === + 'unique_managed_hosts' && ( )} - {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === + 'unique_managed_hosts' && ( )} - {systemConfig?.SUBSCRIPTION_USAGE_MODEL === 'unique_managed_hosts' && ( + {systemConfig?.SUBSCRIPTION_USAGE_MODEL === + 'unique_managed_hosts' && ( ', () => { From 20817789bd0f20f327ff8d286e7237a68f021b06 Mon Sep 17 00:00:00 2001 From: Martin Slemr Date: Wed, 5 Apr 2023 09:54:36 +0200 Subject: [PATCH 165/167] HostMetric task param check --- awx/main/models/inventory.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 626775a9d6..21b3839461 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -892,13 +892,20 @@ class HostMetric(models.Model): @classmethod def cleanup_task(cls, months_ago): - last_automation_before = now() - dateutil.relativedelta.relativedelta(months=months_ago) + try: + months_ago = int(months_ago) + if months_ago <= 0: + raise ValueError() - logger.info(f'Cleanup [HostMetric]: soft-deleting records last automated before {last_automation_before}') - HostMetric.objects.filter(last_automation__lt=last_automation_before).update( - deleted=True, deleted_counter=models.F('deleted_counter') + 1, last_deleted=now() - ) - settings.CLEANUP_HOST_METRICS_LAST_TS = now() + last_automation_before = now() - dateutil.relativedelta.relativedelta(months=months_ago) + + logger.info(f'Cleanup [HostMetric]: soft-deleting records last automated before {last_automation_before}') + HostMetric.active_objects.filter(last_automation__lt=last_automation_before).update( + deleted=True, deleted_counter=models.F('deleted_counter') + 1, last_deleted=now() + ) + settings.CLEANUP_HOST_METRICS_LAST_TS = now() + except (TypeError, ValueError): + logger.error(f"Cleanup [HostMetric]: months_ago({months_ago}) has to be a positive integer value") class HostMetricSummaryMonthly(models.Model): From 328880609b0ed6c9cdb6ed87d0dac0972c9bd217 Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Fri, 7 Apr 2023 11:48:34 -0400 Subject: [PATCH 166/167] Fix importlib-metadata dependency conflict rerun requirements/updator.sh to regenerate requirements.txt fix conflict introduced by https://github.com/ansible/ansible-runner/pull/1224 --- Makefile | 3 --- requirements/requirements.txt | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index fffa237d3d..9afc7c7440 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,6 @@ GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) MANAGEMENT_COMMAND ?= awx-manage VERSION := $(shell $(PYTHON) tools/scripts/scm_version.py) -# temparary workaround for pip resolver issues -PIP_OPTIONS="--use-deprecated=legacy-resolver" - # ansible-test requires semver compatable version, so we allow overrides to hack it COLLECTION_VERSION ?= $(shell $(PYTHON) tools/scripts/scm_version.py | cut -d . -f 1-3) # args for the ansible-test sanity command diff --git a/requirements/requirements.txt b/requirements/requirements.txt index f45e0acb87..217356b5ca 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -172,8 +172,10 @@ idna==3.4 # requests # twisted # yarl -importlib-metadata==5.1.0 - # via markdown +importlib-metadata==4.6.4 + # via + # ansible-runner + # markdown incremental==22.10.0 # via twisted inflect==6.0.2 From 0b1b866128649611906956765a30184a8c7a1529 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Mon, 10 Apr 2023 08:33:25 -0400 Subject: [PATCH 167/167] Fixes bug where attempting to edit a schedule with stringified extra_data threw error (#13795) --- awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js index adc5ff1b97..0ce554a297 100644 --- a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js +++ b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js @@ -113,6 +113,9 @@ function ScheduleEdit({ days: values.daysToKeep, }); } else { + if (typeof requestData.extra_data === 'string') { + requestData.extra_data = JSON.parse(requestData.extra_data); + } requestData.extra_data.days = values.daysToKeep; } }

; } @@ -111,6 +114,27 @@ describe('useWsProject', () => { status: 'running', finished: null, }); + + expect(InventorySourcesAPI.readDetail).toHaveBeenCalledTimes(0); + InventorySourcesAPI.readDetail.mockResolvedValue({ + data: {}, + }); + await act(async () => { + mockServer.send( + JSON.stringify({ + group_name: 'jobs', + inventory_id: 1, + status: 'successful', + type: 'inventory_update', + unified_job_id: 2, + unified_job_template_id: 1, + inventory_source_id: 1, + }) + ); + }); + expect(InventorySourcesAPI.readDetail).toHaveBeenCalledTimes(1); + + jest.clearAllMocks(); WS.clean(); }); }); From e7a739c3d7e65f934a3a71a4a4ced060cfe41201 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 21 Feb 2023 16:28:14 -0500 Subject: [PATCH 073/167] Creates constructed inventory host lists by reusing, and renaming smart inventory host list components. --- .../AdvancedInventoryHost.js} | 21 ++++++------ .../AdvancedInventoryHost.test.js} | 12 +++---- .../Inventory/AdvancedInventoryHost/index.js | 1 + .../AdvancedInventoryHostDetail.js} | 12 ++++--- .../AdvancedInventoryHostDetail.test.js} | 11 ++++--- .../AdvancedInventoryHostDetail/index.js | 1 + .../AdvancedInventoryHostList.js} | 18 ++++++---- .../AdvancedInventoryHostList.test.js} | 12 +++---- .../AdvancedInventoryHostListItem.js} | 28 ++++++++-------- .../AdvancedInventoryHostListItem.test.js} | 6 ++-- .../AdvancedInventoryHosts.js | 27 +++++++++++++++ .../AdvancedInventoryHosts.test.js} | 33 +++++++++++-------- .../Inventory/AdvancedInventoryHosts/index.js | 1 + .../screens/Inventory/ConstructedInventory.js | 16 ++++++--- .../Inventory/ConstructedInventory.test.js | 22 +++++++++---- .../ConstructedInventoryHosts.js | 13 -------- .../ConstructedInventoryHosts.test.js | 15 --------- .../ConstructedInventoryHosts/index.js | 1 - .../src/screens/Inventory/SmartInventory.js | 4 +-- .../Inventory/SmartInventoryHost/index.js | 1 - .../SmartInventoryHostDetail/index.js | 1 - .../SmartInventoryHosts.js | 27 --------------- .../Inventory/SmartInventoryHosts/index.js | 1 - 23 files changed, 144 insertions(+), 140 deletions(-) rename awx/ui/src/screens/Inventory/{SmartInventoryHost/SmartInventoryHost.js => AdvancedInventoryHost/AdvancedInventoryHost.js} (74%) rename awx/ui/src/screens/Inventory/{SmartInventoryHost/SmartInventoryHost.test.js => AdvancedInventoryHost/AdvancedInventoryHost.test.js} (90%) create mode 100644 awx/ui/src/screens/Inventory/AdvancedInventoryHost/index.js rename awx/ui/src/screens/Inventory/{SmartInventoryHostDetail/SmartInventoryHostDetail.js => AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.js} (80%) rename awx/ui/src/screens/Inventory/{SmartInventoryHostDetail/SmartInventoryHostDetail.test.js => AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.test.js} (80%) create mode 100644 awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/index.js rename awx/ui/src/screens/Inventory/{SmartInventoryHosts/SmartInventoryHostList.js => AdvancedInventoryHosts/AdvancedInventoryHostList.js} (87%) rename awx/ui/src/screens/Inventory/{SmartInventoryHosts/SmartInventoryHostList.test.js => AdvancedInventoryHosts/AdvancedInventoryHostList.test.js} (85%) rename awx/ui/src/screens/Inventory/{SmartInventoryHosts/SmartInventoryHostListItem.js => AdvancedInventoryHosts/AdvancedInventoryHostListItem.js} (60%) rename awx/ui/src/screens/Inventory/{SmartInventoryHosts/SmartInventoryHostListItem.test.js => AdvancedInventoryHosts/AdvancedInventoryHostListItem.test.js} (84%) create mode 100644 awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHosts.js rename awx/ui/src/screens/Inventory/{SmartInventoryHosts/SmartInventoryHosts.test.js => AdvancedInventoryHosts/AdvancedInventoryHosts.test.js} (62%) create mode 100644 awx/ui/src/screens/Inventory/AdvancedInventoryHosts/index.js delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js delete mode 100644 awx/ui/src/screens/Inventory/SmartInventoryHost/index.js delete mode 100644 awx/ui/src/screens/Inventory/SmartInventoryHostDetail/index.js delete mode 100644 awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.js delete mode 100644 awx/ui/src/screens/Inventory/SmartInventoryHosts/index.js diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.js similarity index 74% rename from awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.js index 62de1ecf5c..1276c3bbf8 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.js @@ -8,11 +8,11 @@ import ContentLoading from 'components/ContentLoading'; import RoutedTabs from 'components/RoutedTabs'; import useRequest from 'hooks/useRequest'; import { InventoriesAPI } from 'api'; -import SmartInventoryHostDetail from '../SmartInventoryHostDetail'; +import AdvancedInventoryHostDetail from '../AdvancedInventoryHostDetail'; -function SmartInventoryHost({ inventory, setBreadcrumb }) { +function AdvancedInventoryHost({ inventory, setBreadcrumb }) { const { params, path, url } = useRouteMatch( - '/inventories/smart_inventory/:id/hosts/:hostId' + '/inventories/:inventoryType/:id/hosts/:hostId' ); const { @@ -28,7 +28,7 @@ function SmartInventoryHost({ inventory, setBreadcrumb }) { ); return response; }, [inventory.id, params.hostId]), - null + { isLoading: true } ); useEffect(() => { @@ -44,7 +44,6 @@ function SmartInventoryHost({ inventory, setBreadcrumb }) { if (error) { return ; } - const tabsArray = [ { name: ( @@ -53,7 +52,7 @@ function SmartInventoryHost({ inventory, setBreadcrumb }) { {t`Back to Hosts`} ), - link: `/inventories/smart_inventory/${inventory.id}/hosts`, + link: `/inventories/${params.inventoryType}/${inventory.id}/hosts`, id: 0, }, { @@ -72,17 +71,19 @@ function SmartInventoryHost({ inventory, setBreadcrumb }) { {!isLoading && host && ( - + - {t`View smart inventory host details`} + {params.inventoryType === 'smart_inventory' + ? t`View smart inventory host details` + : t`View constructed inventory host details`} @@ -92,4 +93,4 @@ function SmartInventoryHost({ inventory, setBreadcrumb }) { ); } -export default SmartInventoryHost; +export default AdvancedInventoryHost; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.test.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.test.js similarity index 90% rename from awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.test.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.test.js index d3f01bd85e..345b9478b7 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHost/SmartInventoryHost.test.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.test.js @@ -7,14 +7,14 @@ import { waitForElement, } from '../../../../testUtils/enzymeHelpers'; import mockHost from '../shared/data.host.json'; -import SmartInventoryHost from './SmartInventoryHost'; +import AdvancedInventoryHost from './AdvancedInventoryHost'; jest.mock('../../../api'); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useRouteMatch: () => ({ params: { id: 1234, hostId: 2 }, - path: '/inventories/smart_inventory/:id/hosts/:hostId', + path: '/inventories/:inventoryType/:id/hosts/:hostId', url: '/inventories/smart_inventory/1234/hosts/2', }), })); @@ -24,7 +24,7 @@ const mockSmartInventory = { name: 'Mock Smart Inventory', }; -describe('', () => { +describe('', () => { let wrapper; let history; @@ -36,7 +36,7 @@ describe('', () => { InventoriesAPI.readHostDetail.mockResolvedValue(mockHost); await act(async () => { wrapper = mountWithContexts( - {}} /> @@ -55,7 +55,7 @@ describe('', () => { InventoriesAPI.readHostDetail.mockRejectedValueOnce(new Error()); await act(async () => { wrapper = mountWithContexts( - {}} /> @@ -76,7 +76,7 @@ describe('', () => { }); await act(async () => { wrapper = mountWithContexts( - {}} />, diff --git a/awx/ui/src/screens/Inventory/AdvancedInventoryHost/index.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/index.js new file mode 100644 index 0000000000..24b8579c1b --- /dev/null +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHost/index.js @@ -0,0 +1 @@ +export { default } from './AdvancedInventoryHost'; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.js similarity index 80% rename from awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.js index 27af396135..afe2836663 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import { t } from '@lingui/macro'; import { Host } from 'types'; @@ -8,7 +8,8 @@ import { Detail, DetailList, UserDateDetail } from 'components/DetailList'; import Sparkline from 'components/Sparkline'; import { VariablesDetail } from 'components/CodeEditor'; -function SmartInventoryHostDetail({ host }) { +function AdvancedInventoryHostDetail({ host }) { + const { inventoryType } = useParams(); const { created, description, @@ -24,6 +25,7 @@ function SmartInventoryHostDetail({ host }) { type: 'job', })); + const inventoryKind = inventory.kind === '' ? 'inventory' : inventoryType; return ( @@ -37,7 +39,7 @@ function SmartInventoryHostDetail({ host }) { + {inventory?.name} } @@ -61,8 +63,8 @@ function SmartInventoryHostDetail({ host }) { ); } -SmartInventoryHostDetail.propTypes = { +AdvancedInventoryHostDetail.propTypes = { host: Host.isRequired, }; -export default SmartInventoryHostDetail; +export default AdvancedInventoryHostDetail; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.test.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.test.js similarity index 80% rename from awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.test.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.test.js index 93a6092b80..11c7ec7920 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/SmartInventoryHostDetail.test.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/AdvancedInventoryHostDetail.test.js @@ -1,15 +1,17 @@ import React from 'react'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; -import SmartInventoryHostDetail from './SmartInventoryHostDetail'; +import AdvancedInventoryHostDetail from './AdvancedInventoryHostDetail'; import mockHost from '../shared/data.host.json'; jest.mock('../../../api'); -describe('', () => { +describe('', () => { let wrapper; beforeAll(() => { - wrapper = mountWithContexts(); + wrapper = mountWithContexts( + + ); }); test('should render Details', () => { @@ -30,11 +32,12 @@ describe('', () => { test('should not load Activity', () => { wrapper = mountWithContexts( - diff --git a/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/index.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/index.js new file mode 100644 index 0000000000..7162875c23 --- /dev/null +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHostDetail/index.js @@ -0,0 +1 @@ +export { default } from './AdvancedInventoryHostDetail'; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.js similarity index 87% rename from awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.js index 747e7bd058..8406c439e9 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.js @@ -13,7 +13,7 @@ import { getQSConfig, parseQueryString } from 'util/qs'; import { InventoriesAPI } from 'api'; import { Inventory } from 'types'; import AdHocCommands from 'components/AdHocCommands/AdHocCommands'; -import SmartInventoryHostListItem from './SmartInventoryHostListItem'; +import AdvancedInventoryHostListItem from './AdvancedInventoryHostListItem'; const QS_CONFIG = getQSConfig('host', { page: 1, @@ -21,7 +21,7 @@ const QS_CONFIG = getQSConfig('host', { order_by: 'name', }); -function SmartInventoryHostList({ inventory }) { +function AdvancedInventoryHostList({ inventory }) { const location = useLocation(); const [isAdHocLaunchLoading, setIsAdHocLaunchLoading] = useState(false); const { @@ -61,7 +61,10 @@ function SmartInventoryHostList({ inventory }) { useEffect(() => { fetchHosts(); }, [fetchHosts]); - + const inventoryType = + inventory.kind === 'constructed' + ? 'constructed_inventory' + : 'smart_inventory'; return ( } renderRow={(host, index) => ( - row.id === host.id)} onSelect={() => handleSelect(host)} rowIndex={index} @@ -127,8 +131,8 @@ function SmartInventoryHostList({ inventory }) { ); } -SmartInventoryHostList.propTypes = { +AdvancedInventoryHostList.propTypes = { inventory: Inventory.isRequired, }; -export default SmartInventoryHostList; +export default AdvancedInventoryHostList; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.test.js similarity index 85% rename from awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.test.js index 0b87981836..f51befdaf2 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostList.test.js @@ -5,13 +5,13 @@ import { mountWithContexts, waitForElement, } from '../../../../testUtils/enzymeHelpers'; -import SmartInventoryHostList from './SmartInventoryHostList'; +import AdvancedInventoryHostList from './AdvancedInventoryHostList'; import mockInventory from '../shared/data.inventory.json'; import mockHosts from '../shared/data.hosts.json'; jest.mock('../../../api'); -describe('', () => { +describe('', () => { let wrapper; const clonedInventory = { ...mockInventory, @@ -44,7 +44,7 @@ describe('', () => { }); await act(async () => { wrapper = mountWithContexts( - + ); }); await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); @@ -55,12 +55,12 @@ describe('', () => { }); test('initially renders successfully', () => { - expect(wrapper.find('SmartInventoryHostList').length).toBe(1); + expect(wrapper.find('AdvancedInventoryHostList').length).toBe(1); }); test('should fetch hosts from api and render them in the list', () => { expect(InventoriesAPI.readHosts).toHaveBeenCalled(); - expect(wrapper.find('SmartInventoryHostListItem').length).toBe(3); + expect(wrapper.find('AdvancedInventoryHostListItem').length).toBe(3); }); test('should select and deselect all items', async () => { @@ -87,7 +87,7 @@ describe('', () => { ); await act(async () => { wrapper = mountWithContexts( - + ); }); await waitForElement(wrapper, 'ContentError', (el) => el.length === 1); diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.js similarity index 60% rename from awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.js index ae5fe8aab3..8030a7f5d7 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.js @@ -9,20 +9,26 @@ import { Tr, Td } from '@patternfly/react-table'; import Sparkline from 'components/Sparkline'; import { Host } from 'types'; -function SmartInventoryHostListItem({ +function AdvancedInventoryHostListItem({ detailUrl, - host, + host: { + name, + id, + summary_fields: { recent_jobs, inventory }, + }, isSelected, onSelect, rowIndex, + inventoryType, }) { - const recentPlaybookJobs = host.summary_fields.recent_jobs.map((job) => ({ + const recentPlaybookJobs = recent_jobs.map((job) => ({ ...job, type: 'job', })); - + const inventoryKind = inventory.kind === '' ? 'inventory' : inventoryType; + const inventoryLink = `/inventories/${inventoryKind}/${inventory.id}/details`; return ( - + - {host.name} + {name} - - {host.summary_fields.inventory.name} - + {inventory.name} ); } -SmartInventoryHostListItem.propTypes = { +AdvancedInventoryHostListItem.propTypes = { detailUrl: string.isRequired, host: Host.isRequired, isSelected: bool.isRequired, onSelect: func.isRequired, }; -export default SmartInventoryHostListItem; +export default AdvancedInventoryHostListItem; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.test.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.test.js similarity index 84% rename from awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.test.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.test.js index b3d26782ca..be66aaa9b4 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostListItem.test.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHostListItem.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; -import SmartInventoryHostListItem from './SmartInventoryHostListItem'; +import AdvancedInventoryHostListItem from './AdvancedInventoryHostListItem'; const mockHost = { id: 2, @@ -19,14 +19,14 @@ const mockHost = { }, }; -describe('', () => { +describe('', () => { let wrapper; beforeEach(() => { wrapper = mountWithContexts( - + + + + + + + + ); +} + +AdvancedInventoryHosts.propTypes = { + inventory: Inventory.isRequired, +}; + +export default AdvancedInventoryHosts; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.test.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHosts.test.js similarity index 62% rename from awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.test.js rename to awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHosts.test.js index f97b3c73d0..049bc0873c 100644 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.test.js +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHosts.test.js @@ -5,37 +5,39 @@ import { mountWithContexts, waitForElement, } from '../../../../testUtils/enzymeHelpers'; -import SmartInventoryHosts from './SmartInventoryHosts'; +import AdvancedInventoryHosts from './AdvancedInventoryHosts'; jest.mock('../../../api'); -jest.mock('./SmartInventoryHostList', () => { - const SmartInventoryHostList = () =>
; +jest.mock('./AdvancedInventoryHostList', () => { + const AdvancedInventoryHostList = () =>
; return { __esModule: true, - default: SmartInventoryHostList, + default: AdvancedInventoryHostList, }; }); -describe('', () => { +describe('', () => { test('should render smart inventory host list', () => { const history = createMemoryHistory({ initialEntries: ['/inventories/smart_inventory/1/hosts'], }); const match = { - path: '/inventories/smart_inventory/:id/hosts', + path: '/inventories/:inventoryType/:id/hosts', url: '/inventories/smart_inventory/1/hosts', isExact: true, }; const wrapper = mountWithContexts( - , + , { context: { router: { history, route: { match } } }, } ); - expect(wrapper.find('SmartInventoryHostList').length).toBe(1); - expect(wrapper.find('SmartInventoryHostList').prop('inventory')).toEqual({ - id: 1, - }); + expect(wrapper.find('AdvancedInventoryHostList').length).toBe(1); + expect(wrapper.find('AdvancedInventoryHostList').prop('inventory')).toEqual( + { + id: 1, + } + ); jest.clearAllMocks(); }); @@ -45,20 +47,23 @@ describe('', () => { initialEntries: ['/inventories/smart_inventory/1/hosts/2'], }); const match = { - path: '/inventories/smart_inventory/:id/hosts/:hostId', + path: '/inventories/:inventoryType/:id/hosts/:hostId', url: '/inventories/smart_inventory/1/hosts/2', isExact: true, }; await act(async () => { wrapper = mountWithContexts( - {}} />, + {}} + />, { context: { router: { history, route: { match } } }, } ); }); await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); - expect(wrapper.find('SmartInventoryHost').length).toBe(1); + expect(wrapper.find('AdvancedInventoryHost').length).toBe(1); jest.clearAllMocks(); }); }); diff --git a/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/index.js b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/index.js new file mode 100644 index 0000000000..121af5d8c2 --- /dev/null +++ b/awx/ui/src/screens/Inventory/AdvancedInventoryHosts/index.js @@ -0,0 +1 @@ +export { default } from './AdvancedInventoryHosts'; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventory.js b/awx/ui/src/screens/Inventory/ConstructedInventory.js index 58b33b96d2..242cbab585 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventory.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventory.js @@ -23,7 +23,7 @@ import RoutedTabs from 'components/RoutedTabs'; import ConstructedInventoryDetail from './ConstructedInventoryDetail'; import ConstructedInventoryEdit from './ConstructedInventoryEdit'; import ConstructedInventoryGroups from './ConstructedInventoryGroups'; -import ConstructedInventoryHosts from './ConstructedInventoryHosts'; +import AdvancedInventoryHosts from './AdvancedInventoryHosts'; import { getInventoryPath } from './shared/utils'; function ConstructedInventory({ setBreadcrumb }) { @@ -42,8 +42,7 @@ function ConstructedInventory({ setBreadcrumb }) { ); return data; }, [match.params.id]), - - null + { isLoading: true } ); useEffect(() => { @@ -111,7 +110,11 @@ function ConstructedInventory({ setBreadcrumb }) { } let showCardHeader = true; - if (['edit'].some((name) => location.pathname.includes(name))) { + if ( + ['edit', 'add', 'groups/', 'hosts/'].some((name) => + location.pathname.includes(name) + ) + ) { showCardHeader = false; } @@ -154,7 +157,10 @@ function ConstructedInventory({ setBreadcrumb }) { path="/inventories/constructed_inventory/:id/hosts" key="hosts" > - + , ({ describe('', () => { let wrapper; - beforeEach(async () => { + // beforeEach(async () => { + // ConstructedInventoriesAPI.readDetail.mockResolvedValue({ + // data: mockInventory, + // }); + // }); + + test('should render expected tabs', async () => { ConstructedInventoriesAPI.readDetail.mockResolvedValue({ data: mockInventory, }); - }); - - test('should render expected tabs', async () => { const expectedTabs = [ 'Back to Inventories', 'Details', @@ -45,6 +51,9 @@ describe('', () => { }); test('should show content error when user attempts to navigate to erroneous route', async () => { + ConstructedInventoriesAPI.readDetail.mockResolvedValue({ + data: { ...mockInventory, kind: 'constructed' }, + }); const history = createMemoryHistory({ initialEntries: ['/inventories/constructed_inventory/1/foobar'], }); @@ -60,7 +69,7 @@ describe('', () => { match: { params: { id: 1 }, url: '/inventories/constructed_inventory/1/foobar', - path: '/inventories/constructed_inventory/1/foobar', + path: '/inventories/:inventoryType/:id/foobar', }, }, }, @@ -68,6 +77,7 @@ describe('', () => { } ); }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); expect(wrapper.find('ContentError').length).toBe(1); }); }); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js deleted file mode 100644 index 56f0c801b8..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint i18next/no-literal-string: "off" */ -import React from 'react'; -import { CardBody } from 'components/Card'; - -function ConstructedInventoryHosts() { - return ( - -
Coming Soon!
-
- ); -} - -export default ConstructedInventoryHosts; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js deleted file mode 100644 index 0d6b3d6f13..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/ConstructedInventoryHosts.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; -import ConstructedInventoryHosts from './ConstructedInventoryHosts'; - -describe('', () => { - test('initially renders successfully', async () => { - let wrapper; - await act(async () => { - wrapper = mountWithContexts(); - }); - expect(wrapper.length).toBe(1); - expect(wrapper.find('ConstructedInventoryHosts').length).toBe(1); - }); -}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js deleted file mode 100644 index 68464720fb..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryHosts/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ConstructedInventoryHosts'; diff --git a/awx/ui/src/screens/Inventory/SmartInventory.js b/awx/ui/src/screens/Inventory/SmartInventory.js index b91d253dc6..d55327aa27 100644 --- a/awx/ui/src/screens/Inventory/SmartInventory.js +++ b/awx/ui/src/screens/Inventory/SmartInventory.js @@ -22,7 +22,7 @@ import RoutedTabs from 'components/RoutedTabs'; import RelatedTemplateList from 'components/RelatedTemplateList'; import SmartInventoryDetail from './SmartInventoryDetail'; import SmartInventoryEdit from './SmartInventoryEdit'; -import SmartInventoryHosts from './SmartInventoryHosts'; +import AdvancedInventoryHosts from './AdvancedInventoryHosts'; import { getInventoryPath } from './shared/utils'; function SmartInventory({ setBreadcrumb }) { @@ -142,7 +142,7 @@ function SmartInventory({ setBreadcrumb }) { />
, - diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHost/index.js b/awx/ui/src/screens/Inventory/SmartInventoryHost/index.js deleted file mode 100644 index 7e634beb10..0000000000 --- a/awx/ui/src/screens/Inventory/SmartInventoryHost/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SmartInventoryHost'; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/index.js b/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/index.js deleted file mode 100644 index 4c166ddc01..0000000000 --- a/awx/ui/src/screens/Inventory/SmartInventoryHostDetail/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SmartInventoryHostDetail'; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.js b/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.js deleted file mode 100644 index b1f461eabc..0000000000 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHosts.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { Route, Switch } from 'react-router-dom'; -import { Inventory } from 'types'; -import SmartInventoryHostList from './SmartInventoryHostList'; -import SmartInventoryHost from '../SmartInventoryHost'; - -function SmartInventoryHosts({ inventory, setBreadcrumb }) { - return ( - - - - - - - - - ); -} - -SmartInventoryHosts.propTypes = { - inventory: Inventory.isRequired, -}; - -export default SmartInventoryHosts; diff --git a/awx/ui/src/screens/Inventory/SmartInventoryHosts/index.js b/awx/ui/src/screens/Inventory/SmartInventoryHosts/index.js deleted file mode 100644 index 95af99ffe3..0000000000 --- a/awx/ui/src/screens/Inventory/SmartInventoryHosts/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SmartInventoryHosts'; From ba9533f0e2d96781edf4eb225696de5ad2b96764 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Thu, 23 Feb 2023 13:43:54 -0500 Subject: [PATCH 074/167] Adds constructed inventory groups and related groups. --- .../src/api/models/ConstructedInventories.js | 1 - .../screens/Inventory/ConstructedInventory.js | 9 +- .../Inventory/ConstructedInventory.test.js | 6 - .../ConstructedInventoryGroups.js | 13 -- .../ConstructedInventoryGroups.test.js | 15 --- .../ConstructedInventoryGroups/index.js | 1 - .../InventoryGroup/InventoryGroup.js | 24 ++-- .../InventoryGroup/InventoryGroup.test.js | 82 ++++++++++-- .../InventoryGroupDetail.js | 57 ++++---- .../InventoryGroupDetail.test.js | 60 +++++++++ .../InventoryGroupHostList.js | 30 +++-- .../InventoryGroupHostList.test.js | 76 ++++++++++- .../InventoryGroupHostListItem.js | 38 +++--- .../InventoryGroupHostListItem.test.js | 98 ++++++++++---- .../InventoryGroupHosts.js | 2 +- .../InventoryGroups/InventoryGroupItem.js | 50 ++++--- .../InventoryGroupItem.test.js | 37 +++++ .../InventoryGroups/InventoryGroups.js | 9 +- .../InventoryGroups/InventoryGroupsList.js | 47 ++++--- .../InventoryGroupsList.test.js | 91 +++++++++++-- .../InventoryRelatedGroupList.js | 27 ++-- .../InventoryRelatedGroupList.test.js | 126 +++++++++++++++--- .../InventoryRelatedGroupListItem.js | 36 ++--- .../InventoryRelatedGroupListItem.test.js | 109 +++++++++++---- .../InventoryRelatedGroups.js | 4 +- 25 files changed, 765 insertions(+), 283 deletions(-) delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js delete mode 100644 awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js diff --git a/awx/ui/src/api/models/ConstructedInventories.js b/awx/ui/src/api/models/ConstructedInventories.js index b62bffd3f3..d1384e915e 100644 --- a/awx/ui/src/api/models/ConstructedInventories.js +++ b/awx/ui/src/api/models/ConstructedInventories.js @@ -7,5 +7,4 @@ class ConstructedInventories extends InstanceGroupsMixin(Base) { this.baseUrl = 'api/v2/constructed_inventories/'; } } - export default ConstructedInventories; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventory.js b/awx/ui/src/screens/Inventory/ConstructedInventory.js index 242cbab585..086c755adb 100644 --- a/awx/ui/src/screens/Inventory/ConstructedInventory.js +++ b/awx/ui/src/screens/Inventory/ConstructedInventory.js @@ -22,7 +22,7 @@ import { ResourceAccessList } from 'components/ResourceAccessList'; import RoutedTabs from 'components/RoutedTabs'; import ConstructedInventoryDetail from './ConstructedInventoryDetail'; import ConstructedInventoryEdit from './ConstructedInventoryEdit'; -import ConstructedInventoryGroups from './ConstructedInventoryGroups'; +import InventoryGroups from './InventoryGroups'; import AdvancedInventoryHosts from './AdvancedInventoryHosts'; import { getInventoryPath } from './shared/utils'; @@ -164,9 +164,12 @@ function ConstructedInventory({ setBreadcrumb }) { , - + , ({ describe('', () => { let wrapper; - // beforeEach(async () => { - // ConstructedInventoriesAPI.readDetail.mockResolvedValue({ - // data: mockInventory, - // }); - // }); - test('should render expected tabs', async () => { ConstructedInventoriesAPI.readDetail.mockResolvedValue({ data: mockInventory, diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js deleted file mode 100644 index 964dfa9062..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint i18next/no-literal-string: "off" */ -import React from 'react'; -import { CardBody } from 'components/Card'; - -function ConstructedInventoryGroups() { - return ( - -
Coming Soon!
-
- ); -} - -export default ConstructedInventoryGroups; diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js deleted file mode 100644 index db2720ff44..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/ConstructedInventoryGroups.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; -import ConstructedInventoryGroups from './ConstructedInventoryGroups'; - -describe('', () => { - test('initially renders successfully', async () => { - let wrapper; - await act(async () => { - wrapper = mountWithContexts(); - }); - expect(wrapper.length).toBe(1); - expect(wrapper.find('ConstructedInventoryGroups').length).toBe(1); - }); -}); diff --git a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js b/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js deleted file mode 100644 index 7f1b4343b2..0000000000 --- a/awx/ui/src/screens/Inventory/ConstructedInventoryGroups/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ConstructedInventoryGroups'; diff --git a/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js b/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js index 0a8bc79374..6a5765114f 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js +++ b/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js @@ -23,7 +23,7 @@ function InventoryGroup({ setBreadcrumb, inventory }) { const [inventoryGroup, setInventoryGroup] = useState(null); const [contentLoading, setContentLoading] = useState(true); const [contentError, setContentError] = useState(null); - const { id: inventoryId, groupId } = useParams(); + const { id: inventoryId, groupId, inventoryType } = useParams(); const location = useLocation(); useEffect(() => { @@ -50,22 +50,22 @@ function InventoryGroup({ setBreadcrumb, inventory }) { {t`Back to Groups`} ), - link: `/inventories/inventory/${inventory.id}/groups`, + link: `/inventories/${inventoryType}/${inventoryId}/groups`, id: 99, }, { name: t`Details`, - link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup?.id}/details`, + link: `/inventories/${inventoryType}/${inventoryId}/groups/${inventoryGroup?.id}/details`, id: 0, }, { name: t`Related Groups`, - link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup?.id}/nested_groups`, + link: `/inventories/${inventoryType}/${inventoryId}/groups/${inventoryGroup?.id}/nested_groups`, id: 1, }, { name: t`Hosts`, - link: `/inventories/inventory/${inventory.id}/groups/${inventoryGroup?.id}/nested_hosts`, + link: `/inventories/${inventoryType}/${inventoryId}/groups/${inventoryGroup?.id}/nested_hosts`, id: 2, }, ]; @@ -105,32 +105,32 @@ function InventoryGroup({ setBreadcrumb, inventory }) { {showCardHeader && } {inventoryGroup && [ , , , , @@ -138,7 +138,7 @@ function InventoryGroup({ setBreadcrumb, inventory }) { {inventory && ( - + {t`View Inventory Details`} )} diff --git a/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.test.js b/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.test.js index ee468bf7d4..03182dba5c 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.test.js +++ b/awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.test.js @@ -11,15 +11,16 @@ import { import InventoryGroup from './InventoryGroup'; jest.mock('../../../api'); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ - id: 1, - groupId: 2, - }), -})); - describe('', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 1, + inventoryType: 'inventory', + }), + })); + let wrapper; let history; const inventory = { id: 1, name: 'Foo' }; @@ -41,11 +42,11 @@ describe('', () => { }, }); history = createMemoryHistory({ - initialEntries: ['/inventories/inventory/1/groups/1/details'], + initialEntries: [`/inventories/inventory/1/groups/1/details`], }); await act(async () => { wrapper = mountWithContexts( - + {}} inventory={inventory} /> , { context: { router: { history } } } @@ -63,7 +64,7 @@ describe('', () => { expect(routedTabs).toHaveLength(1); const tabs = routedTabs.prop('tabsArray'); - expect(tabs[0].link).toEqual('/inventories/inventory/1/groups'); + expect(tabs[0].link).toEqual(`/inventories/inventory/1/groups`); expect(tabs[1].name).toEqual('Details'); expect(tabs[2].name).toEqual('Related Groups'); expect(tabs[3].name).toEqual('Hosts'); @@ -71,7 +72,7 @@ describe('', () => { test('should show content error when user attempts to navigate to erroneous route', async () => { history = createMemoryHistory({ - initialEntries: ['/inventories/inventory/1/groups/1/foobar'], + initialEntries: [`/inventories/inventory/1/groups/1/foobar`], }); await act(async () => { wrapper = mountWithContexts( @@ -92,3 +93,60 @@ describe('', () => { await waitForElement(wrapper, 'ContentError', (el) => el.length === 1); }); }); + +describe('constructed inventory', () => { + let wrapper; + let history; + const inventory = { id: 1, name: 'Foo' }; + + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + + beforeEach(async () => { + GroupsAPI.readDetail.mockResolvedValue({ + data: { + id: 1, + name: 'Foo', + description: 'Bar', + variables: 'bizz: buzz', + summary_fields: { + inventory: { id: 1 }, + created_by: { id: 1, username: 'Athena' }, + modified_by: { id: 1, username: 'Apollo' }, + }, + created: '2020-04-25T01:23:45.678901Z', + modified: '2020-04-25T01:23:45.678901Z', + }, + }); + history = createMemoryHistory({ + initialEntries: [`/inventories/constructed_inventory/1/groups/1/details`], + }); + + await act(async () => { + wrapper = mountWithContexts( + + {}} inventory={inventory} /> + , + { context: { router: { history } } } + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + test('Constructed Inventory expect all tabs to exist, including Back to Groups', () => { + const routedTabs = wrapper.find('RoutedTabs'); + expect(routedTabs).toHaveLength(1); + + const tabs = routedTabs.prop('tabsArray'); + expect(tabs[0].link).toEqual(`/inventories/constructed_inventory/1/groups`); + expect(tabs[1].name).toEqual('Details'); + expect(tabs[2].name).toEqual('Related Groups'); + expect(tabs[3].name).toEqual('Hosts'); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js b/awx/ui/src/screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js index 94fd284076..6200e49416 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupDetail/InventoryGroupDetail.js @@ -1,9 +1,8 @@ import React, { useState } from 'react'; import { t } from '@lingui/macro'; - +import { useHistory, useParams } from 'react-router-dom'; import { Button } from '@patternfly/react-core'; -import { useHistory, useParams } from 'react-router-dom'; import { VariablesDetail } from 'components/CodeEditor'; import { CardBody, CardActionsRow } from 'components/Card'; import ErrorDetail from 'components/ErrorDetail'; @@ -12,6 +11,7 @@ import { DetailList, Detail, UserDateDetail } from 'components/DetailList'; import InventoryGroupsDeleteModal from '../shared/InventoryGroupsDeleteModal'; function InventoryGroupDetail({ inventoryGroup }) { + const { inventoryType, id, groupId } = useParams(); const { summary_fields: { created_by, modified_by, user_capabilities }, created, @@ -22,7 +22,6 @@ function InventoryGroupDetail({ inventoryGroup }) { } = inventoryGroup; const [error, setError] = useState(false); const history = useHistory(); - const params = useParams(); return ( @@ -47,31 +46,33 @@ function InventoryGroupDetail({ inventoryGroup }) { user={modified_by} /> - - {user_capabilities?.edit && ( - - )} - {user_capabilities?.delete && ( - - history.push(`/inventories/inventory/${params.id}/groups`) - } - /> - )} - + {inventoryType !== 'constructed_inventory' && ( + + {user_capabilities?.edit && ( + + )} + {user_capabilities?.delete && ( + + history.push(`/inventories/inventory/${id}/groups`) + } + /> + )} + + )} {error && ( ', () => { let history; describe('User has full permissions', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 3, + inventoryType: 'inventory', + }), + })); beforeEach(async () => { await act(async () => { history = createMemoryHistory({ @@ -116,6 +124,14 @@ describe('', () => { }); describe('User has read-only permissions', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 3, + inventoryType: 'inventory', + }), + })); test('should hide edit/delete buttons', async () => { const readOnlyGroup = { ...inventoryGroup, @@ -159,4 +175,48 @@ describe('', () => { expect(wrapper.find('button[aria-label="Delete"]').length).toBe(0); }); }); + describe('Cannot edit or delete constructed inventory group', () => { + beforeEach(async () => { + await act(async () => { + history = createMemoryHistory({ + initialEntries: ['/inventories/inventory/1/groups/1/details'], + }); + wrapper = mountWithContexts( + + + , + { + context: { + router: { + history, + route: { + location: history.location, + match: { + params: { + id: 1, + group: 2, + inventoryType: 'constructed_inventory', + }, + }, + }, + }, + }, + } + ); + await waitForElement( + wrapper, + 'ContentLoading', + (el) => el.length === 0 + ); + }); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + test('should not show edit button', () => { + const editButton = wrapper.find('Button[aria-label="edit"]'); + expect(editButton.length).toBe(0); + expect(wrapper.find('Button[aria-label="delete"]').length).toBe(0); + }); + }); }); diff --git a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js index 2825715ede..42903b7db6 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.js @@ -34,7 +34,7 @@ const QS_CONFIG = getQSConfig('host', { function InventoryGroupHostList() { const [isAdHocLaunchLoading, setIsAdHocLaunchLoading] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); - const { id: inventoryId, groupId } = useParams(); + const { id: inventoryId, groupId, inventoryType } = useParams(); const location = useLocation(); const { @@ -145,9 +145,11 @@ function InventoryGroupHostList() { useDismissableError(associateErr); const { error: disassociateError, dismissError: dismissDisassociateError } = useDismissableError(disassociateErr); - + const isNotConstructedInventory = inventoryType !== 'constructed_inventory'; const canAdd = - actions && Object.prototype.hasOwnProperty.call(actions, 'POST'); + actions && + Object.prototype.hasOwnProperty.call(actions, 'POST') && + isNotConstructedInventory; const addFormUrl = `/inventories/inventory/${inventoryId}/groups/${groupId}/nested_hosts/add`; const addExistingHost = t`Add existing host`; const addNewHost = t`Add new host`; @@ -240,17 +242,21 @@ function InventoryGroupHostList() { />, ] : []), - , + />, + ] + : []), ]} /> )} @@ -259,8 +265,8 @@ function InventoryGroupHostList() { key={host.id} rowIndex={index} host={host} - detailUrl={`/inventories/inventory/${inventoryId}/hosts/${host.id}/details`} - editUrl={`/inventories/inventory/${inventoryId}/hosts/${host.id}/edit`} + detailUrl={`/inventories/${inventoryType}/${inventoryId}/hosts/${host.id}/details`} + editUrl={`/inventories/${inventoryType}/${inventoryId}/hosts/${host.id}/edit`} isSelected={selected.some((row) => row.id === host.id)} onSelect={() => handleSelect(host)} /> diff --git a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.test.js b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.test.js index 4205a43171..3385e38d71 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.test.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostList.test.js @@ -8,19 +8,20 @@ import { } from '../../../../testUtils/enzymeHelpers'; import InventoryGroupHostList from './InventoryGroupHostList'; import mockHosts from '../shared/data.hosts.json'; +import { Route } from 'react-router-dom'; jest.mock('../../../api/models/Groups'); jest.mock('../../../api/models/Inventories'); jest.mock('../../../api/models/CredentialTypes'); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ - id: 1, - groupId: 2, - }), -})); describe('', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + }), + })); let wrapper; beforeEach(async () => { @@ -303,3 +304,64 @@ describe('', () => { expect(wrapper.find('AdHocCommands')).toHaveLength(0); }); }); + +describe(' for constructed inventories', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + let wrapper; + + beforeEach(async () => { + GroupsAPI.readAllHosts.mockResolvedValue({ + data: { ...mockHosts }, + }); + InventoriesAPI.readHostsOptions.mockResolvedValue({ + data: { + actions: { + GET: {}, + POST: {}, + }, + }, + }); + InventoriesAPI.readAdHocOptions.mockResolvedValue({ + data: { + actions: { + GET: { + module_name: { + choices: [ + ['command', 'command'], + ['shell', 'shell'], + ], + }, + }, + POST: {}, + }, + }, + }); + const history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/1/groups/2/hosts'], + }); + await act(async () => { + wrapper = mountWithContexts( + + + , + { context: { router: { history } } } + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + test('Should not show associate, or disassociate button', async () => { + expect(wrapper.find('AddDropDownButton').length).toBe(0); + expect(wrapper.find('DisassociateButton').length).toBe(0); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js index b5d56925b4..f5e435c024 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.js @@ -1,6 +1,6 @@ import 'styled-components/macro'; import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import { string, bool, func, number } from 'prop-types'; import { t } from '@lingui/macro'; import { Button, Tooltip } from '@patternfly/react-core'; @@ -24,7 +24,7 @@ function InventoryGroupHostListItem({ ...job, type: 'job', })); - + const { inventoryType } = useParams(); const labelId = `check-action-${host.id}`; return ( @@ -57,22 +57,24 @@ function InventoryGroupHostListItem({ > - - - - - + {inventoryType !== 'constructed_inventory' && ( + + + + + + )} ); diff --git a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.test.js b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.test.js index c26ac566f8..4667c9b02d 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.test.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHostListItem.test.js @@ -1,28 +1,35 @@ import React from 'react'; +import { createMemoryHistory } from 'history'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import InventoryGroupHostListItem from './InventoryGroupHostListItem'; import mockHosts from '../shared/data.hosts.json'; +import { Route } from 'react-router-dom'; jest.mock('../../../api'); describe('', () => { let wrapper; const mockHost = mockHosts.results[0]; - + const history = createMemoryHistory({ + initialEntries: ['/inventories/inventory/1/groups/2/hosts'], + }); beforeEach(() => { wrapper = mountWithContexts( -
- - {}} - rowIndex={0} - /> - -
+ + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } ); }); @@ -52,19 +59,60 @@ describe('', () => { const copyMockHost = { ...mockHost }; copyMockHost.summary_fields.user_capabilities.edit = false; wrapper = mountWithContexts( - - - {}} - rowIndex={0} - /> - -
+ + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } ); expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); }); }); + +describe(' inside constructed inventories', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + let wrapper; + const mockHost = mockHosts.results[0]; + const history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/1/groups/2/hosts'], + }); + beforeEach(() => { + wrapper = mountWithContexts( + + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } + ); + }); + test('Edit button hidden for constructed inventory', () => { + expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHosts.js b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHosts.js index d0e4c34d70..696b5bede8 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHosts.js +++ b/awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHosts.js @@ -9,7 +9,7 @@ function InventoryGroupHosts({ inventoryGroup }) { - +
diff --git a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.js b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.js index 966f4fe2a5..2f8b5b2ab4 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.js +++ b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.js @@ -1,25 +1,20 @@ import React from 'react'; -import { bool, func, number, oneOfType, string } from 'prop-types'; +import { bool, func } from 'prop-types'; import { t } from '@lingui/macro'; import { Button } from '@patternfly/react-core'; import { Tr, Td } from '@patternfly/react-table'; -import { Link } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; import { ActionsTd, ActionItem } from 'components/PaginatedTable'; import { Group } from 'types'; -function InventoryGroupItem({ - group, - inventoryId, - isSelected, - onSelect, - rowIndex, -}) { +function InventoryGroupItem({ group, isSelected, onSelect, rowIndex }) { + const { id: inventoryId, inventoryType } = useParams(); const labelId = `check-action-${group.id}`; - const detailUrl = `/inventories/inventory/${inventoryId}/groups/${group.id}/details`; - const editUrl = `/inventories/inventory/${inventoryId}/groups/${group.id}/edit`; + const detailUrl = `/inventories/${inventoryType}/${inventoryId}/groups/${group.id}/details`; + const editUrl = `/inventories/${inventoryType}/${inventoryId}/groups/${group.id}/edit`; return ( @@ -36,29 +31,30 @@ function InventoryGroupItem({ {group.name} - - - - - + + + + )} ); } InventoryGroupItem.propTypes = { group: Group.isRequired, - inventoryId: oneOfType([number, string]).isRequired, isSelected: bool.isRequired, onSelect: func.isRequired, }; diff --git a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.test.js b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.test.js index cb4956e44a..49f4fe22b5 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.test.js +++ b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupItem.test.js @@ -1,4 +1,6 @@ import React from 'react'; +import { Route } from 'react-router-dom'; +import { act } from 'react-dom/test-utils'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import InventoryGroupItem from './InventoryGroupItem'; @@ -57,4 +59,39 @@ describe('', () => { ); expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); }); + test('edit button should be hidden from constructed inventory group', async () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ id: 42, inventoryType: 'constructed_inventory' }), + })); + const mockGroup = { + id: 2, + type: 'group', + name: 'foo', + inventory: 1, + summary_fields: { + user_capabilities: { + edit: true, + }, + }, + }; + + await act(async () => { + wrapper = mountWithContexts( + + + + {}} + /> + +
+
+ ); + }); + expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); + }); }); diff --git a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroups.js b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroups.js index ae19f09660..97eef35dc6 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroups.js +++ b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroups.js @@ -16,11 +16,14 @@ function InventoryGroups({ setBreadcrumb, inventory }) { inventory={inventory} /> - + - - + + ); diff --git a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.js b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.js index 77bd67c404..fa474845c6 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.js +++ b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.js @@ -29,7 +29,7 @@ function cannotDelete(item) { function InventoryGroupsList() { const location = useLocation(); - const { id: inventoryId } = useParams(); + const { id: inventoryId, inventoryType } = useParams(); const [isAdHocLaunchLoading, setIsAdHocLaunchLoading] = useState(false); const { @@ -102,9 +102,11 @@ function InventoryGroupsList() { } return t`Select a row to delete`; }; - + const isNotConstructedInventory = inventoryType !== 'constructed_inventory'; const canAdd = - actions && Object.prototype.hasOwnProperty.call(actions, 'POST'); + actions && + Object.prototype.hasOwnProperty.call(actions, 'POST') && + isNotConstructedInventory; return ( {t`Name`} - {t`Actions`} + {isNotConstructedInventory && {t`Actions`}} } renderRow={(item, index) => ( row.id === item.id)} onSelect={() => handleSelect(item)} rowIndex={index} @@ -177,20 +178,28 @@ function InventoryGroupsList() { />, ] : []), - -
- { - fetchData(); - clearSelected(); - }} - /> -
-
, + ...(isNotConstructedInventory + ? [ + +
+ { + fetchData(); + clearSelected(); + }} + /> +
+
, + ] + : []), ]} /> )} diff --git a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.test.js b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.test.js index 5743fc96c8..d33127899a 100644 --- a/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.test.js +++ b/awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroupsList.test.js @@ -10,12 +10,6 @@ import { import InventoryGroupsList from './InventoryGroupsList'; jest.mock('../../../api'); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ - id: 1, - }), -})); const mockGroups = [ { id: 1, @@ -60,7 +54,14 @@ const mockGroups = [ describe('', () => { let wrapper; - + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'inventory', + }), + })); beforeEach(async () => { InventoriesAPI.readGroups.mockResolvedValue({ data: { @@ -96,7 +97,7 @@ describe('', () => { }); await act(async () => { wrapper = mountWithContexts( - + , { @@ -316,3 +317,77 @@ describe(' error handling', () => { }); }); }); + +describe('Constructed Inventory group', () => { + let wrapper; + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + + beforeEach(async () => { + InventoriesAPI.readGroups.mockResolvedValue({ + data: { + count: mockGroups.length, + results: mockGroups, + }, + }); + InventoriesAPI.readGroupsOptions.mockResolvedValue({ + data: { + actions: { + GET: {}, + POST: {}, + }, + }, + }); + InventoriesAPI.readAdHocOptions.mockResolvedValue({ + data: { + actions: { + GET: { + module_name: { + choices: [ + ['command', 'command'], + ['shell', 'shell'], + ], + }, + }, + POST: {}, + }, + }, + }); + const history = createMemoryHistory({ + initialEntries: ['/inventories/constructed_inventory/3/groups'], + }); + await act(async () => { + wrapper = mountWithContexts( + + + , + { + context: { + router: { + history, + route: { + location: history.location, + }, + }, + }, + } + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + test('should not show add button', () => { + expect(wrapper.find('ToolbarAddButton').length).toBe(0); + expect(wrapper.find('ToolbarDeleteButton').length).toBe(0); + expect(wrapper.find('AdHocCommands').length).toBe(1); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js index 98aa701e00..0b8ec5054d 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.js @@ -33,7 +33,7 @@ function InventoryRelatedGroupList() { const [isAdHocLaunchLoading, setIsAdHocLaunchLoading] = useState(false); const [associateError, setAssociateError] = useState(null); const [disassociateError, setDisassociateError] = useState(null); - const { id: inventoryId, groupId } = useParams(); + const { id: inventoryId, groupId, inventoryType } = useParams(); const location = useLocation(); const { @@ -69,9 +69,10 @@ function InventoryRelatedGroupList() { searchableKeys: getSearchableKeys(actions.data.actions?.GET), canAdd: actions.data.actions && - Object.prototype.hasOwnProperty.call(actions.data.actions, 'POST'), + Object.prototype.hasOwnProperty.call(actions.data.actions, 'POST') && + inventoryType !== 'constructed_inventory', }; - }, [groupId, location.search, inventoryId]), + }, [groupId, location.search, inventoryType, inventoryId]), { groups: [], itemCount: 0, @@ -164,7 +165,7 @@ function InventoryRelatedGroupList() { ]} /> ); - + const isNotConstructedInventory = inventoryType !== 'constructed_inventory'; return ( <> , ] : []), - , + ...(isNotConstructedInventory + ? [ + , + ] + : []), ]} /> )} headerRow={ {t`Name`} - {t`Actions`} + {isNotConstructedInventory && {t`Actions`}} } renderRow={(group, index) => ( diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js index 0c6045b7dd..a8cba4aeac 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupList.test.js @@ -1,6 +1,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; - +import { createMemoryHistory } from 'history'; +import { Route } from 'react-router-dom'; import { GroupsAPI, InventoriesAPI } from 'api'; import { mountWithContexts, @@ -13,14 +14,6 @@ jest.mock('../../../api/models/Groups'); jest.mock('../../../api/models/Inventories'); jest.mock('../../../api/models/CredentialTypes'); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ - id: 1, - groupId: 2, - }), -})); - const mockGroups = [ { id: 1, @@ -65,6 +58,14 @@ const mockGroups = [ describe('', () => { let wrapper; + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 2, + groupId: 2, + inventoryType: 'inventory', + }), + })); beforeEach(async () => { GroupsAPI.readChildren.mockResolvedValue({ @@ -210,11 +211,22 @@ describe('', () => { GroupsAPI.readPotentialGroups.mockResolvedValue({ data: { count: mockGroups.length, results: mockGroups }, }); - await act(async () => { - wrapper = mountWithContexts(); + const history = createMemoryHistory({ + initialEntries: ['/inventories/inventory/2/groups/2/nested_groups'], }); - await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); - + await act(async () => { + wrapper = mountWithContexts( + + + , + { context: { router: { history } } } + ); + }); + await waitForElement( + wrapper, + 'InventoryRelatedGroupList', + (el) => el.length > 0 + ); act(() => wrapper.find('Button[aria-label="Add"]').prop('onClick')()); wrapper.update(); await act(async () => @@ -222,9 +234,9 @@ describe('', () => { .find('DropdownItem[aria-label="Add existing group"]') .prop('onClick')() ); - expect(GroupsAPI.readPotentialGroups).toBeCalledWith(2, { - not__id: 2, - not__parents: 2, + expect(GroupsAPI.readPotentialGroups).toBeCalledWith('2', { + not__id: '2', + not__parents: '2', order_by: 'name', page: 1, page_size: 5, @@ -261,3 +273,85 @@ describe('', () => { expect(wrapper.find('AdHocCommands')).toHaveLength(0); }); }); + +describe(' for constructed inventories', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + let wrapper; + + beforeEach(async () => { + GroupsAPI.readChildren.mockResolvedValue({ + data: { ...mockRelatedGroups }, + }); + InventoriesAPI.readGroupsOptions.mockResolvedValue({ + data: { + actions: { + GET: {}, + POST: {}, + }, + related_search_fields: [ + 'parents__search', + 'inventory__search', + 'inventory_sources__search', + 'created_by__search', + 'children__search', + 'modified_by__search', + 'hosts__search', + ], + }, + }); + InventoriesAPI.readAdHocOptions.mockResolvedValue({ + data: { + actions: { + GET: { + module_name: { + choices: [ + ['command', 'command'], + ['shell', 'shell'], + ], + }, + }, + POST: {}, + }, + }, + }); + const history = createMemoryHistory({ + initialEntries: [ + '/inventories/constructed_inventory/1/groups/2/nested_groupss', + ], + }); + await act(async () => { + wrapper = mountWithContexts( + + + , + { context: { router: { history } } } + ); + }); + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('Should not show associate, or disassociate button', async () => { + InventoriesAPI.readHostsOptions.mockResolvedValueOnce({ + data: { + actions: { + GET: {}, + }, + }, + }); + + await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0); + expect(wrapper.find('AddDropDownButton').length).toBe(0); + expect(wrapper.find('DisassociateButton').length).toBe(0); + }); +}); diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js index 3c2c9c090f..b30c872ba7 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.js @@ -1,6 +1,6 @@ import 'styled-components/macro'; import React from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import { string, bool, func, number } from 'prop-types'; import { t } from '@lingui/macro'; @@ -21,7 +21,7 @@ function InventoryRelatedGroupListItem({ onSelect, }) { const labelId = `check-action-${group.id}`; - + const { inventoryType } = useParams(); return ( {group.name}
- - - - - + + + + )} ); } diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.test.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.test.js index 4ab8fb17b1..eb3b6d99c2 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.test.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroupListItem.test.js @@ -1,28 +1,43 @@ import React from 'react'; +import { createMemoryHistory } from 'history'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import InventoryRelatedGroupListItem from './InventoryRelatedGroupListItem'; import mockRelatedGroups from '../shared/data.relatedGroups.json'; +import { Route } from 'react-router-dom'; jest.mock('../../../api'); +const mockGroup = mockRelatedGroups.results[0]; describe('', () => { let wrapper; - const mockGroup = mockRelatedGroups.results[0]; - + const history = createMemoryHistory({ + initialEntries: ['/inventories/inventory/1/groups/2/nested_groups'], + }); + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'inventory', + }), + })); beforeEach(() => { wrapper = mountWithContexts( - - - {}} - rowIndex={0} - /> - -
+ + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } ); }); @@ -36,18 +51,60 @@ describe('', () => { test('edit button hidden from users without edit capabilities', () => { wrapper = mountWithContexts( - - - {}} - rowIndex={0} - /> - -
+ + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } + ); + expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); + }); +}); + +describe(' for constructed inventories', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ + id: 1, + groupId: 2, + inventoryType: 'constructed_inventory', + }), + })); + + let wrapper; + + test('edit button hidden from users without edit capabilities', () => { + const history = createMemoryHistory({ + initialEntries: [ + '/inventories/constructed_inventory/1/groups/2/nested_groups', + ], + }); + wrapper = mountWithContexts( + + + + {}} + rowIndex={0} + /> + +
+
, + { context: { router: { history } } } ); expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); }); diff --git a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroups.js b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroups.js index d5904062b3..bca8ffc26a 100644 --- a/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroups.js +++ b/awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroups.js @@ -8,13 +8,13 @@ function InventoryRelatedGroups() { From e3d167dfd16b6f22e944ef3948f2c01080b6f313 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Wed, 22 Feb 2023 15:30:30 -0500 Subject: [PATCH 075/167] Hide constructed and smart inventories in Inventory Lookup --- awx/ui/src/components/HostForm/HostForm.js | 2 +- .../src/components/Lookup/InventoryLookup.js | 25 +++++++++++++------ .../components/Lookup/InventoryLookup.test.js | 4 +-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/awx/ui/src/components/HostForm/HostForm.js b/awx/ui/src/components/HostForm/HostForm.js index 8bbf6ac9f3..06e96c3f7f 100644 --- a/awx/ui/src/components/HostForm/HostForm.js +++ b/awx/ui/src/components/HostForm/HostForm.js @@ -38,7 +38,7 @@ const InventoryLookupField = ({ isDisabled }) => { error={inventoryMeta.error} validate={required(t`Select a value for this field`)} isDisabled={isDisabled} - hideSmartInventories + hideAdvancedInventories autoPopulate={!inventoryField.value?.id} /> ); diff --git a/awx/ui/src/components/Lookup/InventoryLookup.js b/awx/ui/src/components/Lookup/InventoryLookup.js index e37805451d..faf2e24a69 100644 --- a/awx/ui/src/components/Lookup/InventoryLookup.js +++ b/awx/ui/src/components/Lookup/InventoryLookup.js @@ -1,5 +1,5 @@ import React, { useCallback, useEffect } from 'react'; -import { func, bool, string } from 'prop-types'; +import { func, bool, string, oneOfType, arrayOf } from 'prop-types'; import { withRouter } from 'react-router-dom'; import { t } from '@lingui/macro'; import { InventoriesAPI } from 'api'; @@ -23,7 +23,7 @@ function InventoryLookup({ autoPopulate, fieldId, fieldName, - hideSmartInventories, + hideAdvancedInventories, history, isDisabled, isPromptableField, @@ -34,6 +34,7 @@ function InventoryLookup({ required, validate, value, + multiple, }) { const autoPopulateLookup = useAutoPopulateLookup(onChange); @@ -45,8 +46,8 @@ function InventoryLookup({ } = useRequest( useCallback(async () => { const params = parseQueryString(QS_CONFIG, history.location.search); - const inventoryKindParams = hideSmartInventories - ? { not__kind: 'smart' } + const inventoryKindParams = hideAdvancedInventories + ? { not__kind: ['smart', 'constructed'] } : {}; const [{ data }, actionsResponse] = await Promise.all([ InventoriesAPI.read( @@ -69,7 +70,10 @@ function InventoryLookup({ ).map((val) => val.slice(0, -8)), searchableKeys: Object.keys(actionsResponse.data.actions?.GET || {}) .filter((key) => { - if (['kind', 'host_filter'].includes(key) && hideSmartInventories) { + if ( + ['kind', 'host_filter'].includes(key) && + hideAdvancedInventories + ) { return false; } return actionsResponse.data.actions?.GET[key].filterable; @@ -187,6 +191,7 @@ function InventoryLookup({ onDebounce={checkInventoryName} fieldName={fieldName} validate={validate} + multiple={multiple} onBlur={onBlur} required={required} isLoading={isLoading} @@ -227,6 +232,10 @@ function InventoryLookup({ readOnly={!canDelete} selectItem={(item) => dispatch({ type: 'SELECT_ITEM', item })} deselectItem={(item) => dispatch({ type: 'DESELECT_ITEM', item })} + sortSelectedItems={(selectedItems) => + dispatch({ type: 'SET_SELECTED_ITEMS', selectedItems }) + } + isSelectedDraggable /> )} /> @@ -239,19 +248,19 @@ InventoryLookup.propTypes = { autoPopulate: bool, fieldId: string, fieldName: string, - hideSmartInventories: bool, + hideAdvancedInventories: bool, isDisabled: bool, onChange: func.isRequired, required: bool, validate: func, - value: Inventory, + value: oneOfType([Inventory, arrayOf(Inventory)]), }; InventoryLookup.defaultProps = { autoPopulate: false, fieldId: 'inventory', fieldName: 'inventory', - hideSmartInventories: false, + hideAdvancedInventories: false, isDisabled: false, required: false, validate: () => {}, diff --git a/awx/ui/src/components/Lookup/InventoryLookup.test.js b/awx/ui/src/components/Lookup/InventoryLookup.test.js index 120b4927e9..ad6f1aa709 100644 --- a/awx/ui/src/components/Lookup/InventoryLookup.test.js +++ b/awx/ui/src/components/Lookup/InventoryLookup.test.js @@ -70,14 +70,14 @@ describe('InventoryLookup', () => { await act(async () => { wrapper = mountWithContexts( - {}} hideSmartInventories /> + {}} hideAdvancedInventories /> ); }); wrapper.update(); expect(InventoriesAPI.read).toHaveBeenCalledTimes(1); expect(InventoriesAPI.read).toHaveBeenCalledWith({ - not__kind: 'smart', + not__kind: ['smart', 'constructed'], order_by: 'name', page: 1, page_size: 5, From d576e65858cdfbbb879931ead0afba7be439708c Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 23 Feb 2023 10:02:44 -0500 Subject: [PATCH 076/167] Add constructed inventory add form --- awx/ui/.eslintrc.json | 4 +- awx/ui/src/api/models/Inventories.js | 7 + .../components/CodeEditor/VariablesField.js | 35 ++- .../ConstructedInventoryAdd.js | 46 +++- .../ConstructedInventoryAdd.test.js | 115 ++++++++- .../InventoryRelatedGroupList.test.js | 2 +- .../shared/ConstructedInventoryForm.js | 229 ++++++++++++++++++ .../shared/ConstructedInventoryForm.test.js | 123 ++++++++++ .../shared/ConstructedInventoryHint.js | 164 +++++++++++++ .../shared/ConstructedInventoryHint.test.js | 46 ++++ .../Inventory/shared/Inventory.helptext.js | 38 +++ 11 files changed, 795 insertions(+), 14 deletions(-) create mode 100644 awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.js create mode 100644 awx/ui/src/screens/Inventory/shared/ConstructedInventoryForm.test.js create mode 100644 awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.js create mode 100644 awx/ui/src/screens/Inventory/shared/ConstructedInventoryHint.test.js diff --git a/awx/ui/.eslintrc.json b/awx/ui/.eslintrc.json index 7cf4965cbd..85eb903553 100644 --- a/awx/ui/.eslintrc.json +++ b/awx/ui/.eslintrc.json @@ -84,6 +84,7 @@ "displayKey", "sortedColumnKey", "maxHeight", + "maxWidth", "role", "aria-haspopup", "dropDirection", @@ -97,7 +98,8 @@ "data-cy", "fieldName", "splitButtonVariant", - "pageKey" + "pageKey", + "textId" ], "ignore": [ "Ansible", diff --git a/awx/ui/src/api/models/Inventories.js b/awx/ui/src/api/models/Inventories.js index 4fd145e178..8e586201b5 100644 --- a/awx/ui/src/api/models/Inventories.js +++ b/awx/ui/src/api/models/Inventories.js @@ -14,6 +14,7 @@ class Inventories extends InstanceGroupsMixin(Base) { this.readGroupsOptions = this.readGroupsOptions.bind(this); this.promoteGroup = this.promoteGroup.bind(this); this.readInputInventories = this.readInputInventories.bind(this); + this.associateInventory = this.associateInventory.bind(this); } readAccessList(id, params) { @@ -137,6 +138,12 @@ class Inventories extends InstanceGroupsMixin(Base) { disassociate: true, }); } + + associateInventory(id, inputInventoryId) { + return this.http.post(`${this.baseUrl}${id}/input_inventories/`, { + id: inputInventoryId, + }); + } } export default Inventories; diff --git a/awx/ui/src/components/CodeEditor/VariablesField.js b/awx/ui/src/components/CodeEditor/VariablesField.js index bbe8312c3d..eb48332d12 100644 --- a/awx/ui/src/components/CodeEditor/VariablesField.js +++ b/awx/ui/src/components/CodeEditor/VariablesField.js @@ -1,5 +1,5 @@ import React, { useState, useEffect, useCallback } from 'react'; -import { string, bool, func, oneOf } from 'prop-types'; +import { string, bool, func, oneOf, shape } from 'prop-types'; import { t } from '@lingui/macro'; import { useField } from 'formik'; @@ -38,6 +38,8 @@ function VariablesField({ tooltip, initialMode, onModeChange, + isRequired, + validators, }) { // track focus manually, because the Code Editor library doesn't wire // into Formik completely @@ -48,13 +50,22 @@ function VariablesField({ return undefined; } try { - parseVariableField(value); + const parsedVariables = parseVariableField(value); + if (validators) { + const errorMessages = Object.keys(validators) + .map((field) => validators[field](parsedVariables[field])) + .filter((e) => e); + + if (errorMessages.length > 0) { + return errorMessages; + } + } } catch (error) { return error.message; } return undefined; }, - [shouldValidate] + [shouldValidate, validators] ); const [field, meta, helpers] = useField({ name, validate }); const [mode, setMode] = useState(() => @@ -120,6 +131,7 @@ function VariablesField({ setMode={handleModeChange} setShouldValidate={setShouldValidate} handleChange={handleChange} + isRequired={isRequired} /> {meta.error ? (
- {meta.error} + {(Array.isArray(meta.error) ? meta.error : [meta.error]).map( + (errorMessage) => ( +

{errorMessage}

+ ) + )}
) : null}